aboutsummaryrefslogtreecommitdiff
path: root/archival/libunarchive
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/libunarchive
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/libunarchive')
-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
11 files changed, 142 insertions, 258 deletions
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}