diff options
Diffstat (limited to 'archival/libunarchive/unzip.c')
-rw-r--r-- | archival/libunarchive/unzip.c | 140 |
1 files changed, 41 insertions, 99 deletions
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 */ | |||
103 | static unsigned char gunzip_bk; /* bits in bit buffer */ | 103 | static 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 | 106 | static unsigned int bytebuffer_max = 0x8000; |
107 | static unsigned char *bytebuffer = NULL; | 107 | static unsigned char *bytebuffer = NULL; |
108 | static unsigned int bytebuffer_offset = 0; | 108 | static unsigned int bytebuffer_offset = 0; |
109 | static unsigned int bytebuffer_size = 0; | 109 | static 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 | ||
147 | static 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 | |||
158 | static unsigned int fill_bitbuffer(unsigned int bitbuffer, unsigned int *current, const unsigned int required) | 147 | static 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 | ||
862 | static int inflate_get_next_window(void) | 857 | static 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 | 896 | extern void inflate_init(unsigned int bufsize) |
900 | * | ||
901 | * read_gz, GZ_gzReadOpen, GZ_gzReadClose, inflate | ||
902 | */ | ||
903 | |||
904 | extern 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 | ||
934 | extern void GZ_gzReadOpen(int fd, void *unused, int nUnused) | 904 | extern 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 | ||
955 | extern 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 | |||
995 | extern 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 | ||
1012 | extern void check_trailer_gzip(int src_fd) | 951 | extern 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 | } |