From 5699b8525e855a0e851725980964e8755e365f5b Mon Sep 17 00:00:00 2001 From: Glenn L McGrath Date: Sat, 15 Nov 2003 23:19:05 +0000 Subject: Move from read_gz to the pipe()+fork() method. open_transformer(), common code for pipe+fork. Function pointer for read() no longer needed. Allow inflate to be initialised with a specified buffer size to avoid over-reading. Reset static variables in inflate_get_next_window to fix a bug where only the first file in a .zip would be be extracted. --- archival/gunzip.c | 3 +- archival/libunarchive/Makefile.in | 1 + archival/libunarchive/archive_xread.c | 2 +- archival/libunarchive/data_align.c | 1 - archival/libunarchive/decompress_bunzip2.c | 4 +- archival/libunarchive/decompress_unzip.c | 140 ++++++--------------- .../libunarchive/filter_accept_list_reassign.c | 2 - archival/libunarchive/get_header_tar_bz2.c | 42 +------ archival/libunarchive/get_header_tar_gz.c | 17 +-- archival/libunarchive/init_handle.c | 1 - archival/libunarchive/open_transformer.c | 50 ++++++++ archival/libunarchive/unzip.c | 140 ++++++--------------- archival/rpm.c | 7 +- archival/rpm2cpio.c | 3 +- archival/unzip.c | 9 +- include/unarchive.h | 18 +-- 16 files changed, 156 insertions(+), 284 deletions(-) create mode 100644 archival/libunarchive/open_transformer.c diff --git a/archival/gunzip.c b/archival/gunzip.c index 7d382b895..f229ae524 100644 --- a/archival/gunzip.c +++ b/archival/gunzip.c @@ -179,11 +179,10 @@ extern int gunzip_main(int argc, char **argv) #endif if (magic2 == 0x8b) { check_header_gzip(src_fd); - status = inflate(src_fd, dst_fd); + status = inflate_gunzip(src_fd, dst_fd); if (status != 0) { bb_error_msg_and_die("Error inflating"); } - check_trailer_gzip(src_fd); } else { bb_error_msg_and_die("Invalid magic"); } diff --git a/archival/libunarchive/Makefile.in b/archival/libunarchive/Makefile.in index 3d7bdef6b..d449c193e 100644 --- a/archival/libunarchive/Makefile.in +++ b/archival/libunarchive/Makefile.in @@ -49,6 +49,7 @@ LIBUNARCHIVE-y:= \ \ data_align.o \ find_list_entry.o \ + open_transformer.o \ init_handle.o GUNZIP_FILES:= check_header_gzip.o unzip.o diff --git a/archival/libunarchive/archive_xread.c b/archival/libunarchive/archive_xread.c index d63d0d5a2..59b4d77a8 100644 --- a/archival/libunarchive/archive_xread.c +++ b/archival/libunarchive/archive_xread.c @@ -24,7 +24,7 @@ extern ssize_t archive_xread(const archive_handle_t *archive_handle, unsigned ch { ssize_t size; - size = archive_handle->read(archive_handle->src_fd, buf, count); + size = bb_full_read(archive_handle->src_fd, buf, count); if (size < 0) { bb_perror_msg_and_die("Read error"); } diff --git a/archival/libunarchive/data_align.c b/archival/libunarchive/data_align.c index 037242f25..1d433957d 100644 --- a/archival/libunarchive/data_align.c +++ b/archival/libunarchive/data_align.c @@ -27,7 +27,6 @@ extern void data_align(archive_handle_t *archive_handle, const unsigned short bo const unsigned short skip_amount = (boundary - (archive_handle->offset % boundary)) % boundary; archive_handle->seek(archive_handle, skip_amount); - archive_handle->offset += skip_amount; return; diff --git a/archival/libunarchive/decompress_bunzip2.c b/archival/libunarchive/decompress_bunzip2.c index 83232fbe8..3e6138c95 100644 --- a/archival/libunarchive/decompress_bunzip2.c +++ b/archival/libunarchive/decompress_bunzip2.c @@ -424,7 +424,7 @@ got_huff_bits: are ignored, data is written to out_fd and return is RETVAL_OK or error. */ -extern int read_bunzip(bunzip_data *bd, char *outbuf, int len) +static int read_bunzip(bunzip_data *bd, char *outbuf, int len) { const unsigned int *dbuf; int pos,current,previous,gotcount; @@ -511,7 +511,7 @@ decode_next_byte: /* Allocate the structure, read file header. If in_fd==-1, inbuf must contain a complete bunzip file (len bytes long). If in_fd!=-1, inbuf and len are ignored, and data is read from file handle into temporary buffer. */ -extern int start_bunzip(bunzip_data **bdp, int in_fd, char *inbuf, int len) +static int start_bunzip(bunzip_data **bdp, int in_fd, char *inbuf, int len) { bunzip_data *bd; unsigned int i,j,c; diff --git a/archival/libunarchive/decompress_unzip.c b/archival/libunarchive/decompress_unzip.c index 2b16db3c3..29929c282 100644 --- a/archival/libunarchive/decompress_unzip.c +++ b/archival/libunarchive/decompress_unzip.c @@ -103,7 +103,7 @@ static unsigned int gunzip_bb; /* bit buffer */ static unsigned char gunzip_bk; /* bits in bit buffer */ /* These control the size of the bytebuffer */ -#define BYTEBUFFER_MAX 0x8000 +static unsigned int bytebuffer_max = 0x8000; static unsigned char *bytebuffer = NULL; static unsigned int bytebuffer_offset = 0; static unsigned int bytebuffer_size = 0; @@ -144,21 +144,16 @@ static const unsigned char border[] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; -static void fill_bytebuffer(void) -{ - if (bytebuffer_offset >= bytebuffer_size) { - /* Leave the first 4 bytes empty so we can always unwind the bitbuffer - * to the front of the bytebuffer, leave 4 bytes free at end of tail - * so we can easily top up buffer in check_trailer_gzip() */ - bytebuffer_size = 4 + bb_xread(gunzip_src_fd, &bytebuffer[4], BYTEBUFFER_MAX - 8); - bytebuffer_offset = 4; - } -} - static unsigned int fill_bitbuffer(unsigned int bitbuffer, unsigned int *current, const unsigned int required) { while (*current < required) { - fill_bytebuffer(); + if (bytebuffer_offset >= bytebuffer_size) { + /* Leave the first 4 bytes empty so we can always unwind the bitbuffer + * to the front of the bytebuffer, leave 4 bytes free at end of tail + * so we can easily top up buffer in check_trailer_gzip() */ + bytebuffer_size = 4 + bb_xread(gunzip_src_fd, &bytebuffer[4], bytebuffer_max - 8); + bytebuffer_offset = 4; + } bitbuffer |= ((unsigned int) bytebuffer[bytebuffer_offset]) << *current; bytebuffer_offset++; *current += 8; @@ -861,9 +856,9 @@ static void calculate_gunzip_crc(void) 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; + static int needAnotherBlock = 1; gunzip_outbuf_count = 0; @@ -873,6 +868,8 @@ static int inflate_get_next_window(void) if (needAnotherBlock) { if(e) { calculate_gunzip_crc(); + e = 0; + needAnotherBlock = 1; return 0; } // Last block method = inflate_block(&e); @@ -895,54 +892,25 @@ static int inflate_get_next_window(void) /* Doesnt get here */ } -/* - * User functions - * - * read_gz, GZ_gzReadOpen, GZ_gzReadClose, inflate - */ - -extern ssize_t read_gz(int fd, void *buf, size_t count) +/* Initialise bytebuffer, be carefull not to overfill the buffer */ +extern void inflate_init(unsigned int bufsize) { - static int morebytes = 0, finished = 0; - - if (morebytes) { - int bytesRead = morebytes > count ? count : morebytes; - memcpy(buf, gunzip_window + (gunzip_outbuf_count - morebytes), bytesRead); - morebytes -= bytesRead; - return bytesRead; - } else if (finished) { - return 0; - } else if (count >= 0x8000) { // We can decompress direcly to the buffer, 32k at a time - // Could decompress to larger buffer, but it must be a power of 2, and calculating that is probably more expensive than the benefit - unsigned char *old_gunzip_window = gunzip_window; // Save old window - gunzip_window = buf; - if (inflate_get_next_window() == 0) finished = 1; - gunzip_window = old_gunzip_window; // Restore old window - return gunzip_outbuf_count; - } else { // Oh well, need to split up the gunzip_window - int bytesRead; - if (inflate_get_next_window() == 0) finished = 1; - morebytes = gunzip_outbuf_count; - bytesRead = morebytes > count ? count : morebytes; - memcpy(buf, gunzip_window, bytesRead); - morebytes -= bytesRead; - return bytesRead; - } - + /* Set the bytebuffer size, default is same as gunzip_wsize */ + bytebuffer_max = bufsize + 8; + bytebuffer_offset = 4; + bytebuffer_size = 0; } -extern void GZ_gzReadOpen(int fd, void *unused, int nUnused) +extern int inflate_unzip(int in, int out) { + ssize_t nwrote; typedef void (*sig_type) (int); /* Allocate all global buffers (for DYN_ALLOC option) */ gunzip_window = xmalloc(gunzip_wsize); gunzip_outbuf_count = 0; gunzip_bytes_out = 0; - gunzip_src_fd = fd; - - /* Input buffer */ - bytebuffer = xmalloc(BYTEBUFFER_MAX); + gunzip_src_fd = in; /* initialize gunzip_window, bit buffer */ gunzip_bk = 0; @@ -950,10 +918,20 @@ extern void GZ_gzReadOpen(int fd, void *unused, int nUnused) /* Create the crc table */ make_gunzip_crc_table(); -} -extern void GZ_gzReadClose(void) -{ + /* Allocate space for buffer */ + bytebuffer = xmalloc(bytebuffer_max); + + while(1) { + int ret = inflate_get_next_window(); + nwrote = bb_full_write(out, gunzip_window, gunzip_outbuf_count); + if (nwrote == -1) { + bb_perror_msg("write"); + return -1; + } + if (ret == 0) break; + } + /* Cleanup */ free(gunzip_window); free(gunzip_crc_table); @@ -967,57 +945,20 @@ extern void GZ_gzReadClose(void) gunzip_bb >>= 8; gunzip_bk -= 8; } -} - -/*extern int inflate(int in, int out) // Useful for testing read_gz -{ - char buf[8192]; - ssize_t nread, nwrote; - - GZ_gzReadOpen(in, 0, 0); - while(1) { // Robbed from bb_copyfd.c - nread = read_gz(in, buf, sizeof(buf)); - if (nread == 0) break; // no data to write - else if (nread == -1) { - bb_perror_msg("read"); - return -1; - } - nwrote = bb_full_write(out, buf, nread); - if (nwrote == -1) { - bb_perror_msg("write"); - return -1; - } - } - 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 = bb_full_write(out, gunzip_window, gunzip_outbuf_count); - if (nwrote == -1) { - bb_perror_msg("write"); - return -1; - } - if (ret == 0) break; - } - GZ_gzReadClose(); return 0; } -extern void check_trailer_gzip(int src_fd) +extern int inflate_gunzip(int in, int out) { unsigned int stored_crc = 0; unsigned char count; + inflate_unzip(in, out); + /* top up the input buffer with the rest of the trailer */ count = bytebuffer_size - bytebuffer_offset; if (count < 8) { - bb_xread_all(src_fd, &bytebuffer[bytebuffer_size], 8 - count); + bb_xread_all(in, &bytebuffer[bytebuffer_size], 8 - count); bytebuffer_size += 8 - count; } for (count = 0; count != 4; count++) { @@ -1027,14 +968,15 @@ extern void check_trailer_gzip(int src_fd) /* Validate decompression - crc */ if (stored_crc != (gunzip_crc ^ 0xffffffffL)) { - bb_error_msg_and_die("crc error"); + bb_error_msg("crc error"); } /* Validate decompression - size */ if (gunzip_bytes_out != (bytebuffer[bytebuffer_offset] | (bytebuffer[bytebuffer_offset+1] << 8) | (bytebuffer[bytebuffer_offset+2] << 16) | (bytebuffer[bytebuffer_offset+3] << 24))) { - bb_error_msg_and_die("Incorrect length, but crc is correct"); + bb_error_msg("Incorrect length"); } - + + return 0; } diff --git a/archival/libunarchive/filter_accept_list_reassign.c b/archival/libunarchive/filter_accept_list_reassign.c index f34a23c33..1e9da0f2b 100644 --- a/archival/libunarchive/filter_accept_list_reassign.c +++ b/archival/libunarchive/filter_accept_list_reassign.c @@ -40,14 +40,12 @@ extern char filter_accept_list_reassign(archive_handle_t *archive_handle) /* Modify the subarchive handler based on the extension */ #ifdef CONFIG_FEATURE_DEB_TAR_GZ if (strcmp(name_ptr, ".gz") == 0) { - archive_handle->sub_archive->read = read; archive_handle->action_data_subarchive = get_header_tar_gz; return(EXIT_SUCCESS); } #endif #ifdef CONFIG_FEATURE_DEB_TAR_BZ2 if (strcmp(name_ptr, ".bz2") == 0) { - archive_handle->sub_archive->read = read; archive_handle->action_data_subarchive = get_header_tar_bz2; return(EXIT_SUCCESS); } diff --git a/archival/libunarchive/get_header_tar_bz2.c b/archival/libunarchive/get_header_tar_bz2.c index 6354648fc..d49d6b96a 100644 --- a/archival/libunarchive/get_header_tar_bz2.c +++ b/archival/libunarchive/get_header_tar_bz2.c @@ -26,53 +26,13 @@ extern char get_header_tar_bz2(archive_handle_t *archive_handle) { - int fd_pipe[2]; - int pid; - /* Cant lseek over pipe's */ - archive_handle->read = safe_read; archive_handle->seek = seek_by_char; - if (pipe(fd_pipe) != 0) { - bb_error_msg_and_die("Can't create pipe"); - } - - pid = fork(); - if (pid == -1) { - bb_error_msg_and_die("Fork failed\n"); - } - - if (pid == 0) { - /* child process */ - int status; - - close(fd_pipe[0]); /* We don't wan't to read from the pipe */ - uncompressStream(archive_handle->src_fd, fd_pipe[1]); - close(fd_pipe[1]); /* Send EOF */ - exit(status); - /* notreached */ - } - /* parent process */ - close(fd_pipe[1]); /* Don't want to write down the pipe */ - close(archive_handle->src_fd); - - archive_handle->src_fd = fd_pipe[0]; - + archive_handle->src_fd = open_transformer(archive_handle->src_fd, uncompressStream); archive_handle->offset = 0; while (get_header_tar(archive_handle) == EXIT_SUCCESS); - close(fd_pipe[0]); -#if 0 - if (kill(pid, SIGTERM) == -1) { - bb_error_msg_and_die("Couldnt kill gunzip process"); - } -#endif - - /* I dont think this is needed */ - if (waitpid(pid, NULL, 0) == -1) { - bb_error_msg("Couldnt wait ?"); - } - /* Can only do one file at a time */ return(EXIT_FAILURE); } diff --git a/archival/libunarchive/get_header_tar_gz.c b/archival/libunarchive/get_header_tar_gz.c index 64d08f7a7..9c708a951 100644 --- a/archival/libunarchive/get_header_tar_gz.c +++ b/archival/libunarchive/get_header_tar_gz.c @@ -23,6 +23,9 @@ extern char get_header_tar_gz(archive_handle_t *archive_handle) { unsigned char magic[2]; + /* Cant lseek over pipe's */ + archive_handle->seek = seek_by_char; + archive_xread_all(archive_handle, &magic, 2); if ((magic[0] != 0x1f) || (magic[1] != 0x8b)) { bb_error_msg_and_die("Invalid gzip magic"); @@ -30,20 +33,10 @@ extern char get_header_tar_gz(archive_handle_t *archive_handle) check_header_gzip(archive_handle->src_fd); - GZ_gzReadOpen(archive_handle->src_fd, 0, 0); - - archive_handle->read = read_gz; - archive_handle->seek = seek_by_char; - + archive_handle->src_fd = open_transformer(archive_handle->src_fd, inflate_gunzip); archive_handle->offset = 0; while (get_header_tar(archive_handle) == EXIT_SUCCESS); - /* Cleanup */ - GZ_gzReadClose(); - - check_trailer_gzip(archive_handle->src_fd); - - /* Can only do one tar.gz per archive */ + /* Can only do one file at a time */ return(EXIT_FAILURE); } - diff --git a/archival/libunarchive/init_handle.c b/archival/libunarchive/init_handle.c index 2659aa3eb..3cee84f67 100644 --- a/archival/libunarchive/init_handle.c +++ b/archival/libunarchive/init_handle.c @@ -30,7 +30,6 @@ archive_handle_t *init_handle(void) archive_handle->action_header = header_skip; archive_handle->action_data = data_skip; archive_handle->filter = filter_accept_all; - archive_handle->read = bb_full_read; archive_handle->seek = seek_by_jump; return(archive_handle); diff --git a/archival/libunarchive/open_transformer.c b/archival/libunarchive/open_transformer.c new file mode 100644 index 000000000..c1007f982 --- /dev/null +++ b/archival/libunarchive/open_transformer.c @@ -0,0 +1,50 @@ +/* + * 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 + * 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 Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include + +#include "libbb.h" + +/* transformer(), more than meets the eye */ +extern int open_transformer(int src_fd, int (*transformer)(int src_fd, int dst_fd)) +{ + int fd_pipe[2]; + int pid; + + if (pipe(fd_pipe) != 0) { + bb_perror_msg_and_die("Can't create pipe"); + } + + pid = fork(); + if (pid == -1) { + bb_perror_msg_and_die("Fork failed"); + } + + if (pid == 0) { + /* child process */ + close(fd_pipe[0]); /* We don't wan't to read from the pipe */ + transformer(src_fd, fd_pipe[1]); + close(fd_pipe[1]); /* Send EOF */ + exit(0); + /* notreached */ + } + /* parent process */ + close(fd_pipe[1]); /* Don't want to write down the pipe */ + close(src_fd); + + return(fd_pipe[0]); +} diff --git a/archival/libunarchive/unzip.c b/archival/libunarchive/unzip.c index 2b16db3c3..29929c282 100644 --- a/archival/libunarchive/unzip.c +++ b/archival/libunarchive/unzip.c @@ -103,7 +103,7 @@ static unsigned int gunzip_bb; /* bit buffer */ static unsigned char gunzip_bk; /* bits in bit buffer */ /* These control the size of the bytebuffer */ -#define BYTEBUFFER_MAX 0x8000 +static unsigned int bytebuffer_max = 0x8000; static unsigned char *bytebuffer = NULL; static unsigned int bytebuffer_offset = 0; static unsigned int bytebuffer_size = 0; @@ -144,21 +144,16 @@ static const unsigned char border[] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; -static void fill_bytebuffer(void) -{ - if (bytebuffer_offset >= bytebuffer_size) { - /* Leave the first 4 bytes empty so we can always unwind the bitbuffer - * to the front of the bytebuffer, leave 4 bytes free at end of tail - * so we can easily top up buffer in check_trailer_gzip() */ - bytebuffer_size = 4 + bb_xread(gunzip_src_fd, &bytebuffer[4], BYTEBUFFER_MAX - 8); - bytebuffer_offset = 4; - } -} - static unsigned int fill_bitbuffer(unsigned int bitbuffer, unsigned int *current, const unsigned int required) { while (*current < required) { - fill_bytebuffer(); + if (bytebuffer_offset >= bytebuffer_size) { + /* Leave the first 4 bytes empty so we can always unwind the bitbuffer + * to the front of the bytebuffer, leave 4 bytes free at end of tail + * so we can easily top up buffer in check_trailer_gzip() */ + bytebuffer_size = 4 + bb_xread(gunzip_src_fd, &bytebuffer[4], bytebuffer_max - 8); + bytebuffer_offset = 4; + } bitbuffer |= ((unsigned int) bytebuffer[bytebuffer_offset]) << *current; bytebuffer_offset++; *current += 8; @@ -861,9 +856,9 @@ static void calculate_gunzip_crc(void) 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; + static int needAnotherBlock = 1; gunzip_outbuf_count = 0; @@ -873,6 +868,8 @@ static int inflate_get_next_window(void) if (needAnotherBlock) { if(e) { calculate_gunzip_crc(); + e = 0; + needAnotherBlock = 1; return 0; } // Last block method = inflate_block(&e); @@ -895,54 +892,25 @@ static int inflate_get_next_window(void) /* Doesnt get here */ } -/* - * User functions - * - * read_gz, GZ_gzReadOpen, GZ_gzReadClose, inflate - */ - -extern ssize_t read_gz(int fd, void *buf, size_t count) +/* Initialise bytebuffer, be carefull not to overfill the buffer */ +extern void inflate_init(unsigned int bufsize) { - static int morebytes = 0, finished = 0; - - if (morebytes) { - int bytesRead = morebytes > count ? count : morebytes; - memcpy(buf, gunzip_window + (gunzip_outbuf_count - morebytes), bytesRead); - morebytes -= bytesRead; - return bytesRead; - } else if (finished) { - return 0; - } else if (count >= 0x8000) { // We can decompress direcly to the buffer, 32k at a time - // Could decompress to larger buffer, but it must be a power of 2, and calculating that is probably more expensive than the benefit - unsigned char *old_gunzip_window = gunzip_window; // Save old window - gunzip_window = buf; - if (inflate_get_next_window() == 0) finished = 1; - gunzip_window = old_gunzip_window; // Restore old window - return gunzip_outbuf_count; - } else { // Oh well, need to split up the gunzip_window - int bytesRead; - if (inflate_get_next_window() == 0) finished = 1; - morebytes = gunzip_outbuf_count; - bytesRead = morebytes > count ? count : morebytes; - memcpy(buf, gunzip_window, bytesRead); - morebytes -= bytesRead; - return bytesRead; - } - + /* Set the bytebuffer size, default is same as gunzip_wsize */ + bytebuffer_max = bufsize + 8; + bytebuffer_offset = 4; + bytebuffer_size = 0; } -extern void GZ_gzReadOpen(int fd, void *unused, int nUnused) +extern int inflate_unzip(int in, int out) { + ssize_t nwrote; typedef void (*sig_type) (int); /* Allocate all global buffers (for DYN_ALLOC option) */ gunzip_window = xmalloc(gunzip_wsize); gunzip_outbuf_count = 0; gunzip_bytes_out = 0; - gunzip_src_fd = fd; - - /* Input buffer */ - bytebuffer = xmalloc(BYTEBUFFER_MAX); + gunzip_src_fd = in; /* initialize gunzip_window, bit buffer */ gunzip_bk = 0; @@ -950,10 +918,20 @@ extern void GZ_gzReadOpen(int fd, void *unused, int nUnused) /* Create the crc table */ make_gunzip_crc_table(); -} -extern void GZ_gzReadClose(void) -{ + /* Allocate space for buffer */ + bytebuffer = xmalloc(bytebuffer_max); + + while(1) { + int ret = inflate_get_next_window(); + nwrote = bb_full_write(out, gunzip_window, gunzip_outbuf_count); + if (nwrote == -1) { + bb_perror_msg("write"); + return -1; + } + if (ret == 0) break; + } + /* Cleanup */ free(gunzip_window); free(gunzip_crc_table); @@ -967,57 +945,20 @@ extern void GZ_gzReadClose(void) gunzip_bb >>= 8; gunzip_bk -= 8; } -} - -/*extern int inflate(int in, int out) // Useful for testing read_gz -{ - char buf[8192]; - ssize_t nread, nwrote; - - GZ_gzReadOpen(in, 0, 0); - while(1) { // Robbed from bb_copyfd.c - nread = read_gz(in, buf, sizeof(buf)); - if (nread == 0) break; // no data to write - else if (nread == -1) { - bb_perror_msg("read"); - return -1; - } - nwrote = bb_full_write(out, buf, nread); - if (nwrote == -1) { - bb_perror_msg("write"); - return -1; - } - } - 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 = bb_full_write(out, gunzip_window, gunzip_outbuf_count); - if (nwrote == -1) { - bb_perror_msg("write"); - return -1; - } - if (ret == 0) break; - } - GZ_gzReadClose(); return 0; } -extern void check_trailer_gzip(int src_fd) +extern int inflate_gunzip(int in, int out) { unsigned int stored_crc = 0; unsigned char count; + inflate_unzip(in, out); + /* top up the input buffer with the rest of the trailer */ count = bytebuffer_size - bytebuffer_offset; if (count < 8) { - bb_xread_all(src_fd, &bytebuffer[bytebuffer_size], 8 - count); + bb_xread_all(in, &bytebuffer[bytebuffer_size], 8 - count); bytebuffer_size += 8 - count; } for (count = 0; count != 4; count++) { @@ -1027,14 +968,15 @@ extern void check_trailer_gzip(int src_fd) /* Validate decompression - crc */ if (stored_crc != (gunzip_crc ^ 0xffffffffL)) { - bb_error_msg_and_die("crc error"); + bb_error_msg("crc error"); } /* Validate decompression - size */ if (gunzip_bytes_out != (bytebuffer[bytebuffer_offset] | (bytebuffer[bytebuffer_offset+1] << 8) | (bytebuffer[bytebuffer_offset+2] << 16) | (bytebuffer[bytebuffer_offset+3] << 24))) { - bb_error_msg_and_die("Incorrect length, but crc is correct"); + bb_error_msg("Incorrect length"); } - + + return 0; } diff --git a/archival/rpm.c b/archival/rpm.c index 5bde53285..e3f20ca35 100644 --- a/archival/rpm.c +++ b/archival/rpm.c @@ -197,7 +197,6 @@ void extract_cpio_gz(int fd) { /* Initialise */ archive_handle = init_handle(); - archive_handle->read = read_gz; archive_handle->seek = seek_by_char; //archive_handle->action_header = header_list; archive_handle->action_data = data_extract_all; @@ -213,11 +212,9 @@ void extract_cpio_gz(int fd) { check_header_gzip(archive_handle->src_fd); chdir("/"); // Install RPM's to root - GZ_gzReadOpen(archive_handle->src_fd, 0, 0); + archive_handle->src_fd = open_transformer(archive_handle->src_fd, inflate_gunzip); + archive_handle->offset = 0; while (get_header_cpio(archive_handle) == EXIT_SUCCESS); - GZ_gzReadClose(); - - check_trailer_gzip(archive_handle->src_fd); } diff --git a/archival/rpm2cpio.c b/archival/rpm2cpio.c index bb9f69573..47f4e73cd 100644 --- a/archival/rpm2cpio.c +++ b/archival/rpm2cpio.c @@ -96,10 +96,9 @@ extern int rpm2cpio_main(int argc, char **argv) } check_header_gzip(rpm_fd); - if (inflate(rpm_fd, fileno(stdout)) != 0) { + if (inflate_gunzip(rpm_fd, fileno(stdout)) != 0) { bb_error_msg("Error inflating"); } - check_trailer_gzip(rpm_fd); close(rpm_fd); diff --git a/archival/unzip.c b/archival/unzip.c index f2d7f4918..c670073f4 100644 --- a/archival/unzip.c +++ b/archival/unzip.c @@ -199,7 +199,8 @@ extern int unzip_main(int argc, char **argv) archive_handle->action_data(archive_handle); } else { dst_fd = bb_xopen(archive_handle->file_header->name, O_WRONLY | O_CREAT); - inflate(archive_handle->src_fd, dst_fd); + inflate_init(zip_header.formated.cmpsize); + inflate_unzip(archive_handle->src_fd, dst_fd); close(dst_fd); chmod(archive_handle->file_header->name, archive_handle->file_header->mode); @@ -227,10 +228,8 @@ extern int unzip_main(int argc, char **argv) /* Data descriptor section */ if (zip_header.formated.flags & 4) { /* skip over duplicate crc, compressed size and uncompressed size */ - unsigned short i; - for (i = 0; i != 12; i++) { - archive_xread_char(archive_handle); - } + unsigned char data_description[12]; + archive_xread_all(archive_handle, data_description, 12); archive_handle->offset += 12; } } diff --git a/include/unarchive.h b/include/unarchive.h index 9f1331338..fa7233743 100644 --- a/include/unarchive.h +++ b/include/unarchive.h @@ -50,9 +50,6 @@ typedef struct archive_handle_s { /* Count the number of bytes processed */ off_t offset; - /* Function that reads data: read or read_bz */ - ssize_t (*read)(int fd, void *buf, size_t count); - /* Function that skips data: read_by_char or read_by_skip */ void (*seek)(const struct archive_handle_s *archive_handle, const unsigned int amount); @@ -83,7 +80,6 @@ extern void header_list(const file_header_t *file_header); extern void header_verbose_list(const file_header_t *file_header); extern void check_header_gzip(int src_fd); -extern void check_trailer_gzip(int src_fd); extern char get_header_ar(archive_handle_t *archive_handle); extern char get_header_cpio(archive_handle_t *archive_handle); @@ -103,14 +99,12 @@ extern void data_align(archive_handle_t *archive_handle, const unsigned short bo extern void archive_copy_file(const archive_handle_t *archive_handle, const int dst_fd); extern const llist_t *find_list_entry(const llist_t *list, const char *filename); -extern ssize_t read_bz2(int fd, void *buf, size_t count); -extern void BZ2_bzReadOpen(int fd, void *unused, int nUnused); -extern void BZ2_bzReadClose(void); -extern unsigned char uncompressStream(int src_fd, int dst_fd); +extern int uncompressStream(int src_fd, int dst_fd); +extern void inflate_init(unsigned int bufsize); +extern int inflate_unzip(int in, int out); +extern int inflate_gunzip(int in, int out); + +extern int open_transformer(int src_fd, int (*transformer)(int src_fd, int dst_fd)); -extern ssize_t read_gz(int fd, void *buf, size_t count); -extern void GZ_gzReadOpen(int fd, void *unused, int nUnused); -extern void GZ_gzReadClose(void); -extern int inflate(int in, int out); #endif -- cgit v1.2.3