diff options
author | Glenn L McGrath <bug1@ihug.co.nz> | 2002-11-17 21:33:30 +0000 |
---|---|---|
committer | Glenn L McGrath <bug1@ihug.co.nz> | 2002-11-17 21:33:30 +0000 |
commit | fd73b8c2ce6ae9517e37127cba2a48a6ee803287 (patch) | |
tree | af2e3ad9ace98903d663957e6ed29f4840188830 | |
parent | 36233bdd71cd6fd733fc2010d70db28cd5eb57e0 (diff) | |
download | busybox-w32-fd73b8c2ce6ae9517e37127cba2a48a6ee803287.tar.gz busybox-w32-fd73b8c2ce6ae9517e37127cba2a48a6ee803287.tar.bz2 busybox-w32-fd73b8c2ce6ae9517e37127cba2a48a6ee803287.zip |
Patch from Laurence Anderson to provide a read_gz function, doesnt require fork(), pipe(), consistent with read_bz2 and more flexible.
-rw-r--r-- | archival/libunarchive/decompress_unzip.c | 109 | ||||
-rw-r--r-- | archival/libunarchive/unzip.c | 109 |
2 files changed, 162 insertions, 56 deletions
diff --git a/archival/libunarchive/decompress_unzip.c b/archival/libunarchive/decompress_unzip.c index 20bf88f55..046f4dd72 100644 --- a/archival/libunarchive/decompress_unzip.c +++ b/archival/libunarchive/decompress_unzip.c | |||
@@ -81,7 +81,6 @@ typedef struct huft_s { | |||
81 | } huft_t; | 81 | } huft_t; |
82 | 82 | ||
83 | static int gunzip_src_fd; | 83 | static int gunzip_src_fd; |
84 | static int gunzip_dst_fd; | ||
85 | unsigned int gunzip_bytes_out; /* number of output bytes */ | 84 | unsigned int gunzip_bytes_out; /* number of output bytes */ |
86 | static unsigned int gunzip_outbuf_count; /* bytes in output buffer */ | 85 | static unsigned int gunzip_outbuf_count; /* bytes in output buffer */ |
87 | 86 | ||
@@ -93,11 +92,15 @@ unsigned char *gunzip_in_buffer; | |||
93 | /* gunzip_window size--must be a power of two, and | 92 | /* gunzip_window size--must be a power of two, and |
94 | * at least 32K for zip's deflate method */ | 93 | * at least 32K for zip's deflate method */ |
95 | static const int gunzip_wsize = 0x8000; | 94 | static const int gunzip_wsize = 0x8000; |
95 | static int output_buffer_size = 0x8000; // gunzip_wsize initially | ||
96 | 96 | ||
97 | static unsigned char *gunzip_window; | 97 | static unsigned char *gunzip_window; |
98 | static unsigned int *gunzip_crc_table; | 98 | static unsigned int *gunzip_crc_table; |
99 | unsigned int gunzip_crc; | 99 | unsigned int gunzip_crc; |
100 | 100 | ||
101 | static unsigned char *output_buffer; | ||
102 | static unsigned int output_buffer_len; | ||
103 | |||
101 | /* If BMAX needs to be larger than 16, then h and x[] should be ulg. */ | 104 | /* If BMAX needs to be larger than 16, then h and x[] should be ulg. */ |
102 | #define BMAX 16 /* maximum bit length of any code (16 for explode) */ | 105 | #define BMAX 16 /* maximum bit length of any code (16 for explode) */ |
103 | #define N_MAX 288 /* maximum number of codes in any set */ | 106 | #define N_MAX 288 /* maximum number of codes in any set */ |
@@ -410,9 +413,20 @@ static void flush_gunzip_window(void) | |||
410 | gunzip_crc = gunzip_crc_table[((int) gunzip_crc ^ (gunzip_window[n])) & 0xff] ^ (gunzip_crc >> 8); | 413 | gunzip_crc = gunzip_crc_table[((int) gunzip_crc ^ (gunzip_window[n])) & 0xff] ^ (gunzip_crc >> 8); |
411 | } | 414 | } |
412 | 415 | ||
413 | if (write(gunzip_dst_fd, gunzip_window, gunzip_outbuf_count) != gunzip_outbuf_count) { | 416 | if (output_buffer_len == 0) { // Our buffer is empty -> straight memcpy |
414 | error_msg_and_die("Couldnt write"); | 417 | memcpy(output_buffer, gunzip_window, gunzip_outbuf_count); |
418 | output_buffer_len = gunzip_outbuf_count; | ||
419 | } else { // Bit more complicated, append to end of output_buffer, realloc as necessary | ||
420 | int newlen = output_buffer_len + gunzip_outbuf_count; | ||
421 | if (newlen > output_buffer_size) { | ||
422 | output_buffer = xrealloc(output_buffer, newlen); // Could free later, but as we now have the memory... | ||
423 | //printf("Using %d byte output buffer\n", newlen); | ||
424 | output_buffer_size = newlen; | ||
425 | } | ||
426 | memcpy(output_buffer + output_buffer_len, gunzip_window, gunzip_outbuf_count); | ||
427 | output_buffer_len += gunzip_outbuf_count; | ||
415 | } | 428 | } |
429 | |||
416 | gunzip_bytes_out += gunzip_outbuf_count; | 430 | gunzip_bytes_out += gunzip_outbuf_count; |
417 | gunzip_outbuf_count = 0; | 431 | gunzip_outbuf_count = 0; |
418 | } | 432 | } |
@@ -835,20 +849,49 @@ static int inflate_block(int *e) | |||
835 | * | 849 | * |
836 | * GLOBAL VARIABLES: gunzip_outbuf_count, bk, gunzip_bb, hufts, inptr | 850 | * GLOBAL VARIABLES: gunzip_outbuf_count, bk, gunzip_bb, hufts, inptr |
837 | */ | 851 | */ |
838 | extern int inflate(int in, int out) | 852 | |
853 | extern ssize_t read_gz(int fd, void *buf, size_t count) | ||
839 | { | 854 | { |
840 | typedef void (*sig_type) (int); | 855 | static int e = 0; /* last block flag */ |
841 | int e; /* last block flag */ | ||
842 | int r; /* result code */ | 856 | int r; /* result code */ |
843 | unsigned h = 0; /* maximum struct huft's malloc'ed */ | 857 | unsigned h = 0; /* maximum struct huft's malloc'ed */ |
858 | ssize_t written = count; | ||
859 | static char *output_buffer_ptr = 0; | ||
860 | |||
861 | while (output_buffer_len == 0) { // We need more data | ||
862 | if (e) return 0; // No more data here! | ||
863 | gunzip_hufts = 0; | ||
864 | r = inflate_block(&e); | ||
865 | if (r != 0) { | ||
866 | error_msg_and_die("inflate error %d", r); | ||
867 | return -1; | ||
868 | } | ||
869 | if (gunzip_hufts > h) { | ||
870 | h = gunzip_hufts; | ||
871 | } | ||
872 | if (e) { // Ok finished uncompressing, get any buffered uncompressed data | ||
873 | flush_gunzip_window(); | ||
874 | } | ||
875 | output_buffer_ptr = output_buffer; | ||
876 | } | ||
877 | if (count > output_buffer_len) written = output_buffer_len; // We're only giving them as much as we have! | ||
878 | memcpy(buf, output_buffer_ptr, written); | ||
879 | output_buffer_ptr += written; | ||
880 | output_buffer_len -= written; | ||
881 | |||
882 | return written; | ||
883 | } | ||
884 | |||
885 | extern void GZ_gzReadOpen(int fd, void *unused, int nUnused) | ||
886 | { | ||
887 | typedef void (*sig_type) (int); | ||
844 | 888 | ||
845 | /* Allocate all global buffers (for DYN_ALLOC option) */ | 889 | /* Allocate all global buffers (for DYN_ALLOC option) */ |
846 | gunzip_window = xmalloc(0x8000); | 890 | gunzip_window = xmalloc(gunzip_wsize); |
891 | output_buffer = xmalloc(gunzip_wsize); | ||
847 | gunzip_outbuf_count = 0; | 892 | gunzip_outbuf_count = 0; |
848 | gunzip_bytes_out = 0; | 893 | gunzip_bytes_out = 0; |
849 | 894 | gunzip_src_fd = fd; | |
850 | gunzip_src_fd = in; | ||
851 | gunzip_dst_fd = out; | ||
852 | 895 | ||
853 | gunzip_in_buffer = malloc(8); | 896 | gunzip_in_buffer = malloc(8); |
854 | 897 | ||
@@ -867,25 +910,13 @@ extern int inflate(int in, int out) | |||
867 | 910 | ||
868 | /* Create the crc table */ | 911 | /* Create the crc table */ |
869 | make_gunzip_crc_table(); | 912 | make_gunzip_crc_table(); |
913 | } | ||
870 | 914 | ||
871 | /* decompress until the last block */ | 915 | extern void GZ_gzReadClose(void) |
872 | do { | 916 | { |
873 | gunzip_hufts = 0; | ||
874 | r = inflate_block(&e); | ||
875 | if (r != 0) { | ||
876 | error_msg_and_die("inflate error %d", r); | ||
877 | return r; | ||
878 | } | ||
879 | if (gunzip_hufts > h) { | ||
880 | h = gunzip_hufts; | ||
881 | } | ||
882 | } while (!e); | ||
883 | |||
884 | /* write any buffered uncompressed data */ | ||
885 | flush_gunzip_window(); | ||
886 | free(gunzip_window); | ||
887 | |||
888 | /* Cleanup */ | 917 | /* Cleanup */ |
918 | free(gunzip_window); | ||
919 | free(output_buffer); | ||
889 | free(gunzip_crc_table); | 920 | free(gunzip_crc_table); |
890 | 921 | ||
891 | /* Store unused bytes in a global buffer so calling applets can access it */ | 922 | /* Store unused bytes in a global buffer so calling applets can access it */ |
@@ -898,7 +929,29 @@ extern int inflate(int in, int out) | |||
898 | gunzip_bb >>= 8; | 929 | gunzip_bb >>= 8; |
899 | gunzip_bk -= 8; | 930 | gunzip_bk -= 8; |
900 | } | 931 | } |
932 | } | ||
901 | 933 | ||
902 | /* return success */ | 934 | extern int inflate(int in, int out) |
935 | { | ||
936 | char buf[8192]; | ||
937 | ssize_t nread, nwrote; | ||
938 | ssize_t total = 0; | ||
939 | |||
940 | GZ_gzReadOpen(in, 0, 0); | ||
941 | while(1) { // Robbed from copyfd.c | ||
942 | nread = read_gz(in, buf, sizeof(buf)); | ||
943 | if (nread == 0) break; // no data to write | ||
944 | else if (nread == -1) { | ||
945 | perror_msg("read"); | ||
946 | return -1; | ||
947 | } | ||
948 | nwrote = full_write(out, buf, nread); | ||
949 | if (nwrote == -1) { | ||
950 | perror_msg("write"); | ||
951 | return -1; | ||
952 | } | ||
953 | total += nwrote; | ||
954 | } | ||
955 | GZ_gzReadClose(); | ||
903 | return 0; | 956 | return 0; |
904 | } | 957 | } |
diff --git a/archival/libunarchive/unzip.c b/archival/libunarchive/unzip.c index 20bf88f55..046f4dd72 100644 --- a/archival/libunarchive/unzip.c +++ b/archival/libunarchive/unzip.c | |||
@@ -81,7 +81,6 @@ typedef struct huft_s { | |||
81 | } huft_t; | 81 | } huft_t; |
82 | 82 | ||
83 | static int gunzip_src_fd; | 83 | static int gunzip_src_fd; |
84 | static int gunzip_dst_fd; | ||
85 | unsigned int gunzip_bytes_out; /* number of output bytes */ | 84 | unsigned int gunzip_bytes_out; /* number of output bytes */ |
86 | static unsigned int gunzip_outbuf_count; /* bytes in output buffer */ | 85 | static unsigned int gunzip_outbuf_count; /* bytes in output buffer */ |
87 | 86 | ||
@@ -93,11 +92,15 @@ unsigned char *gunzip_in_buffer; | |||
93 | /* gunzip_window size--must be a power of two, and | 92 | /* gunzip_window size--must be a power of two, and |
94 | * at least 32K for zip's deflate method */ | 93 | * at least 32K for zip's deflate method */ |
95 | static const int gunzip_wsize = 0x8000; | 94 | static const int gunzip_wsize = 0x8000; |
95 | static int output_buffer_size = 0x8000; // gunzip_wsize initially | ||
96 | 96 | ||
97 | static unsigned char *gunzip_window; | 97 | static unsigned char *gunzip_window; |
98 | static unsigned int *gunzip_crc_table; | 98 | static unsigned int *gunzip_crc_table; |
99 | unsigned int gunzip_crc; | 99 | unsigned int gunzip_crc; |
100 | 100 | ||
101 | static unsigned char *output_buffer; | ||
102 | static unsigned int output_buffer_len; | ||
103 | |||
101 | /* If BMAX needs to be larger than 16, then h and x[] should be ulg. */ | 104 | /* If BMAX needs to be larger than 16, then h and x[] should be ulg. */ |
102 | #define BMAX 16 /* maximum bit length of any code (16 for explode) */ | 105 | #define BMAX 16 /* maximum bit length of any code (16 for explode) */ |
103 | #define N_MAX 288 /* maximum number of codes in any set */ | 106 | #define N_MAX 288 /* maximum number of codes in any set */ |
@@ -410,9 +413,20 @@ static void flush_gunzip_window(void) | |||
410 | gunzip_crc = gunzip_crc_table[((int) gunzip_crc ^ (gunzip_window[n])) & 0xff] ^ (gunzip_crc >> 8); | 413 | gunzip_crc = gunzip_crc_table[((int) gunzip_crc ^ (gunzip_window[n])) & 0xff] ^ (gunzip_crc >> 8); |
411 | } | 414 | } |
412 | 415 | ||
413 | if (write(gunzip_dst_fd, gunzip_window, gunzip_outbuf_count) != gunzip_outbuf_count) { | 416 | if (output_buffer_len == 0) { // Our buffer is empty -> straight memcpy |
414 | error_msg_and_die("Couldnt write"); | 417 | memcpy(output_buffer, gunzip_window, gunzip_outbuf_count); |
418 | output_buffer_len = gunzip_outbuf_count; | ||
419 | } else { // Bit more complicated, append to end of output_buffer, realloc as necessary | ||
420 | int newlen = output_buffer_len + gunzip_outbuf_count; | ||
421 | if (newlen > output_buffer_size) { | ||
422 | output_buffer = xrealloc(output_buffer, newlen); // Could free later, but as we now have the memory... | ||
423 | //printf("Using %d byte output buffer\n", newlen); | ||
424 | output_buffer_size = newlen; | ||
425 | } | ||
426 | memcpy(output_buffer + output_buffer_len, gunzip_window, gunzip_outbuf_count); | ||
427 | output_buffer_len += gunzip_outbuf_count; | ||
415 | } | 428 | } |
429 | |||
416 | gunzip_bytes_out += gunzip_outbuf_count; | 430 | gunzip_bytes_out += gunzip_outbuf_count; |
417 | gunzip_outbuf_count = 0; | 431 | gunzip_outbuf_count = 0; |
418 | } | 432 | } |
@@ -835,20 +849,49 @@ static int inflate_block(int *e) | |||
835 | * | 849 | * |
836 | * GLOBAL VARIABLES: gunzip_outbuf_count, bk, gunzip_bb, hufts, inptr | 850 | * GLOBAL VARIABLES: gunzip_outbuf_count, bk, gunzip_bb, hufts, inptr |
837 | */ | 851 | */ |
838 | extern int inflate(int in, int out) | 852 | |
853 | extern ssize_t read_gz(int fd, void *buf, size_t count) | ||
839 | { | 854 | { |
840 | typedef void (*sig_type) (int); | 855 | static int e = 0; /* last block flag */ |
841 | int e; /* last block flag */ | ||
842 | int r; /* result code */ | 856 | int r; /* result code */ |
843 | unsigned h = 0; /* maximum struct huft's malloc'ed */ | 857 | unsigned h = 0; /* maximum struct huft's malloc'ed */ |
858 | ssize_t written = count; | ||
859 | static char *output_buffer_ptr = 0; | ||
860 | |||
861 | while (output_buffer_len == 0) { // We need more data | ||
862 | if (e) return 0; // No more data here! | ||
863 | gunzip_hufts = 0; | ||
864 | r = inflate_block(&e); | ||
865 | if (r != 0) { | ||
866 | error_msg_and_die("inflate error %d", r); | ||
867 | return -1; | ||
868 | } | ||
869 | if (gunzip_hufts > h) { | ||
870 | h = gunzip_hufts; | ||
871 | } | ||
872 | if (e) { // Ok finished uncompressing, get any buffered uncompressed data | ||
873 | flush_gunzip_window(); | ||
874 | } | ||
875 | output_buffer_ptr = output_buffer; | ||
876 | } | ||
877 | if (count > output_buffer_len) written = output_buffer_len; // We're only giving them as much as we have! | ||
878 | memcpy(buf, output_buffer_ptr, written); | ||
879 | output_buffer_ptr += written; | ||
880 | output_buffer_len -= written; | ||
881 | |||
882 | return written; | ||
883 | } | ||
884 | |||
885 | extern void GZ_gzReadOpen(int fd, void *unused, int nUnused) | ||
886 | { | ||
887 | typedef void (*sig_type) (int); | ||
844 | 888 | ||
845 | /* Allocate all global buffers (for DYN_ALLOC option) */ | 889 | /* Allocate all global buffers (for DYN_ALLOC option) */ |
846 | gunzip_window = xmalloc(0x8000); | 890 | gunzip_window = xmalloc(gunzip_wsize); |
891 | output_buffer = xmalloc(gunzip_wsize); | ||
847 | gunzip_outbuf_count = 0; | 892 | gunzip_outbuf_count = 0; |
848 | gunzip_bytes_out = 0; | 893 | gunzip_bytes_out = 0; |
849 | 894 | gunzip_src_fd = fd; | |
850 | gunzip_src_fd = in; | ||
851 | gunzip_dst_fd = out; | ||
852 | 895 | ||
853 | gunzip_in_buffer = malloc(8); | 896 | gunzip_in_buffer = malloc(8); |
854 | 897 | ||
@@ -867,25 +910,13 @@ extern int inflate(int in, int out) | |||
867 | 910 | ||
868 | /* Create the crc table */ | 911 | /* Create the crc table */ |
869 | make_gunzip_crc_table(); | 912 | make_gunzip_crc_table(); |
913 | } | ||
870 | 914 | ||
871 | /* decompress until the last block */ | 915 | extern void GZ_gzReadClose(void) |
872 | do { | 916 | { |
873 | gunzip_hufts = 0; | ||
874 | r = inflate_block(&e); | ||
875 | if (r != 0) { | ||
876 | error_msg_and_die("inflate error %d", r); | ||
877 | return r; | ||
878 | } | ||
879 | if (gunzip_hufts > h) { | ||
880 | h = gunzip_hufts; | ||
881 | } | ||
882 | } while (!e); | ||
883 | |||
884 | /* write any buffered uncompressed data */ | ||
885 | flush_gunzip_window(); | ||
886 | free(gunzip_window); | ||
887 | |||
888 | /* Cleanup */ | 917 | /* Cleanup */ |
918 | free(gunzip_window); | ||
919 | free(output_buffer); | ||
889 | free(gunzip_crc_table); | 920 | free(gunzip_crc_table); |
890 | 921 | ||
891 | /* Store unused bytes in a global buffer so calling applets can access it */ | 922 | /* Store unused bytes in a global buffer so calling applets can access it */ |
@@ -898,7 +929,29 @@ extern int inflate(int in, int out) | |||
898 | gunzip_bb >>= 8; | 929 | gunzip_bb >>= 8; |
899 | gunzip_bk -= 8; | 930 | gunzip_bk -= 8; |
900 | } | 931 | } |
932 | } | ||
901 | 933 | ||
902 | /* return success */ | 934 | extern int inflate(int in, int out) |
935 | { | ||
936 | char buf[8192]; | ||
937 | ssize_t nread, nwrote; | ||
938 | ssize_t total = 0; | ||
939 | |||
940 | GZ_gzReadOpen(in, 0, 0); | ||
941 | while(1) { // Robbed from copyfd.c | ||
942 | nread = read_gz(in, buf, sizeof(buf)); | ||
943 | if (nread == 0) break; // no data to write | ||
944 | else if (nread == -1) { | ||
945 | perror_msg("read"); | ||
946 | return -1; | ||
947 | } | ||
948 | nwrote = full_write(out, buf, nread); | ||
949 | if (nwrote == -1) { | ||
950 | perror_msg("write"); | ||
951 | return -1; | ||
952 | } | ||
953 | total += nwrote; | ||
954 | } | ||
955 | GZ_gzReadClose(); | ||
903 | return 0; | 956 | return 0; |
904 | } | 957 | } |