which included commits to RCS files with non-trunk default branches. git-svn-id: svn://10.65.10.50/trunk@5403 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			464 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			464 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
| /* funzip.c -- put in the public domain by Mark Adler */
 | |
| 
 | |
| #define VERSION "3.92 of 31 May 1997"
 | |
| 
 | |
| 
 | |
| /* 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
 | |
|    ----   ---------  --------------  ------------------------------------
 | |
|    1.0    13 Aug 92  M. Adler        really simple unzip filter.
 | |
|    1.1    13 Aug 92  M. Adler        cleaned up somewhat, give help if
 | |
|                                      stdin not redirected, warn if more
 | |
|                                      zip file entries after the first.
 | |
|    1.2    15 Aug 92  M. Adler        added check of lengths for stored
 | |
|                                      entries, added more help.
 | |
|    1.3    16 Aug 92  M. Adler        removed redundant #define's, added
 | |
|                                      decryption.
 | |
|    1.4    27 Aug 92  G. Roelofs      added exit(0).
 | |
|    1.5     1 Sep 92  K. U. Rommel    changed read/write modes for OS/2.
 | |
|    1.6     6 Sep 92  G. Roelofs      modified to use dummy crypt.c and
 | |
|                                      crypt.h instead of -DCRYPT.
 | |
|    1.7    23 Sep 92  G. Roelofs      changed to use DOS_OS2; included
 | |
|                                      crypt.c under MS-DOS.
 | |
|    1.8     9 Oct 92  M. Adler        improved inflation error msgs.
 | |
|    1.9    17 Oct 92  G. Roelofs      changed ULONG/UWORD/byte to ulg/ush/uch;
 | |
|                                      renamed inflate_entry() to inflate();
 | |
|                                      adapted to use new, in-place zdecode.
 | |
|    2.0    22 Oct 92  M. Adler        allow filename argument, prompt for
 | |
|                                      passwords and don't echo, still allow
 | |
|                                      command-line password entry, but as an
 | |
|                                      option.
 | |
|    2.1    23 Oct 92  J-l. Gailly     fixed crypt/store bug,
 | |
|                      G. Roelofs      removed crypt.c under MS-DOS, fixed
 | |
|                                      decryption check to compare single byte.
 | |
|    2.2    28 Oct 92  G. Roelofs      removed declaration of key.
 | |
|    2.3    14 Dec 92  M. Adler        replaced fseek (fails on stdin for SCO
 | |
|                                      Unix V.3.2.4).  added quietflg for
 | |
|                                      inflate.c.
 | |
|    3.0    11 May 93  M. Adler        added gzip support
 | |
|    3.1     9 Jul 93  K. U. Rommel    fixed OS/2 pipe bug (PIPE_ERROR)
 | |
|    3.2     4 Sep 93  G. Roelofs      moved crc_32_tab[] to tables.h; used FOPx
 | |
|                                      from unzip.h; nuked OUTB macro and outbuf;
 | |
|                                      replaced flush(); inlined FlushOutput();
 | |
|                                      renamed decrypt to encrypted
 | |
|    3.3    29 Sep 93  G. Roelofs      replaced ReadByte() with NEXTBYTE macro;
 | |
|                                      revised (restored?) flush(); added FUNZIP
 | |
|    3.4    21 Oct 93  G. Roelofs      renamed quietflg to qflag; changed outcnt,
 | |
|                      H. Gessau       second updcrc() arg and flush() arg to ulg;
 | |
|                                      added inflate_free(); added "g =" to null
 | |
|                                      getc(in) to avoid compiler warnings
 | |
|    3.5    31 Oct 93  H. Gessau       changed DOS_OS2 to DOS_NT_OS2
 | |
|    3.6     6 Dec 93  H. Gessau       added "near" to mask_bits[]
 | |
|    3.7     9 Dec 93  G. Roelofs      added extent typecasts to fwrite() checks
 | |
|    3.8    28 Jan 94  GRR/JlG         initialized g variable in main() for gcc
 | |
|    3.81   22 Feb 94  M. Hanning-Lee  corrected usage message
 | |
|    3.82   27 Feb 94  G. Roelofs      added some typecasts to avoid warnings
 | |
|    3.83   22 Jul 94  G. Roelofs      changed fprintf to macro for DLLs
 | |
|     -      2 Aug 94  -               public release with UnZip 5.11
 | |
|     -     28 Aug 94  -               public release with UnZip 5.12
 | |
|    3.84    1 Oct 94  K. U. Rommel    changes for Metaware High C
 | |
|    3.85   29 Oct 94  G. Roelofs      changed fprintf macro to Info
 | |
|    3.86    7 May 95  K. Davis        RISCOS patches;
 | |
|                      P. Kienitz      Amiga patches
 | |
|    3.87   12 Aug 95  G. Roelofs      inflate_free(), DESTROYGLOBALS fixes
 | |
|    3.88    4 Sep 95  C. Spieler      reordered macro to work around MSC 5.1 bug
 | |
|    3.89   22 Nov 95  PK/CS           ifdef'd out updcrc() for ASM_CRC
 | |
|    3.9    17 Dec 95  G. Roelofs      modified for USE_ZLIB (new fillinbuf())
 | |
|     -     30 Apr 96  -               public release with UnZip 5.2
 | |
|    3.91   17 Aug 96  G. Roelofs      main() -> return int (Peter Seebach)
 | |
|    3.92   13 Apr 97  G. Roelofs      minor cosmetic fixes to messages
 | |
|     -     22 Apr 97  -               public release with UnZip 5.3
 | |
|     -     31 May 97  -               public release with UnZip 5.31
 | |
|  */
 | |
