|
|
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.