Speed and memory usage improvements from Laurence Adnerson

This commit is contained in:
Glenn L McGrath 2002-11-20 22:00:31 +00:00
parent 0126fda5bb
commit 83bf47c02f
2 changed files with 190 additions and 164 deletions

View File

@ -14,6 +14,8 @@
* General cleanup to better adhere to the style guide and make use of standard * General cleanup to better adhere to the style guide and make use of standard
* busybox functions by Glenn McGrath <bug1@optushome.com.au> * busybox functions by Glenn McGrath <bug1@optushome.com.au>
* *
* read_gz interface + associated hacking by Laurence Anderson
*
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
@ -92,20 +94,15 @@ unsigned char *gunzip_in_buffer;
/* gunzip_window size--must be a power of two, and /* gunzip_window size--must be a power of two, and
* at least 32K for zip's deflate method */ * at least 32K for zip's deflate method */
static const int gunzip_wsize = 0x8000; static const int gunzip_wsize = 0x8000;
static int output_buffer_size = 0x8000; // gunzip_wsize initially
static unsigned char *gunzip_window; static unsigned char *gunzip_window;
static unsigned int *gunzip_crc_table; static unsigned int *gunzip_crc_table;
unsigned int gunzip_crc; unsigned int gunzip_crc;
static unsigned char *output_buffer;
static unsigned int output_buffer_len;
/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */ /* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
#define BMAX 16 /* maximum bit length of any code (16 for explode) */ #define BMAX 16 /* maximum bit length of any code (16 for explode) */
#define N_MAX 288 /* maximum number of codes in any set */ #define N_MAX 288 /* maximum number of codes in any set */
static unsigned int gunzip_hufts; /* track memory usage */
static unsigned int gunzip_bb; /* bit buffer */ static unsigned int gunzip_bb; /* bit buffer */
static unsigned char gunzip_bk; /* bits in bit buffer */ static unsigned char gunzip_bk; /* bits in bit buffer */
@ -343,7 +340,6 @@ static int huft_build(unsigned int *b, const unsigned int n,
/* allocate and link in new table */ /* allocate and link in new table */
q = (huft_t *) xmalloc((z + 1) * sizeof(huft_t)); q = (huft_t *) xmalloc((z + 1) * sizeof(huft_t));
gunzip_hufts += z + 1; /* track memory usage */
*t = q + 1; /* link to list for huft_free() */ *t = q + 1; /* link to list for huft_free() */
*(t = &(q->v.t)) = NULL; *(t = &(q->v.t)) = NULL;
u[h] = ++q; /* table starts after link */ u[h] = ++q; /* table starts after link */
@ -395,36 +391,6 @@ static int huft_build(unsigned int *b, const unsigned int n,
return y != 0 && g != 1; return y != 0 && g != 1;
} }
/* ===========================================================================
* Write the output gunzip_window gunzip_window[0..gunzip_outbuf_count-1] and update crc and gunzip_bytes_out.
* (Used for the decompressed data only.)
*/
static void flush_gunzip_window(void)
{
int n;
for (n = 0; n < gunzip_outbuf_count; n++) {
gunzip_crc = gunzip_crc_table[((int) gunzip_crc ^ (gunzip_window[n])) & 0xff] ^ (gunzip_crc >> 8);
}
if (output_buffer_len == 0) { // Our buffer is empty -> straight memcpy
memcpy(output_buffer, gunzip_window, gunzip_outbuf_count);
output_buffer_len = gunzip_outbuf_count;
} else { // Bit more complicated, append to end of output_buffer, realloc as necessary
int newlen = output_buffer_len + gunzip_outbuf_count;
if (newlen > output_buffer_size) {
output_buffer = xrealloc(output_buffer, newlen); // Could free later, but as we now have the memory...
//printf("Using %d byte output buffer\n", newlen);
output_buffer_size = newlen;
}
memcpy(output_buffer + output_buffer_len, gunzip_window, gunzip_outbuf_count);
output_buffer_len += gunzip_outbuf_count;
}
gunzip_bytes_out += gunzip_outbuf_count;
gunzip_outbuf_count = 0;
}
/* /*
* inflate (decompress) the codes in a deflated (compressed) block. * inflate (decompress) the codes in a deflated (compressed) block.
* Return an error code or zero if it all goes ok. * Return an error code or zero if it all goes ok.
@ -468,7 +434,7 @@ static int inflate_codes(huft_t * my_tl, huft_t * my_td, const unsigned int my_b
if ((e = (t = tl + ((unsigned) b & ml))->e) > 16) if ((e = (t = tl + ((unsigned) b & ml))->e) > 16)
do { do {
if (e == 99) { if (e == 99) {
return 1; error_msg_and_die("inflate_codes error 1");;
} }
b >>= t->b; b >>= t->b;
k -= t->b; k -= t->b;
@ -484,7 +450,7 @@ static int inflate_codes(huft_t * my_tl, huft_t * my_td, const unsigned int my_b
gunzip_outbuf_count = (w); gunzip_outbuf_count = (w);
//flush_gunzip_window(); //flush_gunzip_window();
w = 0; w = 0;
return -1; return 1; // We have a block to read
} }
} else { /* it's an EOB or a length */ } else { /* it's an EOB or a length */
@ -504,7 +470,7 @@ static int inflate_codes(huft_t * my_tl, huft_t * my_td, const unsigned int my_b
if ((e = (t = td + ((unsigned) b & md))->e) > 16) if ((e = (t = td + ((unsigned) b & md))->e) > 16)
do { do {
if (e == 99) if (e == 99)
return 1; error_msg_and_die("inflate_codes error 2");;
b >>= t->b; b >>= t->b;
k -= t->b; k -= t->b;
e -= 16; e -= 16;
@ -542,7 +508,7 @@ do_copy: do {
else resumeCopy = 0; else resumeCopy = 0;
//flush_gunzip_window(); //flush_gunzip_window();
w = 0; w = 0;
return -1; return 1;
} }
} while (n); } while (n);
resumeCopy = 0; resumeCopy = 0;
@ -563,7 +529,7 @@ do_copy: do {
return 0; return 0;
} }
int inflate_stored(int my_n, int my_b_stored, int my_k_stored, int setup) static int inflate_stored(int my_n, int my_b_stored, int my_k_stored, int setup)
{ {
static int n, b_stored, k_stored, w; static int n, b_stored, k_stored, w;
if (setup) { if (setup) {
@ -584,7 +550,7 @@ int inflate_stored(int my_n, int my_b_stored, int my_k_stored, int setup)
w = 0; w = 0;
b_stored >>= 8; b_stored >>= 8;
k_stored -= 8; k_stored -= 8;
return -1; // Means more stuff 2do return 1; // We have a block
} }
b_stored >>= 8; b_stored >>= 8;
k_stored -= 8; k_stored -= 8;
@ -866,51 +832,85 @@ static int inflate_block(int *e)
} }
default: default:
/* bad block type */ /* bad block type */
error_msg("bad block type %d\n", t); error_msg_and_die("bad block type %d\n", t);
return 2; }
}
static void calculate_gunzip_crc(void)
{
int n;
for (n = 0; n < gunzip_outbuf_count; n++) {
gunzip_crc = gunzip_crc_table[((int) gunzip_crc ^ (gunzip_window[n])) & 0xff] ^ (gunzip_crc >> 8);
}
gunzip_bytes_out += gunzip_outbuf_count;
}
static int inflate_get_next_window(void)
{
static int needAnotherBlock = 1;
static int method = -1; // Method == -1 for stored, -2 for codes
static int e = 0;
gunzip_outbuf_count = 0;
while(1) {
int ret;
if (needAnotherBlock) {
if(e) { calculate_gunzip_crc(); return 0; } // Last block
method = inflate_block(&e);
needAnotherBlock = 0;
}
switch (method) {
case -1: ret = inflate_stored(0,0,0,0);
break;
case -2: ret = inflate_codes(0,0,0,0,0);
break;
default: error_msg_and_die("inflate error %d", method);
}
if (ret == 1) {
calculate_gunzip_crc();
return 1; // More data left
} else needAnotherBlock = 1; // End of that block
} }
} }
/* /*
* decompress an inflated entry * User functions
* *
* GLOBAL VARIABLES: gunzip_outbuf_count, bk, gunzip_bb, hufts, inptr * read_gz, GZ_gzReadOpen, GZ_gzReadClose, inflate
*/ */
extern ssize_t read_gz(int fd, void *buf, size_t count) extern ssize_t read_gz(int fd, void *buf, size_t count)
{ {
static int e = 0; /* last block flag */ static int morebytes = 0, finished = 0;
int r; /* result code */
unsigned h = 0; /* maximum struct huft's malloc'ed */ if (morebytes) {
ssize_t written = count; int bytesRead = morebytes > count ? count : morebytes;
static char *output_buffer_ptr = 0; memcpy(buf, gunzip_window + (gunzip_outbuf_count - morebytes), bytesRead);
morebytes -= bytesRead;
while (output_buffer_len == 0) { // We need more data return bytesRead;
if (e) return 0; // No more data here! } else if (finished) {
gunzip_hufts = 0; return 0;
r = inflate_block(&e); } else if (count >= 0x8000) { // We can decompress direcly to the buffer, 32k at a time
if (r == -1) { // Call inflate_stored while returning -1 // Could decompress to larger buffer, but it must be a power of 2, and calculating that is probably more expensive than the benefit
while(inflate_stored(0,0,0,0) == -1) flush_gunzip_window(); unsigned char *old_gunzip_window = gunzip_window; // Save old window
} else if (r == -2) { // Call inflate_codes while returning -1 gunzip_window = buf;
while(inflate_codes(0,0,0,0,0) == -1) flush_gunzip_window(); if (inflate_get_next_window() == 0) finished = 1;
} else { gunzip_window = old_gunzip_window; // Restore old window
error_msg_and_die("inflate error %d", r); return gunzip_outbuf_count;
return -1; } else { // Oh well, need to split up the gunzip_window
} int bytesRead;
if (gunzip_hufts > h) { if (inflate_get_next_window() == 0) finished = 1;
h = gunzip_hufts; morebytes = gunzip_outbuf_count;
} bytesRead = morebytes > count ? count : morebytes;
if (e) { // Ok finished uncompressing, get any buffered uncompressed data memcpy(buf, gunzip_window, bytesRead);
flush_gunzip_window(); morebytes -= bytesRead;
} return bytesRead;
output_buffer_ptr = output_buffer;
} }
if (count > output_buffer_len) written = output_buffer_len; // We're only giving them as much as we have!
memcpy(buf, output_buffer_ptr, written);
output_buffer_ptr += written;
output_buffer_len -= written;
return written;
} }
extern void GZ_gzReadOpen(int fd, void *unused, int nUnused) extern void GZ_gzReadOpen(int fd, void *unused, int nUnused)
@ -919,7 +919,6 @@ extern void GZ_gzReadOpen(int fd, void *unused, int nUnused)
/* Allocate all global buffers (for DYN_ALLOC option) */ /* Allocate all global buffers (for DYN_ALLOC option) */
gunzip_window = xmalloc(gunzip_wsize); gunzip_window = xmalloc(gunzip_wsize);
output_buffer = xmalloc(gunzip_wsize);
gunzip_outbuf_count = 0; gunzip_outbuf_count = 0;
gunzip_bytes_out = 0; gunzip_bytes_out = 0;
gunzip_src_fd = fd; gunzip_src_fd = fd;
@ -938,7 +937,6 @@ extern void GZ_gzReadClose(void)
{ {
/* Cleanup */ /* Cleanup */
free(gunzip_window); free(gunzip_window);
free(output_buffer);
free(gunzip_crc_table); free(gunzip_crc_table);
/* Store unused bytes in a global buffer so calling applets can access it */ /* Store unused bytes in a global buffer so calling applets can access it */
@ -953,11 +951,10 @@ extern void GZ_gzReadClose(void)
} }
} }
extern int inflate(int in, int out) /*extern int inflate(int in, int out) // Useful for testing read_gz
{ {
char buf[8192]; char buf[8192];
ssize_t nread, nwrote; ssize_t nread, nwrote;
ssize_t total = 0;
GZ_gzReadOpen(in, 0, 0); GZ_gzReadOpen(in, 0, 0);
while(1) { // Robbed from copyfd.c while(1) { // Robbed from copyfd.c
@ -972,7 +969,23 @@ extern int inflate(int in, int out)
perror_msg("write"); perror_msg("write");
return -1; return -1;
} }
total += nwrote; }
GZ_gzReadClose();
return 0;
}*/
extern int inflate(int in, int out)
{
ssize_t nwrote;
GZ_gzReadOpen(in, 0, 0);
while(1) {
int ret = inflate_get_next_window();
nwrote = full_write(out, gunzip_window, gunzip_outbuf_count);
if (nwrote == -1) {
perror_msg("write");
return -1;
}
if (ret == 0) break;
} }
GZ_gzReadClose(); GZ_gzReadClose();
return 0; return 0;