| 
 | |
| 
 | |
| /*
 | |
| 
 | |
|    All funzip does is take a zipfile from stdin and decompress the
 | |
|    first entry to stdout.  The entry has to be either deflated or
 | |
|    stored.  If the entry is encrypted, then the decryption password
 | |
|    must be supplied on the command line as the first argument.
 | |
| 
 | |
|    funzip needs to be linked with inflate.o and crypt.o compiled from
 | |
|    the unzip source.  If decryption is desired, the full version of
 | |
|    crypt.c (and crypt.h) from zcrypt21.zip or later must be used.
 | |
| 
 | |
|  */
 | |
| 
 | |
| #define FUNZIP
 | |
| #define UNZIP_INTERNAL
 | |
| #include "unzip.h"
 | |
| #include "crypt.h"
 | |
| #include "ttyio.h"
 | |
| 
 | |
| #ifdef EBCDIC
 | |
| #  undef EBCDIC                 /* don't need ebcdic[] */
 | |
| #endif
 | |
| #include "tables.h"             /* crc_32_tab[] */
 | |
| 
 | |
| #ifndef USE_ZLIB  /* zlib's function is called inflate(), too */
 | |
| #  define UZinflate inflate
 | |
| #endif
 | |
| 
 | |
| /* PKZIP header definitions */
 | |
| #define ZIPMAG 0x4b50           /* two-byte zip lead-in */
 | |
| #define LOCREM 0x0403           /* remaining two bytes in zip signature */
 | |
| #define LOCSIG 0x04034b50L      /* full signature */
 | |
| #define LOCFLG 4                /* offset of bit flag */
 | |
| #define  CRPFLG 1               /*  bit for encrypted entry */
 | |
| #define  EXTFLG 8               /*  bit for extended local header */
 | |
| #define LOCHOW 6                /* offset of compression method */
 | |
| #define LOCTIM 8                /* file mod time (for decryption) */
 | |
| #define LOCCRC 12               /* offset of crc */
 | |
| #define LOCSIZ 16               /* offset of compressed size */
 | |
| #define LOCLEN 20               /* offset of uncompressed length */
 | |
| #define LOCFIL 24               /* offset of file name field length */
 | |
| #define LOCEXT 26               /* offset of extra field length */
 | |
| #define LOCHDR 28               /* size of local header, including LOCREM */
 | |
| #define EXTHDR 16               /* size of extended local header, inc sig */
 | |
| 
 | |
