summaryrefslogtreecommitdiff
path: root/contrib/puff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-xcontrib/puff/puffbin0 -> 17344 bytes
-rw-r--r--contrib/puff/puff.c193
-rw-r--r--contrib/puff/puff.h4
3 files changed, 151 insertions, 46 deletions
diff --git a/contrib/puff/puff b/contrib/puff/puff
new file mode 100755
index 0000000..bedac26
--- /dev/null
+++ b/contrib/puff/puff
Binary files differ
diff --git a/contrib/puff/puff.c b/contrib/puff/puff.c
index ce0cc40..df5b79f 100644
--- a/contrib/puff/puff.c
+++ b/contrib/puff/puff.c
@@ -1,8 +1,8 @@
1/* 1/*
2 * puff.c 2 * puff.c
3 * Copyright (C) 2002-2004 Mark Adler 3 * Copyright (C) 2002-2008 Mark Adler
4 * For conditions of distribution and use, see copyright notice in puff.h 4 * For conditions of distribution and use, see copyright notice in puff.h
5 * version 1.8, 9 Jan 2004 5 * version 2.0, 25 Jul 2008
6 * 6 *
7 * puff.c is a simple inflate written to be an unambiguous way to specify the 7 * puff.c is a simple inflate written to be an unambiguous way to specify the
8 * deflate format. It is not written for speed but rather simplicity. As a 8 * deflate format. It is not written for speed but rather simplicity. As a
@@ -61,6 +61,12 @@
61 * 1.7 3 Mar 2003 - Added test code for distribution 61 * 1.7 3 Mar 2003 - Added test code for distribution
62 * - Added zlib-like license 62 * - Added zlib-like license
63 * 1.8 9 Jan 2004 - Added some comments on no distance codes case 63 * 1.8 9 Jan 2004 - Added some comments on no distance codes case
64 * 1.9 21 Feb 2008 - Fix bug on 16-bit integer architectures [Pohland]
65 * - Catch missing end-of-block symbol error
66 * 2.0 25 Jul 2008 - Add #define to permit distance too far back
67 * - Add option in TEST code for puff to write the data
68 * - Add option in TEST code to skip input bytes
69 * - Allow TEST code to read from piped stdin
64 */ 70 */
65 71
66#include <setjmp.h> /* for setjmp(), longjmp(), and jmp_buf */ 72#include <setjmp.h> /* for setjmp(), longjmp(), and jmp_buf */
@@ -194,7 +200,7 @@ struct huffman {
194 * Decode a code from the stream s using huffman table h. Return the symbol or 200 * Decode a code from the stream s using huffman table h. Return the symbol or
195 * a negative value if there is an error. If all of the lengths are zero, i.e. 201 * a negative value if there is an error. If all of the lengths are zero, i.e.
196 * an empty code, or if the code is incomplete and an invalid code is received, 202 * an empty code, or if the code is incomplete and an invalid code is received,
197 * then -9 is returned after reading MAXBITS bits. 203 * then -10 is returned after reading MAXBITS bits.
198 * 204 *
199 * Format notes: 205 * Format notes:
200 * 206 *
@@ -226,14 +232,14 @@ local int decode(struct state *s, struct huffman *h)
226 for (len = 1; len <= MAXBITS; len++) { 232 for (len = 1; len <= MAXBITS; len++) {
227 code |= bits(s, 1); /* get next bit */ 233 code |= bits(s, 1); /* get next bit */
228 count = h->count[len]; 234 count = h->count[len];
229 if (code < first + count) /* if length len, return symbol */ 235 if (code - count < first) /* if length len, return symbol */
230 return h->symbol[index + (code - first)]; 236 return h->symbol[index + (code - first)];
231 index += count; /* else update for next length */ 237 index += count; /* else update for next length */
232 first += count; 238 first += count;
233 first <<= 1; 239 first <<= 1;
234 code <<= 1; 240 code <<= 1;
235 } 241 }
236 return -9; /* ran out of codes */ 242 return -10; /* ran out of codes */
237} 243}
238 244
239/* 245/*
@@ -263,7 +269,7 @@ local int decode(struct state *s, struct huffman *h)
263 code |= bitbuf & 1; 269 code |= bitbuf & 1;
264 bitbuf >>= 1; 270 bitbuf >>= 1;
265 count = *next++; 271 count = *next++;
266 if (code < first + count) { /* if length len, return symbol */ 272 if (code - count < first) { /* if length len, return symbol */
267 s->bitbuf = bitbuf; 273 s->bitbuf = bitbuf;
268 s->bitcnt = (s->bitcnt - len) & 7; 274 s->bitcnt = (s->bitcnt - len) & 7;
269 return h->symbol[index + (code - first)]; 275 return h->symbol[index + (code - first)];
@@ -280,7 +286,7 @@ local int decode(struct state *s, struct huffman *h)
280 bitbuf = s->in[s->incnt++]; 286 bitbuf = s->in[s->incnt++];
281 if (left > 8) left = 8; 287 if (left > 8) left = 8;
282 } 288 }
283 return -9; /* ran out of codes */ 289 return -10; /* ran out of codes */
284} 290}
285#endif /* SLOW */ 291#endif /* SLOW */
286 292
@@ -448,21 +454,27 @@ local int codes(struct state *s,
448 else if (symbol > 256) { /* length */ 454 else if (symbol > 256) { /* length */
449 /* get and compute length */ 455 /* get and compute length */
450 symbol -= 257; 456 symbol -= 257;
451 if (symbol >= 29) return -9; /* invalid fixed code */ 457 if (symbol >= 29) return -10; /* invalid fixed code */
452 len = lens[symbol] + bits(s, lext[symbol]); 458 len = lens[symbol] + bits(s, lext[symbol]);
453 459
454 /* get and check distance */ 460 /* get and check distance */
455 symbol = decode(s, distcode); 461 symbol = decode(s, distcode);
456 if (symbol < 0) return symbol; /* invalid symbol */ 462 if (symbol < 0) return symbol; /* invalid symbol */
457 dist = dists[symbol] + bits(s, dext[symbol]); 463 dist = dists[symbol] + bits(s, dext[symbol]);
464#ifndef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
458 if (dist > s->outcnt) 465 if (dist > s->outcnt)
459 return -10; /* distance too far back */ 466 return -11; /* distance too far back */
467#endif
460 468
461 /* copy length bytes from distance bytes back */ 469 /* copy length bytes from distance bytes back */
462 if (s->out != NIL) { 470 if (s->out != NIL) {
463 if (s->outcnt + len > s->outlen) return 1; 471 if (s->outcnt + len > s->outlen) return 1;
464 while (len--) { 472 while (len--) {
465 s->out[s->outcnt] = s->out[s->outcnt - dist]; 473 s->out[s->outcnt] =
474#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
475 dist > s->outcnt ? 0 :
476#endif
477 s->out[s->outcnt - dist];
466 s->outcnt++; 478 s->outcnt++;
467 } 479 }
468 } 480 }
@@ -680,6 +692,10 @@ local int dynamic(struct state *s)
680 } 692 }
681 } 693 }
682 694
695 /* check for end-of-block code -- there better be one! */
696 if (lengths[256] == 0)
697 return -9;
698
683 /* build huffman table for literal/length codes */ 699 /* build huffman table for literal/length codes */
684 err = construct(&lencode, lengths, nlen); 700 err = construct(&lencode, lengths, nlen);
685 if (err < 0 || (err > 0 && nlen - lencode.count[0] != 1)) 701 if (err < 0 || (err > 0 && nlen - lencode.count[0] != 1))
@@ -724,8 +740,9 @@ local int dynamic(struct state *s)
724 * -6: dynamic block code description: repeat more than specified lengths 740 * -6: dynamic block code description: repeat more than specified lengths
725 * -7: dynamic block code description: invalid literal/length code lengths 741 * -7: dynamic block code description: invalid literal/length code lengths
726 * -8: dynamic block code description: invalid distance code lengths 742 * -8: dynamic block code description: invalid distance code lengths
727 * -9: invalid literal/length or distance code in fixed or dynamic block 743 * -9: dynamic block code description: missing end-of-block code
728 * -10: distance is too far back in fixed or dynamic block 744 * -10: invalid literal/length or distance code in fixed or dynamic block
745 * -11: distance is too far back in fixed or dynamic block
729 * 746 *
730 * Format notes: 747 * Format notes:
731 * 748 *
@@ -783,54 +800,142 @@ int puff(unsigned char *dest, /* pointer to destination pointer */
783} 800}
784 801
785#ifdef TEST 802#ifdef TEST
786/* Example of how to use puff() */ 803/* Examples of how to use puff().
804
805 Usage: puff [-w] [-nnn] file
806 ... | puff [-w] [-nnn]
807
808 where file is the input file with deflate data, nnn is the number of bytes
809 of input to skip before inflating (e.g. to skip a zlib or gzip header), and
810 -w is used to write the decompressed data to stdout */
811
787#include <stdio.h> 812#include <stdio.h>
788#include <stdlib.h> 813#include <stdlib.h>
789#include <sys/types.h>
790#include <sys/stat.h>
791 814
792local unsigned char *yank(char *name, unsigned long *len) 815/* Return size times approximately the cube root of 2, keeping the result as 1,
816 3, or 5 times a power of 2 -- the result is always > size, until the result
817 is the maximum value of an unsigned long, where it remains. This is useful
818 to keep reallocations less than ~33% over the actual data. */
819local size_t bythirds(size_t size)
793{ 820{
794 unsigned long size; 821 int n;
795 unsigned char *buf; 822 size_t m;
823
824 m = size;
825 for (n = 0; m; n++)
826 m >>= 1;
827 if (n < 3)
828 return size + 1;
829 n -= 3;
830 m = size >> n;
831 m += m == 6 ? 2 : 1;
832 m <<= n;
833 return m > size ? m : (size_t)(-1);
834}
835
836/* Read the input file *name, or stdin if name is NULL, into allocated memory.
837 Reallocate to larger buffers until the entire file is read in. Return a
838 pointer to the allocated data, or NULL if there was a memory allocation
839 failure. *len is the number of bytes of data read from the input file (even
840 if load() returns NULL). If the input file was empty or could not be opened
841 or read, *len is zero. */
842local void *load(char *name, size_t *len)
843{
844 size_t size;
845 void *buf, *swap;
796 FILE *in; 846 FILE *in;
797 struct stat s;
798 847
799 *len = 0; 848 *len = 0;
800 if (stat(name, &s)) return NULL; 849 buf = malloc(size = 4096);
801 if ((s.st_mode & S_IFMT) != S_IFREG) return NULL; 850 if (buf == NULL)
802 size = (unsigned long)(s.st_size); 851 return NULL;
803 if (size == 0 || (off_t)size != s.st_size) return NULL; 852 in = name == NULL ? stdin : fopen(name, "rb");
804 in = fopen(name, "r"); 853 if (in != NULL) {
805 if (in == NULL) return NULL; 854 for (;;) {
806 buf = malloc(size); 855 *len += fread((char *)buf + *len, 1, size - *len, in);
807 if (buf != NULL && fread(buf, 1, size, in) != size) { 856 if (*len < size) break;
808 free(buf); 857 size = bythirds(size);
809 buf = NULL; 858 if (size == *len || (swap = realloc(buf, size)) == NULL) {
859 free(buf);
860 buf = NULL;
861 break;
862 }
863 buf = swap;
864 }
865 fclose(in);
810 } 866 }
811 fclose(in);
812 *len = size;
813 return buf; 867 return buf;
814} 868}
815 869
816int main(int argc, char **argv) 870int main(int argc, char **argv)
817{ 871{
818 int ret; 872 int ret, skip = 0, put = 0;
819 unsigned char *source; 873 char *arg, *name = NULL;
820 unsigned long len, sourcelen, destlen; 874 unsigned char *source = NULL, *dest;
821 875 size_t len = 0;
822 if (argc < 2) return 2; 876 unsigned long sourcelen, destlen;
823 source = yank(argv[1], &len); 877
824 if (source == NULL) return 2; 878 /* process arguments */
825 sourcelen = len; 879 while (arg = *++argv, --argc)
826 ret = puff(NIL, &destlen, source, &sourcelen); 880 if (arg[0] == '-') {
881 if (arg[1] == 'w' && arg[2] == 0)
882 put = 1;
883 else if (arg[1] >= '0' && arg[1] <= '9')
884 skip = atoi(arg + 1);
885 else {
886 fprintf(stderr, "invalid option %s\n", arg);
887 return 3;
888 }
889 }
890 else if (name != NULL) {
891 fprintf(stderr, "only one file name allowed\n");
892 return 3;
893 }
894 else
895 name = arg;
896 source = load(name, &len);
897 if (source == NULL) {
898 fprintf(stderr, "memory allocation failure\n");
899 return 4;
900 }
901 if (len == 0) {
902 fprintf(stderr, "could not read %s, or it was empty\n",
903 name == NULL ? "<stdin>" : name);
904 free(source);
905 return 3;
906 }
907 if (skip >= len) {
908 fprintf(stderr, "skip request of %d leaves no input\n", skip);
909 free(source);
910 return 3;
911 }
912
913 /* test inflate data with offset skip */
914 len -= skip;
915 sourcelen = (unsigned long)len;
916 ret = puff(NIL, &destlen, source + skip, &sourcelen);
827 if (ret) 917 if (ret)
828 printf("puff() failed with return code %d\n", ret); 918 fprintf(stderr, "puff() failed with return code %d\n", ret);
829 else { 919 else {
830 printf("puff() succeeded uncompressing %lu bytes\n", destlen); 920 fprintf(stderr, "puff() succeeded uncompressing %lu bytes\n", destlen);
831 if (sourcelen < len) printf("%lu compressed bytes unused\n", 921 if (sourcelen < len) fprintf(stderr, "%lu compressed bytes unused\n",
832 len - sourcelen); 922 len - sourcelen);
833 } 923 }
924
925 /* if requested, inflate again and write decompressd data to stdout */
926 if (put) {
927 dest = malloc(destlen);
928 if (dest == NULL) {
929 fprintf(stderr, "memory allocation failure\n");
930 free(source);
931 return 4;
932 }
933 puff(dest, &destlen, source + skip, &sourcelen);
934 fwrite(dest, 1, destlen, stdout);
935 free(dest);
936 }
937
938 /* clean up */
834 free(source); 939 free(source);
835 return ret; 940 return ret;
836} 941}
diff --git a/contrib/puff/puff.h b/contrib/puff/puff.h
index ef61252..8d7f5f8 100644
--- a/contrib/puff/puff.h
+++ b/contrib/puff/puff.h
@@ -1,6 +1,6 @@
1/* puff.h 1/* puff.h
2 Copyright (C) 2002, 2003 Mark Adler, all rights reserved 2 Copyright (C) 2002-2008 Mark Adler, all rights reserved
3 version 1.7, 3 Mar 2002 3 version 1.9, 10 Jan 2008
4 4
5 This software is provided 'as-is', without any express or implied 5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the author be held liable for any damages 6 warranty. In no event will the author be held liable for any damages