diff options
author | Glenn L McGrath <bug1@ihug.co.nz> | 2002-11-20 22:00:31 +0000 |
---|---|---|
committer | Glenn L McGrath <bug1@ihug.co.nz> | 2002-11-20 22:00:31 +0000 |
commit | 83bf47c02f95a9956eb4f6a185014ab0fb62670b (patch) | |
tree | 058d3c3d2e7b167bd384128583fc248fe7dafa52 | |
parent | 0126fda5bbb01fef3e6de07c8f4619863d606f50 (diff) | |
download | busybox-w32-83bf47c02f95a9956eb4f6a185014ab0fb62670b.tar.gz busybox-w32-83bf47c02f95a9956eb4f6a185014ab0fb62670b.tar.bz2 busybox-w32-83bf47c02f95a9956eb4f6a185014ab0fb62670b.zip |
Speed and memory usage improvements from Laurence Adnerson
-rw-r--r-- | archival/libunarchive/decompress_unzip.c | 177 | ||||
-rw-r--r-- | archival/libunarchive/unzip.c | 177 |
2 files changed, 190 insertions, 164 deletions
diff --git a/archival/libunarchive/decompress_unzip.c b/archival/libunarchive/decompress_unzip.c index 7ebbd0ee7..d8d5b77b1 100644 --- a/archival/libunarchive/decompress_unzip.c +++ b/archival/libunarchive/decompress_unzip.c | |||
@@ -14,6 +14,8 @@ | |||
14 | * General cleanup to better adhere to the style guide and make use of standard | 14 | * General cleanup to better adhere to the style guide and make use of standard |
15 | * busybox functions by Glenn McGrath <bug1@optushome.com.au> | 15 | * busybox functions by Glenn McGrath <bug1@optushome.com.au> |
16 | * | 16 | * |
17 | * read_gz interface + associated hacking by Laurence Anderson | ||
18 | * | ||
17 | * This program is free software; you can redistribute it and/or modify | 19 | * This program is free software; you can redistribute it and/or modify |
18 | * it under the terms of the GNU General Public License as published by | 20 | * it under the terms of the GNU General Public License as published by |
19 | * the Free Software Foundation; either version 2 of the License, or | 21 | * the Free Software Foundation; either version 2 of the License, or |
@@ -92,20 +94,15 @@ unsigned char *gunzip_in_buffer; | |||
92 | /* gunzip_window size--must be a power of two, and | 94 | /* gunzip_window size--must be a power of two, and |
93 | * at least 32K for zip's deflate method */ | 95 | * at least 32K for zip's deflate method */ |
94 | static const int gunzip_wsize = 0x8000; | 96 | static const int gunzip_wsize = 0x8000; |
95 | static int output_buffer_size = 0x8000; // gunzip_wsize initially | ||
96 | 97 | ||
97 | static unsigned char *gunzip_window; | 98 | static unsigned char *gunzip_window; |
98 | static unsigned int *gunzip_crc_table; | 99 | static unsigned int *gunzip_crc_table; |
99 | unsigned int gunzip_crc; | 100 | unsigned int gunzip_crc; |
100 | 101 | ||
101 | static unsigned char *output_buffer; | ||
102 | static unsigned int output_buffer_len; | ||
103 | |||
104 | /* If BMAX needs to be larger than 16, then h and x[] should be ulg. */ | 102 | /* If BMAX needs to be larger than 16, then h and x[] should be ulg. */ |
105 | #define BMAX 16 /* maximum bit length of any code (16 for explode) */ | 103 | #define BMAX 16 /* maximum bit length of any code (16 for explode) */ |
106 | #define N_MAX 288 /* maximum number of codes in any set */ | 104 | #define N_MAX 288 /* maximum number of codes in any set */ |
107 | 105 | ||
108 | static unsigned int gunzip_hufts; /* track memory usage */ | ||
109 | static unsigned int gunzip_bb; /* bit buffer */ | 106 | static unsigned int gunzip_bb; /* bit buffer */ |
110 | static unsigned char gunzip_bk; /* bits in bit buffer */ | 107 | static unsigned char gunzip_bk; /* bits in bit buffer */ |
111 | 108 | ||
@@ -343,7 +340,6 @@ static int huft_build(unsigned int *b, const unsigned int n, | |||
343 | /* allocate and link in new table */ | 340 | /* allocate and link in new table */ |
344 | q = (huft_t *) xmalloc((z + 1) * sizeof(huft_t)); | 341 | q = (huft_t *) xmalloc((z + 1) * sizeof(huft_t)); |
345 | 342 | ||
346 | gunzip_hufts += z + 1; /* track memory usage */ | ||
347 | *t = q + 1; /* link to list for huft_free() */ | 343 | *t = q + 1; /* link to list for huft_free() */ |
348 | *(t = &(q->v.t)) = NULL; | 344 | *(t = &(q->v.t)) = NULL; |
349 | u[h] = ++q; /* table starts after link */ | 345 | u[h] = ++q; /* table starts after link */ |
@@ -395,36 +391,6 @@ static int huft_build(unsigned int *b, const unsigned int n, | |||
395 | return y != 0 && g != 1; | 391 | return y != 0 && g != 1; |
396 | } | 392 | } |
397 | 393 | ||
398 | /* =========================================================================== | ||
399 | * Write the output gunzip_window gunzip_window[0..gunzip_outbuf_count-1] and update crc and gunzip_bytes_out. | ||
400 | * (Used for the decompressed data only.) | ||
401 | */ | ||
402 | static void flush_gunzip_window(void) | ||
403 | { | ||
404 | int n; | ||
405 | |||
406 | for (n = 0; n < gunzip_outbuf_count; n++) { | ||
407 | gunzip_crc = gunzip_crc_table[((int) gunzip_crc ^ (gunzip_window[n])) & 0xff] ^ (gunzip_crc >> 8); | ||
408 | } | ||
409 | |||
410 | if (output_buffer_len == 0) { // Our buffer is empty -> straight memcpy | ||
411 | memcpy(output_buffer, gunzip_window, gunzip_outbuf_count); | ||
412 | output_buffer_len = gunzip_outbuf_count; | ||
413 | } else { // Bit more complicated, append to end of output_buffer, realloc as necessary | ||
414 | int newlen = output_buffer_len + gunzip_outbuf_count; | ||
415 | if (newlen > output_buffer_size) { | ||
416 | output_buffer = xrealloc(output_buffer, newlen); // Could free later, but as we now have the memory... | ||
417 | //printf("Using %d byte output buffer\n", newlen); | ||
418 | output_buffer_size = newlen; | ||
419 | } | ||
420 | memcpy(output_buffer + output_buffer_len, gunzip_window, gunzip_outbuf_count); | ||
421 | output_buffer_len += gunzip_outbuf_count; | ||
422 | } | ||
423 | |||
424 | gunzip_bytes_out += gunzip_outbuf_count; | ||
425 | gunzip_outbuf_count = 0; | ||
426 | } | ||
427 | |||
428 | /* | 394 | /* |
429 | * inflate (decompress) the codes in a deflated (compressed) block. | 395 | * inflate (decompress) the codes in a deflated (compressed) block. |
430 | * Return an error code or zero if it all goes ok. | 396 | * Return an error code or zero if it all goes ok. |
@@ -468,7 +434,7 @@ static int inflate_codes(huft_t * my_tl, huft_t * my_td, const unsigned int my_b | |||
468 | if ((e = (t = tl + ((unsigned) b & ml))->e) > 16) | 434 | if ((e = (t = tl + ((unsigned) b & ml))->e) > 16) |
469 | do { | 435 | do { |
470 | if (e == 99) { | 436 | if (e == 99) { |
471 | return 1; | 437 | error_msg_and_die("inflate_codes error 1");; |
472 | } | 438 | } |
473 | b >>= t->b; | 439 | b >>= t->b; |
474 | k -= t->b; | 440 | k -= t->b; |
@@ -484,7 +450,7 @@ static int inflate_codes(huft_t * my_tl, huft_t * my_td, const unsigned int my_b | |||
484 | gunzip_outbuf_count = (w); | 450 | gunzip_outbuf_count = (w); |
485 | //flush_gunzip_window(); | 451 | //flush_gunzip_window(); |
486 | w = 0; | 452 | w = 0; |
487 | return -1; | 453 | return 1; // We have a block to read |
488 | } | 454 | } |
489 | } else { /* it's an EOB or a length */ | 455 | } else { /* it's an EOB or a length */ |
490 | 456 | ||
@@ -504,7 +470,7 @@ static int inflate_codes(huft_t * my_tl, huft_t * my_td, const unsigned int my_b | |||
504 | if ((e = (t = td + ((unsigned) b & md))->e) > 16) | 470 | if ((e = (t = td + ((unsigned) b & md))->e) > 16) |
505 | do { | 471 | do { |
506 | if (e == 99) | 472 | if (e == 99) |
507 | return 1; | 473 | error_msg_and_die("inflate_codes error 2");; |
508 | b >>= t->b; | 474 | b >>= t->b; |
509 | k -= t->b; | 475 | k -= t->b; |
510 | e -= 16; | 476 | e -= 16; |
@@ -542,7 +508,7 @@ do_copy: do { | |||
542 | else resumeCopy = 0; | 508 | else resumeCopy = 0; |
543 | //flush_gunzip_window(); | 509 | //flush_gunzip_window(); |
544 | w = 0; | 510 | w = 0; |
545 | return -1; | 511 | return 1; |
546 | } | 512 | } |
547 | } while (n); | 513 | } while (n); |
548 | resumeCopy = 0; | 514 | resumeCopy = 0; |
@@ -563,7 +529,7 @@ do_copy: do { | |||
563 | return 0; | 529 | return 0; |
564 | } | 530 | } |
565 | 531 | ||
566 | int inflate_stored(int my_n, int my_b_stored, int my_k_stored, int setup) | 532 | static int inflate_stored(int my_n, int my_b_stored, int my_k_stored, int setup) |
567 | { | 533 | { |
568 | static int n, b_stored, k_stored, w; | 534 | static int n, b_stored, k_stored, w; |
569 | if (setup) { | 535 | if (setup) { |
@@ -584,7 +550,7 @@ int inflate_stored(int my_n, int my_b_stored, int my_k_stored, int setup) | |||
584 | w = 0; | 550 | w = 0; |
585 | b_stored >>= 8; | 551 | b_stored >>= 8; |
586 | k_stored -= 8; | 552 | k_stored -= 8; |
587 | return -1; // Means more stuff 2do | 553 | return 1; // We have a block |
588 | } | 554 | } |
589 | b_stored >>= 8; | 555 | b_stored >>= 8; |
590 | k_stored -= 8; | 556 | k_stored -= 8; |
@@ -866,51 +832,85 @@ static int inflate_block(int *e) | |||
866 | } | 832 | } |
867 | default: | 833 | default: |
868 | /* bad block type */ | 834 | /* bad block type */ |
869 | error_msg("bad block type %d\n", t); | 835 | error_msg_and_die("bad block type %d\n", t); |
870 | return 2; | 836 | } |
837 | } | ||
838 | |||
839 | static void calculate_gunzip_crc(void) | ||
840 | { | ||
841 | int n; | ||
842 | for (n = 0; n < gunzip_outbuf_count; n++) { | ||
843 | gunzip_crc = gunzip_crc_table[((int) gunzip_crc ^ (gunzip_window[n])) & 0xff] ^ (gunzip_crc >> 8); | ||
844 | } | ||
845 | gunzip_bytes_out += gunzip_outbuf_count; | ||
846 | } | ||
847 | |||
848 | static int inflate_get_next_window(void) | ||
849 | { | ||
850 | static int needAnotherBlock = 1; | ||
851 | static int method = -1; // Method == -1 for stored, -2 for codes | ||
852 | static int e = 0; | ||
853 | |||
854 | gunzip_outbuf_count = 0; | ||
855 | |||
856 | while(1) { | ||
857 | int ret; | ||
858 | |||
859 | if (needAnotherBlock) { | ||
860 | if(e) { calculate_gunzip_crc(); return 0; } // Last block | ||
861 | method = inflate_block(&e); | ||
862 | needAnotherBlock = 0; | ||
863 | } | ||
864 | |||
865 | switch (method) { | ||
866 | case -1: ret = inflate_stored(0,0,0,0); | ||
867 | break; | ||
868 | case -2: ret = inflate_codes(0,0,0,0,0); | ||
869 | break; | ||
870 | default: error_msg_and_die("inflate error %d", method); | ||
871 | } | ||
872 | |||
873 | if (ret == 1) { | ||
874 | calculate_gunzip_crc(); | ||
875 | return 1; // More data left | ||
876 | } else needAnotherBlock = 1; // End of that block | ||
871 | } | 877 | } |
872 | } | 878 | } |
873 | 879 | ||
874 | /* | 880 | /* |
875 | * decompress an inflated entry | 881 | * User functions |
876 | * | 882 | * |
877 | * GLOBAL VARIABLES: gunzip_outbuf_count, bk, gunzip_bb, hufts, inptr | 883 | * read_gz, GZ_gzReadOpen, GZ_gzReadClose, inflate |
878 | */ | 884 | */ |
879 | 885 | ||
880 | extern ssize_t read_gz(int fd, void *buf, size_t count) | 886 | extern ssize_t read_gz(int fd, void *buf, size_t count) |
881 | { | 887 | { |
882 | static int e = 0; /* last block flag */ | 888 | static int morebytes = 0, finished = 0; |
883 | int r; /* result code */ | 889 | |
884 | unsigned h = 0; /* maximum struct huft's malloc'ed */ | 890 | if (morebytes) { |
885 | ssize_t written = count; | 891 | int bytesRead = morebytes > count ? count : morebytes; |
886 | static char *output_buffer_ptr = 0; | 892 | memcpy(buf, gunzip_window + (gunzip_outbuf_count - morebytes), bytesRead); |
887 | 893 | morebytes -= bytesRead; | |
888 | while (output_buffer_len == 0) { // We need more data | 894 | return bytesRead; |
889 | if (e) return 0; // No more data here! | 895 | } else if (finished) { |
890 | gunzip_hufts = 0; | 896 | return 0; |
891 | r = inflate_block(&e); | 897 | } else if (count >= 0x8000) { // We can decompress direcly to the buffer, 32k at a time |
892 | if (r == -1) { // Call inflate_stored while returning -1 | 898 | // Could decompress to larger buffer, but it must be a power of 2, and calculating that is probably more expensive than the benefit |
893 | while(inflate_stored(0,0,0,0) == -1) flush_gunzip_window(); | 899 | unsigned char *old_gunzip_window = gunzip_window; // Save old window |
894 | } else if (r == -2) { // Call inflate_codes while returning -1 | 900 | gunzip_window = buf; |
895 | while(inflate_codes(0,0,0,0,0) == -1) flush_gunzip_window(); | 901 | if (inflate_get_next_window() == 0) finished = 1; |
896 | } else { | 902 | gunzip_window = old_gunzip_window; // Restore old window |
897 | error_msg_and_die("inflate error %d", r); | 903 | return gunzip_outbuf_count; |
898 | return -1; | 904 | } else { // Oh well, need to split up the gunzip_window |
899 | } | 905 | int bytesRead; |
900 | if (gunzip_hufts > h) { | 906 | if (inflate_get_next_window() == 0) finished = 1; |
901 | h = gunzip_hufts; | 907 | morebytes = gunzip_outbuf_count; |
902 | } | 908 | bytesRead = morebytes > count ? count : morebytes; |
903 | if (e) { // Ok finished uncompressing, get any buffered uncompressed data | 909 | memcpy(buf, gunzip_window, bytesRead); |
904 | flush_gunzip_window(); | 910 | morebytes -= bytesRead; |
905 | } | 911 | return bytesRead; |
906 | output_buffer_ptr = output_buffer; | ||
907 | } | 912 | } |
908 | if (count > output_buffer_len) written = output_buffer_len; // We're only giving them as much as we have! | 913 | |
909 | memcpy(buf, output_buffer_ptr, written); | ||
910 | output_buffer_ptr += written; | ||
911 | output_buffer_len -= written; | ||
912 | |||
913 | return written; | ||
914 | } | 914 | } |
915 | 915 | ||
916 | extern void GZ_gzReadOpen(int fd, void *unused, int nUnused) | 916 | extern void GZ_gzReadOpen(int fd, void *unused, int nUnused) |
@@ -919,7 +919,6 @@ extern void GZ_gzReadOpen(int fd, void *unused, int nUnused) | |||
919 | 919 | ||
920 | /* Allocate all global buffers (for DYN_ALLOC option) */ | 920 | /* Allocate all global buffers (for DYN_ALLOC option) */ |
921 | gunzip_window = xmalloc(gunzip_wsize); | 921 | gunzip_window = xmalloc(gunzip_wsize); |
922 | output_buffer = xmalloc(gunzip_wsize); | ||
923 | gunzip_outbuf_count = 0; | 922 | gunzip_outbuf_count = 0; |
924 | gunzip_bytes_out = 0; | 923 | gunzip_bytes_out = 0; |
925 | gunzip_src_fd = fd; | 924 | gunzip_src_fd = fd; |
@@ -938,7 +937,6 @@ extern void GZ_gzReadClose(void) | |||
938 | { | 937 | { |
939 | /* Cleanup */ | 938 | /* Cleanup */ |
940 | free(gunzip_window); | 939 | free(gunzip_window); |
941 | free(output_buffer); | ||
942 | free(gunzip_crc_table); | 940 | free(gunzip_crc_table); |
943 | 941 | ||
944 | /* Store unused bytes in a global buffer so calling applets can access it */ | 942 | /* Store unused bytes in a global buffer so calling applets can access it */ |
@@ -953,11 +951,10 @@ extern void GZ_gzReadClose(void) | |||
953 | } | 951 | } |
954 | } | 952 | } |
955 | 953 | ||
956 | extern int inflate(int in, int out) | 954 | /*extern int inflate(int in, int out) // Useful for testing read_gz |
957 | { | 955 | { |
958 | char buf[8192]; | 956 | char buf[8192]; |
959 | ssize_t nread, nwrote; | 957 | ssize_t nread, nwrote; |
960 | ssize_t total = 0; | ||
961 | 958 | ||
962 | GZ_gzReadOpen(in, 0, 0); | 959 | GZ_gzReadOpen(in, 0, 0); |
963 | while(1) { // Robbed from copyfd.c | 960 | while(1) { // Robbed from copyfd.c |
@@ -972,7 +969,23 @@ extern int inflate(int in, int out) | |||
972 | perror_msg("write"); | 969 | perror_msg("write"); |
973 | return -1; | 970 | return -1; |
974 | } | 971 | } |
975 | total += nwrote; | 972 | } |
973 | GZ_gzReadClose(); | ||
974 | return 0; | ||
975 | }*/ | ||
976 | |||
977 | extern int inflate(int in, int out) | ||
978 | { | ||
979 | ssize_t nwrote; | ||
980 | GZ_gzReadOpen(in, 0, 0); | ||
981 | while(1) { | ||
982 | int ret = inflate_get_next_window(); | ||
983 | nwrote = full_write(out, gunzip_window, gunzip_outbuf_count); | ||
984 | if (nwrote == -1) { | ||
985 | perror_msg("write"); | ||
986 | return -1; | ||
987 | } | ||
988 | if (ret == 0) break; | ||
976 | } | 989 | } |
977 | GZ_gzReadClose(); | 990 | GZ_gzReadClose(); |
978 | return 0; | 991 | return 0; |
diff --git a/archival/libunarchive/unzip.c b/archival/libunarchive/unzip.c index 7ebbd0ee7..d8d5b77b1 100644 --- a/archival/libunarchive/unzip.c +++ b/archival/libunarchive/unzip.c | |||
@@ -14,6 +14,8 @@ | |||
14 | * General cleanup to better adhere to the style guide and make use of standard | 14 | * General cleanup to better adhere to the style guide and make use of standard |
15 | * busybox functions by Glenn McGrath <bug1@optushome.com.au> | 15 | * busybox functions by Glenn McGrath <bug1@optushome.com.au> |
16 | * | 16 | * |
17 | * read_gz interface + associated hacking by Laurence Anderson | ||
18 | * | ||
17 | * This program is free software; you can redistribute it and/or modify | 19 | * This program is free software; you can redistribute it and/or modify |
18 | * it under the terms of the GNU General Public License as published by | 20 | * it under the terms of the GNU General Public License as published by |
19 | * the Free Software Foundation; either version 2 of the License, or | 21 | * the Free Software Foundation; either version 2 of the License, or |
@@ -92,20 +94,15 @@ unsigned char *gunzip_in_buffer; | |||
92 | /* gunzip_window size--must be a power of two, and | 94 | /* gunzip_window size--must be a power of two, and |
93 | * at least 32K for zip's deflate method */ | 95 | * at least 32K for zip's deflate method */ |
94 | static const int gunzip_wsize = 0x8000; | 96 | static const int gunzip_wsize = 0x8000; |
95 | static int output_buffer_size = 0x8000; // gunzip_wsize initially | ||
96 | 97 | ||
97 | static unsigned char *gunzip_window; | 98 | static unsigned char *gunzip_window; |
98 | static unsigned int *gunzip_crc_table; | 99 | static unsigned int *gunzip_crc_table; |
99 | unsigned int gunzip_crc; | 100 | unsigned int gunzip_crc; |
100 | 101 | ||
101 | static unsigned char *output_buffer; | ||
102 | static unsigned int output_buffer_len; | ||
103 | |||
104 | /* If BMAX needs to be larger than 16, then h and x[] should be ulg. */ | 102 | /* If BMAX needs to be larger than 16, then h and x[] should be ulg. */ |
105 | #define BMAX 16 /* maximum bit length of any code (16 for explode) */ | 103 | #define BMAX 16 /* maximum bit length of any code (16 for explode) */ |
106 | #define N_MAX 288 /* maximum number of codes in any set */ | 104 | #define N_MAX 288 /* maximum number of codes in any set */ |
107 | 105 | ||
108 | static unsigned int gunzip_hufts; /* track memory usage */ | ||
109 | static unsigned int gunzip_bb; /* bit buffer */ | 106 | static unsigned int gunzip_bb; /* bit buffer */ |
110 | static unsigned char gunzip_bk; /* bits in bit buffer */ | 107 | static unsigned char gunzip_bk; /* bits in bit buffer */ |
111 | 108 | ||
@@ -343,7 +340,6 @@ static int huft_build(unsigned int *b, const unsigned int n, | |||
343 | /* allocate and link in new table */ | 340 | /* allocate and link in new table */ |
344 | q = (huft_t *) xmalloc((z + 1) * sizeof(huft_t)); | 341 | q = (huft_t *) xmalloc((z + 1) * sizeof(huft_t)); |
345 | 342 | ||
346 | gunzip_hufts += z + 1; /* track memory usage */ | ||
347 | *t = q + 1; /* link to list for huft_free() */ | 343 | *t = q + 1; /* link to list for huft_free() */ |
348 | *(t = &(q->v.t)) = NULL; | 344 | *(t = &(q->v.t)) = NULL; |
349 | u[h] = ++q; /* table starts after link */ | 345 | u[h] = ++q; /* table starts after link */ |
@@ -395,36 +391,6 @@ static int huft_build(unsigned int *b, const unsigned int n, | |||
395 | return y != 0 && g != 1; | 391 | return y != 0 && g != 1; |
396 | } | 392 | } |
397 | 393 | ||
398 | /* =========================================================================== | ||
399 | * Write the output gunzip_window gunzip_window[0..gunzip_outbuf_count-1] and update crc and gunzip_bytes_out. | ||
400 | * (Used for the decompressed data only.) | ||
401 | */ | ||
402 | static void flush_gunzip_window(void) | ||
403 | { | ||
404 | int n; | ||
405 | |||
406 | for (n = 0; n < gunzip_outbuf_count; n++) { | ||
407 | gunzip_crc = gunzip_crc_table[((int) gunzip_crc ^ (gunzip_window[n])) & 0xff] ^ (gunzip_crc >> 8); | ||
408 | } | ||
409 | |||
410 | if (output_buffer_len == 0) { // Our buffer is empty -> straight memcpy | ||
411 | memcpy(output_buffer, gunzip_window, gunzip_outbuf_count); | ||
412 | output_buffer_len = gunzip_outbuf_count; | ||
413 | } else { // Bit more complicated, append to end of output_buffer, realloc as necessary | ||
414 | int newlen = output_buffer_len + gunzip_outbuf_count; | ||
415 | if (newlen > output_buffer_size) { | ||
416 | output_buffer = xrealloc(output_buffer, newlen); // Could free later, but as we now have the memory... | ||
417 | //printf("Using %d byte output buffer\n", newlen); | ||
418 | output_buffer_size = newlen; | ||
419 | } | ||
420 | memcpy(output_buffer + output_buffer_len, gunzip_window, gunzip_outbuf_count); | ||
421 | output_buffer_len += gunzip_outbuf_count; | ||
422 | } | ||
423 | |||
424 | gunzip_bytes_out += gunzip_outbuf_count; | ||
425 | gunzip_outbuf_count = 0; | ||
426 | } | ||
427 | |||
428 | /* | 394 | /* |
429 | * inflate (decompress) the codes in a deflated (compressed) block. | 395 | * inflate (decompress) the codes in a deflated (compressed) block. |
430 | * Return an error code or zero if it all goes ok. | 396 | * Return an error code or zero if it all goes ok. |
@@ -468,7 +434,7 @@ static int inflate_codes(huft_t * my_tl, huft_t * my_td, const unsigned int my_b | |||
468 | if ((e = (t = tl + ((unsigned) b & ml))->e) > 16) | 434 | if ((e = (t = tl + ((unsigned) b & ml))->e) > 16) |
469 | do { | 435 | do { |
470 | if (e == 99) { | 436 | if (e == 99) { |
471 | return 1; | 437 | error_msg_and_die("inflate_codes error 1");; |
472 | } | 438 | } |
473 | b >>= t->b; | 439 | b >>= t->b; |
474 | k -= t->b; | 440 | k -= t->b; |
@@ -484,7 +450,7 @@ static int inflate_codes(huft_t * my_tl, huft_t * my_td, const unsigned int my_b | |||
484 | gunzip_outbuf_count = (w); | 450 | gunzip_outbuf_count = (w); |
485 | //flush_gunzip_window(); | 451 | //flush_gunzip_window(); |
486 | w = 0; | 452 | w = 0; |
487 | return -1; | 453 | return 1; // We have a block to read |
488 | } | 454 | } |
489 | } else { /* it's an EOB or a length */ | 455 | } else { /* it's an EOB or a length */ |
490 | 456 | ||
@@ -504,7 +470,7 @@ static int inflate_codes(huft_t * my_tl, huft_t * my_td, const unsigned int my_b | |||
504 | if ((e = (t = td + ((unsigned) b & md))->e) > 16) | 470 | if ((e = (t = td + ((unsigned) b & md))->e) > 16) |
505 | do { | 471 | do { |
506 | if (e == 99) | 472 | if (e == 99) |
507 | return 1; | 473 | error_msg_and_die("inflate_codes error 2");; |
508 | b >>= t->b; | 474 | b >>= t->b; |
509 | k -= t->b; | 475 | k -= t->b; |
510 | e -= 16; | 476 | e -= 16; |
@@ -542,7 +508,7 @@ do_copy: do { | |||
542 | else resumeCopy = 0; | 508 | else resumeCopy = 0; |
543 | //flush_gunzip_window(); | 509 | //flush_gunzip_window(); |
544 | w = 0; | 510 | w = 0; |
545 | return -1; | 511 | return 1; |
546 | } | 512 | } |
547 | } while (n); | 513 | } while (n); |
548 | resumeCopy = 0; | 514 | resumeCopy = 0; |
@@ -563,7 +529,7 @@ do_copy: do { | |||
563 | return 0; | 529 | return 0; |
564 | } | 530 | } |
565 | 531 | ||
566 | int inflate_stored(int my_n, int my_b_stored, int my_k_stored, int setup) | 532 | static int inflate_stored(int my_n, int my_b_stored, int my_k_stored, int setup) |
567 | { | 533 | { |
568 | static int n, b_stored, k_stored, w; | 534 | static int n, b_stored, k_stored, w; |
569 | if (setup) { | 535 | if (setup) { |
@@ -584,7 +550,7 @@ int inflate_stored(int my_n, int my_b_stored, int my_k_stored, int setup) | |||
584 | w = 0; | 550 | w = 0; |
585 | b_stored >>= 8; | 551 | b_stored >>= 8; |
586 | k_stored -= 8; | 552 | k_stored -= 8; |
587 | return -1; // Means more stuff 2do | 553 | return 1; // We have a block |
588 | } | 554 | } |
589 | b_stored >>= 8; | 555 | b_stored >>= 8; |
590 | k_stored -= 8; | 556 | k_stored -= 8; |
@@ -866,51 +832,85 @@ static int inflate_block(int *e) | |||
866 | } | 832 | } |
867 | default: | 833 | default: |
868 | /* bad block type */ | 834 | /* bad block type */ |
869 | error_msg("bad block type %d\n", t); | 835 | error_msg_and_die("bad block type %d\n", t); |
870 | return 2; | 836 | } |
837 | } | ||
838 | |||
839 | static void calculate_gunzip_crc(void) | ||
840 | { | ||
841 | int n; | ||
842 | for (n = 0; n < gunzip_outbuf_count; n++) { | ||
843 | gunzip_crc = gunzip_crc_table[((int) gunzip_crc ^ (gunzip_window[n])) & 0xff] ^ (gunzip_crc >> 8); | ||
844 | } | ||
845 | gunzip_bytes_out += gunzip_outbuf_count; | ||
846 | } | ||
847 | |||
848 | static int inflate_get_next_window(void) | ||
849 | { | ||
850 | static int needAnotherBlock = 1; | ||
851 | static int method = -1; // Method == -1 for stored, -2 for codes | ||
852 | static int e = 0; | ||
853 | |||
854 | gunzip_outbuf_count = 0; | ||
855 | |||
856 | while(1) { | ||
857 | int ret; | ||
858 | |||
859 | if (needAnotherBlock) { | ||
860 | if(e) { calculate_gunzip_crc(); return 0; } // Last block | ||
861 | method = inflate_block(&e); | ||
862 | needAnotherBlock = 0; | ||
863 | } | ||
864 | |||
865 | switch (method) { | ||
866 | case -1: ret = inflate_stored(0,0,0,0); | ||
867 | break; | ||
868 | case -2: ret = inflate_codes(0,0,0,0,0); | ||
869 | break; | ||
870 | default: error_msg_and_die("inflate error %d", method); | ||
871 | } | ||
872 | |||
873 | if (ret == 1) { | ||
874 | calculate_gunzip_crc(); | ||
875 | return 1; // More data left | ||
876 | } else needAnotherBlock = 1; // End of that block | ||
871 | } | 877 | } |
872 | } | 878 | } |
873 | 879 | ||
874 | /* | 880 | /* |
875 | * decompress an inflated entry | 881 | * User functions |
876 | * | 882 | * |
877 | * GLOBAL VARIABLES: gunzip_outbuf_count, bk, gunzip_bb, hufts, inptr | 883 | * read_gz, GZ_gzReadOpen, GZ_gzReadClose, inflate |
878 | */ | 884 | */ |
879 | 885 | ||
880 | extern ssize_t read_gz(int fd, void *buf, size_t count) | 886 | extern ssize_t read_gz(int fd, void *buf, size_t count) |
881 | { | 887 | { |
882 | static int e = 0; /* last block flag */ | 888 | static int morebytes = 0, finished = 0; |
883 | int r; /* result code */ | 889 | |
884 | unsigned h = 0; /* maximum struct huft's malloc'ed */ | 890 | if (morebytes) { |
885 | ssize_t written = count; | 891 | int bytesRead = morebytes > count ? count : morebytes; |
886 | static char *output_buffer_ptr = 0; | 892 | memcpy(buf, gunzip_window + (gunzip_outbuf_count - morebytes), bytesRead); |
887 | 893 | morebytes -= bytesRead; | |
888 | while (output_buffer_len == 0) { // We need more data | 894 | return bytesRead; |
889 | if (e) return 0; // No more data here! | 895 | } else if (finished) { |
890 | gunzip_hufts = 0; | 896 | return 0; |
891 | r = inflate_block(&e); | 897 | } else if (count >= 0x8000) { // We can decompress direcly to the buffer, 32k at a time |
892 | if (r == -1) { // Call inflate_stored while returning -1 | 898 | // Could decompress to larger buffer, but it must be a power of 2, and calculating that is probably more expensive than the benefit |
893 | while(inflate_stored(0,0,0,0) == -1) flush_gunzip_window(); | 899 | unsigned char *old_gunzip_window = gunzip_window; // Save old window |
894 | } else if (r == -2) { // Call inflate_codes while returning -1 | 900 | gunzip_window = buf; |
895 | while(inflate_codes(0,0,0,0,0) == -1) flush_gunzip_window(); | 901 | if (inflate_get_next_window() == 0) finished = 1; |
896 | } else { | 902 | gunzip_window = old_gunzip_window; // Restore old window |
897 | error_msg_and_die("inflate error %d", r); | 903 | return gunzip_outbuf_count; |
898 | return -1; | 904 | } else { // Oh well, need to split up the gunzip_window |
899 | } | 905 | int bytesRead; |
900 | if (gunzip_hufts > h) { | 906 | if (inflate_get_next_window() == 0) finished = 1; |
901 | h = gunzip_hufts; | 907 | morebytes = gunzip_outbuf_count; |
902 | } | 908 | bytesRead = morebytes > count ? count : morebytes; |
903 | if (e) { // Ok finished uncompressing, get any buffered uncompressed data | 909 | memcpy(buf, gunzip_window, bytesRead); |
904 | flush_gunzip_window(); | 910 | morebytes -= bytesRead; |
905 | } | 911 | return bytesRead; |
906 | output_buffer_ptr = output_buffer; | ||
907 | } | 912 | } |
908 | if (count > output_buffer_len) written = output_buffer_len; // We're only giving them as much as we have! | 913 | |
909 | memcpy(buf, output_buffer_ptr, written); | ||
910 | output_buffer_ptr += written; | ||
911 | output_buffer_len -= written; | ||
912 | |||
913 | return written; | ||
914 | } | 914 | } |
915 | 915 | ||
916 | extern void GZ_gzReadOpen(int fd, void *unused, int nUnused) | 916 | extern void GZ_gzReadOpen(int fd, void *unused, int nUnused) |
@@ -919,7 +919,6 @@ extern void GZ_gzReadOpen(int fd, void *unused, int nUnused) | |||
919 | 919 | ||
920 | /* Allocate all global buffers (for DYN_ALLOC option) */ | 920 | /* Allocate all global buffers (for DYN_ALLOC option) */ |
921 | gunzip_window = xmalloc(gunzip_wsize); | 921 | gunzip_window = xmalloc(gunzip_wsize); |
922 | output_buffer = xmalloc(gunzip_wsize); | ||
923 | gunzip_outbuf_count = 0; | 922 | gunzip_outbuf_count = 0; |
924 | gunzip_bytes_out = 0; | 923 | gunzip_bytes_out = 0; |
925 | gunzip_src_fd = fd; | 924 | gunzip_src_fd = fd; |
@@ -938,7 +937,6 @@ extern void GZ_gzReadClose(void) | |||
938 | { | 937 | { |
939 | /* Cleanup */ | 938 | /* Cleanup */ |
940 | free(gunzip_window); | 939 | free(gunzip_window); |
941 | free(output_buffer); | ||
942 | free(gunzip_crc_table); | 940 | free(gunzip_crc_table); |
943 | 941 | ||
944 | /* Store unused bytes in a global buffer so calling applets can access it */ | 942 | /* Store unused bytes in a global buffer so calling applets can access it */ |
@@ -953,11 +951,10 @@ extern void GZ_gzReadClose(void) | |||
953 | } | 951 | } |
954 | } | 952 | } |
955 | 953 | ||
956 | extern int inflate(int in, int out) | 954 | /*extern int inflate(int in, int out) // Useful for testing read_gz |
957 | { | 955 | { |
958 | char buf[8192]; | 956 | char buf[8192]; |
959 | ssize_t nread, nwrote; | 957 | ssize_t nread, nwrote; |
960 | ssize_t total = 0; | ||
961 | 958 | ||
962 | GZ_gzReadOpen(in, 0, 0); | 959 | GZ_gzReadOpen(in, 0, 0); |
963 | while(1) { // Robbed from copyfd.c | 960 | while(1) { // Robbed from copyfd.c |
@@ -972,7 +969,23 @@ extern int inflate(int in, int out) | |||
972 | perror_msg("write"); | 969 | perror_msg("write"); |
973 | return -1; | 970 | return -1; |
974 | } | 971 | } |
975 | total += nwrote; | 972 | } |
973 | GZ_gzReadClose(); | ||
974 | return 0; | ||
975 | }*/ | ||
976 | |||
977 | extern int inflate(int in, int out) | ||
978 | { | ||
979 | ssize_t nwrote; | ||
980 | GZ_gzReadOpen(in, 0, 0); | ||
981 | while(1) { | ||
982 | int ret = inflate_get_next_window(); | ||
983 | nwrote = full_write(out, gunzip_window, gunzip_outbuf_count); | ||
984 | if (nwrote == -1) { | ||
985 | perror_msg("write"); | ||
986 | return -1; | ||
987 | } | ||
988 | if (ret == 0) break; | ||
976 | } | 989 | } |
977 | GZ_gzReadClose(); | 990 | GZ_gzReadClose(); |
978 | return 0; | 991 | return 0; |