1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-12-22 10:19:57 +01:00
gnupg/g10/compress-bz2.c
Werner Koch b008274afd Nuked almost all trailing white space.
We better do this once and for all instead of cluttering all future
commits with diffs of trailing white spaces.  In the majority of cases
blank or single lines are affected and thus this change won't disturb
a git blame too much.  For future commits the pre-commit scripts
checks that this won't happen again.
2011-02-04 12:57:53 +01:00

254 lines
6.8 KiB
C

/* compress.c - bzip2 compress filter
* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GnuPG is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <string.h>
#include <stdio.h> /* Early versions of bzlib (1.0) require stdio.h */
#include <bzlib.h>
#include "gpg.h"
#include "util.h"
#include "packet.h"
#include "filter.h"
#include "main.h"
#include "options.h"
/* Note that the code in compress.c is nearly identical to the code
here, so if you fix a bug here, look there to see if a matching bug
needs to be fixed. I tried to have one set of functions that could
do ZIP, ZLIB, and BZIP2, but it became dangerously unreadable with
#ifdefs and if(algo) -dshaw */
static void
init_compress( compress_filter_context_t *zfx, bz_stream *bzs )
{
int rc;
int level;
if( opt.bz2_compress_level >= 1 && opt.bz2_compress_level <= 9 )
level = opt.bz2_compress_level;
else if( opt.bz2_compress_level == -1 )
level = 6; /* no particular reason, but it seems reasonable */
else
{
log_error("invalid compression level; using default level\n");
level = 6;
}
if((rc=BZ2_bzCompressInit(bzs,level,0,0))!=BZ_OK)
log_fatal("bz2lib problem: %d\n",rc);
zfx->outbufsize = 8192;
zfx->outbuf = xmalloc( zfx->outbufsize );
}
static int
do_compress(compress_filter_context_t *zfx, bz_stream *bzs, int flush, IOBUF a)
{
int rc;
int zrc;
unsigned n;
do
{
bzs->next_out = zfx->outbuf;
bzs->avail_out = zfx->outbufsize;
if( DBG_FILTER )
log_debug("enter bzCompress: avail_in=%u, avail_out=%u, flush=%d\n",
(unsigned)bzs->avail_in, (unsigned)bzs->avail_out, flush );
zrc = BZ2_bzCompress( bzs, flush );
if( zrc == BZ_STREAM_END && flush == BZ_FINISH )
;
else if( zrc != BZ_RUN_OK && zrc != BZ_FINISH_OK )
log_fatal("bz2lib deflate problem: rc=%d\n", zrc );
n = zfx->outbufsize - bzs->avail_out;
if( DBG_FILTER )
log_debug("leave bzCompress:"
" avail_in=%u, avail_out=%u, n=%u, zrc=%d\n",
(unsigned)bzs->avail_in, (unsigned)bzs->avail_out,
(unsigned)n, zrc );
if( (rc=iobuf_write( a, zfx->outbuf, n )) )
{
log_debug("bzCompress: iobuf_write failed\n");
return rc;
}
}
while( bzs->avail_in || (flush == BZ_FINISH && zrc != BZ_STREAM_END) );
return 0;
}
static void
init_uncompress( compress_filter_context_t *zfx, bz_stream *bzs )
{
int rc;
if((rc=BZ2_bzDecompressInit(bzs,0,opt.bz2_decompress_lowmem))!=BZ_OK)
log_fatal("bz2lib problem: %d\n",rc);
zfx->inbufsize = 2048;
zfx->inbuf = xmalloc( zfx->inbufsize );
bzs->avail_in = 0;
}
static int
do_uncompress( compress_filter_context_t *zfx, bz_stream *bzs,
IOBUF a, size_t *ret_len )
{
int zrc;
int rc=0;
size_t n;
int nread, count;
int refill = !bzs->avail_in;
int eofseen = 0;
if( DBG_FILTER )
log_debug("begin bzDecompress: avail_in=%u, avail_out=%u, inbuf=%u\n",
(unsigned)bzs->avail_in, (unsigned)bzs->avail_out,
(unsigned)zfx->inbufsize );
do
{
if( bzs->avail_in < zfx->inbufsize && refill )
{
n = bzs->avail_in;
if( !n )
bzs->next_in = zfx->inbuf;
count = zfx->inbufsize - n;
nread = iobuf_read( a, zfx->inbuf + n, count );
if( nread == -1 )
{
eofseen = 1;
nread = 0;
}
n += nread;
bzs->avail_in = n;
}
if (!eofseen)
refill = 1;
if( DBG_FILTER )
log_debug("enter bzDecompress: avail_in=%u, avail_out=%u\n",
(unsigned)bzs->avail_in, (unsigned)bzs->avail_out);
zrc=BZ2_bzDecompress(bzs);
if( DBG_FILTER )
log_debug("leave bzDecompress: avail_in=%u, avail_out=%u, zrc=%d\n",
(unsigned)bzs->avail_in, (unsigned)bzs->avail_out, zrc);
if( zrc == BZ_STREAM_END )
rc = -1; /* eof */
else if( zrc != BZ_OK && zrc != BZ_PARAM_ERROR )
log_fatal("bz2lib inflate problem: rc=%d\n", zrc );
else if (zrc == BZ_OK && eofseen
&& !bzs->avail_in && bzs->avail_out > 0)
{
log_error ("unexpected EOF in bz2lib\n");
rc = GPG_ERR_BAD_DATA;
break;
}
}
while( bzs->avail_out && zrc != BZ_STREAM_END && zrc != BZ_PARAM_ERROR );
/* I'm not completely happy with the two uses of BZ_PARAM_ERROR
here. The corresponding zlib function is Z_BUF_ERROR, which
covers a narrower scope than BZ_PARAM_ERROR. -dshaw */
*ret_len = zfx->outbufsize - bzs->avail_out;
if( DBG_FILTER )
log_debug("do_uncompress: returning %u bytes\n", (unsigned)*ret_len );
return rc;
}
int
compress_filter_bz2( void *opaque, int control,
IOBUF a, byte *buf, size_t *ret_len)
{
size_t size = *ret_len;
compress_filter_context_t *zfx = opaque;
bz_stream *bzs = zfx->opaque;
int rc=0;
if( control == IOBUFCTRL_UNDERFLOW )
{
if( !zfx->status )
{
bzs = zfx->opaque = xmalloc_clear( sizeof *bzs );
init_uncompress( zfx, bzs );
zfx->status = 1;
}
bzs->next_out = buf;
bzs->avail_out = size;
zfx->outbufsize = size; /* needed only for calculation */
rc = do_uncompress( zfx, bzs, a, ret_len );
}
else if( control == IOBUFCTRL_FLUSH )
{
if( !zfx->status )
{
PACKET pkt;
PKT_compressed cd;
if( zfx->algo != COMPRESS_ALGO_BZIP2 )
BUG();
memset( &cd, 0, sizeof cd );
cd.len = 0;
cd.algorithm = zfx->algo;
init_packet( &pkt );
pkt.pkttype = PKT_COMPRESSED;
pkt.pkt.compressed = &cd;
if( build_packet( a, &pkt ))
log_bug("build_packet(PKT_COMPRESSED) failed\n");
bzs = zfx->opaque = xmalloc_clear( sizeof *bzs );
init_compress( zfx, bzs );
zfx->status = 2;
}
bzs->next_in = buf;
bzs->avail_in = size;
rc = do_compress( zfx, bzs, BZ_RUN, a );
}
else if( control == IOBUFCTRL_FREE )
{
if( zfx->status == 1 )
{
BZ2_bzDecompressEnd(bzs);
xfree(bzs);
zfx->opaque = NULL;
xfree(zfx->outbuf); zfx->outbuf = NULL;
}
else if( zfx->status == 2 )
{
bzs->next_in = buf;
bzs->avail_in = 0;
do_compress( zfx, bzs, BZ_FINISH, a );
BZ2_bzCompressEnd(bzs);
xfree(bzs);
zfx->opaque = NULL;
xfree(zfx->outbuf); zfx->outbuf = NULL;
}
if (zfx->release)
zfx->release (zfx);
}
else if( control == IOBUFCTRL_DESC )
*(char**)buf = "compress_filter";
return rc;
}