| /* GZIP header definitions */
 | |
| #define GZPMAG 0x8b1f           /* two-byte gzip lead-in */
 | |
| #define GZPHOW 0                /* offset of method number */
 | |
| #define GZPFLG 1                /* offset of gzip flags */
 | |
| #define  GZPMUL 2               /* bit for multiple-part gzip file */
 | |
| #define  GZPISX 4               /* bit for extra field present */
 | |
| #define  GZPISF 8               /* bit for filename present */
 | |
| #define  GZPISC 16              /* bit for comment present */
 | |
| #define  GZPISE 32              /* bit for encryption */
 | |
| #define GZPTIM 2                /* offset of Unix file modification time */
 | |
| #define GZPEXF 6                /* offset of extra flags */
 | |
| #define GZPCOS 7                /* offset of operating system compressed on */
 | |
| #define GZPHDR 8                /* length of minimal gzip header */
 | |
| 
 | |
| /* Macros for getting two-byte and four-byte header values */
 | |
| #define SH(p) ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8))
 | |
| #define LG(p) ((ulg)(SH(p)) | ((ulg)(SH((p)+2)) << 16))
 | |
| 
 | |
| /* Function prototypes */
 | |
| void err OF((int, char *));
 | |
| int main OF((int, char **));
 | |
| 
 | |
| /* Globals */
 | |
| FILE *out;                      /* output file (*in moved to G struct) */
 | |
| ulg outsiz;                     /* total bytes written to out */
 | |
| int encrypted;                  /* flag to turn on decryption */
 | |
| 
 | |
| /* Masks for inflate.c */
 | |
| ZCONST ush near mask_bits[] = {
 | |
|     0x0000,
 | |
|     0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
 | |
|     0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
 | |
| };
 | |
| 
 | |
| 
 | |
| #ifdef USE_ZLIB
 | |
| 
 | |
| int fillinbuf(__G)
 | |
| __GDEF
 | |
| /* Fill input buffer for pull-model inflate() in zlib.  Return the number of
 | |
|  * bytes in inbuf. */
 | |
| {
 | |
| /*   GRR: check return value from fread(): same as read()?  check errno? */
 | |
|   if ((G.incnt = fread((char *)G.inbuf, 1, INBUFSIZ, G.in)) <= 0)
 | |
|     return 0;
 | |
|   G.inptr = G.inbuf;
 | |
| 
 | |
| #if CRYPT
 | |
|   if (encrypted) {
 | |
|     uch *p;
 | |
|     int n;
 | |
| 
 | |
|     for (n = G.incnt, p = G.inptr;  n--;  p++)
 | |
|       zdecode(*p);
 | |
|   }
 | |
| #endif /* CRYPT */
 | |
| 
 | |
|   return G.incnt;
 | |
| 
 | |
| }
 | |
| 
 | |
| #endif /* USE_ZLIB */
 | |
| 
 | |
| 
 | |
| #if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB))
 | |
| #ifdef USE_ZLIB
 | |
| uLongf *get_crc_table()
 | |
| {
 | |
|   return (uLongf *)crc_32_tab;
 | |
| }
 | |
| #else /* !USE_ZLIB */
 | |
| ulg near *get_crc_table()
 | |
| {
 | |
|   return crc_32_tab;
 | |
| }
 | |
| #endif /* ?USE_ZLIB */
 | |
| #endif /* !USE_ZLIB || USE_OWN_CRCTAB */
 | |
| 
 | |
| 
 | |
| void err(n, m)
 | |
| int n;
 | |
| char *m;
 | |
| /* Exit on error with a message and a code */
 | |
| {
 | |
|   Info(slide, 1, ((char *)slide, "funzip error: %s\n", m));
 | |
|   DESTROYGLOBALS()
 | |
|   EXIT(n);
 | |
| }
 | |
| 
 | |
| 
 | |
| int flush(w)    /* used by inflate.c (FLUSH macro) */
 | |
| ulg w;          /* number of bytes to flush */
 | |
