diff options
author | Kitty Draper | 2011-03-05 21:39:25 -0500 |
---|---|---|
committer | Kitty Draper | 2011-03-05 21:39:25 -0500 |
commit | d40ae99422e118188a7f48055dc340c6aca022aa (patch) | |
tree | 83ab93f49fd9e66e43bcd824091ae1dbcaa0c173 /source/unzip | |
download | snesemu-d40ae99422e118188a7f48055dc340c6aca022aa.tar.gz snesemu-d40ae99422e118188a7f48055dc340c6aca022aa.tar.bz2 snesemu-d40ae99422e118188a7f48055dc340c6aca022aa.zip |
first commit
Diffstat (limited to 'source/unzip')
-rw-r--r-- | source/unzip/explode.c | 1120 | ||||
-rw-r--r-- | source/unzip/unreduce.c | 217 | ||||
-rw-r--r-- | source/unzip/unshrink.c | 177 | ||||
-rw-r--r-- | source/unzip/unz.h | 994 | ||||
-rw-r--r-- | source/unzip/unzip.c | 1224 | ||||
-rw-r--r-- | source/unzip/unzip.h | 285 | ||||
-rw-r--r-- | source/unzip/unzipP.h | 125 |
7 files changed, 4142 insertions, 0 deletions
diff --git a/source/unzip/explode.c b/source/unzip/explode.c new file mode 100644 index 0000000..6558a7b --- /dev/null +++ b/source/unzip/explode.c @@ -0,0 +1,1120 @@ +/* explode.c -- Not copyrighted 1992 by Mark Adler + version c7, 27 June 1992 */ + + +/* You can do whatever you like with this source file, though I would + prefer that if you modify it and redistribute it that you include + comments to that effect with your name and the date. Thank you. + + History: + vers date who what + ---- --------- -------------- ------------------------------------ + c1 30 Mar 92 M. Adler explode that uses huft_build from inflate + (this gives over a 70% speed improvement + over the original unimplode.c, which + decoded a bit at a time) + c2 4 Apr 92 M. Adler fixed bug for file sizes a multiple of 32k. + c3 10 Apr 92 M. Adler added a little memory tracking if DEBUG + c4 11 Apr 92 M. Adler added NOMEMCPY do kill use of memcpy() + c5 21 Apr 92 M. Adler added the WSIZE #define to allow reducing + the 32K window size for specialized + applications. + c6 31 May 92 M. Adler added typecasts to eliminate some warnings + c7 27 Jun 92 G. Roelofs added more typecasts + */ + + +/* + Explode imploded (PKZIP method 6 compressed) data. This compression + method searches for as much of the current string of bytes (up to a length + of ~320) in the previous 4K or 8K bytes. If it doesn't find any matches + (of at least length 2 or 3), it codes the next byte. Otherwise, it codes + the length of the matched string and its distance backwards from the + current position. Single bytes ("literals") are preceded by a one (a + single bit) and are either uncoded (the eight bits go directly into the + compressed stream for a total of nine bits) or Huffman coded with a + supplied literal code tree. If literals are coded, then the minimum match + length is three, otherwise it is two. + + There are therefore four kinds of imploded streams: 8K search with coded + literals (min match = 3), 4K search with coded literals (min match = 3), + 8K with uncoded literals (min match = 2), and 4K with uncoded literals + (min match = 2). The kind of stream is identified in two bits of a + general purpose bit flag that is outside of the compressed stream. + + Distance-length pairs are always coded. Distance-length pairs for matched + strings are preceded by a zero bit (to distinguish them from literals) and + are always coded. The distance comes first and is either the low six (4K) + or low seven (8K) bits of the distance (uncoded), followed by the high six + bits of the distance coded. Then the length is six bits coded (0..63 + + min match length), and if the maximum such length is coded, then it's + followed by another eight bits (uncoded) to be added to the coded length. + This gives a match length range of 2..320 or 3..321 bytes. + + The literal, length, and distance codes are all represented in a slightly + compressed form themselves. What is sent are the lengths of the codes for + each value, which is sufficient to construct the codes. Each byte of the + code representation is the code length (the low four bits representing + 1..16), and the number of values sequentially with that length (the high + four bits also representing 1..16). There are 256 literal code values (if + literals are coded), 64 length code values, and 64 distance code values, + in that order at the beginning of the compressed stream. Each set of code + values is preceded (redundantly) with a byte indicating how many bytes are + in the code description that follows, in the range 1..256. + + The codes themselves are decoded using tables made by huft_build() from + the bit lengths. That routine and its comments are in the inflate.c + module. + */ + +#include "unz.h" /* this must supply the slide[] (byte) array */ +#include "unzipP.h" +//#include <stdlib.h> +#include "ds2_malloc.h" + +#ifndef WSIZE +# define WSIZE 0x8000 /* window size--must be a power of two, and at least + 8K for zip's implode method */ +#endif /* !WSIZE */ + + +struct huft { + byte e; /* number of extra bits or operation */ + byte b; /* number of bits in this code or subcode */ + union { + UWORD n; /* literal, length base, or distance base */ + struct huft *t; /* pointer to next level of table */ + } v; +}; + +/* Function prototypes */ +/* routines from inflate.c */ +extern unsigned hufts; +int huft_build OF((unsigned *, unsigned, unsigned, UWORD *, UWORD *, + struct huft **, int *)); +int huft_free OF((struct huft *)); +void flush OF((unsigned)); + +/* routines here */ +int get_tree OF((unsigned *, unsigned)); +int explode_lit8 OF((struct huft *, struct huft *, struct huft *, + int, int, int)); +int explode_lit4 OF((struct huft *, struct huft *, struct huft *, + int, int, int)); +int explode_nolit8 OF((struct huft *, struct huft *, int, int)); +int explode_nolit4 OF((struct huft *, struct huft *, int, int)); +int explode (); + +extern file_in_zip_read_info_s *pfile_in_zip_read_info; +extern unz_s *pUnzip; + +/* The implode algorithm uses a sliding 4K or 8K byte window on the + uncompressed stream to find repeated byte strings. This is implemented + here as a circular buffer. The index is updated simply by incrementing + and then and'ing with 0x0fff (4K-1) or 0x1fff (8K-1). Here, the 32K + buffer of inflate is used, and it works just as well to always have + a 32K circular buffer, so the index is anded with 0x7fff. This is + done to allow the window to also be used as the output buffer. */ +/* This must be supplied in an external module useable like "byte slide[8192];" + or "byte *slide;", where the latter would be malloc'ed. In unzip, slide[] + is actually a 32K area for use by inflate, which uses a 32K sliding window. + */ + + +/* Tables for length and distance */ +UWORD cplen2[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65}; +UWORD cplen3[] = {3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, + 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66}; +UWORD extra[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8}; +UWORD cpdist4[] = {1, 65, 129, 193, 257, 321, 385, 449, 513, 577, 641, 705, + 769, 833, 897, 961, 1025, 1089, 1153, 1217, 1281, 1345, 1409, 1473, + 1537, 1601, 1665, 1729, 1793, 1857, 1921, 1985, 2049, 2113, 2177, + 2241, 2305, 2369, 2433, 2497, 2561, 2625, 2689, 2753, 2817, 2881, + 2945, 3009, 3073, 3137, 3201, 3265, 3329, 3393, 3457, 3521, 3585, + 3649, 3713, 3777, 3841, 3905, 3969, 4033}; +UWORD cpdist8[] = {1, 129, 257, 385, 513, 641, 769, 897, 1025, 1153, 1281, + 1409, 1537, 1665, 1793, 1921, 2049, 2177, 2305, 2433, 2561, 2689, + 2817, 2945, 3073, 3201, 3329, 3457, 3585, 3713, 3841, 3969, 4097, + 4225, 4353, 4481, 4609, 4737, 4865, 4993, 5121, 5249, 5377, 5505, + 5633, 5761, 5889, 6017, 6145, 6273, 6401, 6529, 6657, 6785, 6913, + 7041, 7169, 7297, 7425, 7553, 7681, 7809, 7937, 8065}; + + +/* Macros for inflate() bit peeking and grabbing. + The usage is: + + NEEDBITS(j) + x = b & mask_bits[j]; + DUMPBITS(j) + + where NEEDBITS makes sure that b has at least j bits in it, and + DUMPBITS removes the bits from b. The macros use the variable k + for the number of bits in b. Normally, b and k are register + variables for speed. + */ + +extern UWORD bytebuf; /* (use the one in inflate.c) */ +#define NEXTBYTE (ReadByte(&bytebuf), bytebuf) +#define NEEDBITS(n) {while(k<(n)){b|=((ULONG)NEXTBYTE)<<k;k+=8;}} +#define DUMPBITS(n) {b>>=(n);k-=(n);} + +/* HERE */ +UWORD mask_bits[] = { + 0x0000, + 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, + 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff +}; +union work area; /* see unzip.h for the definition of work */ +ULONG crc32val; +ush bytebuf; +ULONG bitbuf; +int bits_left; +boolean zipeof; + +int get_tree(l, n) +unsigned *l; /* bit lengths */ +unsigned n; /* number expected */ +/* Get the bit lengths for a code representation from the compressed + stream. If get_tree() returns 4, then there is an error in the data. + Otherwise zero is returned. */ +{ + unsigned i; /* bytes remaining in list */ + unsigned k; /* lengths entered */ + unsigned j; /* number of codes */ + unsigned b; /* bit length for those codes */ + + + /* get bit lengths */ + ReadByte(&bytebuf); + i = bytebuf + 1; /* length/count pairs to read */ + k = 0; /* next code */ + do { + ReadByte(&bytebuf); + b = ((j = bytebuf) & 0xf) + 1; /* bits in code (1..16) */ + j = ((j & 0xf0) >> 4) + 1; /* codes with those bits (1..16) */ + if (k + j > n) + return 4; /* don't overflow l[] */ + do { + l[k++] = b; + } while (--j); + } while (--i); + return k != n ? 4 : 0; /* should have read n of them */ +} + + + +int explode_lit8(tb, tl, td, bb, bl, bd) +struct huft *tb, *tl, *td; /* literal, length, and distance tables */ +int bb, bl, bd; /* number of bits decoded by those */ +/* Decompress the imploded data using coded literals and an 8K sliding + window. */ +{ + longint s; /* bytes to decompress */ + register unsigned e; /* table entry flag/number of extra bits */ + unsigned n, d; /* length and index for copy */ + unsigned w; /* current window position */ + struct huft *t; /* pointer to table entry */ + unsigned mb, ml, md; /* masks for bb, bl, and bd bits */ + register ULONG b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + unsigned u; /* true if unflushed */ + + + /* explode the coded data */ + b = k = w = 0; /* initialize bit buffer, window */ + u = 1; /* buffer unflushed */ + mb = mask_bits[bb]; /* precompute masks for speed */ + ml = mask_bits[bl]; + md = mask_bits[bd]; + s = pUnzip->pfile_in_zip_read->rest_read_uncompressed; + while (s > 0) /* do until ucsize bytes uncompressed */ + { + NEEDBITS(1) + if (b & 1) /* then literal--decode it */ + { + DUMPBITS(1) + s--; + NEEDBITS((unsigned)bb) /* get coded literal */ + if ((e = (t = tb + ((~(unsigned)b) & mb))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + slide[w++] = (byte)t->v.n; + if (w == WSIZE) + { + flush(w); + w = u = 0; + } + } + else /* else distance/length */ + { + DUMPBITS(1) + NEEDBITS(7) /* get distance low bits */ + d = (unsigned)b & 0x7f; + DUMPBITS(7) + NEEDBITS((unsigned)bd) /* get coded distance high bits */ + if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + d = w - d - t->v.n; /* construct offset */ + NEEDBITS((unsigned)bl) /* get coded length */ + if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + n = t->v.n; + if (e) /* get length extra bits */ + { + NEEDBITS(8) + n += (unsigned)b & 0xff; + DUMPBITS(8) + } + + /* do the copy */ + s -= n; + do { + n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e); + if (u && w <= d) + { + memset(slide + w, 0, e); + w += e; + d += e; + } + else +#ifndef NOMEMCPY + if (w - d >= e) /* (this test assumes unsigned comparison) */ + { + memcpy(slide + w, slide + d, e); + w += e; + d += e; + } + else /* do it slow to avoid memcpy() overlap */ +#endif /* !NOMEMCPY */ + do { + slide[w++] = slide[d++]; + } while (--e); + if (w == WSIZE) + { + flush(w); + w = u = 0; + } + } while (n); + } + } + + /* flush out slide */ + flush(w); + return pfile_in_zip_read_info->rest_read_compressed ? 5 : 0; /* should have read csize bytes */ +} + + + +int explode_lit4(tb, tl, td, bb, bl, bd) +struct huft *tb, *tl, *td; /* literal, length, and distance tables */ +int bb, bl, bd; /* number of bits decoded by those */ +/* Decompress the imploded data using coded literals and a 4K sliding + window. */ +{ + longint s; /* bytes to decompress */ + register unsigned e; /* table entry flag/number of extra bits */ + unsigned n, d; /* length and index for copy */ + unsigned w; /* current window position */ + struct huft *t; /* pointer to table entry */ + unsigned mb, ml, md; /* masks for bb, bl, and bd bits */ + register ULONG b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + unsigned u; /* true if unflushed */ + + + /* explode the coded data */ + b = k = w = 0; /* initialize bit buffer, window */ + u = 1; /* buffer unflushed */ + mb = mask_bits[bb]; /* precompute masks for speed */ + ml = mask_bits[bl]; + md = mask_bits[bd]; + s = pUnzip->pfile_in_zip_read->rest_read_uncompressed; + while (s > 0) /* do until ucsize bytes uncompressed */ + { + NEEDBITS(1) + if (b & 1) /* then literal--decode it */ + { + DUMPBITS(1) + s--; + NEEDBITS((unsigned)bb) /* get coded literal */ + if ((e = (t = tb + ((~(unsigned)b) & mb))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + slide[w++] = (byte)t->v.n; + if (w == WSIZE) + { + flush(w); + w = u = 0; + } + } + else /* else distance/length */ + { + DUMPBITS(1) + NEEDBITS(6) /* get distance low bits */ + d = (unsigned)b & 0x3f; + DUMPBITS(6) + NEEDBITS((unsigned)bd) /* get coded distance high bits */ + if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + d = w - d - t->v.n; /* construct offset */ + NEEDBITS((unsigned)bl) /* get coded length */ + if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + n = t->v.n; + if (e) /* get length extra bits */ + { + NEEDBITS(8) + n += (unsigned)b & 0xff; + DUMPBITS(8) + } + + /* do the copy */ + s -= n; + do { + n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e); + if (u && w <= d) + { + memset(slide + w, 0, e); + w += e; + d += e; + } + else +#ifndef NOMEMCPY + if (w - d >= e) /* (this test assumes unsigned comparison) */ + { + memcpy(slide + w, slide + d, e); + w += e; + d += e; + } + else /* do it slow to avoid memcpy() overlap */ +#endif /* !NOMEMCPY */ + do { + slide[w++] = slide[d++]; + } while (--e); + if (w == WSIZE) + { + flush(w); + w = u = 0; + } + } while (n); + } + } + + /* flush out slide */ + flush(w); + return pfile_in_zip_read_info->rest_read_compressed ? 5 : 0; /* should have read csize bytes */ +} + + + +int explode_nolit8(tl, td, bl, bd) +struct huft *tl, *td; /* length and distance decoder tables */ +int bl, bd; /* number of bits decoded by tl[] and td[] */ +/* Decompress the imploded data using uncoded literals and an 8K sliding + window. */ +{ + longint s; /* bytes to decompress */ + register unsigned e; /* table entry flag/number of extra bits */ + unsigned n, d; /* length and index for copy */ + unsigned w; /* current window position */ + struct huft *t; /* pointer to table entry */ + unsigned ml, md; /* masks for bl and bd bits */ + register ULONG b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + unsigned u; /* true if unflushed */ + + + /* explode the coded data */ + b = k = w = 0; /* initialize bit buffer, window */ + u = 1; /* buffer unflushed */ + ml = mask_bits[bl]; /* precompute masks for speed */ + md = mask_bits[bd]; + s = pUnzip->pfile_in_zip_read->rest_read_uncompressed; + while (s > 0) /* do until ucsize bytes uncompressed */ + { + NEEDBITS(1) + if (b & 1) /* then literal--get eight bits */ + { + DUMPBITS(1) + s--; + NEEDBITS(8) + slide[w++] = (byte)b; + if (w == WSIZE) + { + flush(w); + w = u = 0; + } + DUMPBITS(8) + } + else /* else distance/length */ + { + DUMPBITS(1) + NEEDBITS(7) /* get distance low bits */ + d = (unsigned)b & 0x7f; + DUMPBITS(7) + NEEDBITS((unsigned)bd) /* get coded distance high bits */ + if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + d = w - d - t->v.n; /* construct offset */ + NEEDBITS((unsigned)bl) /* get coded length */ + if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + n = t->v.n; + if (e) /* get length extra bits */ + { + NEEDBITS(8) + n += (unsigned)b & 0xff; + DUMPBITS(8) + } + + /* do the copy */ + s -= n; + do { + n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e); + if (u && w <= d) + { + memset(slide + w, 0, e); + w += e; + d += e; + } + else +#ifndef NOMEMCPY + if (w - d >= e) /* (this test assumes unsigned comparison) */ + { + memcpy(slide + w, slide + d, e); + w += e; + d += e; + } + else /* do it slow to avoid memcpy() overlap */ +#endif /* !NOMEMCPY */ + do { + slide[w++] = slide[d++]; + } while (--e); + if (w == WSIZE) + { + flush(w); + w = u = 0; + } + } while (n); + } + } + + /* flush out slide */ + flush(w); + return pfile_in_zip_read_info->rest_read_compressed ? 5 : 0; /* should have read csize bytes */ +} + + + +int explode_nolit4(tl, td, bl, bd) +struct huft *tl, *td; /* length and distance decoder tables */ +int bl, bd; /* number of bits decoded by tl[] and td[] */ +/* Decompress the imploded data using uncoded literals and a 4K sliding + window. */ +{ + longint s; /* bytes to decompress */ + register unsigned e; /* table entry flag/number of extra bits */ + unsigned n, d; /* length and index for copy */ + unsigned w; /* current window position */ + struct huft *t; /* pointer to table entry */ + unsigned ml, md; /* masks for bl and bd bits */ + register ULONG b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + unsigned u; /* true if unflushed */ + + + /* explode the coded data */ + b = k = w = 0; /* initialize bit buffer, window */ + u = 1; /* buffer unflushed */ + ml = mask_bits[bl]; /* precompute masks for speed */ + md = mask_bits[bd]; + s = pUnzip->pfile_in_zip_read->rest_read_uncompressed; + while (s > 0) /* do until ucsize bytes uncompressed */ + { + NEEDBITS(1) + if (b & 1) /* then literal--get eight bits */ + { + DUMPBITS(1) + s--; + NEEDBITS(8) + slide[w++] = (byte)b; + if (w == WSIZE) + { + flush(w); + w = u = 0; + } + DUMPBITS(8) + } + else /* else distance/length */ + { + DUMPBITS(1) + NEEDBITS(6) /* get distance low bits */ + d = (unsigned)b & 0x3f; + DUMPBITS(6) + NEEDBITS((unsigned)bd) /* get coded distance high bits */ + if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + d = w - d - t->v.n; /* construct offset */ + NEEDBITS((unsigned)bl) /* get coded length */ + if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + n = t->v.n; + if (e) /* get length extra bits */ + { + NEEDBITS(8) + n += (unsigned)b & 0xff; + DUMPBITS(8) + } + + /* do the copy */ + s -= n; + do { + n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e); + if (u && w <= d) + { + memset(slide + w, 0, e); + w += e; + d += e; + } + else +#ifndef NOMEMCPY + if (w - d >= e) /* (this test assumes unsigned comparison) */ + { + memcpy(slide + w, slide + d, e); + w += e; + d += e; + } + else /* do it slow to avoid memcpy() overlap */ +#endif /* !NOMEMCPY */ + do { + slide[w++] = slide[d++]; + } while (--e); + if (w == WSIZE) + { + flush(w); + w = u = 0; + } + } while (n); + } + } + + /* flush out slide */ + flush(w); + return pfile_in_zip_read_info->rest_read_compressed ? 5 : 0; /* should have read csize bytes */ +} + + + +int explode () +/* Explode an imploded compressed stream. Based on the general purpose + bit flag, decide on coded or uncoded literals, and an 8K or 4K sliding + window. Construct the literal (if any), length, and distance codes and + the tables needed to decode them (using huft_build() from inflate.c), + and call the appropriate routine for the type of data in the remainder + of the stream. The four routines are nearly identical, differing only + in whether the literal is decoded or simply read in, and in how many + bits are read in, uncoded, for the low distance bits. */ +{ + unsigned r; /* return codes */ + struct huft *tb; /* literal code table */ + struct huft *tl; /* length code table */ + struct huft *td; /* distance code table */ + int bb; /* bits for tb */ + int bl; /* bits for tl */ + int bd; /* bits for td */ + unsigned l[256]; /* bit lengths for codes */ + + + /* Tune base table sizes. Note: I thought that to truly optimize speed, + I would have to select different bl, bd, and bb values for different + compressed file sizes. I was suprised to find out the the values of + 7, 7, and 9 worked best over a very wide range of sizes, except that + bd = 8 worked marginally better for large compressed sizes. */ + bl = 7; + bd = pUnzip->pfile_in_zip_read->rest_read_compressed > 200000L ? 8 : 7; + + + /* With literal tree--minimum match length is 3 */ + hufts = 0; /* initialze huft's malloc'ed */ + if (pUnzip->cur_file_info.flag & 4) + { + bb = 9; /* base table size for literals */ + if ((r = get_tree(l, 256)) != 0) + return r; + if ((r = huft_build(l, 256, 256, NULL, NULL, &tb, &bb)) != 0) + { + if (r == 1) + huft_free(tb); + return r; + } + if ((r = get_tree(l, 64)) != 0) + return r; + if ((r = huft_build(l, 64, 0, cplen3, extra, &tl, &bl)) != 0) + { + if (r == 1) + huft_free(tl); + huft_free(tb); + return r; + } + if ((r = get_tree(l, 64)) != 0) + return r; + if (pUnzip->cur_file_info.flag & 2) /* true if 8K */ + { + if ((r = huft_build(l, 64, 0, cpdist8, extra, &td, &bd)) != 0) + { + if (r == 1) + huft_free(td); + huft_free(tl); + huft_free(tb); + return r; + } + r = explode_lit8(tb, tl, td, bb, bl, bd); + } + else /* else 4K */ + { + if ((r = huft_build(l, 64, 0, cpdist4, extra, &td, &bd)) != 0) + { + if (r == 1) + huft_free(td); + huft_free(tl); + huft_free(tb); + return r; + } + r = explode_lit4(tb, tl, td, bb, bl, bd); + } + huft_free(td); + huft_free(tl); + huft_free(tb); + } + else + + + /* No literal tree--minimum match length is 2 */ + { + if ((r = get_tree(l, 64)) != 0) + return r; + if ((r = huft_build(l, 64, 0, cplen2, extra, &tl, &bl)) != 0) + { + if (r == 1) + huft_free(tl); + return r; + } + if ((r = get_tree(l, 64)) != 0) + return r; + if (pUnzip->cur_file_info.flag & 2) /* true if 8K */ + { + if ((r = huft_build(l, 64, 0, cpdist8, extra, &td, &bd)) != 0) + { + if (r == 1) + huft_free(td); + huft_free(tl); + return r; + } + r = explode_nolit8(tl, td, bl, bd); + } + else /* else 4K */ + { + if ((r = huft_build(l, 64, 0, cpdist4, extra, &td, &bd)) != 0) + { + if (r == 1) + huft_free(td); + huft_free(tl); + return r; + } + r = explode_nolit4(tl, td, bl, bd); + } + huft_free(td); + huft_free(tl); + } +#ifdef DEBUG + fprintf(stderr, "<%u > ", hufts); +#endif /* DEBUG */ + return r; +} + + +int ReadByte(x) + UWORD *x; +{ + /* + * read a byte; return 8 if byte available, 0 if not + */ + + if (pfile_in_zip_read_info->stream.avail_in == 0) + { + unsigned int uReadThis = UNZ_BUFSIZE; + + if (pfile_in_zip_read_info->rest_read_compressed <= 0) + return (0); + + if (pfile_in_zip_read_info->rest_read_compressed < uReadThis) + uReadThis = (uInt) pfile_in_zip_read_info->rest_read_compressed; + if (uReadThis == 0) + return UNZ_EOF; + if (fseek (pfile_in_zip_read_info->file, + pfile_in_zip_read_info->pos_in_zipfile + + pfile_in_zip_read_info->byte_before_the_zipfile, SEEK_SET) != 0) + return UNZ_ERRNO; + if (fread (pfile_in_zip_read_info->read_buffer, uReadThis, 1, + pfile_in_zip_read_info->file) != 1) + return UNZ_ERRNO; + pfile_in_zip_read_info->pos_in_zipfile += uReadThis; + + pfile_in_zip_read_info->rest_read_compressed -= uReadThis; + + pfile_in_zip_read_info->stream.next_in = + (Bytef *) pfile_in_zip_read_info->read_buffer; + pfile_in_zip_read_info->stream.avail_in = (uInt) uReadThis; + } + + *x = *pfile_in_zip_read_info->stream.next_in++; + pfile_in_zip_read_info->stream.avail_in--; + + return 8; +} + +/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */ +#define BMAX 16 /* maximum bit length of any code (16 for explode) */ +#define N_MAX 288 /* maximum number of codes in any set */ + +unsigned hufts; /* track memory usage */ + + +int huft_build(b, n, s, d, e, t, m) +unsigned *b; /* code lengths in bits (all assumed <= BMAX) */ +unsigned n; /* number of codes (assumed <= N_MAX) */ +unsigned s; /* number of simple-valued codes (0..s-1) */ +ush *d; /* list of base values for non-simple codes */ +ush *e; /* list of extra bits for non-simple codes */ +struct huft **t; /* result: starting table */ +int *m; /* maximum lookup bits, returns actual */ +/* Given a list of code lengths and a maximum table size, make a set of + tables to decode that set of codes. Return zero on success, one if + the given code set is incomplete (the tables are still built in this + case), two if the input is invalid (all zero length codes or an + oversubscribed set of lengths), and three if not enough memory. */ +{ + unsigned a; /* counter for codes of length k */ + unsigned c[BMAX+1]; /* bit length count table */ + unsigned f; /* i repeats in table every f entries */ + int g; /* maximum code length */ + int h; /* table level */ + register unsigned i; /* counter, current code */ + register unsigned j; /* counter */ + register int k; /* number of bits in current code */ + int l; /* bits per table (returned in m) */ + register unsigned *p; /* pointer into c[], b[], or v[] */ + register struct huft *q; /* points to current table */ + struct huft r; /* table entry for structure assignment */ + struct huft *u[BMAX]; /* table stack */ + unsigned v[N_MAX]; /* values in order of bit length */ + register int w; /* bits before this table == (l * h) */ + unsigned x[BMAX+1]; /* bit offsets, then code stack */ + unsigned *xp; /* pointer into x */ + int y; /* number of dummy codes added */ + unsigned z; /* number of entries in current table */ + + + /* Generate counts for each bit length */ + memset(c, 0, sizeof(c)); + p = b; i = n; + do { + c[*p++]++; /* assume all entries <= BMAX */ + } while (--i); + if (c[0] == n) /* null input--all zero length codes */ + { + *t = (struct huft *)NULL; + *m = 0; + return 0; + } + + + /* Find minimum and maximum length, bound *m by those */ + l = *m; + for (j = 1; j <= BMAX; j++) + if (c[j]) + break; + k = j; /* minimum code length */ + if ((unsigned)l < j) + l = j; + for (i = BMAX; i; i--) + if (c[i]) + break; + g = i; /* maximum code length */ + if ((unsigned)l > i) + l = i; + *m = l; + + + /* Adjust last length count to fill out codes, if needed */ + for (y = 1 << j; j < i; j++, y <<= 1) + if ((y -= c[j]) < 0) + return 2; /* bad input: more codes than bits */ + if ((y -= c[i]) < 0) + return 2; + c[i] += y; + + + /* Generate starting offsets into the value table for each length */ + x[1] = j = 0; + p = c + 1; xp = x + 2; + while (--i) { /* note that i == g from above */ + *xp++ = (j += *p++); + } + + + /* Make a table of values in order of bit lengths */ + p = b; i = 0; + do { + if ((j = *p++) != 0) + v[x[j]++] = i; + } while (++i < n); + + + /* Generate the Huffman codes and for each, make the table entries */ + x[0] = i = 0; /* first Huffman code is zero */ + p = v; /* grab values in bit order */ + h = -1; /* no tables yet--level -1 */ + w = -l; /* bits decoded == (l * h) */ + u[0] = (struct huft *)NULL; /* just to keep compilers happy */ + q = (struct huft *)NULL; /* ditto */ + z = 0; /* ditto */ + + /* go through the bit lengths (k already is bits in shortest code) */ + for (; k <= g; k++) + { + a = c[k]; + while (a--) + { + /* here i is the Huffman code of length k bits for value *p */ + /* make tables up to required level */ + while (k > w + l) + { + h++; + w += l; /* previous table always l bits */ + + /* compute minimum size table less than or equal to l bits */ + z = (z = g - w) > (unsigned)l ? l : z; /* upper limit on table size */ + if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ + { /* too few codes for k-w bit table */ + f -= a + 1; /* deduct codes from patterns left */ + xp = c + k; + while (++j < z) /* try smaller tables up to z bits */ + { + if ((f <<= 1) <= *++xp) + break; /* enough codes to use up j bits */ + f -= *xp; /* else deduct codes from patterns */ + } + } + z = 1 << j; /* table entries for j-bit table */ + + /* allocate and link in new table */ + if ((q = (struct huft *)malloc((z + 1)*sizeof(struct huft))) == + (struct huft *)NULL) + { + if (h) + huft_free(u[0]); + return 3; /* not enough memory */ + } + hufts += z + 1; /* track memory usage */ + *t = q + 1; /* link to list for huft_free() */ + *(t = &(q->v.t)) = (struct huft *)NULL; + u[h] = ++q; /* table starts after link */ + + /* connect to last table, if there is one */ + if (h) + { + x[h] = i; /* save pattern for backing up */ + r.b = (uch)l; /* bits to dump before this table */ + r.e = (uch)(16 + j); /* bits in this table */ + r.v.t = q; /* pointer to this table */ + j = i >> (w - l); /* (get around Turbo C bug) */ + u[h-1][j] = r; /* connect to last table */ + } + } + + /* set up table entry in r */ + r.b = (uch)(k - w); + if (p >= v + n) + r.e = 99; /* out of values--invalid code */ + else if (*p < s) + { + r.e = (uch)(*p < 256 ? 16 : 15); /* 256 is end-of-block code */ + r.v.n = *p++; /* simple code is just the value */ + } + else + { + r.e = (uch)e[*p - s]; /* non-simple--look up in lists */ + r.v.n = d[*p++ - s]; + } + + /* fill code-like entries with r */ + f = 1 << (k - w); + for (j = i >> w; j < z; j += f) + q[j] = r; + + /* backwards increment the k-bit code i */ + for (j = 1 << (k - 1); i & j; j >>= 1) + i ^= j; + i ^= j; + + /* backup over finished tables */ + while ((i & ((1 << w) - 1)) != x[h]) + { + h--; /* don't need to update q */ + w -= l; + } + } + } + + + /* Return true (1) if we were given an incomplete table */ + return y != 0 && g != 1; +} + + +int huft_free(t) +struct huft *t; /* table to free */ +/* Free the malloc'ed tables built by huft_build(), which makes a linked + list of the tables it made, with the links in a dummy first entry of + each table. */ +{ + register struct huft *p, *q; + + + /* Go through linked list, freeing from the malloced (t[-1]) address. */ + p = t; + while (p != (struct huft *)NULL) + { + q = (--p)->v.t; + free(p); + p = q; + } + return 0; +} + +void flush(w) +unsigned w; /* number of bytes to flush */ +/* Do the equivalent of OUTB for the bytes slide[0..w-1]. */ +{ + memmove (pfile_in_zip_read_info->stream.next_out, slide, w); + pfile_in_zip_read_info->crc32 = crc32 (pfile_in_zip_read_info->crc32, + pfile_in_zip_read_info->stream.next_out, + w); + pfile_in_zip_read_info->stream.next_out += w; + pfile_in_zip_read_info->stream.avail_out -= w; + pfile_in_zip_read_info->stream.total_out += w; +} + +void flush_stack(w) +unsigned w; /* number of bytes to flush */ +/* Do the equivalent of OUTB for the bytes slide[0..w-1]. */ +{ + memmove (pfile_in_zip_read_info->stream.next_out, stack, w); + pfile_in_zip_read_info->crc32 = crc32 (pfile_in_zip_read_info->crc32, + pfile_in_zip_read_info->stream.next_out, + w); + pfile_in_zip_read_info->stream.next_out += w; + pfile_in_zip_read_info->stream.avail_out -= w; + pfile_in_zip_read_info->stream.total_out += w; +} + +/****************************/ +/* Function FillBitBuffer() */ +/****************************/ + +int FillBitBuffer() +{ + /* + * Fill bitbuf, which is 32 bits. This function is only used by the + * READBIT and PEEKBIT macros (which are used by all of the uncompression + * routines). + */ + UWORD temp; + + zipeof = 1; + while (bits_left < 25 && ReadByte(&temp) == 8) + { + bitbuf |= (ULONG)temp << bits_left; + bits_left += 8; + zipeof = 0; + } + return 0; +} + diff --git a/source/unzip/unreduce.c b/source/unzip/unreduce.c new file mode 100644 index 0000000..e978746 --- /dev/null +++ b/source/unzip/unreduce.c @@ -0,0 +1,217 @@ +/*--------------------------------------------------------------------------- + + unreduce.c + + The Reducing algorithm is actually a combination of two distinct algorithms. + The first algorithm compresses repeated byte sequences, and the second al- + gorithm takes the compressed stream from the first algorithm and applies a + probabilistic compression method. + + ---------------------------------------------------------------------------*/ + + +#include "unz.h" +#include "unzipP.h" + +/**************************************/ +/* UnReduce Defines, Typedefs, etc. */ +/**************************************/ + +#define DLE 144 + +typedef byte f_array[64]; /* for followers[256][64] */ + +static void LoadFollowers (); +void flush OF((unsigned)); /* routine from inflate.c */ + +extern file_in_zip_read_info_s *pfile_in_zip_read_info; +extern unz_s *pUnzip; + +/*******************************/ +/* UnReduce Global Variables */ +/*******************************/ + +#if (defined(MACOS) || defined(MTS)) + f_array *followers; /* shared work space */ +#else + f_array *followers = (f_array *) (slide + 0x4000); +#endif + +byte Slen[256]; +int factor; + +int L_table[] = +{0, 0x7f, 0x3f, 0x1f, 0x0f}; + +int D_shift[] = +{0, 0x07, 0x06, 0x05, 0x04}; +int D_mask[] = +{0, 0x01, 0x03, 0x07, 0x0f}; + +int B_table[] = +{8, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8}; + + + + + +/*************************/ +/* Function unReduce() */ +/*************************/ + +void unReduce() /* expand probabilistically reduced data */ +{ + register int lchar = 0; + int nchar; + int ExState = 0; + int V = 0; + int Len = 0; + longint s = pUnzip->pfile_in_zip_read->rest_read_compressed; + unsigned w = 0; /* position in output window slide[] */ + unsigned u = 1; /* true if slide[] unflushed */ + + +#if (defined(MACOS) || defined(MTS)) + followers = (f_array *) (slide + 0x4000); +#endif + + factor = pUnzip->cur_file_info.compression_method; + LoadFollowers(); + + while (s > 0 /* && (!zipeof) */) { + if (Slen[lchar] == 0) + READBIT(8, nchar) /* ; */ + else { + READBIT(1, nchar); + if (nchar != 0) + READBIT(8, nchar) /* ; */ + else { + int follower; + int bitsneeded = B_table[Slen[lchar]]; + READBIT(bitsneeded, follower); + nchar = followers[lchar][follower]; + } + } + /* expand the resulting byte */ + switch (ExState) { + + case 0: + if (nchar != DLE) { + s--; + slide[w++] = (byte) nchar; + if (w == 0x4000) { + flush(w); + w = u = 0; + } + } + else + ExState = 1; + break; + + case 1: + if (nchar != 0) { + V = nchar; + Len = V & L_table[factor]; + if (Len == L_table[factor]) + ExState = 2; + else + ExState = 3; + } else { + s--; + slide[w++] = DLE; + if (w == 0x4000) + { + flush(w); + w = u = 0; + } + ExState = 0; + } + break; + + case 2:{ + Len += nchar; + ExState = 3; + } + break; + + case 3:{ + register unsigned e; + register unsigned n = Len + 3; + register unsigned d = w - ((((V >> D_shift[factor]) & + D_mask[factor]) << 8) + nchar + 1); + + s -= n; + do { + n -= (e = (e = 0x4000 - ((d &= 0x3fff) > w ? d : w)) > n ? + n : e); + if (u && w <= d) + { + memset(slide + w, 0, e); + w += e; + d += e; + } + else + if (w - d < e) /* (assume unsigned comparison) */ + do { /* slow to avoid memcpy() overlap */ + slide[w++] = slide[d++]; + } while (--e); + else + { + memcpy(slide + w, slide + d, e); + w += e; + d += e; + } + if (w == 0x4000) + { + flush(w); + w = u = 0; + } + } while (n); + + ExState = 0; + } + break; + } + + /* store character for next iteration */ + lchar = nchar; + } + + /* flush out slide */ + flush(w); +} + + + + + +/******************************/ +/* Function LoadFollowers() */ +/******************************/ + +static void LoadFollowers() +{ + register int x; + register int i; + + for (x = 255; x >= 0; x--) { + READBIT(6, Slen[x]); + for (i = 0; (byte) i < Slen[x]; i++) { + READBIT(8, followers[x][i]); + } + } +} diff --git a/source/unzip/unshrink.c b/source/unzip/unshrink.c new file mode 100644 index 0000000..6deb4d4 --- /dev/null +++ b/source/unzip/unshrink.c @@ -0,0 +1,177 @@ +/*--------------------------------------------------------------------------- + + unshrink.c + + Shrinking is a Dynamic Lempel-Ziv-Welch compression algorithm with partial + clearing. + + ---------------------------------------------------------------------------*/ + + +#include "unz.h" +void flush_stack (int); + +/*************************************/ +/* UnShrink Defines, Globals, etc. */ +/*************************************/ + +/* MAX_BITS 13 (in unzip.h; defines size of global work area) */ +#define INIT_BITS 9 +#define FIRST_ENT 257 +#define CLEAR 256 +#define GetCode(dest) READBIT(codesize,dest) + +static void partial_clear (); + +int codesize, maxcode, maxcodemax, free_ent; + + + + +/*************************/ +/* Function unShrink() */ +/*************************/ + +void unShrink() +{ + register int code; + register int stackp; + int finchar; + int oldcode; + int incode; + + + /* decompress the file */ + codesize = INIT_BITS; + maxcode = (1 << codesize) - 1; + maxcodemax = HSIZE; /* (1 << MAX_BITS) */ + free_ent = FIRST_ENT; + + code = maxcodemax; + do { + prefix_of[code] = -1; + } while (--code > 255); +/* + OvdL: -Ox with SCO's 3.2.0 cc gives + a. warning: overflow in constant multiplication + b. segmentation fault (core dumped) when using the executable + for (code = maxcodemax; code > 255; code--) + prefix_of[code] = -1; + */ + + for (code = 255; code >= 0; code--) { + prefix_of[code] = 0; + suffix_of[code] = (byte) code; + } + + GetCode(oldcode); + if (zipeof) + return; + finchar = oldcode; + + stack[0] = finchar; + flush_stack (1); + + stackp = HSIZE; + + while (!zipeof) { + GetCode(code); + if (zipeof) + return; + + while (code == CLEAR) { + GetCode(code); + switch (code) { + case 1: + codesize++; + if (codesize == MAX_BITS) + maxcode = maxcodemax; + else + maxcode = (1 << codesize) - 1; + break; + + case 2: + partial_clear(); + break; + } + + GetCode(code); + if (zipeof) + return; + } + + + /* special case for KwKwK string */ + incode = code; + if (prefix_of[code] == -1) { + stack[--stackp] = (byte) finchar; + code = oldcode; + } + /* generate output characters in reverse order */ + while (code >= FIRST_ENT) { + if (prefix_of[code] == -1) { + stack[--stackp] = (byte) finchar; + code = oldcode; + } else { + stack[--stackp] = suffix_of[code]; + code = prefix_of[code]; + } + } + + finchar = suffix_of[code]; + stack[--stackp] = (byte) finchar; + + /* and put them out in forward order, block copy */ + flush_stack (HSIZE - stackp); + stackp = HSIZE; + + /* generate new entry */ + code = free_ent; + if (code < maxcodemax) { + prefix_of[code] = oldcode; + suffix_of[code] = (byte) finchar; + + do + code++; + while ((code < maxcodemax) && (prefix_of[code] != -1)); + + free_ent = code; + } + /* remember previous code */ + oldcode = incode; + } +} + + + +/******************************/ +/* Function partial_clear() */ +/******************************/ + +static void partial_clear() +{ + register int pr; + register int cd; + + /* mark all nodes as potentially unused */ + for (cd = FIRST_ENT; cd < free_ent; cd++) + prefix_of[cd] |= 0x8000; + + /* unmark those that are used by other nodes */ + for (cd = FIRST_ENT; cd < free_ent; cd++) { + pr = prefix_of[cd] & 0x7fff; /* reference to another node? */ + if (pr >= FIRST_ENT) /* flag node as referenced */ + prefix_of[pr] &= 0x7fff; + } + + /* clear the ones that are still marked */ + for (cd = FIRST_ENT; cd < free_ent; cd++) + if ((prefix_of[cd] & 0x8000) != 0) + prefix_of[cd] = -1; + + /* find first cleared node as next free_ent */ + cd = FIRST_ENT; + while ((cd < maxcodemax) && (prefix_of[cd] != -1)) + cd++; + free_ent = cd; +} diff --git a/source/unzip/unz.h b/source/unzip/unz.h new file mode 100644 index 0000000..1ea7478 --- /dev/null +++ b/source/unzip/unz.h @@ -0,0 +1,994 @@ +/*--------------------------------------------------------------------------- + + unzip.h + + This header file is used by all of the unzip source files. Its contents + are divided into seven more-or-less separate sections: predefined macros, + OS-dependent includes, (mostly) OS-independent defines, typedefs, function + prototypes (or "prototypes," in the case of non-ANSI compilers), macros, + and global-variable declarations. + + ---------------------------------------------------------------------------*/ + +#include "zlib.h" + +/*****************************************/ +/* Predefined, Machine-specific Macros */ +/*****************************************/ + +#if (defined(__GO32__) && defined(unix)) /* DOS extender */ +# undef unix +#endif + +#if defined(unix) || defined(__convexc__) || defined(M_XENIX) +# ifndef UNIX +# define UNIX +# endif /* !UNIX */ +#endif /* unix || __convexc__ || M_XENIX */ + +/* Much of the following is swiped from zip's tailor.h: */ + +/* define MSDOS for Turbo C (unless OS/2) and Power C as well as Microsoft C */ +#ifdef __POWERC +# define __TURBOC__ +# define MSDOS +#endif /* __POWERC */ +#if (defined(__TURBOC__) && defined(__MSDOS__) && !defined(MSDOS)) +# define MSDOS +#endif + +/* use prototypes and ANSI libraries if __STDC__, or Microsoft or Borland C, + * or Silicon Graphics, or Convex, or IBM C Set/2, or GNU gcc under emx, or + * or Watcom C, or Macintosh, or Windows NT. + */ +#if (__STDC__ || defined(MSDOS) || defined(sgi) || defined(CONVEX) || defined(__sun)) +# ifndef PROTO +# define PROTO +# endif +# define MODERN +#endif +#if (defined(__IBMC__) || defined(__EMX__) || defined(__WATCOMC__)) +# ifndef PROTO +# define PROTO +# endif +# define MODERN +#endif +#if (defined(THINK_C) || defined(MPW) || defined(WIN32)) +# ifndef PROTO +# define PROTO +# endif +# define MODERN +#endif + +/* turn off prototypes if requested */ +#if (defined(NOPROTO) && defined(PROTO)) +# undef PROTO +#endif + +#if (defined(ultrix) || defined(bsd4_2) || defined(sun) || defined(pyr)) +# if (!defined(BSD) && !defined(__SYSTEM_FIVE) && !defined(SYSV)) +# define BSD +# endif /* !BSD && !__SYSTEM_FIVE && !SYSV */ +#endif /* ultrix || bsd4_2 || sun || pyr */ + +#if (defined(CONVEX) || defined(CRAY) || defined(__SYSTEM_FIVE)) +# ifndef TERMIO +# define TERMIO +# endif /* !TERMIO */ +#endif /* CONVEX || CRAY || __SYSTEM_FIVE */ + +#ifdef pyr /* Pyramid */ +# ifndef ZMEM +# define ZMEM +# endif /* !ZMEM */ +#endif /* pyr */ + +#ifdef CRAY +# ifdef ZMEM +# undef ZMEM +# endif /* ZMEM */ +#endif /* CRAY */ + +/* the i386 test below is to catch SCO Unix (which has redefinition + * warnings if param.h is included), but it probably doesn't hurt if + * other 386 Unixes get nailed, too...except now that 386BSD and BSDI + * exist. Sigh. <sys/param.h> is mostly included for "BSD", I think. + * [An alternate fix for SCO Unix is below.] + */ +#if (defined(MINIX) || (defined(i386) && defined(unix))) +# define NO_PARAM_H +#endif /* MINIX || (i386 && unix) */ + + + + + +/***************************/ +/* OS-Dependent Includes */ +/***************************/ + +#ifndef MINIX /* Minix needs it after all the other includes (?) */ +# include <stdio.h> +#endif +#include <ctype.h> /* skip for VMS, to use tolower() function? */ +#include <errno.h> /* used in mapname() */ +#ifndef NO_ERRNO +# define DECLARE_ERRNO /* everybody except MSC 6.0, SCO cc, Watcom C/386 */ +#endif /* !NO_ERRNO */ +#ifdef VMS +# include <types.h> /* (placed up here instead of in VMS section below */ +# include <stat.h> /* because types.h is used in some other headers) */ +#else /* !VMS */ +# if !defined(THINK_C) && !defined(MPW) +# include <sys/types.h> /* off_t, time_t, dev_t, ... */ +# include <sys/stat.h> +# endif /* !THINK_C && !MPW */ +#endif /* ?VMS */ + +#ifdef MODERN +# if (!defined(M_XENIX) && !(defined(__GNUC__) && defined(sun))) +# include <stddef.h> +# endif +# if (!defined(__GNUC__) && !defined(apollo)) /* both define __STDC__ */ +# include <stdlib.h> /* standard library prototypes, malloc(), etc. */ +# else +# ifdef __EMX__ +# include <stdlib.h> /* emx IS gcc but has stdlib.h */ +# endif +# endif +# include <string.h> /* defines strcpy, strcmp, memcpy, etc. */ + typedef size_t extent; +#else /* !MODERN */ + char *malloc(); + char *strchr(), *strrchr(); + long lseek(); + typedef unsigned int extent; +# define void int +#endif /* ?MODERN */ + +/* this include must be down here for SysV.4, for some reason... */ +#include <signal.h> /* used in unzip.c, file_io.c */ + + + +/*--------------------------------------------------------------------------- + Next, a word from our Unix (mostly) sponsors: + ---------------------------------------------------------------------------*/ + +#ifdef UNIX +# ifdef AMIGA +# include <libraries/dos.h> +# else /* !AMIGA */ +# ifndef NO_PARAM_H +#if 0 /* [GRR: this is an alternate fix for SCO's redefinition bug] */ +# ifdef NGROUPS_MAX +# undef NGROUPS_MAX /* SCO bug: defined again in <param.h> */ +# endif /* NGROUPS_MAX */ +#endif /* 0 */ +# include <sys/param.h> /* conflict with <sys/types.h>, some systems? */ +# endif /* !NO_PARAM_H */ +# endif /* ?AMIGA */ + +# ifndef BSIZE +# ifdef MINIX +# define BSIZE 1024 +# else /* !MINIX */ +# define BSIZE DEV_BSIZE /* assume common for all Unix systems */ +# endif /* ?MINIX */ +# endif + +# ifndef BSD +# if (!defined(AMIGA) && !defined(MINIX)) +# define NO_MKDIR /* for mapname() */ +# endif /* !AMIGA && !MINIX */ +# include <time.h> + struct tm *gmtime(), *localtime(); +# else /* BSD */ +# include <sys/time.h> +# include <sys/timeb.h> +# ifdef _AIX +# include <time.h> +# endif +# endif + +#else /* !UNIX */ +# define BSIZE 512 /* disk block size */ +#endif /* ?UNIX */ + +#if (defined(V7) || defined(BSD)) +# define strchr index +# define strrchr rindex +#endif + +/*--------------------------------------------------------------------------- + And now, our MS-DOS and OS/2 corner: + ---------------------------------------------------------------------------*/ + +#ifdef __TURBOC__ +# define DOS_OS2 +# include <sys/timeb.h> /* for structure ftime */ +# ifndef __BORLANDC__ /* there appears to be a bug (?) in Borland's */ +# include <mem.h> /* MEM.H related to __STDC__ and far poin- */ +# endif /* ters. (dpk) [mem.h included for memcpy] */ +# include <dos.h> /* for REGS macro (at least for Turbo C 2.0) */ +#else /* NOT Turbo C (or Power C)... */ +# ifdef MSDOS /* but still MS-DOS, so we'll assume it's */ +# ifndef MSC /* Microsoft's compiler and fake the ID, if */ +# define MSC /* necessary (it is in 5.0; apparently not */ +# endif /* in 5.1 and 6.0) */ +# include <dos.h> /* for _dos_setftime() */ +# endif +#endif + +#if (defined(__IBMC__) && defined(__OS2__)) +# define DOS_OS2 +# define S_IFMT 0xF000 +# define timezone _timezone +#endif + +#ifdef __WATCOMC__ +# define DOS_OS2 +# define __32BIT__ +# ifdef DECLARE_ERRNO +# undef DECLARE_ERRNO +# endif +# undef far +# define far +#endif + +#ifdef __EMX__ +# define DOS_OS2 +# define __32BIT__ +# define far +#endif /* __EMX__ */ + +#ifdef MSC /* defined for all versions of MSC now */ +# define DOS_OS2 /* Turbo C under DOS, MSC under DOS or OS/2 */ +# if (defined(_MSC_VER) && (_MSC_VER >= 600)) /* new with 5.1 or 6.0 ... */ +# undef DECLARE_ERRNO /* errno is now a function in a dynamic link */ +# endif /* library (or something)--incompatible with */ +#endif /* the usual "extern int errno" declaration */ + +#ifdef DOS_OS2 /* defined for all MS-DOS and OS/2 compilers */ +# include <io.h> /* lseek(), open(), setftime(), dup(), creat() */ +# include <time.h> /* localtime() */ +#endif + +#ifdef OS2 /* defined for all OS/2 compilers */ +# ifdef isupper +# undef isupper +# endif +# ifdef tolower +# undef tolower +# endif +# define isupper(x) IsUpperNLS((unsigned char)(x)) +# define tolower(x) ToLowerNLS((unsigned char)(x)) +#endif + +#ifdef WIN32 +# include <io.h> /* read(), open(), etc. */ +# include <time.h> +# include <memory.h> +# include <direct.h> /* mkdir() */ +# ifdef FILE_IO_C +# include <fcntl.h> +# include <conio.h> +# include <sys\types.h> +# include <sys\utime.h> +# include <windows.h> +# define DOS_OS2 +# define getch() getchar() +# endif +#endif + +/*--------------------------------------------------------------------------- + Followed by some VMS (mostly) stuff: + ---------------------------------------------------------------------------*/ + +#ifdef VMS +# include <time.h> /* the usual non-BSD time functions */ +# include <file.h> /* same things as fcntl.h has */ +# include <rms.h> +# define _MAX_PATH NAM$C_MAXRSS /* to define FILNAMSIZ below */ +# define UNIX /* can share most of same code from now on */ +# define RETURN return_VMS /* VMS interprets return codes incorrectly */ +#else /* !VMS */ +# ifndef THINK_C +# define RETURN return /* only used in main() */ +# else +# define RETURN(v) { int n;\ + n = (v);\ + fprintf(stderr, "\npress <return> to continue ");\ + while (getc(stdin) != '\n');\ + putc('\n', stderr);\ + InitCursor();\ + goto start;\ + } +# endif +# ifdef V7 +# define O_RDONLY 0 +# define O_WRONLY 1 +# define O_RDWR 2 +# else /* !V7 */ +# ifdef MTS +# include <sys/file.h> /* MTS uses this instead of fcntl.h */ +# include <timeb.h> +# include <time.h> +# else /* !MTS */ +# ifdef COHERENT /* Coherent 3.10/Mark Williams C */ +# include <sys/fcntl.h> +# define SHORT_NAMES +# define tzset settz +# else /* !COHERENT */ +# include <fcntl.h> /* O_BINARY for open() w/o CR/LF translation */ +# endif /* ?COHERENT */ +# endif /* ?MTS */ +# endif /* ?V7 */ +#endif /* ?VMS */ + +#if (defined(MSDOS) || defined(VMS)) +# define DOS_VMS +#endif + +/*--------------------------------------------------------------------------- + And some Mac stuff for good measure: + ---------------------------------------------------------------------------*/ + +#ifdef THINK_C +# define MACOS +# ifndef __STDC__ /* if Think C hasn't defined __STDC__ ... */ +# define __STDC__ 1 /* make sure it's defined: it needs it */ +# else /* __STDC__ defined */ +# if !__STDC__ /* sometimes __STDC__ is defined as 0; */ +# undef __STDC__ /* it needs to be 1 or required header */ +# define __STDC__ 1 /* files are not properly included. */ +# endif /* !__STDC__ */ +# endif /* ?defined(__STDC__) */ +#endif /* THINK_C */ + +#ifdef MPW +# define MACOS +# include <Errors.h> +# include <Files.h> +# include <Memory.h> +# include <Quickdraw.h> +# include <ToolUtils.h> +# define CtoPstr c2pstr +# define PtoCstr p2cstr +# ifdef CR +# undef CR +# endif +#endif /* MPW */ + +#ifdef MACOS +# define open(x,y) macopen(x,y, gnVRefNum, glDirID) +# define close macclose +# define read macread +# define write macwrite +# define lseek maclseek +# define creat(x,y) maccreat(x, gnVRefNum, glDirID, gostCreator, gostType) +# define stat(x,y) macstat(x,y,gnVRefNum, glDirID) + +# ifndef isascii +# define isascii(c) ((unsigned char)(c) <= 0x3F) +# endif + +# include "macstat.h" + +typedef struct _ZipExtraHdr { + unsigned short header; /* 2 bytes */ + unsigned short data; /* 2 bytes */ +} ZIP_EXTRA_HEADER; + +typedef struct _MacInfoMin { + unsigned short header; /* 2 bytes */ + unsigned short data; /* 2 bytes */ + unsigned long signature; /* 4 bytes */ + FInfo finfo; /* 16 bytes */ + unsigned long lCrDat; /* 4 bytes */ + unsigned long lMdDat; /* 4 bytes */ + unsigned long flags ; /* 4 bytes */ + unsigned long lDirID; /* 4 bytes */ + /*------------*/ +} MACINFOMIN; /* = 40 bytes for size of data */ + +typedef struct _MacInfo { + unsigned short header; /* 2 bytes */ + unsigned short data; /* 2 bytes */ + unsigned long signature; /* 4 bytes */ + FInfo finfo; /* 16 bytes */ + unsigned long lCrDat; /* 4 bytes */ + unsigned long lMdDat; /* 4 bytes */ + unsigned long flags ; /* 4 bytes */ + unsigned long lDirID; /* 4 bytes */ + char rguchVolName[28]; /* 28 bytes */ + /*------------*/ +} MACINFO; /* = 68 bytes for size of data */ +#endif /* MACOS */ + +/*--------------------------------------------------------------------------- + And finally, some random extra stuff: + ---------------------------------------------------------------------------*/ + +#ifdef MINIX +# include <stdio.h> +#endif + +#ifdef SHORT_NAMES /* Mark Williams C, ...? */ +# define extract_or_test_files xtr_or_tst_files +# define extract_or_test_member xtr_or_tst_member +#endif + +#ifdef MTS +# include <unix.h> /* Some important non-ANSI routines */ +# define mkdir(s,n) (-1) /* No "make directory" capability */ +# define EBCDIC /* Set EBCDIC conversion on */ +#endif + + + + + +/*************/ +/* Defines */ +/*************/ + +#ifndef WSIZE +# define WSIZE 0x8000 /* window size--must be a power of two, and */ +#endif /* !WSIZE */ /* at least 32K for zip's deflate method */ + +#define DIR_BLKSIZ 64 /* number of directory entries per block + * (should fit in 4096 bytes, usually) */ +#ifndef INBUFSIZ +# define INBUFSIZ 2048 /* works for MS-DOS small model */ +#endif /* !INBUFSIZ */ + +/* + * If <limits.h> exists on most systems, should include that, since it may + * define some or all of the following: NAME_MAX, PATH_MAX, _POSIX_NAME_MAX, + * _POSIX_PATH_MAX. + */ +#ifdef DOS_OS2 +# include <limits.h> +#endif /* DOS_OS2 */ + +#ifdef _MAX_PATH +# define FILNAMSIZ (_MAX_PATH) +#else /* !_MAX_PATH */ +# define FILNAMSIZ 1025 +#endif /* ?_MAX_PATH */ + +#ifndef PATH_MAX +# ifdef MAXPATHLEN /* defined in <sys/param.h> some systems */ +# define PATH_MAX MAXPATHLEN +# else +# if FILENAME_MAX > 255 /* used like PATH_MAX on some systems */ +# define PATH_MAX FILENAME_MAX +# else +# define PATH_MAX (FILNAMSIZ - 1) +# endif +# endif /* ?MAXPATHLEN */ +#endif /* !PATH_MAX */ + +#define OUTBUFSIZ INBUFSIZ + +#define ZSUFX ".zip" +#define CENTRAL_HDR_SIG "\113\001\002" /* the infamous "PK" signature */ +#define LOCAL_HDR_SIG "\113\003\004" /* bytes, sans "P" (so unzip */ +#define END_CENTRAL_SIG "\113\005\006" /* executable not mistaken for */ +#define EXTD_LOCAL_SIG "\113\007\010" /* zipfile itself) */ + +#define SKIP 0 /* choice of activities for do_string() */ +#define DISPLAY 1 +#define FILENAME 2 +#define EXTRA_FIELD 3 + +#define DOES_NOT_EXIST -1 /* return values for check_for_newer() */ +#define EXISTS_AND_OLDER 0 +#define EXISTS_AND_NEWER 1 + +#define DOS_OS2_FAT_ 0 /* version_made_by codes (central dir) */ +#define AMIGA_ 1 +#define VMS_ 2 /* make sure these are not defined on */ +#define UNIX_ 3 /* the respective systems!! (like, for */ +#define VM_CMS_ 4 /* instance, "VMS", or "UNIX": CFLAGS = */ +#define ATARI_ 5 /* -O -DUNIX) */ +#define OS2_HPFS_ 6 +#define MAC_ 7 +#define Z_SYSTEM_ 8 +#define CPM_ 9 +/* #define TOPS20_ 10? (TOPS20_ is to be defined in PKZIP 2.0...) */ +#define NUM_HOSTS 10 /* index of last system + 1 */ + +#define STORED 0 /* compression methods */ +#define SHRUNK 1 +#define REDUCED1 2 +#define REDUCED2 3 +#define REDUCED3 4 +#define REDUCED4 5 +#define IMPLODED 6 +#define TOKENIZED 7 +#define DEFLATED 8 +#define NUM_METHODS 9 /* index of last method + 1 */ +/* don't forget to update list_files() appropriately if NUM_METHODS changes */ + +#define DF_MDY 0 /* date format 10/26/91 (USA only) */ +#define DF_DMY 1 /* date format 26/10/91 (most of the world) */ +#define DF_YMD 2 /* date format 91/10/26 (a few countries) */ + +#define UNZIP_VERSION 20 /* compatible with PKUNZIP 2.0 */ +#define VMS_VERSION 42 /* if OS-needed-to-extract is VMS: can do */ + +/*--------------------------------------------------------------------------- + True sizes of the various headers, as defined by PKWare--so it is not + likely that these will ever change. But if they do, make sure both these + defines AND the typedefs below get updated accordingly. + ---------------------------------------------------------------------------*/ +#define LREC_SIZE 26 /* lengths of local file headers, central */ +#define CREC_SIZE 42 /* directory headers, and the end-of- */ +#define ECREC_SIZE 18 /* central-dir record, respectively */ + +#define MAX_BITS 13 /* used in unShrink() */ +#define HSIZE (1 << MAX_BITS) /* size of global work area */ + +#define LF 10 /* '\n' on ASCII machines. Must be 10 due to EBCDIC */ +#define CR 13 /* '\r' on ASCII machines. Must be 13 due to EBCDIC */ +#define CTRLZ 26 /* DOS & OS/2 EOF marker (used in file_io.c, vms.c) */ + +#ifdef EBCDIC +# define ascii_to_native(c) ebcdic[(c)] +# define NATIVE "EBCDIC" +#endif + +#if MPW +# define FFLUSH putc('\n',stderr); +#else /* !MPW */ +# define FFLUSH fflush(stderr); +#endif /* ?MPW */ + +#ifdef VMS +# define ENV_UNZIP "UNZIP_OPTS" /* name of environment variable */ +# define ENV_ZIPINFO "ZIPINFO_OPTS" +#else /* !VMS */ +# define ENV_UNZIP "UNZIP" +# define ENV_ZIPINFO "ZIPINFO" +#endif /* ?VMS */ + +#ifdef CRYPT +# define PWLEN 80 +# define DECRYPT(b) (update_keys(t=((b)&0xff)^decrypt_byte()),t) +#endif /* CRYPT */ + +#ifdef QQ /* Newtware version */ +# define QCOND (!quietflg) /* for no file comments with -vq or -vqq */ +#else /* (original) Bill Davidsen version */ +# define QCOND (which_hdr) /* no way to kill file comments with -v, -l */ +#endif + +#ifndef TRUE +# define TRUE 1 /* sort of obvious */ +#endif +#ifndef FALSE +# define FALSE 0 +#endif + +#ifndef SEEK_SET /* These should all be declared in stdio.h! But */ +# define SEEK_SET 0 /* since they're not (in many cases), do so here. */ +# define SEEK_CUR 1 +# define SEEK_END 2 +#endif + +#ifndef S_IRUSR +# define S_IRWXU 00700 /* read, write, execute: owner */ +# define S_IRUSR 00400 /* read permission: owner */ +# define S_IWUSR 00200 /* write permission: owner */ +# define S_IXUSR 00100 /* execute permission: owner */ +# define S_IRWXG 00070 /* read, write, execute: group */ +# define S_IRGRP 00040 /* read permission: group */ +# define S_IWGRP 00020 /* write permission: group */ +# define S_IXGRP 00010 /* execute permission: group */ +# define S_IRWXO 00007 /* read, write, execute: other */ +# define S_IROTH 00004 /* read permission: other */ +# define S_IWOTH 00002 /* write permission: other */ +# define S_IXOTH 00001 /* execute permission: other */ +#endif /* !S_IRUSR */ + +#ifdef ZIPINFO /* these are individually checked because SysV doesn't */ +# ifndef S_IFBLK /* have some of them, Microsoft C others, etc. */ +# define S_IFBLK 0060000 /* block special */ +# endif +# ifndef S_IFIFO /* in Borland C, not MSC */ +# define S_IFIFO 0010000 /* fifo */ +# endif +# ifndef S_IFLNK /* in BSD, not SysV */ +# define S_IFLNK 0120000 /* symbolic link */ +# endif +# ifndef S_IFSOCK /* in BSD, not SysV */ +# define S_IFSOCK 0140000 /* socket */ +# endif +# ifndef S_ISUID +# define S_ISUID 04000 /* set user id on execution */ +# endif +# ifndef S_ISGID +# define S_ISGID 02000 /* set group id on execution */ +# endif +# ifndef S_ISVTX +# define S_ISVTX 01000 /* directory permissions control */ +# endif +# ifndef S_ENFMT +# define S_ENFMT S_ISGID /* record locking enforcement flag */ +# endif +#endif /* ZIPINFO */ + + + + + +/**************/ +/* Typedefs */ +/**************/ + +#ifndef _BULL_SOURCE /* Bull has it defined somewhere already */ + typedef unsigned char byte; /* code assumes UNSIGNED bytes */ +#endif /* !_BULL_SOURCE */ + +typedef char boolean; +typedef long longint; +typedef unsigned short UWORD; +typedef unsigned long ULONG; +typedef unsigned char uch; +typedef unsigned short ush; +typedef unsigned long ulg; + +typedef struct min_info { + unsigned unix_attr; + unsigned dos_attr; + int hostnum; + longint offset; + ULONG compr_size; /* compressed size (needed if extended header) */ + ULONG crc; /* crc (needed if extended header) */ + unsigned encrypted : 1; /* file encrypted: decrypt before uncompressing */ + unsigned ExtLocHdr : 1; /* use time instead of CRC for decrypt check */ + unsigned text : 1; /* file is text or binary */ + unsigned lcflag : 1; /* convert filename to lowercase */ +} min_info; + +typedef struct VMStimbuf { + char *revdate; /* (both correspond to Unix modtime/st_mtime) */ + char *credate; +} VMStimbuf; + +/*--------------------------------------------------------------------------- + Zipfile layout declarations. If these headers ever change, make sure the + xxREC_SIZE defines (above) change with them! + ---------------------------------------------------------------------------*/ + + typedef byte local_byte_hdr[ LREC_SIZE ]; +# define L_VERSION_NEEDED_TO_EXTRACT_0 0 +# define L_VERSION_NEEDED_TO_EXTRACT_1 1 +# define L_GENERAL_PURPOSE_BIT_FLAG 2 +# define L_COMPRESSION_METHOD 4 +# define L_LAST_MOD_FILE_TIME 6 +# define L_LAST_MOD_FILE_DATE 8 +# define L_CRC32 10 +# define L_COMPRESSED_SIZE 14 +# define L_UNCOMPRESSED_SIZE 18 +# define L_FILENAME_LENGTH 22 +# define L_EXTRA_FIELD_LENGTH 24 + + typedef byte cdir_byte_hdr[ CREC_SIZE ]; +# define C_VERSION_MADE_BY_0 0 +# define C_VERSION_MADE_BY_1 1 +# define C_VERSION_NEEDED_TO_EXTRACT_0 2 +# define C_VERSION_NEEDED_TO_EXTRACT_1 3 +# define C_GENERAL_PURPOSE_BIT_FLAG 4 +# define C_COMPRESSION_METHOD 6 +# define C_LAST_MOD_FILE_TIME 8 +# define C_LAST_MOD_FILE_DATE 10 +# define C_CRC32 12 +# define C_COMPRESSED_SIZE 16 +# define C_UNCOMPRESSED_SIZE 20 +# define C_FILENAME_LENGTH 24 +# define C_EXTRA_FIELD_LENGTH 26 +# define C_FILE_COMMENT_LENGTH 28 +# define C_DISK_NUMBER_START 30 +# define C_INTERNAL_FILE_ATTRIBUTES 32 +# define C_EXTERNAL_FILE_ATTRIBUTES 34 +# define C_RELATIVE_OFFSET_LOCAL_HEADER 38 + + typedef byte ec_byte_rec[ ECREC_SIZE+4 ]; +/* define SIGNATURE 0 space-holder only */ +# define NUMBER_THIS_DISK 4 +# define NUM_DISK_WITH_START_CENTRAL_DIR 6 +# define NUM_ENTRIES_CENTRL_DIR_THS_DISK 8 +# define TOTAL_ENTRIES_CENTRAL_DIR 10 +# define SIZE_CENTRAL_DIRECTORY 12 +# define OFFSET_START_CENTRAL_DIRECTORY 16 +# define ZIPFILE_COMMENT_LENGTH 20 + + + typedef struct local_file_header { /* LOCAL */ + byte version_needed_to_extract[2]; + UWORD general_purpose_bit_flag; + UWORD compression_method; + UWORD last_mod_file_time; + UWORD last_mod_file_date; + ULONG crc32; + ULONG compressed_size; + ULONG uncompressed_size; + UWORD filename_length; + UWORD extra_field_length; + } local_file_hdr; + + typedef struct central_directory_file_header { /* CENTRAL */ + byte version_made_by[2]; + byte version_needed_to_extract[2]; + UWORD general_purpose_bit_flag; + UWORD compression_method; + UWORD last_mod_file_time; + UWORD last_mod_file_date; + ULONG crc32; + ULONG compressed_size; + ULONG uncompressed_size; + UWORD filename_length; + UWORD extra_field_length; + UWORD file_comment_length; + UWORD disk_number_start; + UWORD internal_file_attributes; + ULONG external_file_attributes; + ULONG relative_offset_local_header; + } cdir_file_hdr; + + typedef struct end_central_dir_record { /* END CENTRAL */ + UWORD number_this_disk; + UWORD num_disk_with_start_central_dir; + UWORD num_entries_centrl_dir_ths_disk; + UWORD total_entries_central_dir; + ULONG size_central_directory; + ULONG offset_start_central_directory; + UWORD zipfile_comment_length; + } ecdir_rec; + + + + + +/*************************/ +/* Function Prototypes */ +/*************************/ + +#ifndef __ +# define __ OF +#endif + +/*--------------------------------------------------------------------------- + Decompression functions: + ---------------------------------------------------------------------------*/ + +int explode (); +void unReduce (); +void unShrink (); + +/*--------------------------------------------------------------------------- + Functions in file_io.c and crypt.c: + ---------------------------------------------------------------------------*/ + +int FillBitBuffer (); +int ReadByte __((UWORD *x)); /* file_io.c */ + +/************/ +/* Macros */ +/************/ + +#ifndef MAX +# define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif + +#ifndef MIN +# define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + + +#define LSEEK(abs_offset) {longint request=(abs_offset)+extra_bytes,\ + inbuf_offset=request%INBUFSIZ, bufstart=request-inbuf_offset;\ + if(request<0) {fprintf(stderr, SeekMsg, ReportMsg); return(3);}\ + else if(bufstart!=cur_zipfile_bufstart)\ + {cur_zipfile_bufstart=lseek(zipfd,bufstart,SEEK_SET);\ + if((incnt=read(zipfd,(char *)inbuf,INBUFSIZ))<=0) return(51);\ + inptr=inbuf+(int)inbuf_offset; incnt-=(int)inbuf_offset;} else\ + {incnt+=(inptr-inbuf)-(int)inbuf_offset; inptr=inbuf+(int)inbuf_offset;}} + +/* + * Seek to the block boundary of the block which includes abs_offset, + * then read block into input buffer and set pointers appropriately. + * If block is already in the buffer, just set the pointers. This macro + * is used by process_end_central_dir (unzip.c) and do_string (misc.c). + * A slightly modified version is embedded within extract_or_test_files + * (unzip.c). ReadByte and readbuf (file_io.c) are compatible. + * + * macro LSEEK(abs_offset) + * ULONG abs_offset; + * { + * longint request = abs_offset + extra_bytes; + * longint inbuf_offset = request % INBUFSIZ; + * longint bufstart = request - inbuf_offset; + * + * if (request < 0) { + * fprintf(stderr, SeekMsg, ReportMsg); + * return(3); /-* 3: severe error in zipfile *-/ + * } else if (bufstart != cur_zipfile_bufstart) { + * cur_zipfile_bufstart = lseek(zipfd, bufstart, SEEK_SET); + * if ((incnt = read(zipfd,inbuf,INBUFSIZ)) <= 0) + * return(51); /-* 51: unexpected EOF *-/ + * inptr = inbuf + (int)inbuf_offset; + * incnt -= (int)inbuf_offset; + * } else { + * incnt += (inptr-inbuf) - (int)inbuf_offset; + * inptr = inbuf + (int)inbuf_offset; + * } + * } + * + */ + + +#define SKIP_(length) if(length&&((error=do_string(length,SKIP))!=0))\ + {error_in_archive=error; if(error>1) return error;} + +/* + * Skip a variable-length field, and report any errors. Used in zipinfo.c + * and unzip.c in several functions. + * + * macro SKIP_(length) + * UWORD length; + * { + * if (length && ((error = do_string(length, SKIP)) != 0)) { + * error_in_archive = error; /-* might be warning *-/ + * if (error > 1) /-* fatal *-/ + * return (error); + * } + * } + * + */ + +#define READBIT(nbits,zdest) {if(nbits>bits_left) FillBitBuffer();\ + zdest=(int)((UWORD)bitbuf&mask_bits[nbits]);bitbuf>>=nbits;bits_left-=nbits;} + +/* + * macro READBIT(nbits,zdest) + * { + * if (nbits > bits_left) + * FillBitBuffer(); + * zdest = (int)((UWORD)bitbuf & mask_bits[nbits]); + * bitbuf >>= nbits; + * bits_left -= nbits; + * } + * + */ + + +#define PEEKBIT(nbits) (nbits>bits_left? (FillBitBuffer(),\ + (UWORD)bitbuf & mask_bits[nbits]) : (UWORD)bitbuf & mask_bits[nbits]) + + +#define NUKE_CRs(buf,len) {register int i,j; for (i=j=0; j<len;\ + (buf)[i++]=(buf)[j++]) if ((buf)[j]=='\r') ++j; len=i;} + +/* + * Remove all the ASCII carriage returns from buffer buf (length len), + * shortening as necessary (note that len gets modified in the process, + * so it CANNOT be an expression). This macro is intended to be used + * BEFORE A_TO_N(); hence the check for CR instead of '\r'. NOTE: The + * if-test gets performed one time too many, but it doesn't matter. + * + * macro NUKE_CRs(buf,len) + * { + * register int i, j; + * + * for (i = j = 0; j < len; (buf)[i++] = (buf)[j++]) + * if ((buf)[j] == CR) + * ++j; + * len = i; + * } + * + */ + + +#define TOLOWER(str1,str2) {char *ps1,*ps2; ps1=(str1)-1; ps2=(str2);\ + while(*++ps1) *ps2++=(char)(isupper((int)(*ps1))?tolower((int)(*ps1)):*ps1);\ + *ps2='\0';} + +/* + * Copy the zero-terminated string in str1 into str2, converting any + * uppercase letters to lowercase as we go. str2 gets zero-terminated + * as well, of course. str1 and str2 may be the same character array. + * + * macro TOLOWER( str1, str2 ) + * { + * char *ps1, *ps2; + * + * ps1 = (str1) - 1; + * ps2 = (str2); + * while (*++ps1) + * *ps2++ = (char)(isupper((int)(*ps1))? tolower((int)(*ps1)) : *ps1); + * *ps2='\0'; + * } + * + * NOTES: This macro makes no assumptions about the characteristics of + * the tolower() function or macro (beyond its existence), nor does it + * make assumptions about the structure of the character set (i.e., it + * should work on EBCDIC machines, too). The fact that either or both + * of isupper() and tolower() may be macros has been taken into account; + * watch out for "side effects" (in the C sense) when modifying this + * macro. + */ + + +#ifndef ascii_to_native +# define ascii_to_native(c) (c) +# define A_TO_N(str1) +#else +# ifndef NATIVE +# define NATIVE "native chars" +# endif +# define A_TO_N(str1) {register unsigned char *ps1;\ + for (ps1=str1; *ps1; ps1++) *ps1=ascii_to_native(*ps1);} +#endif + +/* + * Translate the zero-terminated string in str1 from ASCII to the native + * character set. The translation is performed in-place and uses the + * ascii_to_native macro to translate each character. + * + * macro A_TO_N( str1 ) + * { + * register unsigned char *ps1; + * + * for (ps1 = str1; *ps1; ++ps1) + * *ps1 = ascii_to_native(*ps1); + * } + * + * NOTE: Using the ascii_to_native macro means that is it the only part of + * unzip which knows which translation table (if any) is actually in use + * to produce the native character set. This makes adding new character + * set translation tables easy, insofar as all that is needed is an + * appropriate ascii_to_native macro definition and the translation + * table itself. Currently, the only non-ASCII native character set + * implemented is EBCDIC, but this may not always be so. + */ + +/*************/ +/* Globals */ +/*************/ + +#ifdef MACOS + union work { + struct { + short *Prefix_of; /* (8193 * sizeof(short)) */ + byte *Suffix_of; + byte *Stack; + } shrink; + byte *Slide; + }; +#else + union work { + struct { + short Prefix_of[HSIZE + 2]; /* (8194 * sizeof(short)) */ + byte Suffix_of[HSIZE + 2]; /* also s-f length_nodes (smaller) */ + byte Stack[HSIZE + 2]; /* also s-f distance_nodes (smaller) */ + } shrink; + byte Slide[WSIZE]; + }; +#endif + extern union work area; + +# define prefix_of area.shrink.Prefix_of +# define suffix_of area.shrink.Suffix_of +# define stack area.shrink.Stack +# define slide area.Slide + + extern ULONG crc32val; + extern UWORD mask_bits[]; + extern int bits_left; + extern ULONG bitbuf; + extern boolean zipeof; + diff --git a/source/unzip/unzip.c b/source/unzip/unzip.c new file mode 100644 index 0000000..54695c2 --- /dev/null +++ b/source/unzip/unzip.c @@ -0,0 +1,1224 @@ +/* + * unzip.c -- IO on .zip files using zlib Version 0.15 beta, Mar 19th, 1998, + * + * Read unzip.h for more info + */ + + +//#include <stdio.h> +//#include <stdlib.h> +#include "fs_api.h" +#include "ds2_malloc.h" +#include <string.h> +#include "zlib.h" +#include "unzip.h" +#include "unzipP.h" + +#ifdef STDC +//#include <stddef.h> +//#include <string.h> +//#include <stdlib.h> +#endif + +#ifdef NO_ERRNO_H +extern int errno; +#else +#include <errno.h> +#endif + +const char unz_copyright[] = +" unzip 0.15 Copyright 1998 Gilles Vollant "; + +void unShrink (); +void unReduce (); +int explode (); + +/* + * =========================================================================== + * Read a byte from a gz_stream; update next_in and avail_in. Return EOF for + * end of file. IN assertion: the stream s has been sucessfully opened for + * reading. + */ + + +local int +unzlocal_getByte (FILE * fin, int *pi) +{ + unsigned char c; + int err = fread (&c, 1, 1, fin); + if (err == 1) + { + *pi = (int) c; + return UNZ_OK; + } else + { + if (ferror (fin)) + return UNZ_ERRNO; + else + return UNZ_EOF; + } +} + + +/* + * =========================================================================== + * Reads a long in LSB order from the given gz_stream. Sets + */ +local int +unzlocal_getShort (FILE * fin, uLong * pX) +{ + uLong x; + int i; + int err; + + err = unzlocal_getByte (fin, &i); + x = (uLong) i; + + if (err == UNZ_OK) + err = unzlocal_getByte (fin, &i); + x += ((uLong) i) << 8; + + if (err == UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int +unzlocal_getLong (FILE * fin, uLong * pX) +{ + uLong x; + int i; + int err; + + err = unzlocal_getByte (fin, &i); + x = (uLong) i; + + if (err == UNZ_OK) + err = unzlocal_getByte (fin, &i); + x += ((uLong) i) << 8; + + if (err == UNZ_OK) + err = unzlocal_getByte (fin, &i); + x += ((uLong) i) << 16; + + if (err == UNZ_OK) + err = unzlocal_getByte (fin, &i); + x += ((uLong) i) << 24; + + if (err == UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + + +/* My own strcmpi / strcasecmp */ +local int +strcmpcasenosensitive_internal (const char *fileName1, const char *fileName2) +{ + for (;;) + { + char c1 = *(fileName1++); + char c2 = *(fileName2++); + if ((c1 >= 'a') && (c1 <= 'z')) + c1 -= 0x20; + if ((c2 >= 'a') && (c2 <= 'z')) + c2 -= 0x20; + if (c1 == '\0') + return ((c2 == '\0') ? 0 : -1); + if (c2 == '\0') + return 1; + if (c1 < c2) + return -1; + if (c1 > c2) + return 1; + } +} + + +#ifdef CASESENSITIVITYDEFAULT_NO +#define CASESENSITIVITYDEFAULTVALUE 2 +#else +#define CASESENSITIVITYDEFAULTVALUE 1 +#endif + +#ifndef STRCMPCASENOSENTIVEFUNCTION +#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal +#endif + +/* + * Compare two filename (fileName1,fileName2). If iCaseSenisivity = 1, + * comparision is case sensitivity (like strcmp) If iCaseSenisivity = 2, + * comparision is not case sensitivity (like strcmpi or strcasecmp) If + * iCaseSenisivity = 0, case sensitivity is defaut of your operating system + * (like 1 on Unix, 2 on Windows) + * + */ +extern int ZEXPORT +unzStringFileNameCompare (const char *fileName1, const char *fileName2, int iCaseSensitivity) +{ + if (iCaseSensitivity == 0) + iCaseSensitivity = CASESENSITIVITYDEFAULTVALUE; + + if (iCaseSensitivity == 1) + return strcmp (fileName1, fileName2); + + return STRCMPCASENOSENTIVEFUNCTION (fileName1, fileName2); +} + +#define BUFREADCOMMENT (0x400) + +/* + * Locate the Central directory of a zipfile (at the end, just before the + * global comment) + */ +local uLong +unzlocal_SearchCentralDir (FILE * fin) +{ + unsigned char *buf; + uLong uSizeFile; + uLong uBackRead; + uLong uMaxBack = 0xffff; /* maximum size of global comment */ + uLong uPosFound = 0; + + if (fseek (fin, 0, SEEK_END) != 0) + return 0; + + uSizeFile = ftell (fin); + + if (uMaxBack > uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char *) ALLOC (BUFREADCOMMENT + 4); + if (buf == NULL) + return 0; + + uBackRead = 4; + while (uBackRead < uMaxBack) + { + uLong uReadSize, uReadPos; + int i; + if (uBackRead + BUFREADCOMMENT > uMaxBack) + uBackRead = uMaxBack; + else + uBackRead += BUFREADCOMMENT; + uReadPos = uSizeFile - uBackRead; + + uReadSize = ((BUFREADCOMMENT + 4) < (uSizeFile - uReadPos)) ? + (BUFREADCOMMENT + 4) : (uSizeFile - uReadPos); + if (fseek (fin, uReadPos, SEEK_SET) != 0) + break; + + if (fread (buf, (uInt) uReadSize, 1, fin) != 1) + break; + + for (i = 0; i < (int) uReadSize - 3; i++) + if (((*(buf + i)) == 0x50) && ((*(buf + i + 1)) == 0x4b) && + ((*(buf + i + 2)) == 0x05) && ((*(buf + i + 3)) == 0x06)) + { + uPosFound = uReadPos + i; + break; + } + if (uPosFound != 0) + break; + } + TRYFREE (buf); + return uPosFound; +} + +/* + * Open a Zip file. path contain the full pathname (by example, on a Windows + * NT computer "c:\\test\\zlib109.zip" or on an Unix computer + * "zlib/zlib109.zip". If the zipfile cannot be opened (file don't exist or + * in not valid), the return value is NULL. Else, the return value is a + * unzFile Handle, usable with other function of this unzip package. + */ +extern unzFile ZEXPORT +unzOpen (const char *path) +{ + unz_s us; + unz_s *s; + uLong central_pos, uL; + FILE *fin; + + uLong number_disk;/* number of the current dist, used for + * spaning ZIP, unsupported, always 0 */ + uLong number_disk_with_CD; /* number the the disk with + * central dir, used for + * spaning ZIP, unsupported, + * always 0 */ + uLong number_entry_CD; /* total number of entries in the + * central dir (same than + * number_entry on nospan) */ + + int err = UNZ_OK; + + if (unz_copyright[0] != ' ') + return NULL; + + fin = fopen (path, "rb"); + if (fin == NULL) + return NULL; + + central_pos = unzlocal_SearchCentralDir (fin); + if (central_pos == 0) + err = UNZ_ERRNO; + + if (fseek (fin, central_pos, SEEK_SET) != 0) + err = UNZ_ERRNO; + + /* the signature, already checked */ + if (unzlocal_getLong (fin, &uL) != UNZ_OK) + err = UNZ_ERRNO; + + /* number of this disk */ + if (unzlocal_getShort (fin, &number_disk) != UNZ_OK) + err = UNZ_ERRNO; + + /* number of the disk with the start of the central directory */ + if (unzlocal_getShort (fin, &number_disk_with_CD) != UNZ_OK) + err = UNZ_ERRNO; + + /* total number of entries in the central dir on this disk */ + if (unzlocal_getShort (fin, &us.gi.number_entry) != UNZ_OK) + err = UNZ_ERRNO; + + /* total number of entries in the central dir */ + if (unzlocal_getShort (fin, &number_entry_CD) != UNZ_OK) + err = UNZ_ERRNO; + + if ((number_entry_CD != us.gi.number_entry) || + (number_disk_with_CD != 0) || + (number_disk != 0)) + err = UNZ_BADZIPFILE; + + /* size of the central directory */ + if (unzlocal_getLong (fin, &us.size_central_dir) != UNZ_OK) + err = UNZ_ERRNO; + + /* + * offset of start of central directory with respect to the starting disk + * number + */ + if (unzlocal_getLong (fin, &us.offset_central_dir) != UNZ_OK) + err = UNZ_ERRNO; + + /* zipfile comment length */ + if (unzlocal_getShort (fin, &us.gi.size_comment) != UNZ_OK) + err = UNZ_ERRNO; + + if ((central_pos < us.offset_central_dir + us.size_central_dir) && + (err == UNZ_OK)) + err = UNZ_BADZIPFILE; + + if (err != UNZ_OK) + { + fclose (fin); + return NULL; + } + us.file = fin; + us.byte_before_the_zipfile = central_pos - + (us.offset_central_dir + us.size_central_dir); + us.central_pos = central_pos; + us.pfile_in_zip_read = NULL; + + + s = (unz_s *) ALLOC (sizeof (unz_s)); + *s = us; + unzGoToFirstFile ((unzFile) s); + return (unzFile) s; +} + + +/* + * Close a ZipFile opened with unzipOpen. If there is files inside the .Zip + * opened with unzipOpenCurrentFile (see later), these files MUST be closed + * with unzipCloseCurrentFile before call unzipClose. return UNZ_OK if there + * is no problem. + */ +extern int ZEXPORT +unzClose (unzFile file) +{ + unz_s *s; + if (file == NULL) + return UNZ_PARAMERROR; + s = (unz_s *) file; + + if (s->pfile_in_zip_read != NULL) + unzCloseCurrentFile (file); + + fclose (s->file); + TRYFREE (s); + return UNZ_OK; +} + + +/* + * Write info about the ZipFile in the *pglobal_info structure. No + * preparation of the structure is needed return UNZ_OK if there is no + * problem. + */ +extern int ZEXPORT +unzGetGlobalInfo (unzFile file, unz_global_info * pglobal_info) +{ + unz_s *s; + if (file == NULL) + return UNZ_PARAMERROR; + s = (unz_s *) file; + *pglobal_info = s->gi; + return UNZ_OK; +} + + +/* + * Translate date/time from Dos format to tm_unz (readable more easilty) + */ +local void +unzlocal_DosDateToTmuDate (uLong ulDosDate, tm_unz * ptm) +{ + uLong uDate; + uDate = (uLong) (ulDosDate >> 16); + ptm->tm_mday = (uInt) (uDate & 0x1f); + ptm->tm_mon = (uInt) ((((uDate) & 0x1E0) / 0x20) - 1); + ptm->tm_year = (uInt) (((uDate & 0x0FE00) / 0x0200) + 1980); + + ptm->tm_hour = (uInt) ((ulDosDate & 0xF800) / 0x800); + ptm->tm_min = (uInt) ((ulDosDate & 0x7E0) / 0x20); + ptm->tm_sec = (uInt) (2 * (ulDosDate & 0x1f)); +} + +/* + * Get Info about the current file in the zipfile, with internal only info + */ +local int unzlocal_GetCurrentFileInfoInternal +OF ((unzFile file, + unz_file_info * pfile_info, + unz_file_info_internal + * pfile_info_internal, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); + + local int unzlocal_GetCurrentFileInfoInternal ( + unzFile file, + unz_file_info * pfile_info, + unz_file_info_internal * pfile_info_internal, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize) +{ + unz_s *s; + unz_file_info file_info; + unz_file_info_internal file_info_internal; + int err = UNZ_OK; + uLong uMagic; + long lSeek = 0; + + if (file == NULL) + return UNZ_PARAMERROR; + s = (unz_s *) file; + if (fseek (s->file, s->pos_in_central_dir + s->byte_before_the_zipfile, SEEK_SET) != 0) + err = UNZ_ERRNO; + + + /* we check the magic */ + if (err == UNZ_OK) + { + if (unzlocal_getLong (s->file, &uMagic) != UNZ_OK) + err = UNZ_ERRNO; + else if (uMagic != 0x02014b50) + err = UNZ_BADZIPFILE; + } + if (unzlocal_getShort (s->file, &file_info.version) != UNZ_OK) + err = UNZ_ERRNO; + + if (unzlocal_getShort (s->file, &file_info.version_needed) != UNZ_OK) + err = UNZ_ERRNO; + + if (unzlocal_getShort (s->file, &file_info.flag) != UNZ_OK) + err = UNZ_ERRNO; + + if (unzlocal_getShort (s->file, &file_info.compression_method) != UNZ_OK) + err = UNZ_ERRNO; + + if (unzlocal_getLong (s->file, &file_info.dosDate) != UNZ_OK) + err = UNZ_ERRNO; + + unzlocal_DosDateToTmuDate (file_info.dosDate, &file_info.tmu_date); + + if (unzlocal_getLong (s->file, &file_info.crc) != UNZ_OK) + err = UNZ_ERRNO; + + if (unzlocal_getLong (s->file, &file_info.compressed_size) != UNZ_OK) + err = UNZ_ERRNO; + + if (unzlocal_getLong (s->file, &file_info.uncompressed_size) != UNZ_OK) + err = UNZ_ERRNO; + + if (unzlocal_getShort (s->file, &file_info.size_filename) != UNZ_OK) + err = UNZ_ERRNO; + + if (unzlocal_getShort (s->file, &file_info.size_file_extra) != UNZ_OK) + err = UNZ_ERRNO; + + if (unzlocal_getShort (s->file, &file_info.size_file_comment) != UNZ_OK) + err = UNZ_ERRNO; + + if (unzlocal_getShort (s->file, &file_info.disk_num_start) != UNZ_OK) + err = UNZ_ERRNO; + + if (unzlocal_getShort (s->file, &file_info.internal_fa) != UNZ_OK) + err = UNZ_ERRNO; + + if (unzlocal_getLong (s->file, &file_info.external_fa) != UNZ_OK) + err = UNZ_ERRNO; + + if (unzlocal_getLong (s->file, &file_info_internal.offset_curfile) != UNZ_OK) + err = UNZ_ERRNO; + + lSeek += file_info.size_filename; + if ((err == UNZ_OK) && (szFileName != NULL)) + { + uLong uSizeRead; + if (file_info.size_filename < fileNameBufferSize) + { + *(szFileName + file_info.size_filename) = '\0'; + uSizeRead = file_info.size_filename; + } else + uSizeRead = fileNameBufferSize; + + if ((file_info.size_filename > 0) && (fileNameBufferSize > 0)) + if (fread (szFileName, (uInt) uSizeRead, 1, s->file) != 1) + err = UNZ_ERRNO; + lSeek -= uSizeRead; + } + if ((err == UNZ_OK) && (extraField != NULL)) + { + uLong uSizeRead; + if (file_info.size_file_extra < extraFieldBufferSize) + uSizeRead = file_info.size_file_extra; + else + uSizeRead = extraFieldBufferSize; + + if (lSeek != 0) + { + if (fseek (s->file, lSeek, SEEK_CUR) == 0) + lSeek = 0; + else + err = UNZ_ERRNO; + } + if ((file_info.size_file_extra > 0) && (extraFieldBufferSize > 0)) + if (fread (extraField, (uInt) uSizeRead, 1, s->file) != 1) + err = UNZ_ERRNO; + lSeek += file_info.size_file_extra - uSizeRead; + } else + lSeek += file_info.size_file_extra; + + + if ((err == UNZ_OK) && (szComment != NULL)) + { + uLong uSizeRead; + if (file_info.size_file_comment < commentBufferSize) + { + *(szComment + file_info.size_file_comment) = '\0'; + uSizeRead = file_info.size_file_comment; + } else + uSizeRead = commentBufferSize; + + if (lSeek != 0) + { + if (fseek (s->file, lSeek, SEEK_CUR) == 0) + lSeek = 0; + else + err = UNZ_ERRNO; + } + if ((file_info.size_file_comment > 0) && (commentBufferSize > 0)) + if (fread (szComment, (uInt) uSizeRead, 1, s->file) != 1) + err = UNZ_ERRNO; + lSeek += file_info.size_file_comment - uSizeRead; + } else + lSeek += file_info.size_file_comment; + + if ((err == UNZ_OK) && (pfile_info != NULL)) + *pfile_info = file_info; + + if ((err == UNZ_OK) && (pfile_info_internal != NULL)) + *pfile_info_internal = file_info_internal; + + return err; +} + + + +/* + * Write info about the ZipFile in the *pglobal_info structure. No + * preparation of the structure is needed return UNZ_OK if there is no + * problem. + */ +extern int ZEXPORT +unzGetCurrentFileInfo ( + unzFile file, + unz_file_info * pfile_info, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize) +{ + return unzlocal_GetCurrentFileInfoInternal (file, pfile_info, NULL, + szFileName, fileNameBufferSize, + extraField, extraFieldBufferSize, + szComment, commentBufferSize); +} + +/* + * Set the current file of the zipfile to the first file. return UNZ_OK if + * there is no problem + */ +extern int ZEXPORT +unzGoToFirstFile (unzFile file) +{ + int err = UNZ_OK; + unz_s *s; + if (file == NULL) + return UNZ_PARAMERROR; + s = (unz_s *) file; + s->pos_in_central_dir = s->offset_central_dir; + s->num_file = 0; + err = unzlocal_GetCurrentFileInfoInternal (file, &s->cur_file_info, + &s->cur_file_info_internal, + NULL, 0, NULL, 0, NULL, 0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + + +/* + * Set the current file of the zipfile to the next file. return UNZ_OK if + * there is no problem return UNZ_END_OF_LIST_OF_FILE if the actual file was + * the latest. + */ +extern int ZEXPORT +unzGoToNextFile (unzFile file) +{ + unz_s *s; + int err; + + if (file == NULL) + return UNZ_PARAMERROR; + s = (unz_s *) file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + if (s->num_file + 1 == s->gi.number_entry) + return UNZ_END_OF_LIST_OF_FILE; + + s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + + s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment; + s->num_file++; + err = unzlocal_GetCurrentFileInfoInternal (file, &s->cur_file_info, + &s->cur_file_info_internal, + NULL, 0, NULL, 0, NULL, 0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + + +/* + * Try locate the file szFileName in the zipfile. For the iCaseSensitivity + * signification, see unzipStringFileNameCompare + * + * return value : UNZ_OK if the file is found. It becomes the current file. + * UNZ_END_OF_LIST_OF_FILE if the file is not found + */ +extern int ZEXPORT +unzLocateFile ( + unzFile file, + const char *szFileName, + int iCaseSensitivity) +{ + unz_s *s; + int err; + + + uLong num_fileSaved; + uLong pos_in_central_dirSaved; + + + if (file == NULL) + return UNZ_PARAMERROR; + + if (strlen (szFileName) >= UNZ_MAXFILENAMEINZIP) + return UNZ_PARAMERROR; + + s = (unz_s *) file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + + num_fileSaved = s->num_file; + pos_in_central_dirSaved = s->pos_in_central_dir; + + err = unzGoToFirstFile (file); + + while (err == UNZ_OK) + { + char szCurrentFileName[UNZ_MAXFILENAMEINZIP + 1]; + unzGetCurrentFileInfo (file, NULL, + szCurrentFileName, sizeof (szCurrentFileName) - 1, + NULL, 0, NULL, 0); + if (unzStringFileNameCompare (szCurrentFileName, + szFileName, iCaseSensitivity) == 0) + return UNZ_OK; + err = unzGoToNextFile (file); + } + + s->num_file = num_fileSaved; + s->pos_in_central_dir = pos_in_central_dirSaved; + return err; +} + + +/* + * Read the local header of the current zipfile Check the coherency of the + * local header and info in the end of central directory about this file + * store in *piSizeVar the size of extra info in local header (filename and + * size of extra field data) + */ +local int +unzlocal_CheckCurrentFileCoherencyHeader ( + unz_s * s, + uInt * piSizeVar, + uLong * poffset_local_extrafield, + uInt * psize_local_extrafield) +{ + uLong uMagic, uData, uFlags; + uLong size_filename; + uLong size_extra_field; + int err = UNZ_OK; + + *piSizeVar = 0; + *poffset_local_extrafield = 0; + *psize_local_extrafield = 0; + + if (fseek (s->file, s->cur_file_info_internal.offset_curfile + + s->byte_before_the_zipfile, SEEK_SET) != 0) + return UNZ_ERRNO; + + + if (err == UNZ_OK) + { + if (unzlocal_getLong (s->file, &uMagic) != UNZ_OK) + err = UNZ_ERRNO; + else if (uMagic != 0x04034b50) + err = UNZ_BADZIPFILE; + } + + if (unzlocal_getShort (s->file, &uData) != UNZ_OK) + err = UNZ_ERRNO; + /* + * else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion)) + * err=UNZ_BADZIPFILE; + */ + if (unzlocal_getShort (s->file, &uFlags) != UNZ_OK) + err = UNZ_ERRNO; + + if (unzlocal_getShort (s->file, &uData) != UNZ_OK) + err = UNZ_ERRNO; + else if ((err == UNZ_OK) && (uData != s->cur_file_info.compression_method)) + err = UNZ_BADZIPFILE; + + if ((err == UNZ_OK) && + s->cur_file_info.compression_method > Z_DEFLATED) + err = UNZ_BADZIPFILE; + + if (unzlocal_getLong (s->file, &uData) != UNZ_OK) /* date/time */ + err = UNZ_ERRNO; + + if (unzlocal_getLong (s->file, &uData) != UNZ_OK) /* crc */ + err = UNZ_ERRNO; + else if ((err == UNZ_OK) && (uData != s->cur_file_info.crc) && + ((uFlags & 8) == 0)) + err = UNZ_BADZIPFILE; + + if (unzlocal_getLong (s->file, &uData) != UNZ_OK) /* size compr */ + err = UNZ_ERRNO; + else if ((err == UNZ_OK) && (uData != s->cur_file_info.compressed_size) && + ((uFlags & 8) == 0)) + err = UNZ_BADZIPFILE; + + if (unzlocal_getLong (s->file, &uData) != UNZ_OK) /* size uncompr */ + err = UNZ_ERRNO; + else if ((err == UNZ_OK) && (uData != s->cur_file_info.uncompressed_size) && + ((uFlags & 8) == 0)) + err = UNZ_BADZIPFILE; + + + if (unzlocal_getShort (s->file, &size_filename) != UNZ_OK) + err = UNZ_ERRNO; + else if ((err == UNZ_OK) && (size_filename != s->cur_file_info.size_filename)) + err = UNZ_BADZIPFILE; + + *piSizeVar += (uInt) size_filename; + + if (unzlocal_getShort (s->file, &size_extra_field) != UNZ_OK) + err = UNZ_ERRNO; + *poffset_local_extrafield = s->cur_file_info_internal.offset_curfile + + SIZEZIPLOCALHEADER + size_filename; + *psize_local_extrafield = (uInt) size_extra_field; + + *piSizeVar += (uInt) size_extra_field; + + return err; +} + +/* + * Open for reading data the current file in the zipfile. If there is no + * error and the file is opened, the return value is UNZ_OK. + */ +extern int ZEXPORT +unzOpenCurrentFile (unzFile file) +{ + int err = UNZ_OK; + uInt iSizeVar; + unz_s *s; + file_in_zip_read_info_s *pfile_in_zip_read_info; + uLong offset_local_extrafield; /* offset of the local extra + * field */ + uInt size_local_extrafield; /* size of the local extra + * field */ + + if (file == NULL) + return UNZ_PARAMERROR; + s = (unz_s *) file; + if (!s->current_file_ok) + return UNZ_PARAMERROR; + + if (s->pfile_in_zip_read != NULL) + unzCloseCurrentFile (file); + + if (unzlocal_CheckCurrentFileCoherencyHeader (s, &iSizeVar, + &offset_local_extrafield, &size_local_extrafield) != UNZ_OK) + return UNZ_BADZIPFILE; + + pfile_in_zip_read_info = (file_in_zip_read_info_s *) + ALLOC (sizeof (file_in_zip_read_info_s)); + if (pfile_in_zip_read_info == NULL) + return UNZ_INTERNALERROR; + + pfile_in_zip_read_info->read_buffer = (char *) ALLOC (UNZ_BUFSIZE); + pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; + pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; + pfile_in_zip_read_info->pos_local_extrafield = 0; + + if (pfile_in_zip_read_info->read_buffer == NULL) + { + TRYFREE (pfile_in_zip_read_info); + return UNZ_INTERNALERROR; + } + pfile_in_zip_read_info->stream_initialised = 0; + + if (s->cur_file_info.compression_method > Z_DEFLATED) + err = UNZ_BADZIPFILE; + + pfile_in_zip_read_info->crc32_wait = s->cur_file_info.crc; + pfile_in_zip_read_info->crc32 = 0; + pfile_in_zip_read_info->compression_method = + s->cur_file_info.compression_method; + pfile_in_zip_read_info->file = s->file; + pfile_in_zip_read_info->byte_before_the_zipfile = s->byte_before_the_zipfile; + + pfile_in_zip_read_info->stream.total_out = 0; + + switch (s->cur_file_info.compression_method) + { + case UNZ_STORED: + break; + case UNZ_SHRUNK: + break; + case UNZ_REDUCED1: + case UNZ_REDUCED2: + case UNZ_REDUCED3: + case UNZ_REDUCED4: + break; + case UNZ_IMPLODED: + break; + case UNZ_DEFLATED: + pfile_in_zip_read_info->stream.zalloc = (alloc_func) 0; + pfile_in_zip_read_info->stream.zfree = (free_func) 0; + pfile_in_zip_read_info->stream.opaque = (voidpf) 0; + + err = inflateInit2 (&pfile_in_zip_read_info->stream, -MAX_WBITS); + if (err == Z_OK) + pfile_in_zip_read_info->stream_initialised = 1; + /* + * windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. In unzip, i don't wait absolutely + * Z_STREAM_END because I known the size of both compressed and + * uncompressed data + */ + break; + default: + return UNZ_INTERNALERROR; + break; + } + pfile_in_zip_read_info->rest_read_compressed = + s->cur_file_info.compressed_size; + pfile_in_zip_read_info->rest_read_uncompressed = + s->cur_file_info.uncompressed_size; + + pfile_in_zip_read_info->pos_in_zipfile = + s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + + iSizeVar; + + pfile_in_zip_read_info->stream.avail_in = (uInt) 0; + s->pfile_in_zip_read = pfile_in_zip_read_info; + return UNZ_OK; +} + + +/* + * Read bytes from the current file. buf contain buffer where data must be + * copied len the size of buf. + * + * return the number of byte copied if somes bytes are copied return 0 if the + * end of file was reached return <0 with error code if there is an error + * (UNZ_ERRNO for IO error, or zLib error for uncompress error) + */ + +file_in_zip_read_info_s *pfile_in_zip_read_info = NULL; +unz_s *pUnzip = NULL; +extern int ZEXPORT +unzReadCurrentFile ( + unzFile file, + voidp buf, + unsigned len) +{ + int err = UNZ_OK; + uInt iRead = 0; + unz_s *s; + if (file == NULL) + return UNZ_PARAMERROR; + s = (unz_s *) file; + pUnzip = s; + pfile_in_zip_read_info = s->pfile_in_zip_read; + + if (pfile_in_zip_read_info == NULL) + return UNZ_PARAMERROR; + + + if ((pfile_in_zip_read_info->read_buffer == NULL)) + return UNZ_END_OF_LIST_OF_FILE; + if (len == 0) + return 0; + + pfile_in_zip_read_info->stream.next_out = (Bytef *) buf; + + pfile_in_zip_read_info->stream.avail_out = (uInt) len; + + if (len > pfile_in_zip_read_info->rest_read_uncompressed) + pfile_in_zip_read_info->stream.avail_out = + (uInt) pfile_in_zip_read_info->rest_read_uncompressed; + + while (pfile_in_zip_read_info->stream.avail_out > 0 && err == UNZ_OK) + { + switch (pfile_in_zip_read_info->compression_method) + { + case UNZ_STORED: + case UNZ_DEFLATED: + if ((pfile_in_zip_read_info->stream.avail_in == 0) && + (pfile_in_zip_read_info->rest_read_compressed > 0)) + { + uInt uReadThis = UNZ_BUFSIZE; + if (pfile_in_zip_read_info->rest_read_compressed < uReadThis) + uReadThis = (uInt) pfile_in_zip_read_info->rest_read_compressed; + if (uReadThis == 0) + return UNZ_EOF; + if (fseek (pfile_in_zip_read_info->file, + pfile_in_zip_read_info->pos_in_zipfile + + pfile_in_zip_read_info->byte_before_the_zipfile, SEEK_SET) != 0) + return UNZ_ERRNO; + if (fread (pfile_in_zip_read_info->read_buffer, uReadThis, 1, + pfile_in_zip_read_info->file) != 1) + return UNZ_ERRNO; + pfile_in_zip_read_info->pos_in_zipfile += uReadThis; + + pfile_in_zip_read_info->rest_read_compressed -= uReadThis; + + pfile_in_zip_read_info->stream.next_in = + (Bytef *) pfile_in_zip_read_info->read_buffer; + pfile_in_zip_read_info->stream.avail_in = (uInt) uReadThis; + } + break; + } + switch (pfile_in_zip_read_info->compression_method) + { + case UNZ_STORED: + { + uInt uDoCopy, i; + if (pfile_in_zip_read_info->stream.avail_out < + pfile_in_zip_read_info->stream.avail_in) + uDoCopy = pfile_in_zip_read_info->stream.avail_out; + else + uDoCopy = pfile_in_zip_read_info->stream.avail_in; + + for (i = 0; i < uDoCopy; i++) + *(pfile_in_zip_read_info->stream.next_out + i) = + *(pfile_in_zip_read_info->stream.next_in + i); + + pfile_in_zip_read_info->crc32 = crc32 (pfile_in_zip_read_info->crc32, + pfile_in_zip_read_info->stream.next_out, + uDoCopy); + pfile_in_zip_read_info->rest_read_uncompressed -= uDoCopy; + pfile_in_zip_read_info->stream.avail_in -= uDoCopy; + pfile_in_zip_read_info->stream.avail_out -= uDoCopy; + pfile_in_zip_read_info->stream.next_out += uDoCopy; + pfile_in_zip_read_info->stream.next_in += uDoCopy; + pfile_in_zip_read_info->stream.total_out += uDoCopy; + iRead += uDoCopy; + break; + } + case UNZ_SHRUNK: + iRead = pfile_in_zip_read_info->rest_read_uncompressed; + unShrink (); + break; + case UNZ_REDUCED1: + case UNZ_REDUCED2: + case UNZ_REDUCED3: + case UNZ_REDUCED4: + iRead = pfile_in_zip_read_info->rest_read_uncompressed; + unReduce (); + break; + case UNZ_IMPLODED: + iRead = pfile_in_zip_read_info->rest_read_uncompressed; + err = explode (); + break; + case UNZ_DEFLATED: + { + uLong uTotalOutBefore, uTotalOutAfter; + const Bytef *bufBefore; + uLong uOutThis; + int flush = Z_SYNC_FLUSH; + + uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; + bufBefore = pfile_in_zip_read_info->stream.next_out; + + /* + * if ((pfile_in_zip_read_info->rest_read_uncompressed == + * pfile_in_zip_read_info->stream.avail_out) && + * (pfile_in_zip_read_info->rest_read_compressed == 0)) flush = + * Z_FINISH; + */ + err = inflate (&pfile_in_zip_read_info->stream, flush); + + uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; + uOutThis = uTotalOutAfter - uTotalOutBefore; + + pfile_in_zip_read_info->crc32 = + crc32 (pfile_in_zip_read_info->crc32, bufBefore, + (uInt) (uOutThis)); + + pfile_in_zip_read_info->rest_read_uncompressed -= + uOutThis; + + iRead += (uInt) (uTotalOutAfter - uTotalOutBefore); + + if (err == Z_STREAM_END) + return (iRead == 0) ? UNZ_EOF : iRead; + if (err != Z_OK) + break; + break; + } + default: + return (UNZ_EOF); + } + } + + if (err == Z_OK) + return iRead; + return err; +} + + +/* + * Give the current position in uncompressed data + */ +extern z_off_t ZEXPORT +unztell (unzFile file) +{ + unz_s *s; + file_in_zip_read_info_s *pfile_in_zip_read_info; + if (file == NULL) + return UNZ_PARAMERROR; + s = (unz_s *) file; + pfile_in_zip_read_info = s->pfile_in_zip_read; + + if (pfile_in_zip_read_info == NULL) + return UNZ_PARAMERROR; + + return (z_off_t) pfile_in_zip_read_info->stream.total_out; +} + + +/* + * return 1 if the end of file was reached, 0 elsewhere + */ +extern int ZEXPORT +unzeof (unzFile file) +{ + unz_s *s; + file_in_zip_read_info_s *pfile_in_zip_read_info; + if (file == NULL) + return UNZ_PARAMERROR; + s = (unz_s *) file; + pfile_in_zip_read_info = s->pfile_in_zip_read; + + if (pfile_in_zip_read_info == NULL) + return UNZ_PARAMERROR; + + if (pfile_in_zip_read_info->rest_read_uncompressed == 0) + return 1; + else + return 0; +} + + + +/* + * Read extra field from the current file (opened by unzOpenCurrentFile) This + * is the local-header version of the extra field (sometimes, there is more + * info in the local-header version than in the central-header) + * + * if buf==NULL, it return the size of the local extra field that can be read + * + * if buf!=NULL, len is the size of the buffer, the extra header is copied in + * buf. the return value is the number of bytes copied in buf, or (if <0) the + * error code + */ +extern int ZEXPORT +unzGetLocalExtrafield ( + unzFile file, + voidp buf, + unsigned len) +{ + unz_s *s; + file_in_zip_read_info_s *pfile_in_zip_read_info; + uInt read_now; + uLong size_to_read; + + if (file == NULL) + return UNZ_PARAMERROR; + s = (unz_s *) file; + pfile_in_zip_read_info = s->pfile_in_zip_read; + + if (pfile_in_zip_read_info == NULL) + return UNZ_PARAMERROR; + + size_to_read = (pfile_in_zip_read_info->size_local_extrafield - + pfile_in_zip_read_info->pos_local_extrafield); + + if (buf == NULL) + return (int) size_to_read; + + if (len > size_to_read) + read_now = (uInt) size_to_read; + else + read_now = (uInt) len; + + if (read_now == 0) + return 0; + + if (fseek (pfile_in_zip_read_info->file, + pfile_in_zip_read_info->offset_local_extrafield + + pfile_in_zip_read_info->pos_local_extrafield, SEEK_SET) != 0) + return UNZ_ERRNO; + + if (fread (buf, (uInt) size_to_read, 1, pfile_in_zip_read_info->file) != 1) + return UNZ_ERRNO; + + return (int) read_now; +} + +/* + * Close the file in zip opened with unzipOpenCurrentFile Return UNZ_CRCERROR + * if all the file was read but the CRC is not good + */ +extern int ZEXPORT +unzCloseCurrentFile (unzFile file) +{ + int err = UNZ_OK; + + unz_s *s; + file_in_zip_read_info_s *pfile_in_zip_read_info; + if (file == NULL) + return UNZ_PARAMERROR; + s = (unz_s *) file; + pfile_in_zip_read_info = s->pfile_in_zip_read; + + if (pfile_in_zip_read_info == NULL) + return UNZ_PARAMERROR; + + + if (pfile_in_zip_read_info->rest_read_uncompressed == 0) + { + if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) + err = UNZ_CRCERROR; + } + TRYFREE (pfile_in_zip_read_info->read_buffer); + pfile_in_zip_read_info->read_buffer = NULL; + if (pfile_in_zip_read_info->stream_initialised) + inflateEnd (&pfile_in_zip_read_info->stream); + + pfile_in_zip_read_info->stream_initialised = 0; + TRYFREE (pfile_in_zip_read_info); + + s->pfile_in_zip_read = NULL; + + return err; +} + + +/* + * Get the global comment string of the ZipFile, in the szComment buffer. + * uSizeBuf is the size of the szComment buffer. return the number of byte + * copied or an error code <0 + */ +extern int ZEXPORT +unzGetGlobalComment ( + unzFile file, + char *szComment, + uLong uSizeBuf) +{ + unz_s *s; + uLong uReadThis; + if (file == NULL) + return UNZ_PARAMERROR; + s = (unz_s *) file; + + uReadThis = uSizeBuf; + if (uReadThis > s->gi.size_comment) + uReadThis = s->gi.size_comment; + + if (fseek (s->file, s->central_pos + 22, SEEK_SET) != 0) + return UNZ_ERRNO; + + if (uReadThis > 0) + { + *szComment = '\0'; + if (fread (szComment, (uInt) uReadThis, 1, s->file) != 1) + return UNZ_ERRNO; + } + if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) + *(szComment + s->gi.size_comment) = '\0'; + return (int) uReadThis; +} diff --git a/source/unzip/unzip.h b/source/unzip/unzip.h new file mode 100644 index 0000000..f629782 --- /dev/null +++ b/source/unzip/unzip.h @@ -0,0 +1,285 @@ +/* unzip.h -- IO for uncompress .zip files using zlib + Version 0.15 beta, Mar 19th, 1998, + + Copyright (C) 1998 Gilles Vollant + + This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g + WinZip, InfoZip tools and compatible. + Encryption and multi volume ZipFile (span) are not supported. + Old compressions used by old PKZip 1.x are not supported + + THIS IS AN ALPHA VERSION. AT THIS STAGE OF DEVELOPPEMENT, SOMES API OR STRUCTURE + CAN CHANGE IN FUTURE VERSION !! + I WAIT FEEDBACK at mail info@winimage.com + Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution + + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + +*/ +/* for more info about .ZIP format, see + ftp://ftp.cdrom.com/pub/infozip/doc/appnote-970311-iz.zip + PkWare has also a specification at : + ftp://ftp.pkware.com/probdesc.zip */ + +#ifndef _unz_H +#define _unz_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +#include "zlib.h" +#endif + +#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) +/* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ +typedef struct TagunzFile__ { int unused; } unzFile__; +typedef unzFile__ *unzFile; +#else +typedef voidp unzFile; +#endif + + +#define UNZ_OK (0) +#define UNZ_END_OF_LIST_OF_FILE (-100) +#define UNZ_ERRNO (Z_ERRNO) +#define UNZ_EOF (0) +#define UNZ_PARAMERROR (-102) +#define UNZ_BADZIPFILE (-103) +#define UNZ_INTERNALERROR (-104) +#define UNZ_CRCERROR (-105) + +#define UNZ_STORED 0 /* compression methods */ +#define UNZ_SHRUNK 1 +#define UNZ_REDUCED1 2 +#define UNZ_REDUCED2 3 +#define UNZ_REDUCED3 4 +#define UNZ_REDUCED4 5 +#define UNZ_IMPLODED 6 +#define UNZ_TOKENIZED 7 +#define UNZ_DEFLATED 8 + +/* tm_unz contain date/time info */ +typedef struct tm_unz_s +{ + uInt tm_sec; /* seconds after the minute - [0,59] */ + uInt tm_min; /* minutes after the hour - [0,59] */ + uInt tm_hour; /* hours since midnight - [0,23] */ + uInt tm_mday; /* day of the month - [1,31] */ + uInt tm_mon; /* months since January - [0,11] */ + uInt tm_year; /* years - [1980..2044] */ +} tm_unz; + +/* unz_global_info structure contain global data about the ZIPfile + These data comes from the end of central dir */ +typedef struct unz_global_info_s +{ + uLong number_entry; /* total number of entries in + the central dir on this disk */ + uLong size_comment; /* size of the global comment of the zipfile */ +} unz_global_info; + + +/* unz_file_info contain information about a file in the zipfile */ +typedef struct unz_file_info_s +{ + uLong version; /* version made by 2 bytes */ + uLong version_needed; /* version needed to extract 2 bytes */ + uLong flag; /* general purpose bit flag 2 bytes */ + uLong compression_method; /* compression method 2 bytes */ + uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ + uLong crc; /* crc-32 4 bytes */ + uLong compressed_size; /* compressed size 4 bytes */ + uLong uncompressed_size; /* uncompressed size 4 bytes */ + uLong size_filename; /* filename length 2 bytes */ + uLong size_file_extra; /* extra field length 2 bytes */ + uLong size_file_comment; /* file comment length 2 bytes */ + + uLong disk_num_start; /* disk number start 2 bytes */ + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ + + tm_unz tmu_date; +} unz_file_info; + +extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1, + const char* fileName2, + int iCaseSensitivity)); +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) +*/ + + +extern unzFile ZEXPORT unzOpen OF((const char *path)); +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows NT computer "c:\\zlib\\zlib111.zip" or on an Unix computer + "zlib/zlib111.zip". + If the zipfile cannot be opened (file don't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. +*/ + +extern int ZEXPORT unzClose OF((unzFile file)); +/* + Close a ZipFile opened with unzipOpen. + If there is files inside the .Zip opened with unzOpenCurrentFile (see later), + these files MUST be closed with unzipCloseCurrentFile before call unzipClose. + return UNZ_OK if there is no problem. */ + +extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, + unz_global_info *pglobal_info)); +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ + + +extern int ZEXPORT unzGetGlobalComment OF((unzFile file, + char *szComment, + uLong uSizeBuf)); +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ + + +/***************************************************************************/ +/* Unzip package allow you browse the directory of the zipfile */ + +extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ + +extern int ZEXPORT unzGoToNextFile OF((unzFile file)); +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ + +extern int ZEXPORT unzLocateFile OF((unzFile file, + const char *szFileName, + int iCaseSensitivity)); +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ + + +extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, + unz_file_info *pfile_info, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); +/* + Get Info about the current file + if pfile_info!=NULL, the *pfile_info structure will contain somes info about + the current file + if szFileName!=NULL, the filemane string will be copied in szFileName + (fileNameBufferSize is the size of the buffer) + if extraField!=NULL, the extra field information will be copied in extraField + (extraFieldBufferSize is the size of the buffer). + This is the Central-header version of the extra field + if szComment!=NULL, the comment string of the file will be copied in szComment + (commentBufferSize is the size of the buffer) +*/ + +/***************************************************************************/ +/* for reading the content of the current zipfile, you can open it, read data + from it, and close it (you can close it before reading all the file) + */ + +extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); +/* + Open for reading data the current file in the zipfile. + If there is no error, the return value is UNZ_OK. +*/ + +extern int ZEXPORT unzCloseCurrentFile OF((unzFile file)); +/* + Close the file in zip opened with unzOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ + + +extern int ZEXPORT unzReadCurrentFile OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read bytes from the current file (opened by unzOpenCurrentFile) + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ + +extern z_off_t ZEXPORT unztell OF((unzFile file)); +/* + Give the current position in uncompressed data +*/ + +extern int ZEXPORT unzeof OF((unzFile file)); +/* + return 1 if the end of file was reached, 0 elsewhere +*/ + +extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read extra field from the current file (opened by unzOpenCurrentFile) + This is the local-header version of the extra field (sometimes, there is + more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ + +#ifdef __cplusplus +} +#endif + +#endif /* _unz_H */ diff --git a/source/unzip/unzipP.h b/source/unzip/unzipP.h new file mode 100644 index 0000000..c44e3cb --- /dev/null +++ b/source/unzip/unzipP.h @@ -0,0 +1,125 @@ +#ifndef _UNZIPP_H_ +#define _UNZIPP_H_ + +#include "ds2_malloc.h" +#include "unzip.h" + +#ifndef local +#define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + + + +#if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) && \ + !defined(CASESENSITIVITYDEFAULT_NO) +#define CASESENSITIVITYDEFAULT_NO +#endif + + +#ifndef UNZ_BUFSIZE +#define UNZ_BUFSIZE (16384) +#endif + +#ifndef UNZ_MAXFILENAMEINZIP +#define UNZ_MAXFILENAMEINZIP (256) +#endif + +#ifndef ALLOC +#define ALLOC(size) (malloc(size)) +#endif +#ifndef TRYFREE +#define TRYFREE(p) {if (p) free(p);} +#endif + +#define SIZECENTRALDIRITEM (0x2e) +#define SIZEZIPLOCALHEADER (0x1e) + + +/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ + +#ifndef SEEK_CUR +#define SEEK_CUR 1 +#endif + +#ifndef SEEK_END +#define SEEK_END 2 +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +/* unz_file_info_interntal contain internal info about a file in zipfile */ +typedef struct unz_file_info_internal_s +{ + uLong offset_curfile; /* relative offset of local header 4 + * bytes */ +} unz_file_info_internal; + + +/* + * file_in_zip_read_info_s contain internal information about a file in + * zipfile, when reading and decompress it + */ +typedef struct +{ + char *read_buffer;/* internal buffer for compressed data */ + z_stream stream; /* zLib stream structure for inflate */ + + uLong pos_in_zipfile; /* position in byte on the zipfile, + * for fseek */ + uLong stream_initialised; /* flag set if stream structure is + * initialised */ + + uLong offset_local_extrafield; /* offset of the local extra + * field */ + uInt size_local_extrafield; /* size of the local extra + * field */ + uLong pos_local_extrafield; /* position in the local + * extra field in read */ + + uLong crc32; /* crc32 of all data uncompressed */ + uLong crc32_wait; /* crc32 we must obtain after decompress all */ + uLong rest_read_compressed; /* number of byte to be + * decompressed */ + uLong rest_read_uncompressed; /* number of byte to be + * obtained after decomp */ + FILE *file; /* io structore of the zipfile */ + uLong compression_method; /* compression method (0==store) */ + uLong byte_before_the_zipfile; /* byte before the zipfile, + * (>0 for sfx) */ +} file_in_zip_read_info_s; + + +/* + * unz_s contain internal information about the zipfile + */ +typedef struct +{ + FILE *file; /* io structore of the zipfile */ + unz_global_info gi; /* public global information */ + uLong byte_before_the_zipfile; /* byte before the zipfile, + * (>0 for sfx) */ + uLong num_file; /* number of the current file in the zipfile */ + uLong pos_in_central_dir; /* pos of the current file in the + * central dir */ + uLong current_file_ok; /* flag about the usability of the + * current file */ + uLong central_pos;/* position of the beginning of the central + * dir */ + + uLong size_central_dir; /* size of the central directory */ + uLong offset_central_dir; /* offset of start of central + * directory with respect to the + * starting disk number */ + + unz_file_info cur_file_info; /* public info about the current file + * in zip */ + unz_file_info_internal cur_file_info_internal; /* private info about it */ + file_in_zip_read_info_s *pfile_in_zip_read; /* structure about the + * current file if we are + * decompressing it */ +} unz_s; + +#endif |