forked from KolibriOS/kolibrios
e9b1c1bac6
git-svn-id: svn://kolibrios.org@6725 a494cfbc-eb01-0410-851d-a64ba20cac60
548 lines
19 KiB
C
548 lines
19 KiB
C
/*
|
|
Copyright (c) 1990-2009 Info-ZIP. All rights reserved.
|
|
|
|
See the accompanying file LICENSE, version 2009-Jan-02 or later
|
|
(the contents of which are also included in unzip.h) for terms of use.
|
|
If, for some reason, all these files are missing, the Info-ZIP license
|
|
also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
|
|
*/
|
|
/* funzip.c -- by Mark Adler */
|
|
|
|
#define VERSION "3.95 of 20 January 2009"
|
|
|
|
|
|
/* Copyright history:
|
|
- Starting with UnZip 5.41 of 16-April-2000, this source file
|
|
is covered by the Info-Zip LICENSE cited above.
|
|
- Prior versions of this source file, found in UnZip source packages
|
|
up to UnZip 5.40, were put in the public domain.
|
|
The original copyright note by Mark Adler was:
|
|
"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
|
|
3.93 20 Sep 97 G. Roelofs minor cosmetic fixes to messages
|
|
- 3 Nov 97 - public release with UnZip 5.32
|
|
- 28 Nov 98 - public release with UnZip 5.4
|
|
- 16 Apr 00 - public release with UnZip 5.41
|
|
- 14 Jan 01 - public release with UnZip 5.42
|
|
3.94 20 Feb 01 C. Spieler added support for Deflate64(tm)
|
|
23 Mar 02 C. Spieler changed mask_bits[] type to "unsigned"
|
|
*/
|
|
|
|
|
|
/*
|
|
|
|
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 zcrypt28.zip or later must be used.
|
|
|
|
*/
|
|
|
|
#ifndef FUNZIP
|
|
# define FUNZIP
|
|
#endif
|
|
#define UNZIP_INTERNAL
|
|
#include "unzip.h"
|
|
#include "crc32.h"
|
|
#include "crypt.h"
|
|
#include "ttyio.h"
|
|
|
|
#ifdef EBCDIC
|
|
# undef EBCDIC /* don't need ebcdic[] */
|
|
#endif
|
|
|
|
#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 */
|
|
|
|
#ifdef THEOS
|
|
/* Macros cause stack overflow in compiler */
|
|
ush SH(uch* p) { return ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8)); }
|
|
ulg LG(uch* p) { return ((ulg)(SH(p)) | ((ulg)(SH((p)+2)) << 16)); }
|
|
#else /* !THEOS */
|
|
/* 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))
|
|
#endif /* ?THEOS */
|
|
|
|
/* Function prototypes */
|
|
static void err OF((int, char *));
|
|
#if (defined(USE_DEFLATE64) && defined(__16BIT__))
|
|
static int partflush OF((uch *rawbuf, unsigned w));
|
|
#endif
|
|
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 unsigned near mask_bits[17] = {
|
|
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 */
|
|
|
|
|
|
static 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);
|
|
}
|
|
|
|
|
|
#if (defined(USE_DEFLATE64) && defined(__16BIT__))
|
|
|
|
static int partflush(rawbuf, w)
|
|
uch *rawbuf; /* start of buffer area to flush */
|
|
extent w; /* number of bytes to flush */
|
|
{
|
|
G.crc32val = crc32(G.crc32val, rawbuf, (extent)w);
|
|
if (fwrite((char *)rawbuf,1,(extent)w,out) != (extent)w && !PIPE_ERROR)
|
|
err(9, "out of space on stdout");
|
|
outsiz += w;
|
|
return 0;
|
|
}
|
|
|
|
|
|
int flush(w) /* used by inflate.c (FLUSH macro) */
|
|
ulg w; /* number of bytes to flush */
|
|
{
|
|
uch *rawbuf;
|
|
int ret;
|
|
|
|
/* On 16-bit systems (MSDOS, OS/2 1.x), the standard C library functions
|
|
* cannot handle writes of 64k blocks at once. For these systems, the
|
|
* blocks to flush are split into pieces of 32k or less.
|
|
*/
|
|
rawbuf = slide;
|
|
while (w > 0x8000L) {
|
|
ret = partflush(rawbuf, 0x8000);
|
|
if (ret != PK_OK)
|
|
return ret;
|
|
w -= 0x8000L;
|
|
rawbuf += (unsigned)0x8000;
|
|
}
|
|
return partflush(rawbuf, (extent)w);
|
|
} /* end function flush() */
|
|
|
|
#else /* !(USE_DEFLATE64 && __16BIT__) */
|
|
|
|
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;
|
|
}
|
|
|
|
#endif /* ?(USE_DEFLATE64 && __16BIT__) */
|
|
|
|
|
|
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 */
|
|
unsigned method = 0; /* initialized here to shut up gcc warning */
|
|
#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
|
|
/* The following expression is a cooked-down simplyfication of the
|
|
calculation for the work area size of UnZip (see unzip.c). For
|
|
fUnZip, the work area does not need to match the granularity
|
|
of the complex unshrink structures, because it only supports
|
|
inflation. But, like in UnZip, the zcalloc() wrapper function
|
|
is needed for the allocation, to support the 64kByte buffer on
|
|
16-bit systems.
|
|
*/
|
|
# define UZ_SLIDE_CHUNK (sizeof(shrint)+sizeof(uch)+sizeof(uch))
|
|
# define UZ_NUMOF_CHUNKS (unsigned)( (WSIZE+UZ_SLIDE_CHUNK-1)/UZ_SLIDE_CHUNK )
|
|
G.area.Slide = (uch *)zcalloc(UZ_NUMOF_CHUNKS, UZ_SLIDE_CHUNK);
|
|
# undef UZ_SLIDE_CHUNK
|
|
# undef UZ_NUMOF_CHUNKS
|
|
#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_FLX_NLM_OS2_W32
|
|
#if (defined(__HIGHC__) && !defined(FLEXOS))
|
|
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_FLX_NLM_OS2_W32 */
|
|
|
|
#ifdef RISCOS
|
|
G.in = stdin;
|
|
#else
|
|
if ((G.in = fdopen(0, FOPR)) == (FILE *)NULL)
|
|
err(2, "cannot find stdin");
|
|
#endif
|
|
}
|
|
|
|
#ifdef DOS_FLX_H68_NLM_OS2_W32
|
|
#if (defined(__HIGHC__) && !defined(FLEXOS))
|
|
setmode(stdout, _BINARY);
|
|
#else
|
|
setmode(1, O_BINARY);
|
|
#endif
|
|
#endif /* DOS_FLX_H68_NLM_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");
|
|
switch (method = SH(h + LOCHOW)) {
|
|
case STORED:
|
|
case DEFLATED:
|
|
#ifdef USE_DEFLATE64
|
|
case ENHDEFLATED:
|
|
#endif
|
|
break;
|
|
default:
|
|
err(3, "first entry not deflated or stored--cannot unpack");
|
|
break;
|
|
}
|
|
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 ((method = h[GZPHOW]) != DEFLATED && method != ENHDEFLATED)
|
|
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(IZ_PWLEN+1)) == (char *)NULL)
|
|
err(1, "out of memory");
|
|
else if ((p = getp("Enter password: ", p, IZ_PWLEN+1)) == (char *)NULL)
|
|
err(1, "no tty to prompt for password");
|
|
}
|
|
/* initialize crc_32_tab pointer for decryption */
|
|
CRC_32_TAB = get_crc_table();
|
|
/* prepare the decryption keys for extraction and check the password */
|
|
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__ (method == ENHDEFLATED))) != 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 (defined(USE_DEFLATE64) && defined(__16BIT__))
|
|
if (++G.outcnt == (WSIZE>>1)) /* do FlushOutput() */
|
|
#else
|
|
if (++G.outcnt == WSIZE) /* do FlushOutput() */
|
|
#endif
|
|
{
|
|
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);
|
|
}
|