| {
 | |
|   G.crc32val = crc32(G.crc32val, slide, (extent)w);
 | |
|   if (fwrite((char *)slide,1,(extent)w,out) != (extent)w && !PIPE_ERROR)
 | |
|     err(9, "out of space on stdout");
 | |
|   outsiz += w;
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| int main(argc, argv)
 | |
| int argc;
 | |
| char **argv;
 | |
| /* Given a zipfile on stdin, decompress the first entry to stdout. */
 | |
| {
 | |
|   ush n;
 | |
|   uch h[LOCHDR];                /* first local header (GZPHDR < LOCHDR) */
 | |
|   int g = 0;                    /* true if gzip format */
 | |
| #if CRYPT
 | |
|   char *s = " [-password]";
 | |
|   char *p;                      /* password */
 | |
| #else /* !CRYPT */
 | |
|   char *s = "";
 | |
| #endif /* ?CRYPT */
 | |
|   CONSTRUCTGLOBALS();
 | |
| 
 | |
|   /* skip executable name */
 | |
|   argc--;
 | |
|   argv++;
 | |
| 
 | |
| #if CRYPT
 | |
|   /* get the command line password, if any */
 | |
|   p = (char *)NULL;
 | |
|   if (argc && **argv == '-')
 | |
|   {
 | |
|     argc--;
 | |
|     p = 1 + *argv++;
 | |
|   }
 | |
| #endif /* CRYPT */
 | |
| 
 | |
| #ifdef MALLOC_WORK
 | |
|   G.area.Slide = (uch *)calloc(8193, sizeof(short)+sizeof(char)+sizeof(char));
 | |
| #endif
 | |
| 
 | |
|   /* if no file argument and stdin not redirected, give the user help */
 | |
|   if (argc == 0 && isatty(0))
 | |
|   {
 | |
|     Info(slide, 1, ((char *)slide, "fUnZip (filter UnZip), version %s\n",
 | |
|       VERSION));
 | |
|     Info(slide, 1, ((char *)slide, "usage: ... | funzip%s | ...\n", s));
 | |
|     Info(slide, 1, ((char *)slide, "       ... | funzip%s > outfile\n", s));
 | |
|     Info(slide, 1, ((char *)slide, "       funzip%s infile.zip > outfile\n",s));
 | |
|     Info(slide, 1, ((char *)slide, "       funzip%s infile.gz > outfile\n", s));
 | |
|     Info(slide, 1, ((char *)slide, "Extracts to stdout the gzip file or first\
 | |
|  zip entry of stdin or the given file.\n"));
 | |
|     DESTROYGLOBALS()
 | |
|     EXIT(3);
 | |
|   }
 | |
| 
 | |
|   /* prepare to be a binary filter */
 | |
|   if (argc)
 | |
|   {
 | |
|     if ((G.in = fopen(*argv, FOPR)) == (FILE *)NULL)
 | |
|       err(2, "cannot find input file");
 | |
|   }
 | |
|   else
 | |
|   {
 | |
| #ifdef DOS_H68_OS2_W32
 | |
| #ifdef __HIGHC__
 | |
|     setmode(stdin, _BINARY);
 | |
| #else
 | |
|     setmode(0, O_BINARY);  /* some buggy C libraries require BOTH setmode() */
 | |
| #endif                     /*  call AND the fdopen() in binary mode :-( */
 | |
| #endif /* DOS_H68_OS2_W32 */
 | |
| 
 | |
| #ifdef RISCOS
 | |
|     G.in = stdin;
 | |
| #else
 | |
|     if ((G.in = fdopen(0, FOPR)) == (FILE *)NULL)
 | |
|       err(2, "cannot find stdin");
 | |
| #endif
 | |
|   }
 | |
| 
 | |
| #ifdef DOS_H68_OS2_W32
 | |
| #ifdef __HIGHC__
 | |
|   setmode(stdout, _BINARY);
 | |
| #else
 | |
|   setmode(1, O_BINARY);
 | |
| #endif
 | |
| #endif /* DOS_H68_OS2_W32 */
 | |
| 
 | |
| #ifdef RISCOS
 | |
|   out = stdout;
 | |
| #else
 | |
|   if ((out = fdopen(1, FOPW)) == (FILE *)NULL)
 | |
|     err(2, "cannot write to stdout");
 | |
| #endif
 | |
| 
 | |
|   /* read local header, check validity, and skip name and extra fields */
 | |
|   n = getc(G.in);  n |= getc(G.in) << 8;
 | |
|   if (n == ZIPMAG)
 | |
|   {
 | |
|     if (fread((char *)h, 1, LOCHDR, G.in) != LOCHDR || SH(h) != LOCREM)
 | |
|       err(3, "invalid zipfile");
 | |
|     if (SH(h + LOCHOW) != STORED && SH(h + LOCHOW) != DEFLATED)
 | |
|       err(3, "first entry not deflated or stored--can't funzip");
 | |
|     for (n = SH(h + LOCFIL); n--; ) g = getc(G.in);
 | |
|     for (n = SH(h + LOCEXT); n--; ) g = getc(G.in);
 | |
|     g = 0;
 | |
|     encrypted = h[LOCFLG] & CRPFLG;
 | |
|   }
 | |
|   else if (n == GZPMAG)
 | |
|   {
 | |
|     if (fread((char *)h, 1, GZPHDR, G.in) != GZPHDR)
 | |
|       err(3, "invalid gzip file");
 | |
|     if (h[GZPHOW] != DEFLATED)
 | |
|       err(3, "gzip file not deflated");
 | |
|     if (h[GZPFLG] & GZPMUL)
 | |
|       err(3, "cannot handle multi-part gzip files");
 | |
|     if (h[GZPFLG] & GZPISX)
 | |
|     {
 | |
|       n = getc(G.in);  n |= getc(G.in) << 8;
 | |
|       while (n--) g = getc(G.in);
 | |
|     }
 | |
|     if (h[GZPFLG] & GZPISF)
 | |
|       while ((g = getc(G.in)) != 0 && g != EOF) ;
 | |
|     if (h[GZPFLG] & GZPISC)
 | |
|       while ((g = getc(G.in)) != 0 && g != EOF) ;
 | |
|     g = 1;
 | |
|     encrypted = h[GZPFLG] & GZPISE;
 | |
|   }
 | |
|   else
 | |
|     err(3, "input not a zip or gzip file");
 | |
| 
 | |
|   /* if entry encrypted, decrypt and validate encryption header */
 | |
|   if (encrypted)
 | |
| #if CRYPT
 | |
|     {
 | |
|       ush i, e;
 | |
| 
 | |
|       if (p == (char *)NULL)
 | |
|         if ((p = (char *)malloc(PWLEN+1)) == (char *)NULL)
 | |
|           err(1, "out of memory");
 | |
|         else if ((p = getp("Enter password: ", p, PWLEN+1)) == (char *)NULL)
 | |
|           err(1, "no tty to prompt for password");
 | |
| #if (defined(USE_ZLIB) && !defined(USE_OWN_CRCTAB))
 | |
|       /* initialize crc_32_tab pointer for decryption */
 | |
|       crc_32_tab = (ulg near *)get_crc_table();
 | |
| #endif
 | |
|       init_keys(p);
 | |
|       for (i = 0; i < RAND_HEAD_LEN; i++)
 | |
|         e = NEXTBYTE;
 | |
|       if (e != (ush)(h[LOCFLG] & EXTFLG ? h[LOCTIM + 1] : h[LOCCRC + 3]))
 | |
|         err(3, "incorrect password for first entry");
 | |
|     }
 | |
| #else /* !CRYPT */
 | |
|     err(3, "cannot decrypt entry (need to recompile with full crypt.c)");
 | |
| #endif /* ?CRYPT */
 | |
| 
 | |
|   /* prepare output buffer and crc */
 | |
|   G.outptr = slide;
 | |
|   G.outcnt = 0L;
 | |
|   outsiz = 0L;
 | |
|   G.crc32val = CRCVAL_INITIAL;
 | |
| 
 | |
|   /* decompress */
 | |
|   if (g || h[LOCHOW])
 | |
|   {                             /* deflated entry */
 | |
|     int r;
 | |
| 
 | |
| #ifdef USE_ZLIB
 | |
|     /* need to allocate and prepare input buffer */
 | |
|     if ((G.inbuf = (uch *)malloc(INBUFSIZ)) == (uch *)NULL)
 | |
|        err(1, "out of memory");
 | |
| #endif /* USE_ZLIB */
 | |
|     if ((r = UZinflate(__G)) != 0)
 | |
|       if (r == 3)
 | |
|         err(1, "out of memory");
 | |
|       else
 | |
|         err(4, "invalid compressed data--format violated");
 | |
|     inflate_free(__G);
 | |
|   }
 | |
|   else
 | |
|   {                             /* stored entry */
 | |
|     register ulg n;
 | |
| 
 | |
|     n = LG(h + LOCLEN);
 | |
| #if CRYPT
 | |
|     if (n != LG(h + LOCSIZ) - (encrypted ? RAND_HEAD_LEN : 0)) {
 | |
| #else
 | |
|     if (n != LG(h + LOCSIZ)) {
 | |
| #endif
 | |
|       Info(slide, 1, ((char *)slide, "len %ld, siz %ld\n", n, LG(h + LOCSIZ)));
 | |
|       err(4, "invalid compressed data--length mismatch");
 | |
|     }
 | |
|     while (n--) {
 | |
|       ush c = getc(G.in);
 | |
| #if CRYPT
 | |
|       if (encrypted)
 | |
|         zdecode(c);
 | |
| #endif
 | |
|       *G.outptr++ = (uch)c;
 | |
|       if (++G.outcnt == WSIZE)    /* do FlushOutput() */
 | |
|       {
 | |
|         G.crc32val = crc32(G.crc32val, slide, (extent)G.outcnt);
 | |
|         if (fwrite((char *)slide, 1,(extent)G.outcnt,out) != (extent)G.outcnt
 | |
|             && !PIPE_ERROR)
 | |
|           err(9, "out of space on stdout");
 | |
|         outsiz += G.outcnt;
 | |
|         G.outptr = slide;
 | |
|         G.outcnt = 0L;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   if (G.outcnt)   /* flush one last time; no need to reset G.outptr/outcnt */
 | |
|   {
 | |
|     G.crc32val = crc32(G.crc32val, slide, (extent)G.outcnt);
 | |
|     if (fwrite((char *)slide, 1,(extent)G.outcnt,out) != (extent)G.outcnt
 | |
|         && !PIPE_ERROR)
 | |
|       err(9, "out of space on stdout");
 | |
|     outsiz += G.outcnt;
 | |
|   }
 | |
|   fflush(out);
 | |
| 
 | |
|   /* if extended header, get it */
 | |
|   if (g)
 | |
|   {
 | |
|     if (fread((char *)h + LOCCRC, 1, 8, G.in) != 8)
 | |
|       err(3, "gzip file ended prematurely");
 | |
|   }
 | |
|   else
 | |
|     if ((h[LOCFLG] & EXTFLG) &&
 | |
|         fread((char *)h + LOCCRC - 4, 1, EXTHDR, G.in) != EXTHDR)
 | |
|       err(3, "zipfile ended prematurely");
 | |
| 
 | |
|   /* validate decompression */
 | |
|   if (LG(h + LOCCRC) != G.crc32val)
 | |
|     err(4, "invalid compressed data--crc error");
 | |
|   if (LG((g ? (h + LOCSIZ) : (h + LOCLEN))) != outsiz)
 | |
|     err(4, "invalid compressed data--length error");
 | |
| 
 | |
|   /* check if there are more entries */
 | |
|   if (!g && fread((char *)h, 1, 4, G.in) == 4 && LG(h) == LOCSIG)
 | |
|     Info(slide, 1, ((char *)slide,
 | |
|       "funzip warning: zipfile has more than one entry--rest ignored\n"));
 | |
| 
 | |
|   DESTROYGLOBALS()
 | |
|   RETURN (0);
 | |
| }
 |