aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGlenn L McGrath <bug1@ihug.co.nz>2002-11-20 22:00:31 +0000
committerGlenn L McGrath <bug1@ihug.co.nz>2002-11-20 22:00:31 +0000
commit83bf47c02f95a9956eb4f6a185014ab0fb62670b (patch)
tree058d3c3d2e7b167bd384128583fc248fe7dafa52
parent0126fda5bbb01fef3e6de07c8f4619863d606f50 (diff)
downloadbusybox-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.c177
-rw-r--r--archival/libunarchive/unzip.c177
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 */
94static const int gunzip_wsize = 0x8000; 96static const int gunzip_wsize = 0x8000;
95static int output_buffer_size = 0x8000; // gunzip_wsize initially
96 97
97static unsigned char *gunzip_window; 98static unsigned char *gunzip_window;
98static unsigned int *gunzip_crc_table; 99static unsigned int *gunzip_crc_table;
99unsigned int gunzip_crc; 100unsigned int gunzip_crc;
100 101
101static unsigned char *output_buffer;
102static 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
108static unsigned int gunzip_hufts; /* track memory usage */
109static unsigned int gunzip_bb; /* bit buffer */ 106static unsigned int gunzip_bb; /* bit buffer */
110static unsigned char gunzip_bk; /* bits in bit buffer */ 107static 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 */
402static 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
566int inflate_stored(int my_n, int my_b_stored, int my_k_stored, int setup) 532static 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
839static 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
848static 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
880extern ssize_t read_gz(int fd, void *buf, size_t count) 886extern 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
916extern void GZ_gzReadOpen(int fd, void *unused, int nUnused) 916extern 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
956extern 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
977extern 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 */
94static const int gunzip_wsize = 0x8000; 96static const int gunzip_wsize = 0x8000;
95static int output_buffer_size = 0x8000; // gunzip_wsize initially
96 97
97static unsigned char *gunzip_window; 98static unsigned char *gunzip_window;
98static unsigned int *gunzip_crc_table; 99static unsigned int *gunzip_crc_table;
99unsigned int gunzip_crc; 100unsigned int gunzip_crc;
100 101
101static unsigned char *output_buffer;
102static 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
108static unsigned int gunzip_hufts; /* track memory usage */
109static unsigned int gunzip_bb; /* bit buffer */ 106static unsigned int gunzip_bb; /* bit buffer */
110static unsigned char gunzip_bk; /* bits in bit buffer */ 107static 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 */
402static 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
566int inflate_stored(int my_n, int my_b_stored, int my_k_stored, int setup) 532static 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
839static 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
848static 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
880extern ssize_t read_gz(int fd, void *buf, size_t count) 886extern 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
916extern void GZ_gzReadOpen(int fd, void *unused, int nUnused) 916extern 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
956extern 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
977extern 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;