/* p_zlib.c -- LZO packer This file is part of the LZO real-time data compression package. Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer The LZO library and packer 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 2 of the License, or (at your option) any later version. This program 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; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Markus F.X.J. Oberhumer markus.oberhumer@jk.uni-linz.ac.at */ #include "lzopack.h" #if defined(USE_ZLIB) #error "not yet fully implemented" #include #define X_WBITS 15 #define X_MEM_LEVEL 9 /************************************************************************* // **************************************************************************/ int zlib_set_method(int m, int l) { if (m != M_ZLIB || l < 1 || l > 9) return -1; /* not a zlib method */ opt_method = M_ZLIB; opt_level = l; return 0; } int zlib_get_method(header_t *h) { if (h->method == M_ZLIB) { static char s[8+1] = "zlib-8/ "; s[7] = (char) (h->level + '0'); h->method_name = s; } else return -1; /* not a zlib method */ /* check compression level */ if (h->level < 1 || h->level > 9) return 15; return 0; } void zlib_init_compress_header(header_t *h) { if (opt_checksum) h->flags |= F_ADLER32_D; } /************************************************************************* // **************************************************************************/ static lzo_byte *zlib_heap_ptr = NULL; static lzo_uint32 zlib_heap_used = 0; static lzo_uint32 zlib_heap_size = 0; static voidpf zlib_zalloc ( voidpf opaque, unsigned items, unsigned size ) { lzo_uint32 bytes = (lzo_uint32) items * size; voidpf ptr = (voidpf) zlib_heap_ptr; bytes = (bytes + 15) & ~15; if (!zlib_heap_ptr || zlib_heap_used + bytes > zlib_heap_size) return 0; zlib_heap_ptr += bytes; zlib_heap_used += bytes; UNUSED(opaque); return ptr; } static void zlib_zfree ( voidpf opaque, voidpf ptr ) { UNUSED(opaque); UNUSED(ptr); } static void zlib_alloc_init ( z_stream *strm, lzo_bytep wrkmem ) { zlib_heap_ptr = wrkmem; zlib_heap_used = 0; strm->zalloc = (alloc_func)zlib_zalloc; strm->zfree = (free_func)zlib_zfree; } /************************************************************************* // memory setup **************************************************************************/ #define ZLIB_1KB (ALIGN_UP(sizeof(long),4) * (1024 / 4)) #define ZLIB_MEM_COMPRESS ((128 + 256 + 32) * ZLIB_1KB) #define ZLIB_MEM_DECOMPRESS (60 * ZLIB_1KB) #define BLOCK_SIZE (32*1024l) static lzo_byte *block1 = NULL; static lzo_byte *block2 = NULL; static lzo_byte *wrkmem = NULL; lzo_bool zlib_enter(const header_t *h) { if (block1 == NULL) block1 = malloc(BLOCK_SIZE); if (block2 == NULL) block2 = malloc(BLOCK_SIZE); if (wrkmem == NULL) { if (opt_cmd == CMD_COMPRESS) zlib_heap_size = ZLIB_MEM_COMPRESS; else zlib_heap_size = ZLIB_MEM_DECOMPRESS; wrkmem = malloc(zlib_heap_size); } if (!block1 || !block2 || !wrkmem) { zlib_leave(NULL); return 0; } return 1; } void zlib_leave(const header_t *h) { if (h == NULL || opt_cmd != CMD_COMPRESS) { FREE(wrkmem); zlib_heap_size = 0; FREE(block2); FREE(block1); } } /************************************************************************* // compress a file **************************************************************************/ lzo_bool zlib_compress(file_t *fip, file_t *fop, const header_t *h) { z_stream stream; int flush = Z_NO_FLUSH; int err; lzo_int l; const lzo_int len1 = BLOCK_SIZE; const lzo_int len2 = BLOCK_SIZE; lzo_bool ok; zlib_alloc_init(&stream,wrkmem); if (h->flags & F_ADLER32_D) err = deflateInit2(&stream, h->level, Z_DEFLATED, X_WBITS, X_MEM_LEVEL, Z_DEFAULT_STRATEGY); else /* use the undocumented feature to suppress the zlib header */ err = deflateInit2(&stream, h->level, Z_DEFLATED, -X_WBITS, X_MEM_LEVEL, Z_DEFAULT_STRATEGY); if (err == Z_MEM_ERROR) fatal(fip,"Internal error - deflate out of memory"); stream.avail_in = 0; stream.next_out = block2; stream.avail_out = len2; ok = (err == Z_OK); while (ok) { if (stream.avail_in == 0 && flush == Z_NO_FLUSH) { l = read_buf(fip, block1, len1); if (l == 0) flush = Z_FINISH; fip->bytes_processed += l; stream.next_in = block1; stream.avail_in = l; } err = deflate(&stream, flush); if (err == Z_STREAM_END) { write_buf(fop, block2, len2 - stream.avail_out); fop->bytes_processed += len2 - stream.avail_out; break; } if (err != Z_OK) { ok = 0; break; } if (stream.avail_out == 0) { write_buf(fop, block2, len2); fop->bytes_processed += len2; stream.next_out = block2; stream.avail_out = len2; } } if (deflateEnd(&stream) != Z_OK) ok = 0; if (!ok) fatal(fip,"Internal error - zlib compression failed"); return ok; } /************************************************************************* // decompress a file **************************************************************************/ lzo_bool zlib_decompress(file_t *fip, file_t *fop, const header_t *h, lzo_bool skip) { z_stream stream; int flush = Z_NO_FLUSH; int err; lzo_int l = 0; const lzo_int len1 = BLOCK_SIZE; const lzo_int len2 = BLOCK_SIZE; lzo_bool ok; lzo_bool data_error = 0; zlib_alloc_init(&stream,wrkmem); if (h->flags & F_ADLER32_D) err = inflateInit2(&stream, X_WBITS); else /* use the undocumented feature to suppress the zlib header */ err = inflateInit2(&stream, -X_WBITS); if (err == Z_MEM_ERROR) fatal(fip,"Internal error - inflate out of memory"); stream.avail_in = 0; stream.next_out = block2; stream.avail_out = len2; ok = (err == Z_OK); while (ok) { if (stream.avail_in == 0 && flush == Z_NO_FLUSH) { l = read_buf(fip, block1, len1); if (l == 0) flush = Z_PARTIAL_FLUSH; fip->bytes_processed += l; stream.next_in = block1; stream.avail_in = l; } err = inflate(&stream, flush); if (err == Z_STREAM_END) { write_buf(fop, block2, len2 - stream.avail_out); fop->bytes_processed += len2 - stream.avail_out; break; } if (err != Z_OK) { ok = 0; break; } if (stream.avail_out == 0) { write_buf(fop, block2, len2); fop->bytes_processed += len2; stream.next_out = block2; stream.avail_out = len2; } } l = stream.avail_in; data_error |= (err == Z_DATA_ERROR); err = inflateEnd(&stream); if (err != Z_OK) ok = 0; data_error |= (err == Z_DATA_ERROR); if (data_error) error(fip,"Compressed data violation"); else if (!ok) { #if 0 if (stream.msg) error(fip,stream.msg); else #endif error(fip,"Decompression failed"); } /* seek back to the end of the compressed file */ if (l > 0) { if (lseek(fip->fd, -l, SEEK_CUR) == -1) read_error(fip); fip->bytes_processed -= l; } return ok; } #endif /* USE_ZLIB */ /* vi:ts=4 */