1 /* compress.c - compress filter
2 * Copyright (C) 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
38 init_compress( compress_filter_context_t *zfx, z_stream *zs )
43 if( opt.compress >= 0 && opt.compress <= 9 )
45 else if( opt.compress == -1 )
46 level = Z_DEFAULT_COMPRESSION;
47 else if( opt.compress == 10 ) /* remove this ! */
50 log_error("invalid compression level; using default level\n");
51 level = Z_DEFAULT_COMPRESSION;
55 if( (rc = zfx->algo == 1? deflateInit2( zs, level, Z_DEFLATED,
56 -13, 8, Z_DEFAULT_STRATEGY)
57 : deflateInit( zs, level )
59 log_fatal("zlib problem: %s\n", zs->msg? zs->msg :
60 rc == Z_MEM_ERROR ? "out of core" :
61 rc == Z_VERSION_ERROR ? "invalid lib version" :
65 zfx->outbufsize = 8192;
66 zfx->outbuf = m_alloc( zfx->outbufsize );
70 do_compress( compress_filter_context_t *zfx, z_stream *zs, int flush, IOBUF a )
76 zs->next_out = zfx->outbuf;
77 zs->avail_out = zfx->outbufsize;
79 log_debug("enter deflate: avail_in=%u, avail_out=%u, flush=%d\n",
80 (unsigned)zs->avail_in, (unsigned)zs->avail_out, flush );
81 zrc = deflate( zs, flush );
82 if( zrc == Z_STREAM_END && flush == Z_FINISH )
84 else if( zrc != Z_OK ) {
86 log_fatal("zlib deflate problem: %s\n", zs->msg );
88 log_fatal("zlib deflate problem: rc=%d\n", zrc );
90 n = zfx->outbufsize - zs->avail_out;
92 log_debug("leave deflate: "
93 "avail_in=%u, avail_out=%u, n=%u, zrc=%d\n",
94 (unsigned)zs->avail_in, (unsigned)zs->avail_out,
97 if( iobuf_write( a, zfx->outbuf, n ) ) {
98 log_debug("deflate: iobuf_write failed\n");
99 return G10ERR_WRITE_FILE;
101 } while( zs->avail_in || (flush == Z_FINISH && zrc != Z_STREAM_END) );
106 init_uncompress( compress_filter_context_t *zfx, z_stream *zs )
111 * PGP uses a windowsize of 13 bits. Using a negative value for
112 * it forces zlib not to expect a zlib header. This is a
113 * undocumented feature Peter Gutmann told me about.
115 if( (rc = zfx->algo == 1? inflateInit2( zs, -13)
116 : inflateInit( zs )) != Z_OK ) {
117 log_fatal("zlib problem: %s\n", zs->msg? zs->msg :
118 rc == Z_MEM_ERROR ? "out of core" :
119 rc == Z_VERSION_ERROR ? "invalid lib version" :
123 zfx->inbufsize = 2048;
124 zfx->inbuf = m_alloc( zfx->inbufsize );
129 do_uncompress( compress_filter_context_t *zfx, z_stream *zs,
130 IOBUF a, size_t *ret_len )
137 int refill = !zs->avail_in;
140 log_debug("begin inflate: avail_in=%u, avail_out=%u, inbuf=%u\n",
141 (unsigned)zs->avail_in, (unsigned)zs->avail_out,
142 (unsigned)zfx->inbufsize );
144 if( zs->avail_in < zfx->inbufsize && refill ) {
147 zs->next_in = zfx->inbuf;
148 for( p=zfx->inbuf+n; n < zfx->inbufsize; n++, p++ ) {
149 if( (c=iobuf_get(a)) == -1 )
157 log_debug("enter inflate: avail_in=%u, avail_out=%u\n",
158 (unsigned)zs->avail_in, (unsigned)zs->avail_out);
160 zrc = inflate( zs, Z_SYNC_FLUSH );
162 zrc = inflate( zs, Z_PARTIAL_FLUSH );
165 log_debug("leave inflate: avail_in=%u, avail_out=%u, zrc=%d\n",
166 (unsigned)zs->avail_in, (unsigned)zs->avail_out, zrc);
167 if( zrc == Z_STREAM_END )
169 else if( zrc != Z_OK && zrc != Z_BUF_ERROR ) {
171 log_fatal("zlib inflate problem: %s\n", zs->msg );
173 log_fatal("zlib inflate problem: rc=%d\n", zrc );
175 } while( zs->avail_out && zrc != Z_STREAM_END && zrc != Z_BUF_ERROR );
176 *ret_len = zfx->outbufsize - zs->avail_out;
178 log_debug("do_uncompress: returning %u bytes\n", (unsigned)*ret_len );
183 compress_filter( void *opaque, int control,
184 IOBUF a, byte *buf, size_t *ret_len)
186 size_t size = *ret_len;
187 compress_filter_context_t *zfx = opaque;
188 z_stream *zs = zfx->opaque;
191 if( control == IOBUFCTRL_UNDERFLOW ) {
193 zs = zfx->opaque = m_alloc_clear( sizeof *zs );
194 init_uncompress( zfx, zs );
199 zs->avail_out = size;
200 zfx->outbufsize = size; /* needed only for calculation */
201 rc = do_uncompress( zfx, zs, a, ret_len );
203 else if( control == IOBUFCTRL_FLUSH ) {
209 zfx->algo = opt.def_compress_algo;
210 memset( &cd, 0, sizeof cd );
212 cd.algorithm = zfx->algo;
214 pkt.pkttype = PKT_COMPRESSED;
215 pkt.pkt.compressed = &cd;
216 if( build_packet( a, &pkt ))
217 log_bug("build_packet(PKT_COMPRESSED) failed\n");
218 zs = zfx->opaque = m_alloc_clear( sizeof *zs );
219 init_compress( zfx, zs );
225 rc = do_compress( zfx, zs, Z_NO_FLUSH, a );
227 else if( control == IOBUFCTRL_FREE ) {
228 if( zfx->status == 1 ) {
232 m_free(zfx->outbuf); zfx->outbuf = NULL;
234 else if( zfx->status == 2 ) {
237 do_compress( zfx, zs, Z_FINISH, a );
241 m_free(zfx->outbuf); zfx->outbuf = NULL;
244 else if( control == IOBUFCTRL_DESC )
245 *(char**)buf = "compress_filter";
250 * Handle a compressed packet
253 handle_compressed( PKT_compressed *cd,
254 int (*callback)(IOBUF, void *), void *passthru )
256 compress_filter_context_t cfx;
259 memset( &cfx, 0, sizeof cfx );
260 if( cd->algorithm < 1 || cd->algorithm > 2 )
261 return G10ERR_COMPR_ALGO;
262 cfx.algo = cd->algorithm;
264 iobuf_push_filter( cd->buf, compress_filter, &cfx );
266 rc = callback(cd->buf, passthru );
268 rc = proc_packets(cd->buf);
270 iobuf_pop_filter( cd->buf, compress_filter, &cfx );
272 iobuf_set_limit( cd->buf, 0 ); /* disable the readlimit */
274 iobuf_clear_eof( cd->buf );