summaryrefslogtreecommitdiff
path: root/archival
diff options
context:
space:
mode:
authorGlenn L McGrath <bug1@ihug.co.nz>2003-11-15 23:19:05 +0000
committerGlenn L McGrath <bug1@ihug.co.nz>2003-11-15 23:19:05 +0000
commit5699b8525e855a0e851725980964e8755e365f5b (patch)
treefe3d7ead1f80f5b56e44e52a651f368adf92c91d /archival
parent54ac057c0016ac23b7367342f4834e33cf7d47d7 (diff)
downloadbusybox-w32-5699b8525e855a0e851725980964e8755e365f5b.tar.gz
busybox-w32-5699b8525e855a0e851725980964e8755e365f5b.tar.bz2
busybox-w32-5699b8525e855a0e851725980964e8755e365f5b.zip
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.
Diffstat (limited to 'archival')
-rw-r--r--archival/gunzip.c3
-rw-r--r--archival/libunarchive/Makefile.in1
-rw-r--r--archival/libunarchive/archive_xread.c2
-rw-r--r--archival/libunarchive/data_align.c1
-rw-r--r--archival/libunarchive/decompress_bunzip2.c4
-rw-r--r--archival/libunarchive/decompress_unzip.c140
-rw-r--r--archival/libunarchive/filter_accept_list_reassign.c2
-rw-r--r--archival/libunarchive/get_header_tar_bz2.c42
-rw-r--r--archival/libunarchive/get_header_tar_gz.c17
-rw-r--r--archival/libunarchive/init_handle.c1
-rw-r--r--archival/libunarchive/open_transformer.c50
-rw-r--r--archival/libunarchive/unzip.c140
-rw-r--r--archival/rpm.c7
-rw-r--r--archival/rpm2cpio.c3
-rw-r--r--archival/unzip.c9
15 files changed, 150 insertions, 272 deletions
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)
179#endif 179#endif
180 if (magic2 == 0x8b) { 180 if (magic2 == 0x8b) {
181 check_header_gzip(src_fd); 181 check_header_gzip(src_fd);
182 status = inflate(src_fd, dst_fd); 182 status = inflate_gunzip(src_fd, dst_fd);
183 if (status != 0) { 183 if (status != 0) {
184 bb_error_msg_and_die("Error inflating"); 184 bb_error_msg_and_die("Error inflating");
185 } 185 }
186 check_trailer_gzip(src_fd);
187 } else { 186 } else {
188 bb_error_msg_and_die("Invalid magic"); 187 bb_error_msg_and_die("Invalid magic");
189 } 188 }
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:= \
49\ 49\
50 data_align.o \ 50 data_align.o \
51 find_list_entry.o \ 51 find_list_entry.o \
52 open_transformer.o \
52 init_handle.o 53 init_handle.o
53 54
54GUNZIP_FILES:= check_header_gzip.o unzip.o 55GUNZIP_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
24{ 24{
25 ssize_t size; 25 ssize_t size;
26 26
27 size = archive_handle->read(archive_handle->src_fd, buf, count); 27 size = bb_full_read(archive_handle->src_fd, buf, count);
28 if (size < 0) { 28 if (size < 0) {
29 bb_perror_msg_and_die("Read error"); 29 bb_perror_msg_and_die("Read error");
30 } 30 }
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
27 const unsigned short skip_amount = (boundary - (archive_handle->offset % boundary)) % boundary; 27 const unsigned short skip_amount = (boundary - (archive_handle->offset % boundary)) % boundary;
28 28
29 archive_handle->seek(archive_handle, skip_amount); 29 archive_handle->seek(archive_handle, skip_amount);
30
31 archive_handle->offset += skip_amount; 30 archive_handle->offset += skip_amount;
32 31
33 return; 32 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:
424 are ignored, data is written to out_fd and return is RETVAL_OK or error. 424 are ignored, data is written to out_fd and return is RETVAL_OK or error.
425*/ 425*/
426 426
427extern int read_bunzip(bunzip_data *bd, char *outbuf, int len) 427static int read_bunzip(bunzip_data *bd, char *outbuf, int len)
428{ 428{
429 const unsigned int *dbuf; 429 const unsigned int *dbuf;
430 int pos,current,previous,gotcount; 430 int pos,current,previous,gotcount;
@@ -511,7 +511,7 @@ decode_next_byte:
511/* Allocate the structure, read file header. If in_fd==-1, inbuf must contain 511/* Allocate the structure, read file header. If in_fd==-1, inbuf must contain
512 a complete bunzip file (len bytes long). If in_fd!=-1, inbuf and len are 512 a complete bunzip file (len bytes long). If in_fd!=-1, inbuf and len are
513 ignored, and data is read from file handle into temporary buffer. */ 513 ignored, and data is read from file handle into temporary buffer. */
514extern int start_bunzip(bunzip_data **bdp, int in_fd, char *inbuf, int len) 514static int start_bunzip(bunzip_data **bdp, int in_fd, char *inbuf, int len)
515{ 515{
516 bunzip_data *bd; 516 bunzip_data *bd;
517 unsigned int i,j,c; 517 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 */
103static unsigned char gunzip_bk; /* bits in bit buffer */ 103static unsigned char gunzip_bk; /* bits in bit buffer */
104 104
105/* These control the size of the bytebuffer */ 105/* These control the size of the bytebuffer */
106#define BYTEBUFFER_MAX 0x8000 106static unsigned int bytebuffer_max = 0x8000;
107static unsigned char *bytebuffer = NULL; 107static unsigned char *bytebuffer = NULL;
108static unsigned int bytebuffer_offset = 0; 108static unsigned int bytebuffer_offset = 0;
109static unsigned int bytebuffer_size = 0; 109static unsigned int bytebuffer_size = 0;
@@ -144,21 +144,16 @@ static const unsigned char border[] = {
144 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 144 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
145}; 145};
146 146
147static void fill_bytebuffer(void)
148{
149 if (bytebuffer_offset >= bytebuffer_size) {
150 /* Leave the first 4 bytes empty so we can always unwind the bitbuffer
151 * to the front of the bytebuffer, leave 4 bytes free at end of tail
152 * so we can easily top up buffer in check_trailer_gzip() */
153 bytebuffer_size = 4 + bb_xread(gunzip_src_fd, &bytebuffer[4], BYTEBUFFER_MAX - 8);
154 bytebuffer_offset = 4;
155 }
156}
157
158static unsigned int fill_bitbuffer(unsigned int bitbuffer, unsigned int *current, const unsigned int required) 147static unsigned int fill_bitbuffer(unsigned int bitbuffer, unsigned int *current, const unsigned int required)
159{ 148{
160 while (*current < required) { 149 while (*current < required) {
161 fill_bytebuffer(); 150 if (bytebuffer_offset >= bytebuffer_size) {
151 /* Leave the first 4 bytes empty so we can always unwind the bitbuffer
152 * to the front of the bytebuffer, leave 4 bytes free at end of tail
153 * so we can easily top up buffer in check_trailer_gzip() */
154 bytebuffer_size = 4 + bb_xread(gunzip_src_fd, &bytebuffer[4], bytebuffer_max - 8);
155 bytebuffer_offset = 4;
156 }
162 bitbuffer |= ((unsigned int) bytebuffer[bytebuffer_offset]) << *current; 157 bitbuffer |= ((unsigned int) bytebuffer[bytebuffer_offset]) << *current;
163 bytebuffer_offset++; 158 bytebuffer_offset++;
164 *current += 8; 159 *current += 8;
@@ -861,9 +856,9 @@ static void calculate_gunzip_crc(void)
861 856
862static int inflate_get_next_window(void) 857static int inflate_get_next_window(void)
863{ 858{
864 static int needAnotherBlock = 1;
865 static int method = -1; // Method == -1 for stored, -2 for codes 859 static int method = -1; // Method == -1 for stored, -2 for codes
866 static int e = 0; 860 static int e = 0;
861 static int needAnotherBlock = 1;
867 862
868 gunzip_outbuf_count = 0; 863 gunzip_outbuf_count = 0;
869 864
@@ -873,6 +868,8 @@ static int inflate_get_next_window(void)
873 if (needAnotherBlock) { 868 if (needAnotherBlock) {
874 if(e) { 869 if(e) {
875 calculate_gunzip_crc(); 870 calculate_gunzip_crc();
871 e = 0;
872 needAnotherBlock = 1;
876 return 0; 873 return 0;
877 } // Last block 874 } // Last block
878 method = inflate_block(&e); 875 method = inflate_block(&e);
@@ -895,54 +892,25 @@ static int inflate_get_next_window(void)
895 /* Doesnt get here */ 892 /* Doesnt get here */
896} 893}
897 894
898/* 895/* Initialise bytebuffer, be carefull not to overfill the buffer */
899 * User functions 896extern void inflate_init(unsigned int bufsize)
900 *
901 * read_gz, GZ_gzReadOpen, GZ_gzReadClose, inflate
902 */
903
904extern ssize_t read_gz(int fd, void *buf, size_t count)
905{ 897{
906 static int morebytes = 0, finished = 0; 898 /* Set the bytebuffer size, default is same as gunzip_wsize */
907 899 bytebuffer_max = bufsize + 8;
908 if (morebytes) { 900 bytebuffer_offset = 4;
909 int bytesRead = morebytes > count ? count : morebytes; 901 bytebuffer_size = 0;
910 memcpy(buf, gunzip_window + (gunzip_outbuf_count - morebytes), bytesRead);
911 morebytes -= bytesRead;
912 return bytesRead;
913 } else if (finished) {
914 return 0;
915 } else if (count >= 0x8000) { // We can decompress direcly to the buffer, 32k at a time
916 // Could decompress to larger buffer, but it must be a power of 2, and calculating that is probably more expensive than the benefit
917 unsigned char *old_gunzip_window = gunzip_window; // Save old window
918 gunzip_window = buf;
919 if (inflate_get_next_window() == 0) finished = 1;
920 gunzip_window = old_gunzip_window; // Restore old window
921 return gunzip_outbuf_count;
922 } else { // Oh well, need to split up the gunzip_window
923 int bytesRead;
924 if (inflate_get_next_window() == 0) finished = 1;
925 morebytes = gunzip_outbuf_count;
926 bytesRead = morebytes > count ? count : morebytes;
927 memcpy(buf, gunzip_window, bytesRead);
928 morebytes -= bytesRead;
929 return bytesRead;
930 }
931
932} 902}
933 903
934extern void GZ_gzReadOpen(int fd, void *unused, int nUnused) 904extern int inflate_unzip(int in, int out)
935{ 905{
906 ssize_t nwrote;
936 typedef void (*sig_type) (int); 907 typedef void (*sig_type) (int);
937 908
938 /* Allocate all global buffers (for DYN_ALLOC option) */ 909 /* Allocate all global buffers (for DYN_ALLOC option) */
939 gunzip_window = xmalloc(gunzip_wsize); 910 gunzip_window = xmalloc(gunzip_wsize);
940 gunzip_outbuf_count = 0; 911 gunzip_outbuf_count = 0;
941 gunzip_bytes_out = 0; 912 gunzip_bytes_out = 0;
942 gunzip_src_fd = fd; 913 gunzip_src_fd = in;
943
944 /* Input buffer */
945 bytebuffer = xmalloc(BYTEBUFFER_MAX);
946 914
947 /* initialize gunzip_window, bit buffer */ 915 /* initialize gunzip_window, bit buffer */
948 gunzip_bk = 0; 916 gunzip_bk = 0;
@@ -950,10 +918,20 @@ extern void GZ_gzReadOpen(int fd, void *unused, int nUnused)
950 918
951 /* Create the crc table */ 919 /* Create the crc table */
952 make_gunzip_crc_table(); 920 make_gunzip_crc_table();
953}
954 921
955extern void GZ_gzReadClose(void) 922 /* Allocate space for buffer */
956{ 923 bytebuffer = xmalloc(bytebuffer_max);
924
925 while(1) {
926 int ret = inflate_get_next_window();
927 nwrote = bb_full_write(out, gunzip_window, gunzip_outbuf_count);
928 if (nwrote == -1) {
929 bb_perror_msg("write");
930 return -1;
931 }
932 if (ret == 0) break;
933 }
934
957 /* Cleanup */ 935 /* Cleanup */
958 free(gunzip_window); 936 free(gunzip_window);
959 free(gunzip_crc_table); 937 free(gunzip_crc_table);
@@ -967,57 +945,20 @@ extern void GZ_gzReadClose(void)
967 gunzip_bb >>= 8; 945 gunzip_bb >>= 8;
968 gunzip_bk -= 8; 946 gunzip_bk -= 8;
969 } 947 }
970}
971
972/*extern int inflate(int in, int out) // Useful for testing read_gz
973{
974 char buf[8192];
975 ssize_t nread, nwrote;
976
977 GZ_gzReadOpen(in, 0, 0);
978 while(1) { // Robbed from bb_copyfd.c
979 nread = read_gz(in, buf, sizeof(buf));
980 if (nread == 0) break; // no data to write
981 else if (nread == -1) {
982 bb_perror_msg("read");
983 return -1;
984 }
985 nwrote = bb_full_write(out, buf, nread);
986 if (nwrote == -1) {
987 bb_perror_msg("write");
988 return -1;
989 }
990 }
991 GZ_gzReadClose();
992 return 0;
993}*/
994
995extern int inflate(int in, int out)
996{
997 ssize_t nwrote;
998 GZ_gzReadOpen(in, 0, 0);
999 while(1) {
1000 int ret = inflate_get_next_window();
1001 nwrote = bb_full_write(out, gunzip_window, gunzip_outbuf_count);
1002 if (nwrote == -1) {
1003 bb_perror_msg("write");
1004 return -1;
1005 }
1006 if (ret == 0) break;
1007 }
1008 GZ_gzReadClose();
1009 return 0; 948 return 0;
1010} 949}
1011 950
1012extern void check_trailer_gzip(int src_fd) 951extern int inflate_gunzip(int in, int out)
1013{ 952{
1014 unsigned int stored_crc = 0; 953 unsigned int stored_crc = 0;
1015 unsigned char count; 954 unsigned char count;
1016 955
956 inflate_unzip(in, out);
957
1017 /* top up the input buffer with the rest of the trailer */ 958 /* top up the input buffer with the rest of the trailer */
1018 count = bytebuffer_size - bytebuffer_offset; 959 count = bytebuffer_size - bytebuffer_offset;
1019 if (count < 8) { 960 if (count < 8) {
1020 bb_xread_all(src_fd, &bytebuffer[bytebuffer_size], 8 - count); 961 bb_xread_all(in, &bytebuffer[bytebuffer_size], 8 - count);
1021 bytebuffer_size += 8 - count; 962 bytebuffer_size += 8 - count;
1022 } 963 }
1023 for (count = 0; count != 4; count++) { 964 for (count = 0; count != 4; count++) {
@@ -1027,14 +968,15 @@ extern void check_trailer_gzip(int src_fd)
1027 968
1028 /* Validate decompression - crc */ 969 /* Validate decompression - crc */
1029 if (stored_crc != (gunzip_crc ^ 0xffffffffL)) { 970 if (stored_crc != (gunzip_crc ^ 0xffffffffL)) {
1030 bb_error_msg_and_die("crc error"); 971 bb_error_msg("crc error");
1031 } 972 }
1032 973
1033 /* Validate decompression - size */ 974 /* Validate decompression - size */
1034 if (gunzip_bytes_out != 975 if (gunzip_bytes_out !=
1035 (bytebuffer[bytebuffer_offset] | (bytebuffer[bytebuffer_offset+1] << 8) | 976 (bytebuffer[bytebuffer_offset] | (bytebuffer[bytebuffer_offset+1] << 8) |
1036 (bytebuffer[bytebuffer_offset+2] << 16) | (bytebuffer[bytebuffer_offset+3] << 24))) { 977 (bytebuffer[bytebuffer_offset+2] << 16) | (bytebuffer[bytebuffer_offset+3] << 24))) {
1037 bb_error_msg_and_die("Incorrect length, but crc is correct"); 978 bb_error_msg("Incorrect length");
1038 } 979 }
1039 980
981 return 0;
1040} 982}
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)
40 /* Modify the subarchive handler based on the extension */ 40 /* Modify the subarchive handler based on the extension */
41#ifdef CONFIG_FEATURE_DEB_TAR_GZ 41#ifdef CONFIG_FEATURE_DEB_TAR_GZ
42 if (strcmp(name_ptr, ".gz") == 0) { 42 if (strcmp(name_ptr, ".gz") == 0) {
43 archive_handle->sub_archive->read = read;
44 archive_handle->action_data_subarchive = get_header_tar_gz; 43 archive_handle->action_data_subarchive = get_header_tar_gz;
45 return(EXIT_SUCCESS); 44 return(EXIT_SUCCESS);
46 } 45 }
47#endif 46#endif
48#ifdef CONFIG_FEATURE_DEB_TAR_BZ2 47#ifdef CONFIG_FEATURE_DEB_TAR_BZ2
49 if (strcmp(name_ptr, ".bz2") == 0) { 48 if (strcmp(name_ptr, ".bz2") == 0) {
50 archive_handle->sub_archive->read = read;
51 archive_handle->action_data_subarchive = get_header_tar_bz2; 49 archive_handle->action_data_subarchive = get_header_tar_bz2;
52 return(EXIT_SUCCESS); 50 return(EXIT_SUCCESS);
53 } 51 }
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 @@
26 26
27extern char get_header_tar_bz2(archive_handle_t *archive_handle) 27extern char get_header_tar_bz2(archive_handle_t *archive_handle)
28{ 28{
29 int fd_pipe[2];
30 int pid;
31
32 /* Cant lseek over pipe's */ 29 /* Cant lseek over pipe's */
33 archive_handle->read = safe_read;
34 archive_handle->seek = seek_by_char; 30 archive_handle->seek = seek_by_char;
35 31
36 if (pipe(fd_pipe) != 0) { 32 archive_handle->src_fd = open_transformer(archive_handle->src_fd, uncompressStream);
37 bb_error_msg_and_die("Can't create pipe");
38 }
39
40 pid = fork();
41 if (pid == -1) {
42 bb_error_msg_and_die("Fork failed\n");
43 }
44
45 if (pid == 0) {
46 /* child process */
47 int status;
48
49 close(fd_pipe[0]); /* We don't wan't to read from the pipe */
50 uncompressStream(archive_handle->src_fd, fd_pipe[1]);
51 close(fd_pipe[1]); /* Send EOF */
52 exit(status);
53 /* notreached */
54 }
55 /* parent process */
56 close(fd_pipe[1]); /* Don't want to write down the pipe */
57 close(archive_handle->src_fd);
58
59 archive_handle->src_fd = fd_pipe[0];
60
61 archive_handle->offset = 0; 33 archive_handle->offset = 0;
62 while (get_header_tar(archive_handle) == EXIT_SUCCESS); 34 while (get_header_tar(archive_handle) == EXIT_SUCCESS);
63 35
64 close(fd_pipe[0]);
65#if 0
66 if (kill(pid, SIGTERM) == -1) {
67 bb_error_msg_and_die("Couldnt kill gunzip process");
68 }
69#endif
70
71 /* I dont think this is needed */
72 if (waitpid(pid, NULL, 0) == -1) {
73 bb_error_msg("Couldnt wait ?");
74 }
75
76 /* Can only do one file at a time */ 36 /* Can only do one file at a time */
77 return(EXIT_FAILURE); 37 return(EXIT_FAILURE);
78} 38}
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)
23{ 23{
24 unsigned char magic[2]; 24 unsigned char magic[2];
25 25
26 /* Cant lseek over pipe's */
27 archive_handle->seek = seek_by_char;
28
26 archive_xread_all(archive_handle, &magic, 2); 29 archive_xread_all(archive_handle, &magic, 2);
27 if ((magic[0] != 0x1f) || (magic[1] != 0x8b)) { 30 if ((magic[0] != 0x1f) || (magic[1] != 0x8b)) {
28 bb_error_msg_and_die("Invalid gzip magic"); 31 bb_error_msg_and_die("Invalid gzip magic");
@@ -30,20 +33,10 @@ extern char get_header_tar_gz(archive_handle_t *archive_handle)
30 33
31 check_header_gzip(archive_handle->src_fd); 34 check_header_gzip(archive_handle->src_fd);
32 35
33 GZ_gzReadOpen(archive_handle->src_fd, 0, 0); 36 archive_handle->src_fd = open_transformer(archive_handle->src_fd, inflate_gunzip);
34
35 archive_handle->read = read_gz;
36 archive_handle->seek = seek_by_char;
37
38 archive_handle->offset = 0; 37 archive_handle->offset = 0;
39 while (get_header_tar(archive_handle) == EXIT_SUCCESS); 38 while (get_header_tar(archive_handle) == EXIT_SUCCESS);
40 39
41 /* Cleanup */ 40 /* Can only do one file at a time */
42 GZ_gzReadClose();
43
44 check_trailer_gzip(archive_handle->src_fd);
45
46 /* Can only do one tar.gz per archive */
47 return(EXIT_FAILURE); 41 return(EXIT_FAILURE);
48} 42}
49
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)
30 archive_handle->action_header = header_skip; 30 archive_handle->action_header = header_skip;
31 archive_handle->action_data = data_skip; 31 archive_handle->action_data = data_skip;
32 archive_handle->filter = filter_accept_all; 32 archive_handle->filter = filter_accept_all;
33 archive_handle->read = bb_full_read;
34 archive_handle->seek = seek_by_jump; 33 archive_handle->seek = seek_by_jump;
35 34
36 return(archive_handle); 35 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 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU Library General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15 */
16
17#include <stdlib.h>
18#include <unistd.h>
19
20#include "libbb.h"
21
22/* transformer(), more than meets the eye */
23extern int open_transformer(int src_fd, int (*transformer)(int src_fd, int dst_fd))
24{
25 int fd_pipe[2];
26 int pid;
27
28 if (pipe(fd_pipe) != 0) {
29 bb_perror_msg_and_die("Can't create pipe");
30 }
31
32 pid = fork();
33 if (pid == -1) {
34 bb_perror_msg_and_die("Fork failed");
35 }
36
37 if (pid == 0) {
38 /* child process */
39 close(fd_pipe[0]); /* We don't wan't to read from the pipe */
40 transformer(src_fd, fd_pipe[1]);
41 close(fd_pipe[1]); /* Send EOF */
42 exit(0);
43 /* notreached */
44 }
45 /* parent process */
46 close(fd_pipe[1]); /* Don't want to write down the pipe */
47 close(src_fd);
48
49 return(fd_pipe[0]);
50}
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 */
103static unsigned char gunzip_bk; /* bits in bit buffer */ 103static unsigned char gunzip_bk; /* bits in bit buffer */
104 104
105/* These control the size of the bytebuffer */ 105/* These control the size of the bytebuffer */
106#define BYTEBUFFER_MAX 0x8000 106static unsigned int bytebuffer_max = 0x8000;
107static unsigned char *bytebuffer = NULL; 107static unsigned char *bytebuffer = NULL;
108static unsigned int bytebuffer_offset = 0; 108static unsigned int bytebuffer_offset = 0;
109static unsigned int bytebuffer_size = 0; 109static unsigned int bytebuffer_size = 0;
@@ -144,21 +144,16 @@ static const unsigned char border[] = {
144 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 144 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
145}; 145};
146 146
147static void fill_bytebuffer(void)
148{
149 if (bytebuffer_offset >= bytebuffer_size) {
150 /* Leave the first 4 bytes empty so we can always unwind the bitbuffer
151 * to the front of the bytebuffer, leave 4 bytes free at end of tail
152 * so we can easily top up buffer in check_trailer_gzip() */
153 bytebuffer_size = 4 + bb_xread(gunzip_src_fd, &bytebuffer[4], BYTEBUFFER_MAX - 8);
154 bytebuffer_offset = 4;
155 }
156}
157
158static unsigned int fill_bitbuffer(unsigned int bitbuffer, unsigned int *current, const unsigned int required) 147static unsigned int fill_bitbuffer(unsigned int bitbuffer, unsigned int *current, const unsigned int required)
159{ 148{
160 while (*current < required) { 149 while (*current < required) {
161 fill_bytebuffer(); 150 if (bytebuffer_offset >= bytebuffer_size) {
151 /* Leave the first 4 bytes empty so we can always unwind the bitbuffer
152 * to the front of the bytebuffer, leave 4 bytes free at end of tail
153 * so we can easily top up buffer in check_trailer_gzip() */
154 bytebuffer_size = 4 + bb_xread(gunzip_src_fd, &bytebuffer[4], bytebuffer_max - 8);
155 bytebuffer_offset = 4;
156 }
162 bitbuffer |= ((unsigned int) bytebuffer[bytebuffer_offset]) << *current; 157 bitbuffer |= ((unsigned int) bytebuffer[bytebuffer_offset]) << *current;
163 bytebuffer_offset++; 158 bytebuffer_offset++;
164 *current += 8; 159 *current += 8;
@@ -861,9 +856,9 @@ static void calculate_gunzip_crc(void)
861 856
862static int inflate_get_next_window(void) 857static int inflate_get_next_window(void)
863{ 858{
864 static int needAnotherBlock = 1;
865 static int method = -1; // Method == -1 for stored, -2 for codes 859 static int method = -1; // Method == -1 for stored, -2 for codes
866 static int e = 0; 860 static int e = 0;
861 static int needAnotherBlock = 1;
867 862
868 gunzip_outbuf_count = 0; 863 gunzip_outbuf_count = 0;
869 864
@@ -873,6 +868,8 @@ static int inflate_get_next_window(void)
873 if (needAnotherBlock) { 868 if (needAnotherBlock) {
874 if(e) { 869 if(e) {
875 calculate_gunzip_crc(); 870 calculate_gunzip_crc();
871 e = 0;
872 needAnotherBlock = 1;
876 return 0; 873 return 0;
877 } // Last block 874 } // Last block
878 method = inflate_block(&e); 875 method = inflate_block(&e);
@@ -895,54 +892,25 @@ static int inflate_get_next_window(void)
895 /* Doesnt get here */ 892 /* Doesnt get here */
896} 893}
897 894
898/* 895/* Initialise bytebuffer, be carefull not to overfill the buffer */
899 * User functions 896extern void inflate_init(unsigned int bufsize)
900 *
901 * read_gz, GZ_gzReadOpen, GZ_gzReadClose, inflate
902 */
903
904extern ssize_t read_gz(int fd, void *buf, size_t count)
905{ 897{
906 static int morebytes = 0, finished = 0; 898 /* Set the bytebuffer size, default is same as gunzip_wsize */
907 899 bytebuffer_max = bufsize + 8;
908 if (morebytes) { 900 bytebuffer_offset = 4;
909 int bytesRead = morebytes > count ? count : morebytes; 901 bytebuffer_size = 0;
910 memcpy(buf, gunzip_window + (gunzip_outbuf_count - morebytes), bytesRead);
911 morebytes -= bytesRead;
912 return bytesRead;
913 } else if (finished) {
914 return 0;
915 } else if (count >= 0x8000) { // We can decompress direcly to the buffer, 32k at a time
916 // Could decompress to larger buffer, but it must be a power of 2, and calculating that is probably more expensive than the benefit
917 unsigned char *old_gunzip_window = gunzip_window; // Save old window
918 gunzip_window = buf;
919 if (inflate_get_next_window() == 0) finished = 1;
920 gunzip_window = old_gunzip_window; // Restore old window
921 return gunzip_outbuf_count;
922 } else { // Oh well, need to split up the gunzip_window
923 int bytesRead;
924 if (inflate_get_next_window() == 0) finished = 1;
925 morebytes = gunzip_outbuf_count;
926 bytesRead = morebytes > count ? count : morebytes;
927 memcpy(buf, gunzip_window, bytesRead);
928 morebytes -= bytesRead;
929 return bytesRead;
930 }
931
932} 902}
933 903
934extern void GZ_gzReadOpen(int fd, void *unused, int nUnused) 904extern int inflate_unzip(int in, int out)
935{ 905{
906 ssize_t nwrote;
936 typedef void (*sig_type) (int); 907 typedef void (*sig_type) (int);
937 908
938 /* Allocate all global buffers (for DYN_ALLOC option) */ 909 /* Allocate all global buffers (for DYN_ALLOC option) */
939 gunzip_window = xmalloc(gunzip_wsize); 910 gunzip_window = xmalloc(gunzip_wsize);
940 gunzip_outbuf_count = 0; 911 gunzip_outbuf_count = 0;
941 gunzip_bytes_out = 0; 912 gunzip_bytes_out = 0;
942 gunzip_src_fd = fd; 913 gunzip_src_fd = in;
943
944 /* Input buffer */
945 bytebuffer = xmalloc(BYTEBUFFER_MAX);
946 914
947 /* initialize gunzip_window, bit buffer */ 915 /* initialize gunzip_window, bit buffer */
948 gunzip_bk = 0; 916 gunzip_bk = 0;
@@ -950,10 +918,20 @@ extern void GZ_gzReadOpen(int fd, void *unused, int nUnused)
950 918
951 /* Create the crc table */ 919 /* Create the crc table */
952 make_gunzip_crc_table(); 920 make_gunzip_crc_table();
953}
954 921
955extern void GZ_gzReadClose(void) 922 /* Allocate space for buffer */
956{ 923 bytebuffer = xmalloc(bytebuffer_max);
924
925 while(1) {
926 int ret = inflate_get_next_window();
927 nwrote = bb_full_write(out, gunzip_window, gunzip_outbuf_count);
928 if (nwrote == -1) {
929 bb_perror_msg("write");
930 return -1;
931 }
932 if (ret == 0) break;
933 }
934
957 /* Cleanup */ 935 /* Cleanup */
958 free(gunzip_window); 936 free(gunzip_window);
959 free(gunzip_crc_table); 937 free(gunzip_crc_table);
@@ -967,57 +945,20 @@ extern void GZ_gzReadClose(void)
967 gunzip_bb >>= 8; 945 gunzip_bb >>= 8;
968 gunzip_bk -= 8; 946 gunzip_bk -= 8;
969 } 947 }
970}
971
972/*extern int inflate(int in, int out) // Useful for testing read_gz
973{
974 char buf[8192];
975 ssize_t nread, nwrote;
976
977 GZ_gzReadOpen(in, 0, 0);
978 while(1) { // Robbed from bb_copyfd.c
979 nread = read_gz(in, buf, sizeof(buf));
980 if (nread == 0) break; // no data to write
981 else if (nread == -1) {
982 bb_perror_msg("read");
983 return -1;
984 }
985 nwrote = bb_full_write(out, buf, nread);
986 if (nwrote == -1) {
987 bb_perror_msg("write");
988 return -1;
989 }
990 }
991 GZ_gzReadClose();
992 return 0;
993}*/
994
995extern int inflate(int in, int out)
996{
997 ssize_t nwrote;
998 GZ_gzReadOpen(in, 0, 0);
999 while(1) {
1000 int ret = inflate_get_next_window();
1001 nwrote = bb_full_write(out, gunzip_window, gunzip_outbuf_count);
1002 if (nwrote == -1) {
1003 bb_perror_msg("write");
1004 return -1;
1005 }
1006 if (ret == 0) break;
1007 }
1008 GZ_gzReadClose();
1009 return 0; 948 return 0;
1010} 949}
1011 950
1012extern void check_trailer_gzip(int src_fd) 951extern int inflate_gunzip(int in, int out)
1013{ 952{
1014 unsigned int stored_crc = 0; 953 unsigned int stored_crc = 0;
1015 unsigned char count; 954 unsigned char count;
1016 955
956 inflate_unzip(in, out);
957
1017 /* top up the input buffer with the rest of the trailer */ 958 /* top up the input buffer with the rest of the trailer */
1018 count = bytebuffer_size - bytebuffer_offset; 959 count = bytebuffer_size - bytebuffer_offset;
1019 if (count < 8) { 960 if (count < 8) {
1020 bb_xread_all(src_fd, &bytebuffer[bytebuffer_size], 8 - count); 961 bb_xread_all(in, &bytebuffer[bytebuffer_size], 8 - count);
1021 bytebuffer_size += 8 - count; 962 bytebuffer_size += 8 - count;
1022 } 963 }
1023 for (count = 0; count != 4; count++) { 964 for (count = 0; count != 4; count++) {
@@ -1027,14 +968,15 @@ extern void check_trailer_gzip(int src_fd)
1027 968
1028 /* Validate decompression - crc */ 969 /* Validate decompression - crc */
1029 if (stored_crc != (gunzip_crc ^ 0xffffffffL)) { 970 if (stored_crc != (gunzip_crc ^ 0xffffffffL)) {
1030 bb_error_msg_and_die("crc error"); 971 bb_error_msg("crc error");
1031 } 972 }
1032 973
1033 /* Validate decompression - size */ 974 /* Validate decompression - size */
1034 if (gunzip_bytes_out != 975 if (gunzip_bytes_out !=
1035 (bytebuffer[bytebuffer_offset] | (bytebuffer[bytebuffer_offset+1] << 8) | 976 (bytebuffer[bytebuffer_offset] | (bytebuffer[bytebuffer_offset+1] << 8) |
1036 (bytebuffer[bytebuffer_offset+2] << 16) | (bytebuffer[bytebuffer_offset+3] << 24))) { 977 (bytebuffer[bytebuffer_offset+2] << 16) | (bytebuffer[bytebuffer_offset+3] << 24))) {
1037 bb_error_msg_and_die("Incorrect length, but crc is correct"); 978 bb_error_msg("Incorrect length");
1038 } 979 }
1039 980
981 return 0;
1040} 982}
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) {
197 197
198 /* Initialise */ 198 /* Initialise */
199 archive_handle = init_handle(); 199 archive_handle = init_handle();
200 archive_handle->read = read_gz;
201 archive_handle->seek = seek_by_char; 200 archive_handle->seek = seek_by_char;
202 //archive_handle->action_header = header_list; 201 //archive_handle->action_header = header_list;
203 archive_handle->action_data = data_extract_all; 202 archive_handle->action_data = data_extract_all;
@@ -213,11 +212,9 @@ void extract_cpio_gz(int fd) {
213 check_header_gzip(archive_handle->src_fd); 212 check_header_gzip(archive_handle->src_fd);
214 chdir("/"); // Install RPM's to root 213 chdir("/"); // Install RPM's to root
215 214
216 GZ_gzReadOpen(archive_handle->src_fd, 0, 0); 215 archive_handle->src_fd = open_transformer(archive_handle->src_fd, inflate_gunzip);
216 archive_handle->offset = 0;
217 while (get_header_cpio(archive_handle) == EXIT_SUCCESS); 217 while (get_header_cpio(archive_handle) == EXIT_SUCCESS);
218 GZ_gzReadClose();
219
220 check_trailer_gzip(archive_handle->src_fd);
221} 218}
222 219
223 220
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)
96 } 96 }
97 97
98 check_header_gzip(rpm_fd); 98 check_header_gzip(rpm_fd);
99 if (inflate(rpm_fd, fileno(stdout)) != 0) { 99 if (inflate_gunzip(rpm_fd, fileno(stdout)) != 0) {
100 bb_error_msg("Error inflating"); 100 bb_error_msg("Error inflating");
101 } 101 }
102 check_trailer_gzip(rpm_fd);
103 102
104 close(rpm_fd); 103 close(rpm_fd);
105 104
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)
199 archive_handle->action_data(archive_handle); 199 archive_handle->action_data(archive_handle);
200 } else { 200 } else {
201 dst_fd = bb_xopen(archive_handle->file_header->name, O_WRONLY | O_CREAT); 201 dst_fd = bb_xopen(archive_handle->file_header->name, O_WRONLY | O_CREAT);
202 inflate(archive_handle->src_fd, dst_fd); 202 inflate_init(zip_header.formated.cmpsize);
203 inflate_unzip(archive_handle->src_fd, dst_fd);
203 close(dst_fd); 204 close(dst_fd);
204 chmod(archive_handle->file_header->name, archive_handle->file_header->mode); 205 chmod(archive_handle->file_header->name, archive_handle->file_header->mode);
205 206
@@ -227,10 +228,8 @@ extern int unzip_main(int argc, char **argv)
227 /* Data descriptor section */ 228 /* Data descriptor section */
228 if (zip_header.formated.flags & 4) { 229 if (zip_header.formated.flags & 4) {
229 /* skip over duplicate crc, compressed size and uncompressed size */ 230 /* skip over duplicate crc, compressed size and uncompressed size */
230 unsigned short i; 231 unsigned char data_description[12];
231 for (i = 0; i != 12; i++) { 232 archive_xread_all(archive_handle, data_description, 12);
232 archive_xread_char(archive_handle);
233 }
234 archive_handle->offset += 12; 233 archive_handle->offset += 12;
235 } 234 }
236 } 235 }