1 /* 2 Copyright (c) 1990-2002 Info-ZIP. All rights reserved. 3 4 See the accompanying file LICENSE, version 2000-Apr-09 or later 5 (the contents of which are also included in unzip.h) for terms of use. 6 If, for some reason, all these files are missing, the Info-ZIP license 7 also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html 8 */ 9 /* funzip.c -- by Mark Adler */ 10 11 #define VERSION "3.94 of 20 January 2002" 12 13 14 /* Copyright history: 15 - Starting with UnZip 5.41 of 16-April-2000, this source file 16 is covered by the Info-Zip LICENSE cited above. 17 - Prior versions of this source file, found in UnZip source packages 18 up to UnZip 5.40, were put in the public domain. 19 The original copyright note by Mark Adler was: 20 "You can do whatever you like with this source file, 21 though I would prefer that if you modify it and 22 redistribute it that you include comments to that effect 23 with your name and the date. Thank you." 24 25 History: 26 vers date who what 27 ---- --------- -------------- ------------------------------------ 28 1.0 13 Aug 92 M. Adler really simple unzip filter. 29 1.1 13 Aug 92 M. Adler cleaned up somewhat, give help if 30 stdin not redirected, warn if more 31 zip file entries after the first. 32 1.2 15 Aug 92 M. Adler added check of lengths for stored 33 entries, added more help. 34 1.3 16 Aug 92 M. Adler removed redundant #define's, added 35 decryption. 36 1.4 27 Aug 92 G. Roelofs added exit(0). 37 1.5 1 Sep 92 K. U. Rommel changed read/write modes for OS/2. 38 1.6 6 Sep 92 G. Roelofs modified to use dummy crypt.c and 39 crypt.h instead of -DCRYPT. 40 1.7 23 Sep 92 G. Roelofs changed to use DOS_OS2; included 41 crypt.c under MS-DOS. 42 1.8 9 Oct 92 M. Adler improved inflation error msgs. 43 1.9 17 Oct 92 G. Roelofs changed ULONG/UWORD/byte to ulg/ush/uch; 44 renamed inflate_entry() to inflate(); 45 adapted to use new, in-place zdecode. 46 2.0 22 Oct 92 M. Adler allow filename argument, prompt for 47 passwords and don't echo, still allow 48 command-line password entry, but as an 49 option. 50 2.1 23 Oct 92 J-l. Gailly fixed crypt/store bug, 51 G. Roelofs removed crypt.c under MS-DOS, fixed 52 decryption check to compare single byte. 53 2.2 28 Oct 92 G. Roelofs removed declaration of key. 54 2.3 14 Dec 92 M. Adler replaced fseek (fails on stdin for SCO 55 Unix V.3.2.4). added quietflg for 56 inflate.c. 57 3.0 11 May 93 M. Adler added gzip support 58 3.1 9 Jul 93 K. U. Rommel fixed OS/2 pipe bug (PIPE_ERROR) 59 3.2 4 Sep 93 G. Roelofs moved crc_32_tab[] to tables.h; used FOPx 60 from unzip.h; nuked OUTB macro and outbuf; 61 replaced flush(); inlined FlushOutput(); 62 renamed decrypt to encrypted 63 3.3 29 Sep 93 G. Roelofs replaced ReadByte() with NEXTBYTE macro; 64 revised (restored?) flush(); added FUNZIP 65 3.4 21 Oct 93 G. Roelofs renamed quietflg to qflag; changed outcnt, 66 H. Gessau second updcrc() arg and flush() arg to ulg; 67 added inflate_free(); added "g =" to null 68 getc(in) to avoid compiler warnings 69 3.5 31 Oct 93 H. Gessau changed DOS_OS2 to DOS_NT_OS2 70 3.6 6 Dec 93 H. Gessau added "near" to mask_bits[] 71 3.7 9 Dec 93 G. Roelofs added extent typecasts to fwrite() checks 72 3.8 28 Jan 94 GRR/JlG initialized g variable in main() for gcc 73 3.81 22 Feb 94 M. Hanning-Lee corrected usage message 74 3.82 27 Feb 94 G. Roelofs added some typecasts to avoid warnings 75 3.83 22 Jul 94 G. Roelofs changed fprintf to macro for DLLs 76 - 2 Aug 94 - public release with UnZip 5.11 77 - 28 Aug 94 - public release with UnZip 5.12 78 3.84 1 Oct 94 K. U. Rommel changes for Metaware High C 79 3.85 29 Oct 94 G. Roelofs changed fprintf macro to Info 80 3.86 7 May 95 K. Davis RISCOS patches; 81 P. Kienitz Amiga patches 82 3.87 12 Aug 95 G. Roelofs inflate_free(), DESTROYGLOBALS fixes 83 3.88 4 Sep 95 C. Spieler reordered macro to work around MSC 5.1 bug 84 3.89 22 Nov 95 PK/CS ifdef'd out updcrc() for ASM_CRC 85 3.9 17 Dec 95 G. Roelofs modified for USE_ZLIB (new fillinbuf()) 86 - 30 Apr 96 - public release with UnZip 5.2 87 3.91 17 Aug 96 G. Roelofs main() -> return int (Peter Seebach) 88 3.92 13 Apr 97 G. Roelofs minor cosmetic fixes to messages 89 - 22 Apr 97 - public release with UnZip 5.3 90 - 31 May 97 - public release with UnZip 5.31 91 3.93 20 Sep 97 G. Roelofs minor cosmetic fixes to messages 92 - 3 Nov 97 - public release with UnZip 5.32 93 - 28 Nov 98 - public release with UnZip 5.4 94 - 16 Apr 00 - public release with UnZip 5.41 95 - 14 Jan 01 - public release with UnZip 5.42 96 3.94 20 Feb 01 C. Spieler added support for Deflate64(tm) 97 */ 98 99 100 /* 101 102 All funzip does is take a zipfile from stdin and decompress the 103 first entry to stdout. The entry has to be either deflated or 104 stored. If the entry is encrypted, then the decryption password 105 must be supplied on the command line as the first argument. 106 107 funzip needs to be linked with inflate.o and crypt.o compiled from 108 the unzip source. If decryption is desired, the full version of 109 crypt.c (and crypt.h) from zcrypt28.zip or later must be used. 110 111 */ 112 113 #ifndef FUNZIP 114 # define FUNZIP 115 #endif 116 #define UNZIP_INTERNAL 117 #include "unzip.h" 118 #include "crypt.h" 119 #include "ttyio.h" 120 121 #ifdef EBCDIC 122 # undef EBCDIC /* don't need ebcdic[] */ 123 #endif 124 #include "tables.h" /* crc_32_tab[] */ 125 126 #ifndef USE_ZLIB /* zlib's function is called inflate(), too */ 127 # define UZinflate inflate 128 #endif 129 130 /* PKZIP header definitions */ 131 #define ZIPMAG 0x4b50 /* two-byte zip lead-in */ 132 #define LOCREM 0x0403 /* remaining two bytes in zip signature */ 133 #define LOCSIG 0x04034b50L /* full signature */ 134 #define LOCFLG 4 /* offset of bit flag */ 135 #define CRPFLG 1 /* bit for encrypted entry */ 136 #define EXTFLG 8 /* bit for extended local header */ 137 #define LOCHOW 6 /* offset of compression method */ 138 #define LOCTIM 8 /* file mod time (for decryption) */ 139 #define LOCCRC 12 /* offset of crc */ 140 #define LOCSIZ 16 /* offset of compressed size */ 141 #define LOCLEN 20 /* offset of uncompressed length */ 142 #define LOCFIL 24 /* offset of file name field length */ 143 #define LOCEXT 26 /* offset of extra field length */ 144 #define LOCHDR 28 /* size of local header, including LOCREM */ 145 #define EXTHDR 16 /* size of extended local header, inc sig */ 146 147 /* GZIP header definitions */ 148 #define GZPMAG 0x8b1f /* two-byte gzip lead-in */ 149 #define GZPHOW 0 /* offset of method number */ 150 #define GZPFLG 1 /* offset of gzip flags */ 151 #define GZPMUL 2 /* bit for multiple-part gzip file */ 152 #define GZPISX 4 /* bit for extra field present */ 153 #define GZPISF 8 /* bit for filename present */ 154 #define GZPISC 16 /* bit for comment present */ 155 #define GZPISE 32 /* bit for encryption */ 156 #define GZPTIM 2 /* offset of Unix file modification time */ 157 #define GZPEXF 6 /* offset of extra flags */ 158 #define GZPCOS 7 /* offset of operating system compressed on */ 159 #define GZPHDR 8 /* length of minimal gzip header */ 160 161 #ifdef THEOS 162 /* Macros cause stack overflow in compiler */ 163 ush SH(uch* p) { return ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8)); } 164 ulg LG(uch* p) { return ((ulg)(SH(p)) | ((ulg)(SH((p)+2)) << 16)); } 165 #else /* !THEOS */ 166 /* Macros for getting two-byte and four-byte header values */ 167 #define SH(p) ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8)) 168 #define LG(p) ((ulg)(SH(p)) | ((ulg)(SH((p)+2)) << 16)) 169 #endif /* ?THEOS */ 170 171 /* Function prototypes */ 172 static void err OF((int, char *)); 173 #if (defined(USE_DEFLATE64) && defined(__16BIT__)) 174 static int partflush OF((uch *rawbuf, unsigned w)); 175 #endif 176 int main OF((int, char **)); 177 178 /* Globals */ 179 FILE *out; /* output file (*in moved to G struct) */ 180 ulg outsiz; /* total bytes written to out */ 181 int encrypted; /* flag to turn on decryption */ 182 183 /* Masks for inflate.c */ 184 ZCONST ush near mask_bits[] = { 185 0x0000, 186 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, 187 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff 188 }; 189 190 191 #ifdef USE_ZLIB 192 193 int fillinbuf(__G) 194 __GDEF 195 /* Fill input buffer for pull-model inflate() in zlib. Return the number of 196 * bytes in inbuf. */ 197 { 198 /* GRR: check return value from fread(): same as read()? check errno? */ 199 if ((G.incnt = fread((char *)G.inbuf, 1, INBUFSIZ, G.in)) <= 0) 200 return 0; 201 G.inptr = G.inbuf; 202 203 #if CRYPT 204 if (encrypted) { 205 uch *p; 206 int n; 207 208 for (n = G.incnt, p = G.inptr; n--; p++) 209 zdecode(*p); 210 } 211 #endif /* CRYPT */ 212 213 return G.incnt; 214 215 } 216 217 #endif /* USE_ZLIB */ 218 219 220 #if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB)) 221 #ifdef USE_ZLIB 222 ZCONST uLongf *get_crc_table() 223 { 224 return (ZCONST uLongf *)crc_32_tab; 225 } 226 #else /* !USE_ZLIB */ 227 ZCONST ulg near *get_crc_table() 228 { 229 return crc_32_tab; 230 } 231 #endif /* ?USE_ZLIB */ 232 #endif /* !USE_ZLIB || USE_OWN_CRCTAB */ 233 234 235 static void err(n, m) 236 int n; 237 char *m; 238 /* Exit on error with a message and a code */ 239 { 240 Info(slide, 1, ((char *)slide, "funzip error: %s\n", m)); 241 DESTROYGLOBALS(); 242 EXIT(n); 243 } 244 245 246 #if (defined(USE_DEFLATE64) && defined(__16BIT__)) 247 248 static int partflush(rawbuf, w) 249 uch *rawbuf; /* start of buffer area to flush */ 250 extent w; /* number of bytes to flush */ 251 { 252 G.crc32val = crc32(G.crc32val, rawbuf, (extent)w); 253 if (fwrite((char *)rawbuf,1,(extent)w,out) != (extent)w && !PIPE_ERROR) 254 err(9, "out of space on stdout"); 255 outsiz += w; 256 return 0; 257 } 258 259 260 int flush(w) /* used by inflate.c (FLUSH macro) */ 261 ulg w; /* number of bytes to flush */ 262 { 263 uch *rawbuf; 264 int ret; 265 266 /* On 16-bit systems (MSDOS, OS/2 1.x), the standard C library functions 267 * cannot handle writes of 64k blocks at once. For these systems, the 268 * blocks to flush are split into pieces of 32k or less. 269 */ 270 rawbuf = slide; 271 while (w > 0x8000L) { 272 ret = partflush(rawbuf, 0x8000); 273 if (ret != PK_OK) 274 return ret; 275 w -= 0x8000L; 276 rawbuf += (unsigned)0x8000; 277 } 278 return partflush(rawbuf, (extent)w); 279 } /* end function flush() */ 280 281 #else /* !(USE_DEFLATE64 && __16BIT__) */ 282 283 int flush(w) /* used by inflate.c (FLUSH macro) */ 284 ulg w; /* number of bytes to flush */ 285 { 286 G.crc32val = crc32(G.crc32val, slide, (extent)w); 287 if (fwrite((char *)slide,1,(extent)w,out) != (extent)w && !PIPE_ERROR) 288 err(9, "out of space on stdout"); 289 outsiz += w; 290 return 0; 291 } 292 293 #endif /* ?(USE_DEFLATE64 && __16BIT__) */ 294 295 296 int main(argc, argv) 297 int argc; 298 char **argv; 299 /* Given a zipfile on stdin, decompress the first entry to stdout. */ 300 { 301 ush n; 302 uch h[LOCHDR]; /* first local header (GZPHDR < LOCHDR) */ 303 int g = 0; /* true if gzip format */ 304 unsigned method = 0; /* initialized here to shut up gcc warning */ 305 #if CRYPT 306 char *s = " [-password]"; 307 char *p; /* password */ 308 #else /* !CRYPT */ 309 char *s = ""; 310 #endif /* ?CRYPT */ 311 CONSTRUCTGLOBALS(); 312 313 /* skip executable name */ 314 argc--; 315 argv++; 316 317 #if CRYPT 318 /* get the command line password, if any */ 319 p = (char *)NULL; 320 if (argc && **argv == '-') 321 { 322 argc--; 323 p = 1 + *argv++; 324 } 325 #endif /* CRYPT */ 326 327 #ifdef MALLOC_WORK 328 /* The following expression is a cooked-down simplyfication of the 329 calculation for the work area size of UnZip (see unzip.c). For 330 fUnZip, the work area does not need to match the granularity 331 of the complex unshrink structures, because it only supports 332 inflation. But, like in UnZip, the zcalloc() wrapper function 333 is needed for the allocation, to support the 64kByte buffer on 334 16-bit systems. 335 */ 336 # define UZ_SLIDE_CHUNK (sizeof(shrint)+sizeof(uch)+sizeof(uch)) 337 # define UZ_NUMOF_CHUNKS (unsigned)( (WSIZE+UZ_SLIDE_CHUNK-1)/UZ_SLIDE_CHUNK ) 338 G.area.Slide = (uch *)zcalloc(UZ_NUMOF_CHUNKS, UZ_SLIDE_CHUNK); 339 # undef UZ_SLIDE_CHUNK 340 # undef UZ_NUMOF_CHUNKS 341 #endif 342 343 /* if no file argument and stdin not redirected, give the user help */ 344 if (argc == 0 && isatty(0)) 345 { 346 Info(slide, 1, ((char *)slide, "fUnZip (filter UnZip), version %s\n", 347 VERSION)); 348 Info(slide, 1, ((char *)slide, "usage: ... | funzip%s | ...\n", s)); 349 Info(slide, 1, ((char *)slide, " ... | funzip%s > outfile\n", s)); 350 Info(slide, 1, ((char *)slide, " funzip%s infile.zip > outfile\n",s)); 351 Info(slide, 1, ((char *)slide, " funzip%s infile.gz > outfile\n", s)); 352 Info(slide, 1, ((char *)slide, "Extracts to stdout the gzip file or first\ 353 zip entry of stdin or the given file.\n")); 354 DESTROYGLOBALS(); 355 EXIT(3); 356 } 357 358 /* prepare to be a binary filter */ 359 if (argc) 360 { 361 if ((G.in = fopen(*argv, FOPR)) == (FILE *)NULL) 362 err(2, "cannot find input file"); 363 } 364 else 365 { 366 #ifdef DOS_FLX_NLM_OS2_W32 367 #if (defined(__HIGHC__) && !defined(FLEXOS)) 368 setmode(stdin, _BINARY); 369 #else 370 setmode(0, O_BINARY); /* some buggy C libraries require BOTH setmode() */ 371 #endif /* call AND the fdopen() in binary mode :-( */ 372 #endif /* DOS_FLX_NLM_OS2_W32 */ 373 374 #ifdef RISCOS 375 G.in = stdin; 376 #else 377 if ((G.in = fdopen(0, FOPR)) == (FILE *)NULL) 378 err(2, "cannot find stdin"); 379 #endif 380 } 381 382 #ifdef DOS_FLX_H68_NLM_OS2_W32 383 #if (defined(__HIGHC__) && !defined(FLEXOS)) 384 setmode(stdout, _BINARY); 385 #else 386 setmode(1, O_BINARY); 387 #endif 388 #endif /* DOS_FLX_H68_NLM_OS2_W32 */ 389 390 #ifdef RISCOS 391 out = stdout; 392 #else 393 if ((out = fdopen(1, FOPW)) == (FILE *)NULL) 394 err(2, "cannot write to stdout"); 395 #endif 396 397 /* read local header, check validity, and skip name and extra fields */ 398 n = getc(G.in); n |= getc(G.in) << 8; 399 if (n == ZIPMAG) 400 { 401 if (fread((char *)h, 1, LOCHDR, G.in) != LOCHDR || SH(h) != LOCREM) 402 err(3, "invalid zipfile"); 403 switch (method = SH(h + LOCHOW)) { 404 case STORED: 405 case DEFLATED: 406 #ifdef USE_DEFLATE64 407 case ENHDEFLATED: 408 #endif 409 break; 410 default: 411 err(3, "first entry not deflated or stored--cannot unpack"); 412 break; 413 } 414 for (n = SH(h + LOCFIL); n--; ) g = getc(G.in); 415 for (n = SH(h + LOCEXT); n--; ) g = getc(G.in); 416 g = 0; 417 encrypted = h[LOCFLG] & CRPFLG; 418 } 419 else if (n == GZPMAG) 420 { 421 if (fread((char *)h, 1, GZPHDR, G.in) != GZPHDR) 422 err(3, "invalid gzip file"); 423 if ((method = h[GZPHOW]) != DEFLATED && method != ENHDEFLATED) 424 err(3, "gzip file not deflated"); 425 if (h[GZPFLG] & GZPMUL) 426 err(3, "cannot handle multi-part gzip files"); 427 if (h[GZPFLG] & GZPISX) 428 { 429 n = getc(G.in); n |= getc(G.in) << 8; 430 while (n--) g = getc(G.in); 431 } 432 if (h[GZPFLG] & GZPISF) 433 while ((g = getc(G.in)) != 0 && g != EOF) ; 434 if (h[GZPFLG] & GZPISC) 435 while ((g = getc(G.in)) != 0 && g != EOF) ; 436 g = 1; 437 encrypted = h[GZPFLG] & GZPISE; 438 } 439 else 440 err(3, "input not a zip or gzip file"); 441 442 /* if entry encrypted, decrypt and validate encryption header */ 443 if (encrypted) 444 #if CRYPT 445 { 446 ush i, e; 447 448 if (p == (char *)NULL) { 449 if ((p = (char *)malloc(IZ_PWLEN+1)) == (char *)NULL) 450 err(1, "out of memory"); 451 else if ((p = getp("Enter password: ", p, IZ_PWLEN+1)) == (char *)NULL) 452 err(1, "no tty to prompt for password"); 453 } 454 #if (defined(USE_ZLIB) && !defined(USE_OWN_CRCTAB)) 455 /* initialize crc_32_tab pointer for decryption */ 456 CRC_32_TAB = (ZCONST ulg Far *)get_crc_table(); 457 #endif 458 init_keys(p); 459 for (i = 0; i < RAND_HEAD_LEN; i++) 460 e = NEXTBYTE; 461 if (e != (ush)(h[LOCFLG] & EXTFLG ? h[LOCTIM + 1] : h[LOCCRC + 3])) 462 err(3, "incorrect password for first entry"); 463 } 464 #else /* !CRYPT */ 465 err(3, "cannot decrypt entry (need to recompile with full crypt.c)"); 466 #endif /* ?CRYPT */ 467 468 /* prepare output buffer and crc */ 469 G.outptr = slide; 470 G.outcnt = 0L; 471 outsiz = 0L; 472 G.crc32val = CRCVAL_INITIAL; 473 474 /* decompress */ 475 if (g || h[LOCHOW]) 476 { /* deflated entry */ 477 int r; 478 479 #ifdef USE_ZLIB 480 /* need to allocate and prepare input buffer */ 481 if ((G.inbuf = (uch *)malloc(INBUFSIZ)) == (uch *)NULL) 482 err(1, "out of memory"); 483 #endif /* USE_ZLIB */ 484 if ((r = UZinflate(__G__ (method == ENHDEFLATED))) != 0) { 485 if (r == 3) 486 err(1, "out of memory"); 487 else 488 err(4, "invalid compressed data--format violated"); 489 } 490 inflate_free(__G); 491 } 492 else 493 { /* stored entry */ 494 register ulg n; 495 496 n = LG(h + LOCLEN); 497 #if CRYPT 498 if (n != LG(h + LOCSIZ) - (encrypted ? RAND_HEAD_LEN : 0)) { 499 #else 500 if (n != LG(h + LOCSIZ)) { 501 #endif 502 Info(slide, 1, ((char *)slide, "len %ld, siz %ld\n", n, LG(h + LOCSIZ))); 503 err(4, "invalid compressed data--length mismatch"); 504 } 505 while (n--) { 506 ush c = getc(G.in); 507 #if CRYPT 508 if (encrypted) 509 zdecode(c); 510 #endif 511 *G.outptr++ = (uch)c; 512 #if (defined(USE_DEFLATE64) && defined(__16BIT__)) 513 if (++G.outcnt == (WSIZE>>1)) /* do FlushOutput() */ 514 #else 515 if (++G.outcnt == WSIZE) /* do FlushOutput() */ 516 #endif 517 { 518 G.crc32val = crc32(G.crc32val, slide, (extent)G.outcnt); 519 if (fwrite((char *)slide, 1,(extent)G.outcnt,out) != (extent)G.outcnt 520 && !PIPE_ERROR) 521 err(9, "out of space on stdout"); 522 outsiz += G.outcnt; 523 G.outptr = slide; 524 G.outcnt = 0L; 525 } 526 } 527 } 528 if (G.outcnt) /* flush one last time; no need to reset G.outptr/outcnt */ 529 { 530 G.crc32val = crc32(G.crc32val, slide, (extent)G.outcnt); 531 if (fwrite((char *)slide, 1,(extent)G.outcnt,out) != (extent)G.outcnt 532 && !PIPE_ERROR) 533 err(9, "out of space on stdout"); 534 outsiz += G.outcnt; 535 } 536 fflush(out); 537 538 /* if extended header, get it */ 539 if (g) 540 { 541 if (fread((char *)h + LOCCRC, 1, 8, G.in) != 8) 542 err(3, "gzip file ended prematurely"); 543 } 544 else 545 if ((h[LOCFLG] & EXTFLG) && 546 fread((char *)h + LOCCRC - 4, 1, EXTHDR, G.in) != EXTHDR) 547 err(3, "zipfile ended prematurely"); 548 549 /* validate decompression */ 550 if (LG(h + LOCCRC) != G.crc32val) 551 err(4, "invalid compressed data--crc error"); 552 if (LG((g ? (h + LOCSIZ) : (h + LOCLEN))) != outsiz) 553 err(4, "invalid compressed data--length error"); 554 555 /* check if there are more entries */ 556 if (!g && fread((char *)h, 1, 4, G.in) == 4 && LG(h) == LOCSIG) 557 Info(slide, 1, ((char *)slide, 558 "funzip warning: zipfile has more than one entry--rest ignored\n")); 559 560 DESTROYGLOBALS(); 561 RETURN (0); 562 } 563