|
|
1.1 root 1: /* unzip.c -- decompress files in gzip or pkzip format.
2: * Copyright (C) 1992-1993 Jean-loup Gailly
3: * This is free software; you can redistribute it and/or modify it under the
4: * terms of the GNU General Public License, see the file COPYING.
5: *
6: * The code in this file is derived from the file funzip.c written
7: * and put in the public domain by Mark Adler.
8: */
9:
10: /*
11: This version can extract files in gzip or pkzip format.
12: For the latter, only the first entry is extracted, and it has to be
13: either deflated or stored.
14: */
15:
16: #ifndef lint
17: static char rcsid[] = "$Id: unzip.c,v 0.10 1993/02/24 18:23:13 jloup Exp $";
18: #endif
19:
20: #include "tailor.h"
21: #include "gzip.h"
22: #include "crypt.h"
23:
24: #include <stdio.h>
25:
26: /* PKZIP header definitions */
27: #define LOCSIG 0x04034b50L /* four-byte lead-in (lsb first) */
28: #define LOCFLG 6 /* offset of bit flag */
29: #define CRPFLG 1 /* bit for encrypted entry */
30: #define EXTFLG 8 /* bit for extended local header */
31: #define LOCHOW 8 /* offset of compression method */
32: #define LOCTIM 10 /* file mod time (for decryption) */
33: #define LOCCRC 14 /* offset of crc */
34: #define LOCSIZ 18 /* offset of compressed size */
35: #define LOCLEN 22 /* offset of uncompressed length */
36: #define LOCFIL 26 /* offset of file name field length */
37: #define LOCEXT 28 /* offset of extra field length */
38: #define LOCHDR 30 /* size of local header, including sig */
39: #define EXTHDR 16 /* size of extended local header, inc sig */
40:
41:
42: /* Globals */
43:
44: int decrypt; /* flag to turn on decryption */
45: char *key; /* not used--needed to link crypt.c */
46: int pkzip = 0; /* set for a pkzip file */
47: int extended = 0; /* set if extended local header */
48:
49: /* ===========================================================================
50: * Check zip file and advance inptr to the start of the compressed data.
51: * Get ofname from the local header if necessary.
52: */
53: int check_zipfile(in)
54: int in; /* input file descriptors */
55: {
56: uch *h = inbuf + inptr; /* first local header */
57:
58: ifd = in;
59:
60: /* Check validity of local header, and skip name and extra fields */
61: inptr += LOCHDR + SH(h + LOCFIL) + SH(h + LOCEXT);
62:
63: if (inptr > insize || LG(h) != LOCSIG) {
64: error("input not a zip file or empty");
65: }
66: method = h[LOCHOW];
67: if (method != STORED && method != DEFLATED) {
68: error("first entry not deflated or stored -- use unzip");
69: }
70:
71: /* If entry encrypted, decrypt and validate encryption header */
72: if ((decrypt = h[LOCFLG] & CRPFLG) != 0) {
73: fprintf(stderr, "encrypted file, not yet supported.\n");
74: exit_code = ERROR;
75: return -1;
76: }
77:
78: /* Save flags for unzip() */
79: extended = (h[LOCFLG] & EXTFLG) != 0;
80: pkzip = 1;
81:
82: /* Get ofname and time stamp from local header (to be done) */
83: return 0;
84: }
85:
86: /* ===========================================================================
87: * Unzip in to out. This routine works on both gzip and pkzip files.
88: *
89: * IN assertions: the buffer inbuf contains already the beginning of
90: * the compressed data, from offsets inptr to insize-1 included.
91: * The magic header has already been checked. The output buffer is cleared.
92: */
93: void unzip(in, out)
94: int in, out; /* input and output file descriptors */
95: {
96: ulg orig_crc = 0; /* original crc */
97: ulg orig_len = 0; /* original uncompressed length */
98: int n;
99: uch buf[EXTHDR]; /* extended local header */
100:
101: ifd = in;
102: ofd = out;
103:
104: updcrc(NULL, 0); /* initialize crc */
105:
106: if (pkzip && !extended) { /* crc and length at the end otherwise */
107: orig_crc = LG(inbuf + LOCCRC);
108: orig_len = LG(inbuf + LOCLEN);
109: }
110:
111: /* Decompress */
112: if (method == DEFLATED) {
113:
114: int res = inflate();
115:
116: if (res == 3) {
117: error("out of memory");
118: } else if (res != 0) {
119: error("invalid compressed data--format violated");
120: }
121:
122: } else if (pkzip && method == STORED) {
123:
124: register ulg n = LG(inbuf + LOCLEN);
125:
126: if (n != LG(inbuf + LOCSIZ) - (decrypt ? RAND_HEAD_LEN : 0)) {
127:
128: fprintf(stderr, "len %ld, siz %ld\n", n, LG(inbuf + LOCSIZ));
129: error("invalid compressed data--length mismatch");
130: }
131: while (n--) {
132: uch c = (uch)get_byte();
133: #ifdef CRYPT
134: if (decrypt) zdecode(c);
135: #endif
136: put_char(c);
137: }
138: flush_window();
139: } else {
140: error("internal error, invalid method");
141: }
142:
143: /* Get the crc and original length */
144: if (!pkzip) {
145: /* crc32 (see algorithm.doc)
146: * uncompressed input size modulo 2^32
147: */
148: for (n = 0; n < 8; n++) {
149: buf[n] = (uch)get_byte(); /* may cause an error if EOF */
150: }
151: orig_crc = LG(buf);
152: orig_len = LG(buf+4);
153:
154: } else if (extended) { /* If extended header, check it */
155: /* signature - 4bytes: 0x50 0x4b 0x07 0x08
156: * CRC-32 value
157: * compressed size 4-bytes
158: * uncompressed size 4-bytes
159: */
160: for (n = 0; n < EXTHDR; n++) {
161: buf[n] = (uch)get_byte(); /* may cause an error if EOF */
162: }
163: orig_crc = LG(buf+4);
164: orig_len = LG(buf+12);
165: }
166:
167: /* Validate decompression */
168: if (orig_crc != updcrc(outbuf, 0)) {
169: error("invalid compressed data--crc error");
170: }
171: if (orig_len != bytes_out) {
172: error("invalid compressed data--length error");
173: }
174:
175: /* Check if there are more entries in a pkzip file */
176: if (pkzip && inptr + 4 < insize && LG(inbuf+inptr) == LOCSIG) {
177: if (to_stdout) {
178: fprintf(stderr,
179: "warning: zip file has more than one entry--rest ignored\n");
180: } else {
181: /* Don't destroy the input zip file */
182: error("zip file has more than one entry");
183: }
184: }
185: extended = pkzip = 0; /* for next file */
186: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.