aboutsummaryrefslogtreecommitdiff
path: root/archival/libunarchive/unzip.c
diff options
context:
space:
mode:
Diffstat (limited to 'archival/libunarchive/unzip.c')
-rw-r--r--archival/libunarchive/unzip.c140
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 */
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}