View File

@ -14,6 +14,8 @@
* General cleanup to better adhere to the style guide and make use of standard * General cleanup to better adhere to the style guide and make use of standard
* busybox functions by Glenn McGrath <bug1@optushome.com.au> * busybox functions by Glenn McGrath <bug1@optushome.com.au>
* *
* read_gz interface + associated hacking by Laurence Anderson
*
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
@ -92,20 +94,15 @@ unsigned char *gunzip_in_buffer;
/* gunzip_window size--must be a power of two, and /* gunzip_window size--must be a power of two, and
* at least 32K for zip's deflate method */ * at least 32K for zip's deflate method */
static const int gunzip_wsize = 0x8000; static const int gunzip_wsize = 0x8000;
static int output_buffer_size = 0x8000; // gunzip_wsize initially
static unsigned char *gunzip_window; static unsigned char *gunzip_window;
static unsigned int *gunzip_crc_table; static unsigned int *gunzip_crc_table;
unsigned int gunzip_crc; unsigned int gunzip_crc;
static unsigned char *output_buffer;
static unsigned int output_buffer_len;
/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */ /* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
#define BMAX 16 /* maximum bit length of any code (16 for explode) */ #define BMAX 16 /* maximum bit length of any code (16 for explode) */
#define N_MAX 288 /* maximum number of codes in any set */ #define N_MAX 288 /* maximum number of codes in any set */
static unsigned int gunzip_hufts; /* track memory usage */
static unsigned int gunzip_bb; /* bit buffer */ static unsigned int gunzip_bb; /* bit buffer */
static unsigned char gunzip_bk; /* bits in bit buffer */ static unsigned char gunzip_bk; /* bits in bit buffer */
@ -343,7 +340,6 @@ static int huft_build(unsigned int *b, const unsigned int n,
/* allocate and link in new table */ /* allocate and link in new table */
q = (huft_t *) xmalloc((z + 1) * sizeof(huft_t)); q = (huft_t *) xmalloc((z + 1) * sizeof(huft_t));
gunzip_hufts += z + 1; /* track memory usage */
*t = q + 1; /* link to list for huft_free() */ *t = q + 1; /* link to list for huft_free() */
*(t = &(q->v.t)) = NULL; *(t = &(q->v.t)) = NULL;
u[h] = ++q; /* table starts after link */ u[h] = ++q; /* table starts after link */
@ -395,36 +391,6 @@ static int huft_build(unsigned int *b, const unsigned int n,
return y != 0 && g != 1; return y != 0 && g != 1;
} }
/* ===========================================================================
* Write the output gunzip_window gunzip_window[0..gunzip_outbuf_count-1] and update crc and gunzip_bytes_out.
* (Used for the decompressed data only.)
*/
static void flush_gunzip_window(void)
{
int n;
for (n = 0; n < gunzip_outbuf_count; n++) {
gunzip_crc = gunzip_crc_table[((int) gunzip_crc ^ (gunzip_window[n])) & 0xff] ^ (gunzip_crc >> 8);
}
if (output_buffer_len == 0) { // Our buffer is empty -> straight memcpy
memcpy(output_buffer, gunzip_window, gunzip_outbuf_count);
output_buffer_len = gunzip_outbuf_count;
} else { // Bit more complicated, append to end of output_buffer, realloc as necessary
int newlen = output_buffer_len + gunzip_outbuf_count;
if (newlen > output_buffer_size) {
output_buffer = xrealloc(output_buffer, newlen); // Could free later, but as we now have the memory...
//printf("Using %d byte output buffer\n", newlen);
output_buffer_size = newlen;
}
memcpy(output_buffer + output_buffer_len, gunzip_window, gunzip_outbuf_count);
output_buffer_len += gunzip_outbuf_count;
}
gunzip_bytes_out += gunzip_outbuf_count;
gunzip_outbuf_count = 0;
}
/* /*
* inflate (decompress) the codes in a deflated (compressed) block. * inflate (decompress) the codes in a deflated (compressed) block.
* Return an error code or zero if it all goes ok. * Return an error code or zero if it all goes ok.
@ -468,7 +434,7 @@ static int inflate_codes(huft_t * my_tl, huft_t * my_td, const unsigned int my_b
if ((e = (t = tl + ((unsigned) b & ml))->e) > 16) if ((e = (t = tl + ((unsigned) b & ml))->e) > 16)
do { do {
if (e == 99) { if (e == 99) {
return 1; error_msg_and_die("inflate_codes error 1");;
} }
b >>= t->b; b >>= t->b;
k -= t->b; k -= t->b;
@ -484,7 +450,7 @@ static int inflate_codes(huft_t * my_tl, huft_t * my_td, const unsigned int my_b
gunzip_outbuf_count = (w); gunzip_outbuf_count = (w);
//flush_gunzip_window(); //flush_gunzip_window();
w = 0; w = 0;
return -1; return 1; // We have a block to read
} }
} else { /* it's an EOB or a length */ } else { /* it's an EOB or a length */
@ -504,7 +470,7 @@ static int inflate_codes(huft_t * my_tl, huft_t * my_td, const unsigned int my_b
if ((e = (t = td + ((unsigned) b & md))->e) > 16) if ((e = (t = td + ((unsigned) b & md))->e) > 16)
do { do {
if (e == 99) if (e == 99)
return 1; error_msg_and_die("inflate_codes error 2");;
b >>= t->b; b >>= t->b;
k -= t->b; k -= t->b;
e -= 16; e -= 16;
@ -542,7 +508,7 @@ do_copy: do {
else resumeCopy = 0; else resumeCopy = 0;
//flush_gunzip_window(); //flush_gunzip_window();
w = 0; w = 0;
return -1; return 1;
} }
} while (n); } while (n);
resumeCopy = 0; resumeCopy = 0;
@ -563,7 +529,7 @@ do_copy: do {
return 0; return 0;
} }
int inflate_stored(int my_n, int my_b_stored, int my_k_stored, int setup) static int inflate_stored(int my_n, int my_b_stored, int my_k_stored, int setup)
{ {
static int n, b_stored, k_stored, w; static int n, b_stored, k_stored, w;
if (setup) { if (setup) {
@ -584,7 +550,7 @@ int inflate_stored(int my_n, int my_b_stored, int my_k_stored, int setup)
w = 0; w = 0;
b_stored >>= 8; b_stored >>= 8;
k_stored -= 8; k_stored -= 8;
return -1; // Means more stuff 2do return 1; // We have a block
} }
b_stored >>= 8; b_stored >>= 8;
k_stored -= 8; k_stored -= 8;
@ -866,51 +832,85 @@ static int inflate_block(int *e)
} }
default: default:
/* bad block type */ /* bad block type */
error_msg("bad block type %d\n", t); error_msg_and_die("bad block type %d\n", t);
return 2; }
}
static void calculate_gunzip_crc(void)
{
int n;
for (n = 0; n < gunzip_outbuf_count; n++) {
gunzip_crc = gunzip_crc_table[((int) gunzip_crc ^ (gunzip_window[n])) & 0xff] ^ (gunzip_crc >> 8);
}
gunzip_bytes_out += gunzip_outbuf_count;
}
static int inflate_get_next_window(void)
{
static int needAnotherBlock = 1;
static int method = -1; // Method == -1 for stored, -2 for codes
static int e = 0;
gunzip_outbuf_count = 0;
while(1) {
int ret;
if (needAnotherBlock) {
if(e) { calculate_gunzip_crc(); return 0; } // Last block
method = inflate_block(&e);
needAnotherBlock = 0;
}
switch (method) {
case -1: ret = inflate_stored(0,0,0,0);
break;
case -2: ret = inflate_codes(0,0,0,0,0);
break;
default: error_msg_and_die("inflate error %d", method);
}
if (ret == 1) {
calculate_gunzip_crc();
return 1; // More data left
} else needAnotherBlock = 1; // End of that block
} }
} }
/* /*
* decompress an inflated entry * User functions
* *
* GLOBAL VARIABLES: gunzip_outbuf_count, bk, gunzip_bb, hufts, inptr * read_gz, GZ_gzReadOpen, GZ_gzReadClose, inflate
*/ */
extern ssize_t read_gz(int fd, void *buf, size_t count) extern ssize_t read_gz(int fd, void *buf, size_t count)
{ {
static int e = 0; /* last block flag */ static int morebytes = 0, finished = 0;
int r; /* result code */
unsigned h = 0; /* maximum struct huft's malloc'ed */ if (morebytes) {
ssize_t written = count; int bytesRead = morebytes > count ? count : morebytes;
static char *output_buffer_ptr = 0; memcpy(buf, gunzip_window + (gunzip_outbuf_count - morebytes), bytesRead);
morebytes -= bytesRead;
while (output_buffer_len == 0) { // We need more data return bytesRead;
if (e) return 0; // No more data here! } else if (finished) {
gunzip_hufts = 0; return 0;
r = inflate_block(&e); } else if (count >= 0x8000) { // We can decompress direcly to the buffer, 32k at a time
if (r == -1) { // Call inflate_stored while returning -1 // Could decompress to larger buffer, but it must be a power of 2, and calculating that is probably more expensive than the benefit
while(inflate_stored(0,0,0,0) == -1) flush_gunzip_window(); unsigned char *old_gunzip_window = gunzip_window; // Save old window
} else if (r == -2) { // Call inflate_codes while returning -1 gunzip_window = buf;
while(inflate_codes(0,0,0,0,0) == -1) flush_gunzip_window(); if (inflate_get_next_window() == 0) finished = 1;
} else { gunzip_window = old_gunzip_window; // Restore old window
error_msg_and_die("inflate error %d", r); return gunzip_outbuf_count;
return -1; } else { // Oh well, need to split up the gunzip_window
} int bytesRead;
if (gunzip_hufts > h) { if (inflate_get_next_window() == 0) finished = 1;
h = gunzip_hufts; morebytes = gunzip_outbuf_count;
} bytesRead = morebytes > count ? count : morebytes;
if (e) { // Ok finished uncompressing, get any buffered uncompressed data memcpy(buf, gunzip_window, bytesRead);
flush_gunzip_window(); morebytes -= bytesRead;
} return bytesRead;
output_buffer_ptr = output_buffer;
} }
if (count > output_buffer_len) written = output_buffer_len; // We're only giving them as much as we have!
memcpy(buf, output_buffer_ptr, written);
output_buffer_ptr += written;
output_buffer_len -= written;
return written;
} }
extern void GZ_gzReadOpen(int fd, void *unused, int nUnused) extern void GZ_gzReadOpen(int fd, void *unused, int nUnused)
@ -919,7 +919,6 @@ extern void GZ_gzReadOpen(int fd, void *unused, int nUnused)
/* Allocate all global buffers (for DYN_ALLOC option) */ /* Allocate all global buffers (for DYN_ALLOC option) */
gunzip_window = xmalloc(gunzip_wsize); gunzip_window = xmalloc(gunzip_wsize);
output_buffer = xmalloc(gunzip_wsize);
gunzip_outbuf_count = 0; gunzip_outbuf_count = 0;
gunzip_bytes_out = 0; gunzip_bytes_out = 0;
gunzip_src_fd = fd; gunzip_src_fd = fd;
@ -938,7 +937,6 @@ extern void GZ_gzReadClose(void)
{ {
/* Cleanup */ /* Cleanup */
free(gunzip_window); free(gunzip_window);
free(output_buffer);
free(gunzip_crc_table); free(gunzip_crc_table);
/* Store unused bytes in a global buffer so calling applets can access it */ /* Store unused bytes in a global buffer so calling applets can access it */
@ -953,11 +951,10 @@ extern void GZ_gzReadClose(void)
} }
} }
extern int inflate(int in, int out) /*extern int inflate(int in, int out) // Useful for testing read_gz
{ {
char buf[8192]; char buf[8192];
ssize_t nread, nwrote; ssize_t nread, nwrote;
ssize_t total = 0;
GZ_gzReadOpen(in, 0, 0); GZ_gzReadOpen(in, 0, 0);
while(1) { // Robbed from copyfd.c while(1) { // Robbed from copyfd.c
@ -972,7 +969,23 @@ extern int inflate(int in, int out)
perror_msg("write"); perror_msg("write");
return -1; return -1;
} }
total += nwrote; }
GZ_gzReadClose();
return 0;
}*/
extern int inflate(int in, int out)
{
ssize_t nwrote;
GZ_gzReadOpen(in, 0, 0);
while(1) {
int ret = inflate_get_next_window();
nwrote = full_write(out, gunzip_window, gunzip_outbuf_count);
if (nwrote == -1) {
perror_msg("write");
return -1;
}
if (ret == 0) break;
} }
GZ_gzReadClose(); GZ_gzReadClose();
return 0; return 0;