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 th
No binary (build failed)
—
(log yok)
| @@ -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"); | |
| } | |
| @@ -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 | |
| @@ -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"); | |
| } | |
| @@ -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; | |
| @@ -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; | |
| @@ -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; |
| } | |
| @@ -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); | |
| } | |
| @@ -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); | |
| } | |
| @@ -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); | |
| } | |
| - | |
| @@ -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); | |
| @@ -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 <stdlib.h> |
| + | #include <unistd.h> |
| + | |
| + | #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]); |
| + | } |
| @@ -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; |
| } | |
| @@ -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); |
| } | |
| @@ -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); | |
| @@ -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; | |
| } | |
| } | |
| @@ -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 | |