summaryrefslogtreecommitdiff
path: root/Build/source/libs/unzip
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2006-01-16 00:09:26 +0000
committerKarl Berry <karl@freefriends.org>2006-01-16 00:09:26 +0000
commit6c0eafbb1395d426a72a74538e0b2a95e8344ca6 (patch)
tree2a5f80b80fc76086a2602b812c2a182d00f961b7 /Build/source/libs/unzip
parent70f7efeb5c9965a63a4143ad1c1f473585dc364c (diff)
libs 1
git-svn-id: svn://tug.org/texlive/trunk@1483 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/libs/unzip')
-rw-r--r--Build/source/libs/unzip/api.c601
-rw-r--r--Build/source/libs/unzip/consts.h46
-rw-r--r--Build/source/libs/unzip/crc32.c56
-rw-r--r--Build/source/libs/unzip/crctab.c219
-rw-r--r--Build/source/libs/unzip/crypt.c12
-rw-r--r--Build/source/libs/unzip/crypt.h24
-rw-r--r--Build/source/libs/unzip/depend.mak83
-rw-r--r--Build/source/libs/unzip/ebcdic.h272
-rw-r--r--Build/source/libs/unzip/explode.c871
-rw-r--r--Build/source/libs/unzip/extract.c1985
-rw-r--r--Build/source/libs/unzip/fileio.c2151
-rw-r--r--Build/source/libs/unzip/globals.c204
-rw-r--r--Build/source/libs/unzip/globals.h395
-rw-r--r--Build/source/libs/unzip/inflate.c1305
-rw-r--r--Build/source/libs/unzip/inflate.h24
-rw-r--r--Build/source/libs/unzip/list.c644
-rw-r--r--Build/source/libs/unzip/match.c294
-rw-r--r--Build/source/libs/unzip/process.c1378
-rw-r--r--Build/source/libs/unzip/ttyio.c625
-rw-r--r--Build/source/libs/unzip/ttyio.h186
-rw-r--r--Build/source/libs/unzip/unreduce.c230
-rw-r--r--Build/source/libs/unzip/unshrink.c301
-rw-r--r--Build/source/libs/unzip/unzip.dep191
-rw-r--r--Build/source/libs/unzip/unzip.dsp258
-rw-r--r--Build/source/libs/unzip/unzip.dsw29
-rw-r--r--Build/source/libs/unzip/unzip.h545
-rw-r--r--Build/source/libs/unzip/unzip.mak369
-rw-r--r--Build/source/libs/unzip/unzip.plg30
-rw-r--r--Build/source/libs/unzip/unzip.vcproj235
-rw-r--r--Build/source/libs/unzip/unzpriv.h2387
-rw-r--r--Build/source/libs/unzip/version.h44
-rw-r--r--Build/source/libs/unzip/win32.mak83
-rw-r--r--Build/source/libs/unzip/win32/nt.c659
-rw-r--r--Build/source/libs/unzip/win32/nt.h28
-rw-r--r--Build/source/libs/unzip/win32/w32cfg.h222
-rw-r--r--Build/source/libs/unzip/win32/win32.c2390
-rw-r--r--Build/source/libs/unzip/windll/decs.h29
-rw-r--r--Build/source/libs/unzip/windll/structs.h72
-rw-r--r--Build/source/libs/unzip/windll/unzver.h15
-rw-r--r--Build/source/libs/unzip/windll/windll.c744
-rw-r--r--Build/source/libs/unzip/windll/windll.h46
-rw-r--r--Build/source/libs/unzip/windll/windll.rc40
-rw-r--r--Build/source/libs/unzip/zip.h15
-rw-r--r--Build/source/libs/unzip/zipinfo.c1912
44 files changed, 22249 insertions, 0 deletions
diff --git a/Build/source/libs/unzip/api.c b/Build/source/libs/unzip/api.c
new file mode 100644
index 00000000000..5a4e73abf8b
--- /dev/null
+++ b/Build/source/libs/unzip/api.c
@@ -0,0 +1,601 @@
+/*---------------------------------------------------------------------------
+
+ api.c
+
+ This module supplies an UnZip engine for use directly from C/C++
+ programs. The functions are:
+
+ UzpVer *UzpVersion(void);
+ void UzpVersion2(UzpVer2 *version)
+ int UzpMain(int argc, char *argv[]);
+ int UzpAltMain(int argc, char *argv[], UzpInit *init);
+ int UzpValidate(char *archive, int AllCodes);
+ void UzpFreeMemBuffer(UzpBuffer *retstr);
+ int UzpUnzipToMemory(char *zip, char *file, UzpOpts *optflgs,
+ UzpCB *UsrFuncts, UzpBuffer *retstr);
+
+ non-WINDLL only (a special WINDLL variant is defined in windll/windll.c):
+ int UzpGrep(char *archive, char *file, char *pattern, int cmd, int SkipBin,
+ UzpCB *UsrFuncts);
+
+ OS/2 only (for now):
+ int UzpFileTree(char *name, cbList(callBack), char *cpInclude[],
+ char *cpExclude[]);
+
+ You must define `DLL' in order to include the API extensions.
+
+ ---------------------------------------------------------------------------*/
+
+
+#ifdef OS2
+# define INCL_DOSMEMMGR
+# include <os2.h>
+#endif
+#include <setjmp.h>
+
+#define UNZIP_INTERNAL
+#include "unzip.h"
+#include "version.h"
+#ifdef WINDLL
+# include "windll/windll.h"
+#endif
+
+#ifdef DLL /* This source file supplies DLL-only interface code. */
+
+jmp_buf dll_error_return;
+
+/*---------------------------------------------------------------------------
+ Documented API entry points
+ ---------------------------------------------------------------------------*/
+
+
+UzpVer * UZ_EXP UzpVersion() /* should be pointer to const struct */
+{
+ static UzpVer version; /* doesn't change between calls */
+
+
+ version.structlen = UZPVER_LEN;
+
+#ifdef BETA
+ version.flag = 1;
+#else
+ version.flag = 0;
+#endif
+ version.betalevel = BETALEVEL;
+ version.date = VERSION_DATE;
+
+#ifdef ZLIB_VERSION
+ version.zlib_version = ZLIB_VERSION;
+ version.flag |= 2;
+#else
+ version.zlib_version = NULL;
+#endif
+
+ /* someday each of these may have a separate patchlevel: */
+ version.unzip.major = UZ_MAJORVER;
+ version.unzip.minor = UZ_MINORVER;
+ version.unzip.patchlevel = PATCHLEVEL;
+
+ version.zipinfo.major = ZI_MAJORVER;
+ version.zipinfo.minor = ZI_MINORVER;
+ version.zipinfo.patchlevel = PATCHLEVEL;
+
+ /* these are retained for backward compatibility only: */
+ version.os2dll.major = UZ_MAJORVER;
+ version.os2dll.minor = UZ_MINORVER;
+ version.os2dll.patchlevel = PATCHLEVEL;
+
+ version.windll.major = UZ_MAJORVER;
+ version.windll.minor = UZ_MINORVER;
+ version.windll.patchlevel = PATCHLEVEL;
+
+ return &version;
+}
+
+void UZ_EXP UzpVersion2(UzpVer2 *version)
+{
+
+ version->structlen = UZPVER_LEN;
+
+#ifdef BETA
+ version->flag = 1;
+#else
+ version->flag = 0;
+#endif
+ strcpy(version->betalevel, BETALEVEL);
+ strcpy(version->date, VERSION_DATE);
+
+#ifdef ZLIB_VERSION
+ strcpy(version->zlib_version, ZLIB_VERSION);
+ version->flag |= 2;
+#else
+ version->zlib_version[0] = '\0';
+#endif
+
+ /* someday each of these may have a separate patchlevel: */
+ version->unzip.major = UZ_MAJORVER;
+ version->unzip.minor = UZ_MINORVER;
+ version->unzip.patchlevel = PATCHLEVEL;
+
+ version->zipinfo.major = ZI_MAJORVER;
+ version->zipinfo.minor = ZI_MINORVER;
+ version->zipinfo.patchlevel = PATCHLEVEL;
+
+ /* these are retained for backward compatibility only: */
+ version->os2dll.major = UZ_MAJORVER;
+ version->os2dll.minor = UZ_MINORVER;
+ version->os2dll.patchlevel = PATCHLEVEL;
+
+ version->windll.major = UZ_MAJORVER;
+ version->windll.minor = UZ_MINORVER;
+ version->windll.patchlevel = PATCHLEVEL;
+}
+
+
+
+
+
+#ifndef WINDLL
+
+int UZ_EXP UzpAltMain(int argc, char *argv[], UzpInit *init)
+{
+ int r, (*dummyfn)();
+
+
+ CONSTRUCTGLOBALS();
+
+ if (init->structlen >= (sizeof(ulg) + sizeof(dummyfn)) && init->msgfn)
+ G.message = init->msgfn;
+
+ if (init->structlen >= (sizeof(ulg) + 2*sizeof(dummyfn)) && init->inputfn)
+ G.input = init->inputfn;
+
+ if (init->structlen >= (sizeof(ulg) + 3*sizeof(dummyfn)) && init->pausefn)
+ G.mpause = init->pausefn;
+
+ if (init->structlen >= (sizeof(ulg) + 4*sizeof(dummyfn)) && init->userfn)
+ (*init->userfn)(); /* allow void* arg? */
+
+ r = unzip(__G__ argc, argv);
+ DESTROYGLOBALS()
+ RETURN(r);
+}
+
+#endif /* !WINDLL */
+
+
+
+
+#ifndef __16BIT__
+
+void UZ_EXP UzpFreeMemBuffer(UzpBuffer *retstr)
+{
+ if (retstr->strptr != NULL) {
+ free(retstr->strptr);
+ retstr->strptr = NULL;
+ }
+}
+
+
+
+
+#ifndef WINDLL
+
+static int UzpDLL_Init OF((zvoid *pG, UzpCB *UsrFuncts));
+
+static int UzpDLL_Init(pG, UsrFuncts)
+zvoid *pG;
+UzpCB *UsrFuncts;
+{
+ int (*dummyfn)();
+
+ if (UsrFuncts->structlen >= (sizeof(ulg) + sizeof(dummyfn)) &&
+ UsrFuncts->msgfn)
+ ((Uz_Globs *)pG)->message = UsrFuncts->msgfn;
+ else
+ return FALSE;
+
+ if (UsrFuncts->structlen >= (sizeof(ulg) + 2*sizeof(dummyfn)) &&
+ UsrFuncts->inputfn)
+ ((Uz_Globs *)pG)->input = UsrFuncts->inputfn;
+
+ if (UsrFuncts->structlen >= (sizeof(ulg) + 3*sizeof(dummyfn)) &&
+ UsrFuncts->pausefn)
+ ((Uz_Globs *)pG)->mpause = UsrFuncts->pausefn;
+
+ if (UsrFuncts->structlen >= (sizeof(ulg) + 4*sizeof(dummyfn)) &&
+ UsrFuncts->passwdfn)
+ ((Uz_Globs *)pG)->decr_passwd = UsrFuncts->passwdfn;
+
+ if (UsrFuncts->structlen >= (sizeof(ulg) + 5*sizeof(dummyfn)) &&
+ UsrFuncts->statrepfn)
+ ((Uz_Globs *)pG)->statreportcb = UsrFuncts->statrepfn;
+
+ return TRUE;
+}
+
+
+int UZ_EXP UzpUnzipToMemory(char *zip, char *file, UzpOpts *optflgs,
+ UzpCB *UsrFuncts, UzpBuffer *retstr)
+{
+ int r;
+#if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO))
+ char *intern_zip, *intern_file;
+#endif
+
+ CONSTRUCTGLOBALS();
+#if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO))
+ intern_zip = (char *)malloc(strlen(zip)+1);
+ if (intern_zip == NULL) {
+ DESTROYGLOBALS()
+ return PK_MEM;
+ }
+ intern_file = (char *)malloc(strlen(file)+1);
+ if (intern_file == NULL) {
+ DESTROYGLOBALS()
+ free(intern_zip);
+ return PK_MEM;
+ }
+ ISO_TO_INTERN(zip, intern_zip);
+ ISO_TO_INTERN(file, intern_file);
+# define zip intern_zip
+# define file intern_file
+#endif
+ /* Copy those options that are meaningful for UzpUnzipToMemory, instead of
+ * a simple "memcpy(G.UzO, optflgs, sizeof(UzpOpts));"
+ */
+ uO.pwdarg = optflgs->pwdarg;
+ uO.aflag = optflgs->aflag;
+ uO.C_flag = optflgs->C_flag;
+ uO.qflag = optflgs->qflag; /* currently, overridden in unzipToMemory */
+
+ if (!UzpDLL_Init((zvoid *)&G, UsrFuncts)) {
+ DESTROYGLOBALS();
+ return PK_BADERR;
+ }
+ G.redirect_data = 1;
+
+ r = (unzipToMemory(__G__ zip, file, retstr) <= PK_WARN);
+
+ DESTROYGLOBALS()
+#if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO))
+# undef file
+# undef zip
+ free(intern_file);
+ free(intern_zip);
+#endif
+ if (!r && retstr->strlength) {
+ free(retstr->strptr);
+ retstr->strptr = NULL;
+ }
+ return r;
+}
+#endif /* !WINDLL */
+#endif /* !__16BIT__ */
+
+
+
+
+
+#ifdef OS2DLL
+
+int UZ_EXP UzpFileTree(char *name, cbList(callBack), char *cpInclude[],
+ char *cpExclude[])
+{
+ int r;
+
+ CONSTRUCTGLOBALS();
+ uO.qflag = 2;
+ uO.vflag = 1;
+ uO.C_flag = 1;
+ G.wildzipfn = name;
+ G.process_all_files = TRUE;
+ if (cpInclude) {
+ char **ptr = cpInclude;
+
+ while (*ptr != NULL) ptr++;
+ G.filespecs = ptr - cpInclude;
+ G.pfnames = cpInclude, G.process_all_files = FALSE;
+ }
+ if (cpExclude) {
+ char **ptr = cpExclude;
+
+ while (*ptr != NULL) ptr++;
+ G.xfilespecs = ptr - cpExclude;
+ G.pxnames = cpExclude, G.process_all_files = FALSE;
+ }
+
+ G.processExternally = callBack;
+ r = process_zipfiles(__G)==0;
+ DESTROYGLOBALS()
+ return r;
+}
+
+#endif /* OS2DLL */
+
+
+
+
+/*---------------------------------------------------------------------------
+ Helper functions
+ ---------------------------------------------------------------------------*/
+
+
+void setFileNotFound(__G)
+ __GDEF
+{
+ G.filenotfound++;
+}
+
+
+
+int unzipToMemory(__GPRO__ char *zip, char *file, UzpBuffer *retstr)
+{
+ int r;
+ char *incname[2];
+
+ G.process_all_files = FALSE;
+ G.extract_flag = TRUE;
+ uO.qflag = 2;
+ G.wildzipfn = zip;
+
+ G.pfnames = incname;
+ incname[0] = file;
+ incname[1] = NULL;
+ G.filespecs = 1;
+
+ r = process_zipfiles(__G);
+ if (retstr) {
+ retstr->strptr = (char *)G.redirect_buffer;
+ retstr->strlength = G.redirect_size;
+ }
+ return r; /* returns `PK_???' error values */
+}
+
+
+
+int redirect_outfile(__G)
+ __GDEF
+{
+ if (G.redirect_size != 0 || G.redirect_buffer != NULL)
+ return FALSE;
+
+#ifndef NO_SLIDE_REDIR
+ G.redirect_slide = !G.pInfo->textmode;
+#endif
+ G.redirect_size = (G.pInfo->textmode ?
+ G.lrec.ucsize * lenEOL : G.lrec.ucsize);
+#ifdef OS2
+ DosAllocMem((void **)&G.redirect_buffer, G.redirect_size+1,
+ PAG_READ|PAG_WRITE|PAG_COMMIT);
+ G.redirect_pointer = G.redirect_buffer;
+#else
+#ifdef __16BIT__
+ if ((ulg)((extent)G.redirect_size) != G.redirect_size)
+ return FALSE;
+#endif
+ G.redirect_pointer = G.redirect_buffer = malloc(G.redirect_size+1);
+#endif
+ if (!G.redirect_buffer)
+ return FALSE;
+ G.redirect_pointer[G.redirect_size] = '\0';
+ return TRUE;
+}
+
+
+
+int writeToMemory(__GPRO__ uch *rawbuf, ulg size)
+{
+ if (rawbuf != G.redirect_pointer)
+ memcpy(G.redirect_pointer,rawbuf,size);
+ G.redirect_pointer += size;
+ return 0;
+}
+
+
+
+
+int close_redirect(__G)
+ __GDEF
+{
+ if (G.pInfo->textmode) {
+ *G.redirect_pointer = '\0';
+ G.redirect_size = G.redirect_pointer - G.redirect_buffer;
+ if ((G.redirect_buffer =
+ realloc(G.redirect_buffer, G.redirect_size + 1)) == NULL) {
+ G.redirect_size = 0;
+ return EOF;
+ }
+ }
+ return 0;
+}
+
+
+
+
+#ifndef __16BIT__
+#ifndef WINDLL
+
+/* Purpose: Determine if file in archive contains the string szSearch
+
+ Parameters: archive = archive name
+ file = file contained in the archive. This cannot be
+ a wild card to be meaningful
+ pattern = string to search for
+ cmd = 0 - case-insensitive search
+ 1 - case-sensitve search
+ 2 - case-insensitive, whole words only
+ 3 - case-sensitive, whole words only
+ SkipBin = if true, skip any files that have control
+ characters other than CR, LF, or tab in the first
+ 100 characters.
+
+ Returns: TRUE if a match is found
+ FALSE if no match is found
+ -1 on error
+
+ Comments: This does not pretend to be as useful as the standard
+ Unix grep, which returns the strings associated with a
+ particular pattern, nor does it search past the first
+ matching occurrence of the pattern.
+ */
+
+int UZ_EXP UzpGrep(char *archive, char *file, char *pattern, int cmd,
+ int SkipBin, UzpCB *UsrFuncts)
+{
+ int retcode = FALSE, compare;
+ ulg i, j, patternLen, buflen;
+ char * sz, *p;
+ UzpOpts flgopts;
+ UzpBuffer retstr;
+
+ memzero(&flgopts, sizeof(UzpOpts)); /* no special options */
+
+ if (!UzpUnzipToMemory(archive, file, &flgopts, UsrFuncts, &retstr)) {
+ return -1; /* not enough memory, file not found, or other error */
+ }
+
+ if (SkipBin) {
+ if (retstr.strlength < 100)
+ buflen = retstr.strlength;
+ else
+ buflen = 100;
+ for (i = 0; i < buflen; i++) {
+ if (iscntrl(retstr.strptr[i])) {
+ if ((retstr.strptr[i] != 0x0A) &&
+ (retstr.strptr[i] != 0x0D) &&
+ (retstr.strptr[i] != 0x09))
+ {
+ /* OK, we now think we have a binary file of some sort */
+ free(retstr.strptr);
+ return FALSE;
+ }
+ }
+ }
+ }
+
+ patternLen = strlen(pattern);
+
+ if (retstr.strlength < patternLen) {
+ free(retstr.strptr);
+ return FALSE;
+ }
+
+ sz = malloc(patternLen + 3); /* add two in case doing whole words only */
+ if (cmd > 1) {
+ strcpy(sz, " ");
+ strcat(sz, pattern);
+ strcat(sz, " ");
+ } else
+ strcpy(sz, pattern);
+
+ if ((cmd == 0) || (cmd == 2)) {
+ for (i = 0; i < strlen(sz); i++)
+ sz[i] = toupper(sz[i]);
+ for (i = 0; i < retstr.strlength; i++)
+ retstr.strptr[i] = toupper(retstr.strptr[i]);
+ }
+
+ for (i = 0; i < (retstr.strlength - patternLen); i++) {
+ p = &retstr.strptr[i];
+ compare = TRUE;
+ for (j = 0; j < patternLen; j++) {
+ /* We cannot do strncmp here, as we may be dealing with a
+ * "binary" file, such as a word processing file, or perhaps
+ * even a true executable of some sort. */
+ if (p[j] != sz[j]) {
+ compare = FALSE;
+ break;
+ }
+ }
+ if (compare == TRUE) {
+ retcode = TRUE;
+ break;
+ }
+ }
+
+ free(sz);
+ free(retstr.strptr);
+
+ return retcode;
+}
+#endif /* !WINDLL */
+#endif /* !__16BIT__ */
+
+
+
+
+int UZ_EXP UzpValidate(char *archive, int AllCodes)
+{
+ int retcode;
+ CONSTRUCTGLOBALS();
+
+ uO.jflag = 1;
+ uO.tflag = 1;
+ uO.overwrite_none = 0;
+ G.extract_flag = (!uO.zipinfo_mode &&
+ !uO.cflag && !uO.tflag && !uO.vflag && !uO.zflag
+#ifdef TIMESTAMP
+ && !uO.T_flag
+#endif
+ );
+
+ uO.qflag = 2; /* turn off all messages */
+ G.fValidate = TRUE;
+ G.pfnames = (char **)&fnames[0]; /* assign default filename vector */
+#ifdef WINDLL
+ Wiz_NoPrinting(TRUE);
+#endif
+
+ if (archive == NULL) { /* something is screwed up: no filename */
+ DESTROYGLOBALS();
+ return PK_NOZIP;
+ }
+
+ G.wildzipfn = (char *)malloc(FILNAMSIZ + 1);
+ strcpy(G.wildzipfn, archive);
+#if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO))
+ _ISO_INTERN(G.wildzipfn);
+#endif
+
+ G.process_all_files = TRUE; /* for speed */
+
+ retcode = setjmp(dll_error_return);
+
+ if (retcode) {
+#ifdef WINDLL
+ Wiz_NoPrinting(FALSE);
+#endif
+ free(G.wildzipfn);
+ DESTROYGLOBALS();
+ return PK_BADERR;
+ }
+
+ retcode = process_zipfiles(__G);
+
+ free(G.wildzipfn);
+#ifdef WINDLL
+ Wiz_NoPrinting(FALSE);
+#endif
+ DESTROYGLOBALS();
+
+ /* PK_WARN == 1 and PK_FIND == 11. When we are just looking at an
+ archive, we should still be able to see the files inside it,
+ even if we can't decode them for some reason.
+
+ We also still want to be able to get at files even if there is
+ something odd about the zip archive, hence allow PK_WARN,
+ PK_FIND, IZ_UNSUP as well as PK_ERR
+ */
+
+ if (AllCodes)
+ return retcode;
+
+ if ((retcode == PK_OK) || (retcode == PK_WARN) || (retcode == PK_ERR) ||
+ (retcode == IZ_UNSUP) || (retcode == PK_FIND))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+#endif /* DLL */
diff --git a/Build/source/libs/unzip/consts.h b/Build/source/libs/unzip/consts.h
new file mode 100644
index 00000000000..f418a6c8fe1
--- /dev/null
+++ b/Build/source/libs/unzip/consts.h
@@ -0,0 +1,46 @@
+/*---------------------------------------------------------------------------
+
+ consts.h
+
+ This file contains global, initialized variables that never change. It is
+ included by unzip.c and windll/windll.c.
+
+ ---------------------------------------------------------------------------*/
+
+
+/* And'ing with mask_bits[n] masks the lower n bits */
+ZCONST ush near mask_bits[] = {
+ 0x0000,
+ 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+ 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+
+ZCONST char Far VersionDate[] = VERSION_DATE; /* now defined in version.h */
+
+#ifndef SFX
+ ZCONST char Far EndSigMsg[] =
+ "\nnote: didn't find end-of-central-dir signature at end of central dir.\n";
+#endif
+
+ZCONST char Far CentSigMsg[] =
+ "error: expected central file header signature not found (file #%u).\n";
+ZCONST char Far SeekMsg[] =
+ "error [%s]: attempt to seek before beginning of zipfile\n%s";
+ZCONST char Far FilenameNotMatched[] = "caution: filename not matched: %s\n";
+ZCONST char Far ExclFilenameNotMatched[] =
+ "caution: excluded filename not matched: %s\n";
+
+#ifdef VMS
+ ZCONST char Far ReportMsg[] = "\
+ (please check that you have transferred or created the zipfile in the\n\
+ appropriate BINARY mode--this includes ftp, Kermit, AND unzip'd zipfiles)\n";
+#else
+ ZCONST char Far ReportMsg[] = "\
+ (please check that you have transferred or created the zipfile in the\n\
+ appropriate BINARY mode and that you have compiled UnZip properly)\n";
+#endif
+
+#ifndef SFX
+ ZCONST char Far Zipnfo[] = "zipinfo";
+ ZCONST char Far CompiledWith[] = "Compiled with %s%s for %s%s%s%s.\n\n";
+#endif
diff --git a/Build/source/libs/unzip/crc32.c b/Build/source/libs/unzip/crc32.c
new file mode 100644
index 00000000000..ff2daa0c088
--- /dev/null
+++ b/Build/source/libs/unzip/crc32.c
@@ -0,0 +1,56 @@
+/* crc32.c -- compute the CRC-32 of a data stream
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* $Id: crc32.c,v 1.1 1999/02/01 04:22:50 mik Exp $ */
+
+#define __CRC32_C /* identifies this source module */
+
+#include "zip.h"
+
+#ifndef USE_ZLIB
+#ifndef ASM_CRC
+
+#ifndef ZCONST
+# define ZCONST const
+#endif
+
+#ifdef CRC32
+# undef CRC32
+#endif
+#define CRC32(c, b) (crc_table[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8))
+#define DO1(buf) crc = CRC32(crc, *buf++)
+#define DO2(buf) DO1(buf); DO1(buf)
+#define DO4(buf) DO2(buf); DO2(buf)
+#define DO8(buf) DO4(buf); DO4(buf)
+
+/* ========================================================================= */
+ulg crc32(crc, buf, len)
+ register ulg crc; /* crc shift register */
+ register ZCONST uch *buf; /* pointer to bytes to pump through */
+ extent len; /* number of bytes in buf[] */
+/* Run a set of bytes through the crc shift register. If buf is a NULL
+ pointer, then initialize the crc shift register contents instead.
+ Return the current crc in either case. */
+{
+ register ZCONST ulg near *crc_table;
+
+ if (buf == NULL) return 0L;
+
+ crc_table = get_crc_table();
+
+ crc = crc ^ 0xffffffffL;
+#ifndef NO_UNROLLED_LOOPS
+ while (len >= 8) {
+ DO8(buf);
+ len -= 8;
+ }
+#endif
+ if (len) do {
+ DO1(buf);
+ } while (--len);
+ return crc ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */
+}
+#endif /* !ASM_CRC */
+#endif /* !USE_ZLIB */
diff --git a/Build/source/libs/unzip/crctab.c b/Build/source/libs/unzip/crctab.c
new file mode 100644
index 00000000000..4eb6461c23b
--- /dev/null
+++ b/Build/source/libs/unzip/crctab.c
@@ -0,0 +1,219 @@
+/* crctab.c -- supply the CRC table needed for CRC-32 calculations.
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* $Id: crctab.c,v 1.1 1999/02/01 04:22:50 mik Exp $ */
+
+/*
+ Generate a table for a byte-wise 32-bit CRC calculation on the polynomial:
+ x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
+
+ Polynomials over GF(2) are represented in binary, one bit per coefficient,
+ with the lowest powers in the most significant bit. Then adding polynomials
+ is just exclusive-or, and multiplying a polynomial by x is a right shift by
+ one. If we call the above polynomial p, and represent a byte as the
+ polynomial q, also with the lowest power in the most significant bit (so the
+ byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
+ where a mod b means the remainder after dividing a by b.
+
+ This calculation is done using the shift-register method of multiplying and
+ taking the remainder. The register is initialized to zero, and for each
+ incoming bit, x^32 is added mod p to the register if the bit is a one (where
+ x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
+ x (which is shifting right by one and adding x^32 mod p if the bit shifted
+ out is a one). We start with the highest power (least significant bit) of
+ q and repeat for all eight bits of q.
+
+ The table is simply the CRC of all possible eight bit values. This is all
+ the information needed to generate CRC's on data a byte at a time for all
+ combinations of CRC register values and incoming bytes.
+*/
+
+#define __CRCTAB_C /* identifies this source module */
+
+#include "zip.h"
+
+#if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB))
+
+#ifndef ZCONST
+# define ZCONST const
+#endif
+
+#ifdef DYNAMIC_CRC_TABLE
+
+/* =========================================================================
+ * Make the crc table. This function is needed only if you want to compute
+ * the table dynamically.
+ */
+
+local void make_crc_table OF((void));
+
+#if (defined(DYNALLOC_CRCTAB) && defined(REENTRANT))
+ error: Dynamic allocation of CRC table not safe with reentrant code.
+#endif /* DYNALLOC_CRCTAB && REENTRANT */
+
+#ifdef DYNALLOC_CRCTAB
+ local ulg near *crc_table = NULL;
+# if 0 /* not used, since sizeof("near *") <= sizeof(int) */
+ /* Use this section when access to a "local int" is faster than access to
+ a "local pointer" (e.g.: i86 16bit code with far pointers). */
+ local int crc_table_empty = 1;
+# define CRC_TABLE_IS_EMPTY (crc_table_empty != 0)
+# define MARK_CRCTAB_FILLED crc_table_empty = 0
+# define MARK_CRCTAB_EMPTY crc_table_empty = 1
+# else
+ /* Use this section on systems where the size of pointers and ints is
+ equal (e.g.: all 32bit systems). */
+# define CRC_TABLE_IS_EMPTY (crc_table == NULL)
+# define MARK_CRCTAB_FILLED crc_table = crctab_p
+# define MARK_CRCTAB_EMPTY crc_table = NULL
+# endif
+#else /* !DYNALLOC_CRCTAB */
+ local ulg near crc_table[256];
+ local int crc_table_empty = 1;
+# define CRC_TABLE_IS_EMPTY (crc_table_empty != 0)
+# define MARK_CRCTAB_FILLED crc_table_empty = 0
+#endif /* ?DYNALLOC_CRCTAB */
+
+
+local void make_crc_table()
+{
+ ulg c; /* crc shift register */
+ int n; /* counter for all possible eight bit values */
+ int k; /* byte being shifted into crc apparatus */
+#ifdef DYNALLOC_CRCTAB
+ ulg near *crctab_p; /* temporary pointer to allocated crc_table area */
+#else /* !DYNALLOC_CRCTAB */
+# define crctab_p crc_table
+#endif /* DYNALLOC_CRCTAB */
+
+#ifdef COMPUTE_XOR_PATTERN
+ /* This piece of code has been left here to explain how the XOR pattern
+ * used in the creation of the crc_table values can be recomputed.
+ * For production versions of this function, it is more efficient to
+ * supply the resultant pattern at compile time.
+ */
+ ulg xor; /* polynomial exclusive-or pattern */
+ /* terms of polynomial defining this crc (except x^32): */
+ static uch p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
+
+ /* make exclusive-or pattern from polynomial (0xedb88320L) */
+ xor = 0L;
+ for (i = 0; i < sizeof(p)/sizeof(uch); i++)
+ xor |= 1L << (31 - p[i]);
+#else
+# define xor 0xedb88320L
+#endif
+
+#ifdef DYNALLOC_CRCTAB
+ crctab_p = (ulg near *) nearmalloc (256*sizeof(ulg));
+ if (crctab_p == NULL) {
+ ziperr(ZE_MEM, "crc_table allocation");
+ }
+#endif /* DYNALLOC_CRCTAB */
+
+ for (n = 0; n < 256; n++) {
+ c = (ulg)n;
+ for (k = 8; k; k--)
+ c = c & 1 ? xor ^ (c >> 1) : c >> 1;
+ crctab_p[n] = c;
+ }
+ MARK_CRCTAB_FILLED;
+}
+
+#else /* !DYNAMIC_CRC_TABLE */
+
+#ifdef DYNALLOC_CRCTAB
+ error: Inconsistent flags, DYNALLOC_CRCTAB without DYNAMIC_CRC_TABLE.
+#endif
+
+/* ========================================================================
+ * Table of CRC-32's of all single-byte values (made by make_crc_table)
+ */
+local ZCONST ulg near crc_table[256] = {
+ 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+ 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+ 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+ 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+ 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+ 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+ 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+ 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+ 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+ 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+ 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+ 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+ 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+ 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+ 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+ 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+ 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+ 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+ 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+ 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+ 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+ 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+ 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+ 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+ 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+ 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+ 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+ 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+ 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+ 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+ 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+ 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+ 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+ 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+ 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+ 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+ 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+ 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+ 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+ 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+ 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+ 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+ 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+ 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+ 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+ 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+ 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+ 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+ 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+ 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+ 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+ 0x2d02ef8dL
+};
+#endif /* ?DYNAMIC_CRC_TABLE */
+
+/* use "OF((void))" here to work around a Borland TC++ 1.0 problem */
+#ifdef USE_ZLIB
+ZCONST uLongf *get_crc_table OF((void))
+#else
+ZCONST ulg near *get_crc_table OF((void))
+#endif
+{
+#ifdef DYNAMIC_CRC_TABLE
+ if (CRC_TABLE_IS_EMPTY)
+ make_crc_table();
+#endif
+#ifdef USE_ZLIB
+ return (ZCONST uLongf *)crc_table;
+#else
+ return (ZCONST ulg near *)crc_table;
+#endif
+}
+
+#ifdef DYNALLOC_CRCTAB
+void free_crc_table()
+{
+ if (!CRC_TABLE_IS_EMPTY)
+ {
+ nearfree((ulg near *)crc_table);
+ MARK_CRCTAB_EMPTY;
+ }
+}
+#endif
+
+#endif /* !USE_ZLIB || USE_OWN_CRCTAB */
diff --git a/Build/source/libs/unzip/crypt.c b/Build/source/libs/unzip/crypt.c
new file mode 100644
index 00000000000..0dbe227f810
--- /dev/null
+++ b/Build/source/libs/unzip/crypt.c
@@ -0,0 +1,12 @@
+/*
+ crypt.c (dummy version) by Info-ZIP. Last revised: 15 Aug 98
+
+ This is a non-functional version of Info-ZIP's crypt.c encryption/
+ decryption code for Zip, ZipCloak, UnZip and fUnZip. This file is
+ not copyrighted and may be distributed freely. :-) See the "WHERE"
+ file for sites from which to obtain the full encryption/decryption
+ sources (zcrypt28.zip or later).
+ */
+
+/* something "externally visible" to shut up compiler/linker warnings */
+int zcr_dummy;
diff --git a/Build/source/libs/unzip/crypt.h b/Build/source/libs/unzip/crypt.h
new file mode 100644
index 00000000000..d462f2d7ba5
--- /dev/null
+++ b/Build/source/libs/unzip/crypt.h
@@ -0,0 +1,24 @@
+/*
+ crypt.h (dummy version) by Info-ZIP. Last revised: 15 Aug 98
+
+ This is a non-functional version of Info-ZIP's crypt.h encryption/
+ decryption header file for Zip, ZipCloak, UnZip and fUnZip. This
+ file is not copyrighted and may be distributed without restriction.
+ See the "WHERE" file for sites from which to obtain the full crypt
+ sources (zcrypt28.zip or later).
+ */
+
+#ifndef __crypt_h /* don't include more than once */
+#define __crypt_h
+
+#ifdef CRYPT
+# undef CRYPT
+#endif
+#define CRYPT 0 /* dummy version */
+
+#define zencode
+#define zdecode
+
+#define zfwrite fwrite
+
+#endif /* !__crypt_h */
diff --git a/Build/source/libs/unzip/depend.mak b/Build/source/libs/unzip/depend.mak
new file mode 100644
index 00000000000..2575add1c92
--- /dev/null
+++ b/Build/source/libs/unzip/depend.mak
@@ -0,0 +1,83 @@
+# DO NOT DELETE
+
+$(objdir)/api.obj: api.c \
+ unzip.h \
+ windll/structs.h unzpriv.h \
+ $(gnuw32dir)/win32lib.h \
+ $(gnuw32dir)/oldnames.h win32/w32cfg.h \
+ globals.h version.h windll/windll.h \
+ windll/structs.h windll/decs.h
+$(objdir)/crc32.obj: crc32.c zip.h unzip.h \
+ windll/structs.h unzpriv.h \
+ $(gnuw32dir)/win32lib.h \
+ $(gnuw32dir)/oldnames.h win32/w32cfg.h \
+ globals.h
+$(objdir)/crctab.obj: crctab.c zip.h unzip.h \
+ windll/structs.h unzpriv.h \
+ $(gnuw32dir)/win32lib.h \
+ $(gnuw32dir)/oldnames.h win32/w32cfg.h \
+ globals.h
+$(objdir)/explode.obj: explode.c unzip.h \
+ windll/structs.h unzpriv.h \
+ $(gnuw32dir)/win32lib.h \
+ $(gnuw32dir)/oldnames.h win32/w32cfg.h \
+ globals.h
+$(objdir)/extract.obj: extract.c unzip.h \
+ windll/structs.h unzpriv.h \
+ $(gnuw32dir)/win32lib.h \
+ $(gnuw32dir)/oldnames.h win32/w32cfg.h \
+ globals.h crypt.h windll/windll.h \
+ windll/structs.h windll/decs.h
+$(objdir)/fileio.obj: fileio.c unzip.h \
+ windll/structs.h unzpriv.h \
+ $(gnuw32dir)/win32lib.h \
+ $(gnuw32dir)/oldnames.h win32/w32cfg.h \
+ globals.h windll/windll.h \
+ windll/structs.h windll/decs.h crypt.h ttyio.h ebcdic.h
+$(objdir)/globals.obj: globals.c unzip.h \
+ windll/structs.h unzpriv.h \
+ $(gnuw32dir)/win32lib.h \
+ $(gnuw32dir)/oldnames.h win32/w32cfg.h \
+ globals.h
+$(objdir)/inflate.obj: inflate.c inflate.h unzip.h \
+ windll/structs.h unzpriv.h \
+ $(gnuw32dir)/win32lib.h \
+ $(gnuw32dir)/oldnames.h win32/w32cfg.h \
+ globals.h
+$(objdir)/list.obj: list.c unzip.h \
+ windll/structs.h unzpriv.h \
+ $(gnuw32dir)/win32lib.h \
+ $(gnuw32dir)/oldnames.h win32/w32cfg.h \
+ globals.h windll/windll.h \
+ windll/structs.h windll/decs.h
+$(objdir)/match.obj: match.c unzip.h \
+ windll/structs.h unzpriv.h \
+ $(gnuw32dir)/win32lib.h \
+ $(gnuw32dir)/oldnames.h win32/w32cfg.h \
+ globals.h
+$(objdir)/process.obj: process.c unzip.h \
+ windll/structs.h unzpriv.h \
+ $(gnuw32dir)/win32lib.h \
+ $(gnuw32dir)/oldnames.h win32/w32cfg.h \
+ globals.h windll/windll.h \
+ windll/structs.h windll/decs.h
+$(objdir)/ttyio.obj: ttyio.c zip.h unzip.h \
+ windll/structs.h unzpriv.h \
+ $(gnuw32dir)/win32lib.h \
+ $(gnuw32dir)/oldnames.h win32/w32cfg.h \
+ globals.h crypt.h ttyio.h
+$(objdir)/unreduce.obj: unreduce.c unzip.h \
+ windll/structs.h unzpriv.h \
+ $(gnuw32dir)/win32lib.h \
+ $(gnuw32dir)/oldnames.h win32/w32cfg.h \
+ globals.h
+$(objdir)/unshrink.obj: unshrink.c unzip.h \
+ windll/structs.h unzpriv.h \
+ $(gnuw32dir)/win32lib.h \
+ $(gnuw32dir)/oldnames.h win32/w32cfg.h \
+ globals.h
+$(objdir)/zipinfo.obj: zipinfo.c unzip.h \
+ windll/structs.h unzpriv.h \
+ $(gnuw32dir)/win32lib.h \
+ $(gnuw32dir)/oldnames.h win32/w32cfg.h \
+ globals.h
diff --git a/Build/source/libs/unzip/ebcdic.h b/Build/source/libs/unzip/ebcdic.h
new file mode 100644
index 00000000000..db2e976b7fa
--- /dev/null
+++ b/Build/source/libs/unzip/ebcdic.h
@@ -0,0 +1,272 @@
+/*---------------------------------------------------------------------------
+
+ ebcdic.h
+
+ The CECP 1047 (Extended de-facto EBCDIC) <-> ISO 8859-1 conversion tables,
+ from ftp://aix1.segi.ulg.ac.be/pub/docs/iso8859/iso8859.networking
+
+ NOTES:
+ <Paul_von_Behren@stortek.com> (OS/390 port 12/97)
+ These table no longer represent the standard mappings (for example in the
+ OS/390 iconv utility). In order to follow current standards I remapped
+ ebcdic x0a to ascii x15 and
+ ebcdic x85 to ascii x25 (and vice-versa)
+ Without these changes, newlines in auto-convert text files appeared
+ as literal \045.
+ I'm not sure what effect this remap would have on the MVS and CMS ports, so
+ I ifdef'd these changes. Hopefully these ifdef's can be removed when the
+ MVS/CMS folks test the new mappings.
+
+ Christian Spieler <spieler@ikp.tu-darmstadt.de>, 27-Apr-1998
+ The problem mentioned by Paul von Behren was already observed previously
+ on VM/CMS, during the preparation of the CMS&MVS port of UnZip 5.20 in
+ 1996. At that point, the ebcdic tables were not changed since they seemed
+ to be an adopted standard (to my knowledge, these tables are still used
+ as presented in mainfraime KERMIT). Instead, the "end-of-line" conversion
+ feature of Zip's and UnZip's "text-translation" mode was used to force
+ correct mappings between ASCII and EBCDIC newline markers.
+ Before interchanging the ASCII mappings of the EBCDIC control characters
+ "NL" 0x25 and "LF" 0x15 according to the OS/390 setting, we have to
+ make sure that EBCDIC 0x15 is never used as line termination.
+
+ ---------------------------------------------------------------------------*/
+
+#ifndef __ebcdic_h /* prevent multiple inclusions */
+#define __ebcdic_h
+
+
+#ifndef ZCONST
+# define ZCONST const
+#endif
+
+#ifdef EBCDIC
+#ifndef MTS /* MTS uses a slightly "special" EBCDIC code page */
+
+ZCONST uch ebcdic[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F, /* 00 - 07 */
+#ifdef OS390
+ 0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* 08 - 0F */
+#else
+ 0x16, 0x05, 0x25, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* 08 - 0F */
+#endif
+ 0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26, /* 10 - 17 */
+ 0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F, /* 18 - 1F */
+ 0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D, /* 20 - 27 */
+ 0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61, /* 28 - 2F */
+ 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, /* 30 - 37 */
+ 0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F, /* 38 - 3F */
+ 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, /* 40 - 47 */
+ 0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, /* 48 - 4F */
+ 0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, /* 50 - 57 */
+ 0xE7, 0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D, /* 58 - 5F */
+ 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 60 - 67 */
+ 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, /* 68 - 6F */
+ 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, /* 70 - 77 */
+ 0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07, /* 78 - 7F */
+#ifdef OS390
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x06, 0x17, /* 80 - 87 */
+#else
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17, /* 80 - 87 */
+#endif
+ 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x09, 0x0A, 0x1B, /* 88 - 8F */
+ 0x30, 0x31, 0x1A, 0x33, 0x34, 0x35, 0x36, 0x08, /* 90 - 97 */
+ 0x38, 0x39, 0x3A, 0x3B, 0x04, 0x14, 0x3E, 0xFF, /* 98 - 9F */
+ 0x41, 0xAA, 0x4A, 0xB1, 0x9F, 0xB2, 0x6A, 0xB5, /* A0 - A7 */
+ 0xBB, 0xB4, 0x9A, 0x8A, 0xB0, 0xCA, 0xAF, 0xBC, /* A8 - AF */
+ 0x90, 0x8F, 0xEA, 0xFA, 0xBE, 0xA0, 0xB6, 0xB3, /* B0 - B7 */
+ 0x9D, 0xDA, 0x9B, 0x8B, 0xB7, 0xB8, 0xB9, 0xAB, /* B8 - BF */
+ 0x64, 0x65, 0x62, 0x66, 0x63, 0x67, 0x9E, 0x68, /* C0 - C7 */
+ 0x74, 0x71, 0x72, 0x73, 0x78, 0x75, 0x76, 0x77, /* C8 - CF */
+ 0xAC, 0x69, 0xED, 0xEE, 0xEB, 0xEF, 0xEC, 0xBF, /* D0 - D7 */
+ 0x80, 0xFD, 0xFE, 0xFB, 0xFC, 0xBA, 0xAE, 0x59, /* D8 - DF */
+ 0x44, 0x45, 0x42, 0x46, 0x43, 0x47, 0x9C, 0x48, /* E0 - E7 */
+ 0x54, 0x51, 0x52, 0x53, 0x58, 0x55, 0x56, 0x57, /* E8 - EF */
+ 0x8C, 0x49, 0xCD, 0xCE, 0xCB, 0xCF, 0xCC, 0xE1, /* F0 - F7 */
+ 0x70, 0xDD, 0xDE, 0xDB, 0xDC, 0x8D, 0x8E, 0xDF /* F8 - FF */
+};
+
+#if (defined(ZIP) || CRYPT)
+ZCONST uch ascii[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F, /* 00 - 07 */
+ 0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* 08 - 0F */
+#ifdef OS390
+ 0x10, 0x11, 0x12, 0x13, 0x9D, 0x0A, 0x08, 0x87, /* 10 - 17 */
+#else
+ 0x10, 0x11, 0x12, 0x13, 0x9D, 0x85, 0x08, 0x87, /* 10 - 17 */
+#endif
+ 0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F, /* 18 - 1F */
+#ifdef OS390
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x17, 0x1B, /* 20 - 27 */
+#else
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x0A, 0x17, 0x1B, /* 20 - 27 */
+#endif
+ 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07, /* 28 - 2F */
+ 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04, /* 30 - 37 */
+ 0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A, /* 38 - 3F */
+ 0x20, 0xA0, 0xE2, 0xE4, 0xE0, 0xE1, 0xE3, 0xE5, /* 40 - 47 */
+ 0xE7, 0xF1, 0xA2, 0x2E, 0x3C, 0x28, 0x2B, 0x7C, /* 48 - 4F */
+ 0x26, 0xE9, 0xEA, 0xEB, 0xE8, 0xED, 0xEE, 0xEF, /* 50 - 57 */
+ 0xEC, 0xDF, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0x5E, /* 58 - 5F */
+ 0x2D, 0x2F, 0xC2, 0xC4, 0xC0, 0xC1, 0xC3, 0xC5, /* 60 - 67 */
+ 0xC7, 0xD1, 0xA6, 0x2C, 0x25, 0x5F, 0x3E, 0x3F, /* 68 - 6F */
+ 0xF8, 0xC9, 0xCA, 0xCB, 0xC8, 0xCD, 0xCE, 0xCF, /* 70 - 77 */
+ 0xCC, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22, /* 78 - 7F */
+ 0xD8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 80 - 87 */
+ 0x68, 0x69, 0xAB, 0xBB, 0xF0, 0xFD, 0xFE, 0xB1, /* 88 - 8F */
+ 0xB0, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, /* 90 - 97 */
+ 0x71, 0x72, 0xAA, 0xBA, 0xE6, 0xB8, 0xC6, 0xA4, /* 98 - 9F */
+ 0xB5, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, /* A0 - A7 */
+ 0x79, 0x7A, 0xA1, 0xBF, 0xD0, 0x5B, 0xDE, 0xAE, /* A8 - AF */
+ 0xAC, 0xA3, 0xA5, 0xB7, 0xA9, 0xA7, 0xB6, 0xBC, /* B0 - B7 */
+ 0xBD, 0xBE, 0xDD, 0xA8, 0xAF, 0x5D, 0xB4, 0xD7, /* B8 - BF */
+ 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* C0 - C7 */
+ 0x48, 0x49, 0xAD, 0xF4, 0xF6, 0xF2, 0xF3, 0xF5, /* C8 - CF */
+ 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, /* D0 - D7 */
+ 0x51, 0x52, 0xB9, 0xFB, 0xFC, 0xF9, 0xFA, 0xFF, /* D8 - DF */
+ 0x5C, 0xF7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, /* E0 - E7 */
+ 0x59, 0x5A, 0xB2, 0xD4, 0xD6, 0xD2, 0xD3, 0xD5, /* E8 - EF */
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* F0 - F7 */
+ 0x38, 0x39, 0xB3, 0xDB, 0xDC, 0xD9, 0xDA, 0x9F /* F8 - FF */
+};
+#endif /* ZIP || CRYPT */
+
+#else /* MTS */
+
+/*
+ * This is the MTS ASCII->EBCDIC translation table. It provides a 1-1
+ * translation from ISO 8859/1 8-bit ASCII to IBM Code Page 37 EBCDIC.
+ */
+
+ZCONST uch ebcdic[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F, /* 00 - 07 */
+ 0x16, 0x05, 0x25, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* 08 - 0F */
+ 0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26, /* 10 - 17 */
+ 0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F, /* 18 - 1F */
+ 0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D, /* 20 - 27 */
+ 0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61, /* 28 - 2F */
+ 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, /* 30 - 37 */
+ 0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F, /* 38 - 3F */
+ 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, /* 40 - 47 */
+ 0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, /* 48 - 4F */
+ 0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, /* 50 - 57 */
+ 0xE7, 0xE8, 0xE9, 0xBA, 0xE0, 0xBB, 0xB0, 0x6D, /* 58 - 5F */
+ 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 60 - 67 */
+ 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, /* 68 - 6F */
+ 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, /* 70 - 77 */
+ 0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07, /* 78 - 7F */
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17, /* 80 - 87 */
+ 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x09, 0x0A, 0x1B, /* 88 - 8F */
+ 0x30, 0x31, 0x1A, 0x33, 0x34, 0x35, 0x36, 0x08, /* 90 - 97 */
+ 0x38, 0x39, 0x3A, 0x3B, 0x04, 0x14, 0x3E, 0xFF, /* 98 - 9F */
+ 0x41, 0xAA, 0x4A, 0xB1, 0x9F, 0xB2, 0x6A, 0xB5, /* A0 - A7 */
+ 0xBD, 0xB4, 0x9A, 0x8A, 0x5F, 0xCA, 0xAF, 0xBC, /* A8 - AF */
+ 0x90, 0x8F, 0xEA, 0xFA, 0xBE, 0xA0, 0xB6, 0xB3, /* B0 - B7 */
+ 0x9D, 0xDA, 0x9B, 0x8B, 0xB7, 0xB8, 0xB9, 0xAB, /* B8 - BF */
+ 0x64, 0x65, 0x62, 0x66, 0x63, 0x67, 0x9E, 0x68, /* C0 - C7 */
+ 0x74, 0x71, 0x72, 0x73, 0x78, 0x75, 0x76, 0x77, /* C8 - CF */
+ 0xAC, 0x69, 0xED, 0xEE, 0xEB, 0xEF, 0xEC, 0xBF, /* D0 - D7 */
+ 0x80, 0xFD, 0xFE, 0xFB, 0xFC, 0xAD, 0xAE, 0x59, /* D8 - DF */
+ 0x44, 0x45, 0x42, 0x46, 0x43, 0x47, 0x9C, 0x48, /* E0 - E7 */
+ 0x54, 0x51, 0x52, 0x53, 0x58, 0x55, 0x56, 0x57, /* E8 - EF */
+ 0x8C, 0x49, 0xCD, 0xCE, 0xCB, 0xCF, 0xCC, 0xE1, /* F0 - F7 */
+ 0x70, 0xDD, 0xDE, 0xDB, 0xDC, 0x8D, 0x8E, 0xDF /* F8 - FF */
+};
+
+#if (defined(ZIP) || CRYPT)
+ZCONST uch ascii[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F, /* 00 - 07 */
+ 0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* 08 - 0F */
+ 0x10, 0x11, 0x12, 0x13, 0x9D, 0x85, 0x08, 0x87, /* 10 - 17 */
+ 0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F, /* 18 - 1F */
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x0A, 0x17, 0x1B, /* 20 - 27 */
+ 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07, /* 28 - 2F */
+ 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04, /* 30 - 37 */
+ 0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A, /* 38 - 3F */
+ 0x20, 0xA0, 0xE2, 0xE4, 0xE0, 0xE1, 0xE3, 0xE5, /* 40 - 47 */
+ 0xE7, 0xF1, 0xA2, 0x2E, 0x3C, 0x28, 0x2B, 0x7C, /* 48 - 4F */
+ 0x26, 0xE9, 0xEA, 0xEB, 0xE8, 0xED, 0xEE, 0xEF, /* 50 - 57 */
+ 0xEC, 0xDF, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAC, /* 58 - 5F */
+ 0x2D, 0x2F, 0xC2, 0xC4, 0xC0, 0xC1, 0xC3, 0xC5, /* 60 - 67 */
+ 0xC7, 0xD1, 0xA6, 0x2C, 0x25, 0x5F, 0x3E, 0x3F, /* 68 - 6F */
+ 0xF8, 0xC9, 0xCA, 0xCB, 0xC8, 0xCD, 0xCE, 0xCF, /* 70 - 77 */
+ 0xCC, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22, /* 78 - 7F */
+ 0xD8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 80 - 87 */
+ 0x68, 0x69, 0xAB, 0xBB, 0xF0, 0xFD, 0xFE, 0xB1, /* 88 - 8F */
+ 0xB0, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, /* 90 - 97 */
+ 0x71, 0x72, 0xAA, 0xBA, 0xE6, 0xB8, 0xC6, 0xA4, /* 98 - 9F */
+ 0xB5, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, /* A0 - A7 */
+ 0x79, 0x7A, 0xA1, 0xBF, 0xD0, 0xDD, 0xDE, 0xAE, /* A8 - AF */
+ 0x5E, 0xA3, 0xA5, 0xB7, 0xA9, 0xA7, 0xB6, 0xBC, /* B0 - B7 */
+ 0xBD, 0xBE, 0x5B, 0x5D, 0xAF, 0xA8, 0xB4, 0xD7, /* B8 - BF */
+ 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* C0 - C7 */
+ 0x48, 0x49, 0xAD, 0xF4, 0xF6, 0xF2, 0xF3, 0xF5, /* C8 - CF */
+ 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, /* D0 - D7 */
+ 0x51, 0x52, 0xB9, 0xFB, 0xFC, 0xF9, 0xFA, 0xFF, /* D8 - DF */
+ 0x5C, 0xF7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, /* E0 - E7 */
+ 0x59, 0x5A, 0xB2, 0xD4, 0xD6, 0xD2, 0xD3, 0xD5, /* E8 - EF */
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* F0 - F7 */
+ 0x38, 0x39, 0xB3, 0xDB, 0xDC, 0xD9, 0xDA, 0x9F /* F8 - FF */
+};
+#endif /* ZIP || CRYPT */
+
+#endif /* ?MTS */
+#endif /* EBCDIC */
+
+/*---------------------------------------------------------------------------
+
+ The following conversion tables translate between IBM PC CP 850
+ (OEM codepage) and the "Western Europe & America" Windows codepage 1252.
+ The Windows codepage 1252 contains the ISO 8859-1 "Latin 1" codepage,
+ with some additional printable characters in the range (0x80 - 0x9F),
+ that is reserved to control codes in the ISO 8859-1 character table.
+
+ The ISO <--> OEM conversion tables were constructed with the help
+ of the WIN32 (Win16?) API's OemToAnsi() and AnsiToOem() conversion
+ functions and have been checked against the CP850 and LATIN1 tables
+ provided in the MS-Kermit 3.14 distribution.
+
+ ---------------------------------------------------------------------------*/
+
+#ifdef IZ_ISO2OEM_ARRAY
+ZCONST uch Far iso2oem[] = {
+ 0x3F, 0x3F, 0x27, 0x9F, 0x22, 0x2E, 0xC5, 0xCE, /* 80 - 87 */
+ 0x5E, 0x25, 0x53, 0x3C, 0x4F, 0x3F, 0x3F, 0x3F, /* 88 - 8F */
+ 0x3F, 0x27, 0x27, 0x22, 0x22, 0x07, 0x2D, 0x2D, /* 90 - 97 */
+ 0x7E, 0x54, 0x73, 0x3E, 0x6F, 0x3F, 0x3F, 0x59, /* 98 - 9F */
+ 0xFF, 0xAD, 0xBD, 0x9C, 0xCF, 0xBE, 0xDD, 0xF5, /* A0 - A7 */
+ 0xF9, 0xB8, 0xA6, 0xAE, 0xAA, 0xF0, 0xA9, 0xEE, /* A8 - AF */
+ 0xF8, 0xF1, 0xFD, 0xFC, 0xEF, 0xE6, 0xF4, 0xFA, /* B0 - B7 */
+ 0xF7, 0xFB, 0xA7, 0xAF, 0xAC, 0xAB, 0xF3, 0xA8, /* B8 - BF */
+ 0xB7, 0xB5, 0xB6, 0xC7, 0x8E, 0x8F, 0x92, 0x80, /* C0 - C7 */
+ 0xD4, 0x90, 0xD2, 0xD3, 0xDE, 0xD6, 0xD7, 0xD8, /* C8 - CF */
+ 0xD1, 0xA5, 0xE3, 0xE0, 0xE2, 0xE5, 0x99, 0x9E, /* D0 - D7 */
+ 0x9D, 0xEB, 0xE9, 0xEA, 0x9A, 0xED, 0xE8, 0xE1, /* D8 - DF */
+ 0x85, 0xA0, 0x83, 0xC6, 0x84, 0x86, 0x91, 0x87, /* E0 - E7 */
+ 0x8A, 0x82, 0x88, 0x89, 0x8D, 0xA1, 0x8C, 0x8B, /* E8 - EF */
+ 0xD0, 0xA4, 0x95, 0xA2, 0x93, 0xE4, 0x94, 0xF6, /* F0 - F7 */
+ 0x9B, 0x97, 0xA3, 0x96, 0x81, 0xEC, 0xE7, 0x98 /* F8 - FF */
+};
+#endif /* IZ_ISO2OEM_ARRAY */
+
+#ifdef IZ_OEM2ISO_ARRAY
+ZCONST uch Far oem2iso[] = {
+ 0xC7, 0xFC, 0xE9, 0xE2, 0xE4, 0xE0, 0xE5, 0xE7, /* 80 - 87 */
+ 0xEA, 0xEB, 0xE8, 0xEF, 0xEE, 0xEC, 0xC4, 0xC5, /* 88 - 8F */
+ 0xC9, 0xE6, 0xC6, 0xF4, 0xF6, 0xF2, 0xFB, 0xF9, /* 90 - 97 */
+ 0xFF, 0xD6, 0xDC, 0xF8, 0xA3, 0xD8, 0xD7, 0x83, /* 98 - 9F */
+ 0xE1, 0xED, 0xF3, 0xFA, 0xF1, 0xD1, 0xAA, 0xBA, /* A0 - A7 */
+ 0xBF, 0xAE, 0xAC, 0xBD, 0xBC, 0xA1, 0xAB, 0xBB, /* A8 - AF */
+ 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xC1, 0xC2, 0xC0, /* B0 - B7 */
+ 0xA9, 0xA6, 0xA6, 0x2B, 0x2B, 0xA2, 0xA5, 0x2B, /* B8 - BF */
+ 0x2B, 0x2D, 0x2D, 0x2B, 0x2D, 0x2B, 0xE3, 0xC3, /* C0 - C7 */
+ 0x2B, 0x2B, 0x2D, 0x2D, 0xA6, 0x2D, 0x2B, 0xA4, /* C8 - CF */
+ 0xF0, 0xD0, 0xCA, 0xCB, 0xC8, 0x69, 0xCD, 0xCE, /* D0 - D7 */
+ 0xCF, 0x2B, 0x2B, 0xA6, 0x5F, 0xA6, 0xCC, 0xAF, /* D8 - DF */
+ 0xD3, 0xDF, 0xD4, 0xD2, 0xF5, 0xD5, 0xB5, 0xFE, /* E0 - E7 */
+ 0xDE, 0xDA, 0xDB, 0xD9, 0xFD, 0xDD, 0xAF, 0xB4, /* E8 - EF */
+ 0xAD, 0xB1, 0x3D, 0xBE, 0xB6, 0xA7, 0xF7, 0xB8, /* F0 - F7 */
+ 0xB0, 0xA8, 0xB7, 0xB9, 0xB3, 0xB2, 0xA6, 0xA0 /* F8 - FF */
+};
+#endif /* IZ_OEM2ISO_ARRAY */
+
+#endif /* __ebcdic_h */
diff --git a/Build/source/libs/unzip/explode.c b/Build/source/libs/unzip/explode.c
new file mode 100644
index 00000000000..c1a8f80032a
--- /dev/null
+++ b/Build/source/libs/unzip/explode.c
@@ -0,0 +1,871 @@
+/* explode.c -- put in the public domain by Mark Adler
+ version c15, 6 July 1996 */
+
+
+/* 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
+ ---- --------- -------------- ------------------------------------
+ c1 30 Mar 92 M. Adler explode that uses huft_build from inflate
+ (this gives over a 70% speed improvement
+ over the original unimplode.c, which
+ decoded a bit at a time)
+ c2 4 Apr 92 M. Adler fixed bug for file sizes a multiple of 32k.
+ c3 10 Apr 92 M. Adler added a little memory tracking if DEBUG
+ c4 11 Apr 92 M. Adler added NOMEMCPY do kill use of memcpy()
+ c5 21 Apr 92 M. Adler added the WSIZE #define to allow reducing
+ the 32K window size for specialized
+ applications.
+ c6 31 May 92 M. Adler added typecasts to eliminate some warnings
+ c7 27 Jun 92 G. Roelofs added more typecasts.
+ c8 17 Oct 92 G. Roelofs changed ULONG/UWORD/byte to ulg/ush/uch.
+ c9 19 Jul 93 J. Bush added more typecasts (to return values);
+ made l[256] array static for Amiga.
+ c10 8 Oct 93 G. Roelofs added used_csize for diagnostics; added
+ buf and unshrink arguments to flush();
+ undef'd various macros at end for Turbo C;
+ removed NEXTBYTE macro (now in unzip.h)
+ and bytebuf variable (not used); changed
+ memset() to memzero().
+ c11 9 Jan 94 M. Adler fixed incorrect used_csize calculation.
+ c12 9 Apr 94 G. Roelofs fixed split comments on preprocessor lines
+ to avoid bug in Encore compiler.
+ c13 25 Aug 94 M. Adler fixed distance-length comment (orig c9 fix)
+ c14 22 Nov 95 S. Maxwell removed unnecessary "static" on auto array
+ c15 6 Jul 96 W. Haidinger added ulg typecasts to flush() calls.
+ c16 8 Feb 98 C. Spieler added ZCONST modifiers to const tables
+ and #ifdef DEBUG around debugging code.
+ c16b 25 Mar 98 C. Spieler modified DLL code for slide redirection.
+ */
+
+
+/*
+ Explode imploded (PKZIP method 6 compressed) data. This compression
+ method searches for as much of the current string of bytes (up to a length
+ of ~320) in the previous 4K or 8K bytes. If it doesn't find any matches
+ (of at least length 2 or 3), it codes the next byte. Otherwise, it codes
+ the length of the matched string and its distance backwards from the
+ current position. Single bytes ("literals") are preceded by a one (a
+ single bit) and are either uncoded (the eight bits go directly into the
+ compressed stream for a total of nine bits) or Huffman coded with a
+ supplied literal code tree. If literals are coded, then the minimum match
+ length is three, otherwise it is two.
+
+ There are therefore four kinds of imploded streams: 8K search with coded
+ literals (min match = 3), 4K search with coded literals (min match = 3),
+ 8K with uncoded literals (min match = 2), and 4K with uncoded literals
+ (min match = 2). The kind of stream is identified in two bits of a
+ general purpose bit flag that is outside of the compressed stream.
+
+ Distance-length pairs for matched strings are preceded by a zero bit (to
+ distinguish them from literals) and are always coded. The distance comes
+ first and is either the low six (4K) or low seven (8K) bits of the
+ distance (uncoded), followed by the high six bits of the distance coded.
+ Then the length is six bits coded (0..63 + min match length), and if the
+ maximum such length is coded, then it's followed by another eight bits
+ (uncoded) to be added to the coded length. This gives a match length
+ range of 2..320 or 3..321 bytes.
+
+ The literal, length, and distance codes are all represented in a slightly
+ compressed form themselves. What is sent are the lengths of the codes for
+ each value, which is sufficient to construct the codes. Each byte of the
+ code representation is the code length (the low four bits representing
+ 1..16), and the number of values sequentially with that length (the high
+ four bits also representing 1..16). There are 256 literal code values (if
+ literals are coded), 64 length code values, and 64 distance code values,
+ in that order at the beginning of the compressed stream. Each set of code
+ values is preceded (redundantly) with a byte indicating how many bytes are
+ in the code description that follows, in the range 1..256.
+
+ The codes themselves are decoded using tables made by huft_build() from
+ the bit lengths. That routine and its comments are in the inflate.c
+ module.
+ */
+
+#define UNZIP_INTERNAL
+#include "unzip.h" /* must supply slide[] (uch) array and NEXTBYTE macro */
+
+#ifndef WSIZE
+# define WSIZE 0x8000 /* window size--must be a power of two, and */
+#endif /* at least 8K for zip's implode method */
+
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+# define wsize G._wsize
+#else
+# define wsize WSIZE
+#endif
+
+/* routines here */
+static int get_tree OF((__GPRO__ unsigned *l, unsigned n));
+static int explode_lit8 OF((__GPRO__ struct huft *tb, struct huft *tl,
+ struct huft *td, int bb, int bl, int bd));
+static int explode_lit4 OF((__GPRO__ struct huft *tb, struct huft *tl,
+ struct huft *td, int bb, int bl, int bd));
+static int explode_nolit8 OF((__GPRO__ struct huft *tl, struct huft *td,
+ int bl, int bd));
+static int explode_nolit4 OF((__GPRO__ struct huft *tl, struct huft *td,
+ int bl, int bd));
+int explode OF((__GPRO));
+
+
+/* The implode algorithm uses a sliding 4K or 8K byte window on the
+ uncompressed stream to find repeated byte strings. This is implemented
+ here as a circular buffer. The index is updated simply by incrementing
+ and then and'ing with 0x0fff (4K-1) or 0x1fff (8K-1). Here, the 32K
+ buffer of inflate is used, and it works just as well to always have
+ a 32K circular buffer, so the index is anded with 0x7fff. This is
+ done to allow the window to also be used as the output buffer. */
+/* This must be supplied in an external module useable like "uch slide[8192];"
+ or "uch *slide;", where the latter would be malloc'ed. In unzip, slide[]
+ is actually a 32K area for use by inflate, which uses a 32K sliding window.
+ */
+
+
+/* Tables for length and distance */
+static ZCONST ush cplen2[] =
+ {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65};
+static ZCONST ush cplen3[] =
+ {3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+ 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66};
+static ZCONST ush extra[] =
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 8};
+static ZCONST ush cpdist4[] =
+ {1, 65, 129, 193, 257, 321, 385, 449, 513, 577, 641, 705,
+ 769, 833, 897, 961, 1025, 1089, 1153, 1217, 1281, 1345, 1409, 1473,
+ 1537, 1601, 1665, 1729, 1793, 1857, 1921, 1985, 2049, 2113, 2177,
+ 2241, 2305, 2369, 2433, 2497, 2561, 2625, 2689, 2753, 2817, 2881,
+ 2945, 3009, 3073, 3137, 3201, 3265, 3329, 3393, 3457, 3521, 3585,
+ 3649, 3713, 3777, 3841, 3905, 3969, 4033};
+static ZCONST ush cpdist8[] =
+ {1, 129, 257, 385, 513, 641, 769, 897, 1025, 1153, 1281,
+ 1409, 1537, 1665, 1793, 1921, 2049, 2177, 2305, 2433, 2561, 2689,
+ 2817, 2945, 3073, 3201, 3329, 3457, 3585, 3713, 3841, 3969, 4097,
+ 4225, 4353, 4481, 4609, 4737, 4865, 4993, 5121, 5249, 5377, 5505,
+ 5633, 5761, 5889, 6017, 6145, 6273, 6401, 6529, 6657, 6785, 6913,
+ 7041, 7169, 7297, 7425, 7553, 7681, 7809, 7937, 8065};
+
+
+/* Macros for inflate() bit peeking and grabbing.
+ The usage is:
+
+ NEEDBITS(j)
+ x = b & mask_bits[j];
+ DUMPBITS(j)
+
+ where NEEDBITS makes sure that b has at least j bits in it, and
+ DUMPBITS removes the bits from b. The macros use the variable k
+ for the number of bits in b. Normally, b and k are register
+ variables for speed.
+ */
+
+#define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE)<<k;k+=8;}}
+#define DUMPBITS(n) {b>>=(n);k-=(n);}
+
+
+
+static int get_tree(__G__ l, n)
+ __GDEF
+unsigned *l; /* bit lengths */
+unsigned n; /* number expected */
+/* Get the bit lengths for a code representation from the compressed
+ stream. If get_tree() returns 4, then there is an error in the data.
+ Otherwise zero is returned. */
+{
+ unsigned i; /* bytes remaining in list */
+ unsigned k; /* lengths entered */
+ unsigned j; /* number of codes */
+ unsigned b; /* bit length for those codes */
+
+
+ /* get bit lengths */
+ i = NEXTBYTE + 1; /* length/count pairs to read */
+ k = 0; /* next code */
+ do {
+ b = ((j = NEXTBYTE) & 0xf) + 1; /* bits in code (1..16) */
+ j = ((j & 0xf0) >> 4) + 1; /* codes with those bits (1..16) */
+ if (k + j > n)
+ return 4; /* don't overflow l[] */
+ do {
+ l[k++] = b;
+ } while (--j);
+ } while (--i);
+ return k != n ? 4 : 0; /* should have read n of them */
+}
+
+
+
+static int explode_lit8(__G__ tb, tl, td, bb, bl, bd)
+ __GDEF
+struct huft *tb, *tl, *td; /* literal, length, and distance tables */
+int bb, bl, bd; /* number of bits decoded by those */
+/* Decompress the imploded data using coded literals and an 8K sliding
+ window. */
+{
+ long s; /* bytes to decompress */
+ register unsigned e; /* table entry flag/number of extra bits */
+ unsigned n, d; /* length and index for copy */
+ unsigned w; /* current window position */
+ struct huft *t; /* pointer to table entry */
+ unsigned mb, ml, md; /* masks for bb, bl, and bd bits */
+ register ulg b; /* bit buffer */
+ register unsigned k; /* number of bits in bit buffer */
+ unsigned u; /* true if unflushed */
+
+
+ /* explode the coded data */
+ b = k = w = 0; /* initialize bit buffer, window */
+ u = 1; /* buffer unflushed */
+ mb = mask_bits[bb]; /* precompute masks for speed */
+ ml = mask_bits[bl];
+ md = mask_bits[bd];
+ s = G.ucsize;
+ while (s > 0) /* do until ucsize bytes uncompressed */
+ {
+ NEEDBITS(1)
+ if (b & 1) /* then literal--decode it */
+ {
+ DUMPBITS(1)
+ s--;
+ NEEDBITS((unsigned)bb) /* get coded literal */
+ if ((e = (t = tb + ((~(unsigned)b) & mb))->e) > 16)
+ do {
+ if (e == 99)
+ return 1;
+ DUMPBITS(t->b)
+ e -= 16;
+ NEEDBITS(e)
+ } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+ DUMPBITS(t->b)
+ redirSlide[w++] = (uch)t->v.n;
+ if (w == wsize)
+ {
+ flush(__G__ redirSlide, (ulg)w, 0);
+ w = u = 0;
+ }
+ }
+ else /* else distance/length */
+ {
+ DUMPBITS(1)
+ NEEDBITS(7) /* get distance low bits */
+ d = (unsigned)b & 0x7f;
+ DUMPBITS(7)
+ NEEDBITS((unsigned)bd) /* get coded distance high bits */
+ if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16)
+ do {
+ if (e == 99)
+ return 1;
+ DUMPBITS(t->b)
+ e -= 16;
+ NEEDBITS(e)
+ } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+ DUMPBITS(t->b)
+ d = w - d - t->v.n; /* construct offset */
+ NEEDBITS((unsigned)bl) /* get coded length */
+ if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16)
+ do {
+ if (e == 99)
+ return 1;
+ DUMPBITS(t->b)
+ e -= 16;
+ NEEDBITS(e)
+ } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+ DUMPBITS(t->b)
+ n = t->v.n;
+ if (e) /* get length extra bits */
+ {
+ NEEDBITS(8)
+ n += (unsigned)b & 0xff;
+ DUMPBITS(8)
+ }
+
+ /* do the copy */
+ s -= n;
+ do {
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+ if (G.redirect_slide) {
+ /* &= w/ wsize not needed and wrong if redirect */
+ if (d >= wsize)
+ return 1;
+ n -= (e = (e = wsize - (d > w ? d : w)) > n ? n : e);
+ } else
+#endif
+ n -= (e = (e = wsize - ((d &= wsize-1) > w ? d : w)) > n ? n : e);
+ if (u && w <= d)
+ {
+ memzero(redirSlide + w, e);
+ w += e;
+ d += e;
+ }
+ else
+#ifndef NOMEMCPY
+ if (w - d >= e) /* (this test assumes unsigned comparison) */
+ {
+ memcpy(redirSlide + w, redirSlide + d, e);
+ w += e;
+ d += e;
+ }
+ else /* do it slow to avoid memcpy() overlap */
+#endif /* !NOMEMCPY */
+ do {
+ redirSlide[w++] = redirSlide[d++];
+ } while (--e);
+ if (w == wsize)
+ {
+ flush(__G__ redirSlide, (ulg)w, 0);
+ w = u = 0;
+ }
+ } while (n);
+ }
+ }
+
+ /* flush out redirSlide */
+ flush(__G__ redirSlide, (ulg)w, 0);
+ if (G.csize + G.incnt + (k >> 3)) /* should have read csize bytes, but */
+ { /* sometimes read one too many: k>>3 compensates */
+ G.used_csize = G.lrec.csize - G.csize - G.incnt - (k >> 3);
+ return 5;
+ }
+ return 0;
+}
+
+
+
+static int explode_lit4(__G__ tb, tl, td, bb, bl, bd)
+ __GDEF
+struct huft *tb, *tl, *td; /* literal, length, and distance tables */
+int bb, bl, bd; /* number of bits decoded by those */
+/* Decompress the imploded data using coded literals and a 4K sliding
+ window. */
+{
+ long s; /* bytes to decompress */
+ register unsigned e; /* table entry flag/number of extra bits */
+ unsigned n, d; /* length and index for copy */
+ unsigned w; /* current window position */
+ struct huft *t; /* pointer to table entry */
+ unsigned mb, ml, md; /* masks for bb, bl, and bd bits */
+ register ulg b; /* bit buffer */
+ register unsigned k; /* number of bits in bit buffer */
+ unsigned u; /* true if unflushed */
+
+
+ /* explode the coded data */
+ b = k = w = 0; /* initialize bit buffer, window */
+ u = 1; /* buffer unflushed */
+ mb = mask_bits[bb]; /* precompute masks for speed */
+ ml = mask_bits[bl];
+ md = mask_bits[bd];
+ s = G.ucsize;
+ while (s > 0) /* do until ucsize bytes uncompressed */
+ {
+ NEEDBITS(1)
+ if (b & 1) /* then literal--decode it */
+ {
+ DUMPBITS(1)
+ s--;
+ NEEDBITS((unsigned)bb) /* get coded literal */
+ if ((e = (t = tb + ((~(unsigned)b) & mb))->e) > 16)
+ do {
+ if (e == 99)
+ return 1;
+ DUMPBITS(t->b)
+ e -= 16;
+ NEEDBITS(e)
+ } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+ DUMPBITS(t->b)
+ redirSlide[w++] = (uch)t->v.n;
+ if (w == wsize)
+ {
+ flush(__G__ redirSlide, (ulg)w, 0);
+ w = u = 0;
+ }
+ }
+ else /* else distance/length */
+ {
+ DUMPBITS(1)
+ NEEDBITS(6) /* get distance low bits */
+ d = (unsigned)b & 0x3f;
+ DUMPBITS(6)
+ NEEDBITS((unsigned)bd) /* get coded distance high bits */
+ if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16)
+ do {
+ if (e == 99)
+ return 1;
+ DUMPBITS(t->b)
+ e -= 16;
+ NEEDBITS(e)
+ } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+ DUMPBITS(t->b)
+ d = w - d - t->v.n; /* construct offset */
+ NEEDBITS((unsigned)bl) /* get coded length */
+ if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16)
+ do {
+ if (e == 99)
+ return 1;
+ DUMPBITS(t->b)
+ e -= 16;
+ NEEDBITS(e)
+ } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+ DUMPBITS(t->b)
+ n = t->v.n;
+ if (e) /* get length extra bits */
+ {
+ NEEDBITS(8)
+ n += (unsigned)b & 0xff;
+ DUMPBITS(8)
+ }
+
+ /* do the copy */
+ s -= n;
+ do {
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+ if (G.redirect_slide) {
+ /* &= w/ wsize not needed and wrong if redirect */
+ if (d >= wsize)
+ return 1;
+ n -= (e = (e = wsize - (d > w ? d : w)) > n ? n : e);
+ } else
+#endif
+ n -= (e = (e = wsize - ((d &= wsize-1) > w ? d : w)) > n ? n : e);
+ if (u && w <= d)
+ {
+ memzero(redirSlide + w, e);
+ w += e;
+ d += e;
+ }
+ else
+#ifndef NOMEMCPY
+ if (w - d >= e) /* (this test assumes unsigned comparison) */
+ {
+ memcpy(redirSlide + w, redirSlide + d, e);
+ w += e;
+ d += e;
+ }
+ else /* do it slow to avoid memcpy() overlap */
+#endif /* !NOMEMCPY */
+ do {
+ redirSlide[w++] = redirSlide[d++];
+ } while (--e);
+ if (w == wsize)
+ {
+ flush(__G__ redirSlide, (ulg)w, 0);
+ w = u = 0;
+ }
+ } while (n);
+ }
+ }
+
+ /* flush out redirSlide */
+ flush(__G__ redirSlide, (ulg)w, 0);
+ if (G.csize + G.incnt + (k >> 3)) /* should have read csize bytes, but */
+ { /* sometimes read one too many: k>>3 compensates */
+ G.used_csize = G.lrec.csize - G.csize - G.incnt - (k >> 3);
+ return 5;
+ }
+ return 0;
+}
+
+
+
+static int explode_nolit8(__G__ tl, td, bl, bd)
+ __GDEF
+struct huft *tl, *td; /* length and distance decoder tables */
+int bl, bd; /* number of bits decoded by tl[] and td[] */
+/* Decompress the imploded data using uncoded literals and an 8K sliding
+ window. */
+{
+ long s; /* bytes to decompress */
+ register unsigned e; /* table entry flag/number of extra bits */
+ unsigned n, d; /* length and index for copy */
+ unsigned w; /* current window position */
+ struct huft *t; /* pointer to table entry */
+ unsigned ml, md; /* masks for bl and bd bits */
+ register ulg b; /* bit buffer */
+ register unsigned k; /* number of bits in bit buffer */
+ unsigned u; /* true if unflushed */
+
+
+ /* explode the coded data */
+ b = k = w = 0; /* initialize bit buffer, window */
+ u = 1; /* buffer unflushed */
+ ml = mask_bits[bl]; /* precompute masks for speed */
+ md = mask_bits[bd];
+ s = G.ucsize;
+ while (s > 0) /* do until ucsize bytes uncompressed */
+ {
+ NEEDBITS(1)
+ if (b & 1) /* then literal--get eight bits */
+ {
+ DUMPBITS(1)
+ s--;
+ NEEDBITS(8)
+ redirSlide[w++] = (uch)b;
+ if (w == wsize)
+ {
+ flush(__G__ redirSlide, (ulg)w, 0);
+ w = u = 0;
+ }
+ DUMPBITS(8)
+ }
+ else /* else distance/length */
+ {
+ DUMPBITS(1)
+ NEEDBITS(7) /* get distance low bits */
+ d = (unsigned)b & 0x7f;
+ DUMPBITS(7)
+ NEEDBITS((unsigned)bd) /* get coded distance high bits */
+ if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16)
+ do {
+ if (e == 99)
+ return 1;
+ DUMPBITS(t->b)
+ e -= 16;
+ NEEDBITS(e)
+ } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+ DUMPBITS(t->b)
+ d = w - d - t->v.n; /* construct offset */
+ NEEDBITS((unsigned)bl) /* get coded length */
+ if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16)
+ do {
+ if (e == 99)
+ return 1;
+ DUMPBITS(t->b)
+ e -= 16;
+ NEEDBITS(e)
+ } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+ DUMPBITS(t->b)
+ n = t->v.n;
+ if (e) /* get length extra bits */
+ {
+ NEEDBITS(8)
+ n += (unsigned)b & 0xff;
+ DUMPBITS(8)
+ }
+
+ /* do the copy */
+ s -= n;
+ do {
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+ if (G.redirect_slide) {
+ /* &= w/ wsize not needed and wrong if redirect */
+ if (d >= wsize)
+ return 1;
+ n -= (e = (e = wsize - (d > w ? d : w)) > n ? n : e);
+ } else
+#endif
+ n -= (e = (e = wsize - ((d &= wsize-1) > w ? d : w)) > n ? n : e);
+ if (u && w <= d)
+ {
+ memzero(redirSlide + w, e);
+ w += e;
+ d += e;
+ }
+ else
+#ifndef NOMEMCPY
+ if (w - d >= e) /* (this test assumes unsigned comparison) */
+ {
+ memcpy(redirSlide + w, redirSlide + d, e);
+ w += e;
+ d += e;
+ }
+ else /* do it slow to avoid memcpy() overlap */
+#endif /* !NOMEMCPY */
+ do {
+ redirSlide[w++] = redirSlide[d++];
+ } while (--e);
+ if (w == wsize)
+ {
+ flush(__G__ redirSlide, (ulg)w, 0);
+ w = u = 0;
+ }
+ } while (n);
+ }
+ }
+
+ /* flush out redirSlide */
+ flush(__G__ redirSlide, (ulg)w, 0);
+ if (G.csize + G.incnt + (k >> 3)) /* should have read csize bytes, but */
+ { /* sometimes read one too many: k>>3 compensates */
+ G.used_csize = G.lrec.csize - G.csize - G.incnt - (k >> 3);
+ return 5;
+ }
+ return 0;
+}
+
+
+
+static int explode_nolit4(__G__ tl, td, bl, bd)
+ __GDEF
+struct huft *tl, *td; /* length and distance decoder tables */
+int bl, bd; /* number of bits decoded by tl[] and td[] */
+/* Decompress the imploded data using uncoded literals and a 4K sliding
+ window. */
+{
+ long s; /* bytes to decompress */
+ register unsigned e; /* table entry flag/number of extra bits */
+ unsigned n, d; /* length and index for copy */
+ unsigned w; /* current window position */
+ struct huft *t; /* pointer to table entry */
+ unsigned ml, md; /* masks for bl and bd bits */
+ register ulg b; /* bit buffer */
+ register unsigned k; /* number of bits in bit buffer */
+ unsigned u; /* true if unflushed */
+
+
+ /* explode the coded data */
+ b = k = w = 0; /* initialize bit buffer, window */
+ u = 1; /* buffer unflushed */
+ ml = mask_bits[bl]; /* precompute masks for speed */
+ md = mask_bits[bd];
+ s = G.ucsize;
+ while (s > 0) /* do until ucsize bytes uncompressed */
+ {
+ NEEDBITS(1)
+ if (b & 1) /* then literal--get eight bits */
+ {
+ DUMPBITS(1)
+ s--;
+ NEEDBITS(8)
+ redirSlide[w++] = (uch)b;
+ if (w == wsize)
+ {
+ flush(__G__ redirSlide, (ulg)w, 0);
+ w = u = 0;
+ }
+ DUMPBITS(8)
+ }
+ else /* else distance/length */
+ {
+ DUMPBITS(1)
+ NEEDBITS(6) /* get distance low bits */
+ d = (unsigned)b & 0x3f;
+ DUMPBITS(6)
+ NEEDBITS((unsigned)bd) /* get coded distance high bits */
+ if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16)
+ do {
+ if (e == 99)
+ return 1;
+ DUMPBITS(t->b)
+ e -= 16;
+ NEEDBITS(e)
+ } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+ DUMPBITS(t->b)
+ d = w - d - t->v.n; /* construct offset */
+ NEEDBITS((unsigned)bl) /* get coded length */
+ if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16)
+ do {
+ if (e == 99)
+ return 1;
+ DUMPBITS(t->b)
+ e -= 16;
+ NEEDBITS(e)
+ } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+ DUMPBITS(t->b)
+ n = t->v.n;
+ if (e) /* get length extra bits */
+ {
+ NEEDBITS(8)
+ n += (unsigned)b & 0xff;
+ DUMPBITS(8)
+ }
+
+ /* do the copy */
+ s -= n;
+ do {
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+ if (G.redirect_slide) {
+ /* &= w/ wsize not needed and wrong if redirect */
+ if (d >= wsize)
+ return 1;
+ n -= (e = (e = wsize - (d > w ? d : w)) > n ? n : e);
+ } else
+#endif
+ n -= (e = (e = wsize - ((d &= wsize-1) > w ? d : w)) > n ? n : e);
+ if (u && w <= d)
+ {
+ memzero(redirSlide + w, e);
+ w += e;
+ d += e;
+ }
+ else
+#ifndef NOMEMCPY
+ if (w - d >= e) /* (this test assumes unsigned comparison) */
+ {
+ memcpy(redirSlide + w, redirSlide + d, e);
+ w += e;
+ d += e;
+ }
+ else /* do it slow to avoid memcpy() overlap */
+#endif /* !NOMEMCPY */
+ do {
+ redirSlide[w++] = redirSlide[d++];
+ } while (--e);
+ if (w == wsize)
+ {
+ flush(__G__ redirSlide, (ulg)w, 0);
+ w = u = 0;
+ }
+ } while (n);
+ }
+ }
+
+ /* flush out redirSlide */
+ flush(__G__ redirSlide, (ulg)w, 0);
+ if (G.csize + G.incnt + (k >> 3)) /* should have read csize bytes, but */
+ { /* sometimes read one too many: k>>3 compensates */
+ G.used_csize = G.lrec.csize - G.csize - G.incnt - (k >> 3);
+ return 5;
+ }
+ return 0;
+}
+
+
+
+int explode(__G)
+ __GDEF
+/* Explode an imploded compressed stream. Based on the general purpose
+ bit flag, decide on coded or uncoded literals, and an 8K or 4K sliding
+ window. Construct the literal (if any), length, and distance codes and
+ the tables needed to decode them (using huft_build() from inflate.c),
+ and call the appropriate routine for the type of data in the remainder
+ of the stream. The four routines are nearly identical, differing only
+ in whether the literal is decoded or simply read in, and in how many
+ bits are read in, uncoded, for the low distance bits. */
+{
+ unsigned r; /* return codes */
+ struct huft *tb; /* literal code table */
+ struct huft *tl; /* length code table */
+ struct huft *td; /* distance code table */
+ int bb; /* bits for tb */
+ int bl; /* bits for tl */
+ int bd; /* bits for td */
+ unsigned l[256]; /* bit lengths for codes */
+
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+ if (G.redirect_slide)
+ wsize = G.redirect_size, redirSlide = G.redirect_buffer;
+ else
+ wsize = WSIZE, redirSlide = slide;
+#endif
+
+ /* Tune base table sizes. Note: I thought that to truly optimize speed,
+ I would have to select different bl, bd, and bb values for different
+ compressed file sizes. I was surprised to find out that the values of
+ 7, 7, and 9 worked best over a very wide range of sizes, except that
+ bd = 8 worked marginally better for large compressed sizes. */
+ bl = 7;
+ bd = (G.csize + G.incnt) > 200000L ? 8 : 7;
+
+
+ /* With literal tree--minimum match length is 3 */
+#ifdef DEBUG
+ G.hufts = 0; /* initialize huft's malloc'ed */
+#endif
+ if (G.lrec.general_purpose_bit_flag & 4)
+ {
+ bb = 9; /* base table size for literals */
+ if ((r = get_tree(__G__ l, 256)) != 0)
+ return (int)r;
+ if ((r = huft_build(__G__ l, 256, 256, NULL, NULL, &tb, &bb)) != 0)
+ {
+ if (r == 1)
+ huft_free(tb);
+ return (int)r;
+ }
+ if ((r = get_tree(__G__ l, 64)) != 0)
+ return (int)r;
+ if ((r = huft_build(__G__ l, 64, 0, cplen3, extra, &tl, &bl)) != 0)
+ {
+ if (r == 1)
+ huft_free(tl);
+ huft_free(tb);
+ return (int)r;
+ }
+ if ((r = get_tree(__G__ l, 64)) != 0)
+ return (int)r;
+ if (G.lrec.general_purpose_bit_flag & 2) /* true if 8K */
+ {
+ if ((r = huft_build(__G__ l, 64, 0, cpdist8, extra, &td, &bd)) != 0)
+ {
+ if (r == 1)
+ huft_free(td);
+ huft_free(tl);
+ huft_free(tb);
+ return (int)r;
+ }
+ r = explode_lit8(__G__ tb, tl, td, bb, bl, bd);
+ }
+ else /* else 4K */
+ {
+ if ((r = huft_build(__G__ l, 64, 0, cpdist4, extra, &td, &bd)) != 0)
+ {
+ if (r == 1)
+ huft_free(td);
+ huft_free(tl);
+ huft_free(tb);
+ return (int)r;
+ }
+ r = explode_lit4(__G__ tb, tl, td, bb, bl, bd);
+ }
+ huft_free(td);
+ huft_free(tl);
+ huft_free(tb);
+ }
+ else
+
+
+ /* No literal tree--minimum match length is 2 */
+ {
+ if ((r = get_tree(__G__ l, 64)) != 0)
+ return (int)r;
+ if ((r = huft_build(__G__ l, 64, 0, cplen2, extra, &tl, &bl)) != 0)
+ {
+ if (r == 1)
+ huft_free(tl);
+ return (int)r;
+ }
+ if ((r = get_tree(__G__ l, 64)) != 0)
+ return (int)r;
+ if (G.lrec.general_purpose_bit_flag & 2) /* true if 8K */
+ {
+ if ((r = huft_build(__G__ l, 64, 0, cpdist8, extra, &td, &bd)) != 0)
+ {
+ if (r == 1)
+ huft_free(td);
+ huft_free(tl);
+ return (int)r;
+ }
+ r = explode_nolit8(__G__ tl, td, bl, bd);
+ }
+ else /* else 4K */
+ {
+ if ((r = huft_build(__G__ l, 64, 0, cpdist4, extra, &td, &bd)) != 0)
+ {
+ if (r == 1)
+ huft_free(td);
+ huft_free(tl);
+ return (int)r;
+ }
+ r = explode_nolit4(__G__ tl, td, bl, bd);
+ }
+ huft_free(td);
+ huft_free(tl);
+ }
+ Trace((stderr, "<%u > ", G.hufts));
+ return (int)r;
+}
+
+/* so explode.c and inflate.c can be compiled together into one object: */
+#undef NEXTBYTE
+#undef NEEDBITS
+#undef DUMPBITS
diff --git a/Build/source/libs/unzip/extract.c b/Build/source/libs/unzip/extract.c
new file mode 100644
index 00000000000..75ed7e0fd0e
--- /dev/null
+++ b/Build/source/libs/unzip/extract.c
@@ -0,0 +1,1985 @@
+/*---------------------------------------------------------------------------
+
+ extract.c
+
+ This file contains the high-level routines ("driver routines") for extrac-
+ ting and testing zipfile members. It calls the low-level routines in files
+ explode.c, inflate.c, unreduce.c and unshrink.c.
+
+ Contains: extract_or_test_files()
+ store_info()
+ extract_or_test_member()
+ TestExtraField()
+ test_compr_eb()
+ memextract()
+ memflush()
+ fnfilter()
+
+ ---------------------------------------------------------------------------*/
+
+
+#define EXTRACT_C
+#define UNZIP_INTERNAL
+#include "unzip.h"
+#include "crypt.h"
+#ifdef WINDLL
+# ifdef POCKET_UNZIP
+# include "wince/intrface.h"
+# else
+# include "windll/windll.h"
+# endif
+#endif
+
+#define GRRDUMP(buf,len) { \
+ int i, j; \
+ \
+ for (j = 0; j < (len)/16; ++j) { \
+ printf(" "); \
+ for (i = 0; i < 16; ++i) \
+ printf("%02x ", (uch)(buf)[i+(j<<4)]); \
+ printf("\n "); \
+ for (i = 0; i < 16; ++i) { \
+ char c = (char)(buf)[i+(j<<4)]; \
+ \
+ if (c == '\n') \
+ printf("\\n "); \
+ else if (c == '\r') \
+ printf("\\r "); \
+ else \
+ printf(" %c ", c); \
+ } \
+ printf("\n"); \
+ } \
+ if ((len) % 16) { \
+ printf(" "); \
+ for (i = j<<4; i < (len); ++i) \
+ printf("%02x ", (uch)(buf)[i]); \
+ printf("\n "); \
+ for (i = j<<4; i < (len); ++i) { \
+ char c = (char)(buf)[i]; \
+ \
+ if (c == '\n') \
+ printf("\\n "); \
+ else if (c == '\r') \
+ printf("\\r "); \
+ else \
+ printf(" %c ", c); \
+ } \
+ printf("\n"); \
+ } \
+}
+
+static int store_info OF((__GPRO));
+static int extract_or_test_member OF((__GPRO));
+#ifndef SFX
+ static int TestExtraField OF((__GPRO__ uch *ef, unsigned ef_len));
+ static int test_compr_eb OF((__GPRO__ uch *eb, unsigned eb_size,
+ unsigned compr_offset,
+ int (*test_uc_ebdata)(__GPRO__ uch *eb, unsigned eb_size,
+ uch *eb_ucptr, ulg eb_ucsize)));
+#endif
+#ifdef SET_DIR_ATTRIB
+ static int dircomp OF((ZCONST zvoid *a, ZCONST zvoid *b));
+#endif
+
+
+
+/*******************************/
+/* Strings used in extract.c */
+/*******************************/
+
+static ZCONST char Far VersionMsg[] =
+ " skipping: %-22s need %s compat. v%u.%u (can do v%u.%u)\n";
+static ZCONST char Far ComprMsgNum[] =
+ " skipping: %-22s unsupported compression method %u\n";
+#ifndef SFX
+ static ZCONST char Far ComprMsgName[] =
+ " skipping: %-22s `%s' method not supported\n";
+ static ZCONST char Far CmprNone[] = "store";
+ static ZCONST char Far CmprShrink[] = "shrink";
+ static ZCONST char Far CmprReduce[] = "reduce";
+ static ZCONST char Far CmprImplode[] = "implode";
+ static ZCONST char Far CmprTokenize[] = "tokenize";
+ static ZCONST char Far CmprDeflate[] = "deflate";
+ static ZCONST char Far CmprEnDeflate[] = "enhanced deflate";
+ static ZCONST char Far CmprDCLImplode[] = "DCL implode";
+ static ZCONST char Far *ComprNames[NUM_METHODS] = {
+ CmprNone, CmprShrink, CmprReduce, CmprReduce, CmprReduce, CmprReduce,
+ CmprImplode, CmprTokenize, CmprDeflate, CmprEnDeflate, CmprDCLImplode
+ };
+#endif /* !SFX */
+static ZCONST char Far FilNamMsg[] =
+ "%s: bad filename length (%s)\n";
+static ZCONST char Far ExtFieldMsg[] =
+ "%s: bad extra field length (%s)\n";
+static ZCONST char Far OffsetMsg[] =
+ "file #%u: bad zipfile offset (%s): %ld\n";
+static ZCONST char Far ExtractMsg[] =
+ "%8sing: %-22s %s%s";
+#ifndef SFX
+ static ZCONST char Far LengthMsg[] =
+ "%s %s: %ld bytes required to uncompress to %lu bytes;\n %s\
+ supposed to require %lu bytes%s%s%s\n";
+#endif
+
+static ZCONST char Far BadFileCommLength[] = "%s: bad file comment length\n";
+static ZCONST char Far LocalHdrSig[] = "local header sig";
+static ZCONST char Far BadLocalHdr[] = "file #%u: bad local header\n";
+static ZCONST char Far AttemptRecompensate[] =
+ " (attempting to re-compensate)\n";
+#ifndef SFX
+ static ZCONST char Far BackslashPathSep[] =
+ "warning: %s appears to use backslashes as path separators\n";
+#endif
+static ZCONST char Far SkipVolumeLabel[] =
+ " skipping: %-22s %svolume label\n";
+
+#ifdef SET_DIR_ATTRIB /* messages of code for setting directory attributes */
+ static ZCONST char Far DirlistEntryNoMem[] =
+ "warning: cannot alloc memory for dir times/permissions/UID/GID\n";
+ static ZCONST char Far DirlistSortNoMem[] =
+ "warning: cannot alloc memory to sort dir times/perms/etc.\n";
+ static ZCONST char Far DirlistSetAttrFailed[] =
+ "warning: set times/attribs failed for %s\n";
+#endif
+
+#ifndef WINDLL
+ static ZCONST char Far ReplaceQuery[] =
+ "replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: ";
+ static ZCONST char Far AssumeNone[] = " NULL\n(assuming [N]one)\n";
+ static ZCONST char Far NewNameQuery[] = "new name: ";
+ static ZCONST char Far InvalidResponse[] = "error: invalid response [%c]\n";
+#endif /* !WINDLL */
+
+static ZCONST char Far ErrorInArchive[] =
+ "At least one %serror was detected in %s.\n";
+static ZCONST char Far ZeroFilesTested[] =
+ "Caution: zero files tested in %s.\n";
+
+#ifndef VMS
+ static ZCONST char Far VMSFormatQuery[] =
+ "\n%s: stored in VMS format. Extract anyway? (y/n) ";
+#endif
+
+#if CRYPT
+ static ZCONST char Far SkipCannotGetPasswd[] =
+ " skipping: %-22s unable to get password\n";
+ static ZCONST char Far SkipIncorrectPasswd[] =
+ " skipping: %-22s incorrect password\n";
+ static ZCONST char Far FilesSkipBadPasswd[] =
+ "%u file%s skipped because of incorrect password.\n";
+ static ZCONST char Far MaybeBadPasswd[] =
+ " (may instead be incorrect password)\n";
+#else
+ static ZCONST char Far SkipEncrypted[] =
+ " skipping: %-22s encrypted (not supported)\n";
+#endif
+
+static ZCONST char Far NoErrInCompData[] =
+ "No errors detected in compressed data of %s.\n";
+static ZCONST char Far NoErrInTestedFiles[] =
+ "No errors detected in %s for the %u file%s tested.\n";
+static ZCONST char Far FilesSkipped[] =
+ "%u file%s skipped because of unsupported compression or encoding.\n";
+
+static ZCONST char Far ErrUnzipFile[] = " error: %s%s %s\n";
+static ZCONST char Far ErrUnzipNoFile[] = "\n error: %s%s\n";
+static ZCONST char Far NotEnoughMem[] = "not enough memory to ";
+static ZCONST char Far InvalidComprData[] = "invalid compressed data to ";
+static ZCONST char Far Inflate[] = "inflate";
+
+#ifndef SFX
+ static ZCONST char Far Explode[] = "explode";
+#ifndef LZW_CLEAN
+ static ZCONST char Far Unshrink[] = "unshrink";
+#endif
+#endif
+
+#if (!defined(DELETE_IF_FULL) || !defined(HAVE_UNLINK))
+ static ZCONST char Far FileTruncated[] =
+ "warning: %s is probably truncated\n";
+#endif
+
+static ZCONST char Far FileUnknownCompMethod[] =
+ "%s: unknown compression method\n";
+static ZCONST char Far BadCRC[] = " bad CRC %08lx (should be %08lx)\n";
+
+ /* TruncEAs[] also used in OS/2 mapname(), close_outfile() */
+char ZCONST Far TruncEAs[] = " compressed EA data missing (%d bytes)%s";
+char ZCONST Far TruncNTSD[] =
+ " compressed WinNT security data missing (%d bytes)%s";
+
+#ifndef SFX
+ static ZCONST char Far InconsistEFlength[] = "bad extra-field entry:\n \
+ EF block length (%u bytes) exceeds remaining EF data (%u bytes)\n";
+ static ZCONST char Far InvalidComprDataEAs[] =
+ " invalid compressed data for EAs\n";
+# if (defined(WIN32) && defined(NTSD_EAS))
+ static ZCONST char Far InvalidSecurityEAs[] =
+ " EAs fail security check\n";
+# endif
+ static ZCONST char Far UnsuppNTSDVersEAs[] =
+ " unsupported NTSD EAs version %d\n";
+ static ZCONST char Far BadCRC_EAs[] = " bad CRC for extended attributes\n";
+ static ZCONST char Far UnknComprMethodEAs[] =
+ " unknown compression method for EAs (%u)\n";
+ static ZCONST char Far NotEnoughMemEAs[] =
+ " out of memory while inflating EAs\n";
+ static ZCONST char Far UnknErrorEAs[] =
+ " unknown error on extended attributes\n";
+#endif /* !SFX */
+
+static ZCONST char Far UnsupportedExtraField[] =
+ "\nerror: unsupported extra-field compression type (%u)--skipping\n";
+static ZCONST char Far BadExtraFieldCRC[] =
+ "error [%s]: bad extra-field CRC %08lx (should be %08lx)\n";
+
+
+
+
+
+/**************************************/
+/* Function extract_or_test_files() */
+/**************************************/
+
+int extract_or_test_files(__G) /* return PK-type error code */
+ __GDEF
+{
+ uch *cd_inptr;
+ unsigned i, j, filnum=0, blknum=0;
+ int cd_incnt, renamed, query;
+ int error, error_in_archive=PK_COOL, *fn_matched=NULL, *xn_matched=NULL;
+#ifdef WINDLL
+ int done_once = 0;
+#else
+ extent len;
+#endif
+ unsigned members_remaining, num_skipped=0, num_bad_pwd=0;
+ long cd_bufstart, bufstart, inbuf_offset, request;
+ LONGINT old_extra_bytes = 0L;
+#ifdef SET_DIR_ATTRIB
+ unsigned num_dirs=0;
+ dirtime *dirlist=(dirtime *)NULL, **sorted_dirlist=(dirtime **)NULL;
+#endif
+
+
+/*---------------------------------------------------------------------------
+ The basic idea of this function is as follows. Since the central di-
+ rectory lies at the end of the zipfile and the member files lie at the
+ beginning or middle or wherever, it is not very desirable to simply
+ read a central directory entry, jump to the member and extract it, and
+ then jump back to the central directory. In the case of a large zipfile
+ this would lead to a whole lot of disk-grinding, especially if each mem-
+ ber file is small. Instead, we read from the central directory the per-
+ tinent information for a block of files, then go extract/test the whole
+ block. Thus this routine contains two small(er) loops within a very
+ large outer loop: the first of the small ones reads a block of files
+ from the central directory; the second extracts or tests each file; and
+ the outer one loops over blocks. There's some file-pointer positioning
+ stuff in between, but that's about it. Btw, it's because of this jump-
+ ing around that we can afford to be lenient if an error occurs in one of
+ the member files: we should still be able to go find the other members,
+ since we know the offset of each from the beginning of the zipfile.
+ ---------------------------------------------------------------------------*/
+
+ G.pInfo = G.info;
+ members_remaining = (unsigned)G.ecrec.total_entries_central_dir;
+
+#if CRYPT
+ G.newzip = TRUE;
+#endif
+#ifndef SFX
+ G.reported_backslash = FALSE;
+#endif
+
+ /* malloc space for check on unmatched filespecs (OK if one or both NULL) */
+ if (G.filespecs > 0 &&
+ (fn_matched=(int *)malloc(G.filespecs*sizeof(int))) != (int *)NULL)
+ for (i = 0; i < G.filespecs; ++i)
+ fn_matched[i] = FALSE;
+ if (G.xfilespecs > 0 &&
+ (xn_matched=(int *)malloc(G.xfilespecs*sizeof(int))) != (int *)NULL)
+ for (i = 0; i < G.xfilespecs; ++i)
+ xn_matched[i] = FALSE;
+
+/*---------------------------------------------------------------------------
+ Begin main loop over blocks of member files. We know the entire central
+ directory is on this disk: we would not have any of this information un-
+ less the end-of-central-directory record was on this disk, and we would
+ not have gotten to this routine unless this is also the disk on which
+ the central directory starts. In practice, this had better be the ONLY
+ disk in the archive, but we'll add multi-disk support soon.
+ ---------------------------------------------------------------------------*/
+
+ while (members_remaining) {
+ j = 0;
+#ifdef AMIGA
+ memzero(G.filenotes, DIR_BLKSIZ * sizeof(char *));
+#endif
+
+ /*
+ * Loop through files in central directory, storing offsets, file
+ * attributes, case-conversion and text-conversion flags until block
+ * size is reached.
+ */
+
+ while (members_remaining && (j < DIR_BLKSIZ)) {
+ --members_remaining;
+ G.pInfo = &G.info[j];
+
+ if (readbuf(__G__ G.sig, 4) == 0) {
+ error_in_archive = PK_EOF;
+ members_remaining = 0; /* ...so no more left to do */
+ break;
+ }
+ if (strncmp(G.sig, central_hdr_sig, 4)) { /* just to make sure */
+ Info(slide, 0x401, ((char *)slide, LoadFarString(CentSigMsg),
+ j + blknum*DIR_BLKSIZ + 1));
+ Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg)));
+ error_in_archive = PK_BADERR;
+ members_remaining = 0; /* ...so no more left to do */
+ break;
+ }
+ /* process_cdir_file_hdr() sets pInfo->hostnum, pInfo->lcflag */
+ if ((error = process_cdir_file_hdr(__G)) != PK_COOL) {
+ error_in_archive = error; /* only PK_EOF defined */
+ members_remaining = 0; /* ...so no more left to do */
+ break;
+ }
+ if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) !=
+ PK_COOL)
+ {
+ if (error > error_in_archive)
+ error_in_archive = error;
+ if (error > PK_WARN) { /* fatal: no more left to do */
+ Info(slide, 0x401, ((char *)slide, LoadFarString(FilNamMsg),
+ FnFilter1(G.filename), "central"));
+ members_remaining = 0;
+ break;
+ }
+ }
+ if ((error = do_string(__G__ G.crec.extra_field_length,
+ EXTRA_FIELD)) != 0)
+ {
+ if (error > error_in_archive)
+ error_in_archive = error;
+ if (error > PK_WARN) { /* fatal */
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(ExtFieldMsg),
+ FnFilter1(G.filename), "central"));
+ members_remaining = 0;
+ break;
+ }
+ }
+#ifdef AMIGA
+ G.filenote_slot = j;
+ if ((error = do_string(__G__ G.crec.file_comment_length,
+ uO.N_flag ? FILENOTE : SKIP)) != PK_COOL)
+#else
+ if ((error = do_string(__G__ G.crec.file_comment_length, SKIP))
+ != PK_COOL)
+#endif
+ {
+ if (error > error_in_archive)
+ error_in_archive = error;
+ if (error > PK_WARN) { /* fatal */
+ Info(slide, 0x421, ((char *)slide,
+ LoadFarString(BadFileCommLength),
+ FnFilter1(G.filename)));
+ members_remaining = 0;
+ break;
+ }
+ }
+ if (G.process_all_files) {
+ if (store_info(__G))
+ ++j; /* file is OK; info[] stored; continue with next */
+ else
+ ++num_skipped;
+ } else {
+ int do_this_file;
+
+ if (G.filespecs == 0)
+ do_this_file = TRUE;
+ else { /* check if this entry matches an `include' argument */
+ do_this_file = FALSE;
+ for (i = 0; i < G.filespecs; i++)
+ if (match(G.filename, G.pfnames[i], uO.C_flag)) {
+ do_this_file = TRUE; /* ^-- ignore case or not? */
+ if (fn_matched)
+ fn_matched[i] = TRUE;
+ break; /* found match, so stop looping */
+ }
+ }
+ if (do_this_file) { /* check if this is an excluded file */
+ for (i = 0; i < G.xfilespecs; i++)
+ if (match(G.filename, G.pxnames[i], uO.C_flag)) {
+ do_this_file = FALSE; /* ^-- ignore case or not? */
+ if (xn_matched)
+ xn_matched[i] = TRUE;
+ break;
+ }
+ }
+ if (do_this_file) {
+ if (store_info(__G))
+ ++j; /* file is OK */
+ else
+ ++num_skipped; /* unsupp. compression or encryption */
+ }
+ } /* end if (process_all_files) */
+
+
+ } /* end while-loop (adding files to current block) */
+
+ /* save position in central directory so can come back later */
+ cd_bufstart = G.cur_zipfile_bufstart;
+ cd_inptr = G.inptr;
+ cd_incnt = G.incnt;
+
+ /*-----------------------------------------------------------------------
+ Second loop: process files in current block, extracting or testing
+ each one.
+ -----------------------------------------------------------------------*/
+
+ for (i = 0; i < j; ++i) {
+ filnum++; /* filnum = i + blknum*DIR_BLKSIZ + 1; */
+ G.pInfo = &G.info[i];
+#ifdef NOVELL_BUG_FAILSAFE
+ G.dne = FALSE; /* assume file exists until stat() says otherwise */
+#endif
+
+ /* if the target position is not within the current input buffer
+ * (either haven't yet read far enough, or (maybe) skipping back-
+ * ward), skip to the target position and reset readbuf(). */
+
+ /* ZLSEEK(pInfo->offset): */
+ request = G.pInfo->offset + G.extra_bytes;
+ inbuf_offset = request % INBUFSIZ;
+ bufstart = request - inbuf_offset;
+
+ Trace((stderr, "\ndebug: request = %ld, inbuf_offset = %ld\n",
+ request, inbuf_offset));
+ Trace((stderr,
+ "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n",
+ bufstart, G.cur_zipfile_bufstart));
+ if (request < 0) {
+ Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(SeekMsg),
+ G.zipfn, LoadFarString(ReportMsg)));
+ error_in_archive = PK_ERR;
+ if (filnum == 1 && G.extra_bytes != 0L) {
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(AttemptRecompensate)));
+ old_extra_bytes = G.extra_bytes;
+ G.extra_bytes = 0L;
+ request = G.pInfo->offset; /* could also check if != 0 */
+ inbuf_offset = request % INBUFSIZ;
+ bufstart = request - inbuf_offset;
+ Trace((stderr, "debug: request = %ld, inbuf_offset = %ld\n",
+ request, inbuf_offset));
+ Trace((stderr,
+ "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n",
+ bufstart, G.cur_zipfile_bufstart));
+ } else {
+ error_in_archive = PK_BADERR;
+ continue; /* this one hosed; try next */
+ }
+ }
+ /* try again */
+ if (request < 0) {
+ Trace((stderr, "debug: recompensated request still < 0\n"));
+ Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(SeekMsg),
+ G.zipfn, LoadFarString(ReportMsg)));
+ error_in_archive = PK_BADERR;
+ continue;
+ } else if (bufstart != G.cur_zipfile_bufstart) {
+ Trace((stderr, "debug: bufstart != cur_zipfile_bufstart\n"));
+#ifdef USE_STRM_INPUT
+ fseek((FILE *)G.zipfd,(LONGINT)bufstart,SEEK_SET);
+ G.cur_zipfile_bufstart = ftell((FILE *)G.zipfd);
+#else /* !USE_STRM_INPUT */
+ G.cur_zipfile_bufstart =
+ lseek(G.zipfd,(LONGINT)bufstart,SEEK_SET);
+#endif /* ?USE_STRM_INPUT */
+ if ((G.incnt = read(G.zipfd,(char *)G.inbuf,INBUFSIZ)) <= 0)
+ {
+ Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg),
+ filnum, "lseek", bufstart));
+ error_in_archive = PK_BADERR;
+ continue; /* can still do next file */
+ }
+ G.inptr = G.inbuf + (int)inbuf_offset;
+ G.incnt -= (int)inbuf_offset;
+ } else {
+ G.incnt += (int)(G.inptr-G.inbuf) - (int)inbuf_offset;
+ G.inptr = G.inbuf + (int)inbuf_offset;
+ }
+
+ /* should be in proper position now, so check for sig */
+ if (readbuf(__G__ G.sig, 4) == 0) { /* bad offset */
+ Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg),
+ filnum, "EOF", request));
+ error_in_archive = PK_BADERR;
+ continue; /* but can still try next one */
+ }
+ if (strncmp(G.sig, local_hdr_sig, 4)) {
+ Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg),
+ filnum, LoadFarStringSmall(LocalHdrSig), request));
+ /*
+ GRRDUMP(G.sig, 4)
+ GRRDUMP(local_hdr_sig, 4)
+ */
+ error_in_archive = PK_ERR;
+ if ((filnum == 1 && G.extra_bytes != 0L) ||
+ (G.extra_bytes == 0L && old_extra_bytes != 0L)) {
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(AttemptRecompensate)));
+ if (G.extra_bytes) {
+ old_extra_bytes = G.extra_bytes;
+ G.extra_bytes = 0L;
+ } else
+ G.extra_bytes = old_extra_bytes; /* third attempt */
+ ZLSEEK(G.pInfo->offset)
+ if (readbuf(__G__ G.sig, 4) == 0) { /* bad offset */
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(OffsetMsg), filnum, "EOF", request));
+ error_in_archive = PK_BADERR;
+ continue; /* but can still try next one */
+ }
+ if (strncmp(G.sig, local_hdr_sig, 4)) {
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(OffsetMsg), filnum,
+ LoadFarStringSmall(LocalHdrSig), request));
+ error_in_archive = PK_BADERR;
+ continue;
+ }
+ } else
+ continue; /* this one hosed; try next */
+ }
+ if ((error = process_local_file_hdr(__G)) != PK_COOL) {
+ Info(slide, 0x421, ((char *)slide, LoadFarString(BadLocalHdr),
+ filnum));
+ error_in_archive = error; /* only PK_EOF defined */
+ continue; /* can still try next one */
+ }
+ if ((error = do_string(__G__ G.lrec.filename_length, DS_FN)) !=
+ PK_COOL)
+ {
+ if (error > error_in_archive)
+ error_in_archive = error;
+ if (error > PK_WARN) {
+ Info(slide, 0x401, ((char *)slide, LoadFarString(FilNamMsg),
+ FnFilter1(G.filename), "local"));
+ continue; /* go on to next one */
+ }
+ }
+ if (G.extra_field != (uch *)NULL) {
+ free(G.extra_field);
+ G.extra_field = (uch *)NULL;
+ }
+ if ((error =
+ do_string(__G__ G.lrec.extra_field_length, EXTRA_FIELD)) != 0)
+ {
+ if (error > error_in_archive)
+ error_in_archive = error;
+ if (error > PK_WARN) {
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(ExtFieldMsg),
+ FnFilter1(G.filename), "local"));
+ continue; /* go on */
+ }
+ }
+
+#if CRYPT
+ if (G.pInfo->encrypted &&
+ (error = decrypt(__G__ uO.pwdarg)) != PK_COOL) {
+ if (error == PK_WARN) {
+ if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(SkipIncorrectPasswd),
+ FnFilter1(G.filename)));
+ ++num_bad_pwd;
+ } else { /* (error > PK_WARN) */
+ if (error > error_in_archive)
+ error_in_archive = error;
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(SkipCannotGetPasswd),
+ FnFilter1(G.filename)));
+ }
+ continue; /* go on to next file */
+ }
+#endif /* CRYPT */
+
+ /*
+ * just about to extract file: if extracting to disk, check if
+ * already exists, and if so, take appropriate action according to
+ * fflag/uflag/overwrite_all/etc. (we couldn't do this in upper
+ * loop because we don't store the possibly renamed filename[] in
+ * info[])
+ */
+#ifdef DLL
+ if (!uO.tflag && !uO.cflag && !G.redirect_data)
+#else
+ if (!uO.tflag && !uO.cflag)
+#endif
+ {
+ renamed = FALSE; /* user hasn't renamed output file yet */
+
+startover:
+ query = FALSE;
+ /* for files from DOS FAT, check for use of backslash instead
+ * of slash as directory separator (bug in some zipper(s); so
+ * far, not a problem in HPFS, NTFS or VFAT systems)
+ */
+#ifndef SFX
+ if (G.pInfo->hostnum == FS_FAT_ && !strchr(G.filename, '/')) {
+ char *p=G.filename-1;
+
+ while (*++p) {
+ if (*p == '\\') {
+ if (!G.reported_backslash) {
+ Info(slide, 0x21, ((char *)slide,
+ LoadFarString(BackslashPathSep), G.zipfn));
+ G.reported_backslash = TRUE;
+ if (!error_in_archive)
+ error_in_archive = PK_WARN;
+ }
+ *p = '/';
+ }
+ }
+ }
+#endif /* !SFX */
+
+ /* mapname can create dirs if not freshening or if renamed */
+ if ((error = mapname(__G__ renamed)) > PK_WARN) {
+ if (error == IZ_CREATED_DIR) {
+#ifdef SET_DIR_ATTRIB
+ dirtime *d_entry;
+
+ d_entry = (dirtime *)malloc(sizeof(dirtime));
+ if (d_entry == (dirtime *)NULL) {
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(DirlistEntryNoMem)));
+ } else {
+ unsigned eb_izux_flg;
+
+ d_entry->next = dirlist;
+ dirlist = d_entry;
+ dirlist->fn =
+ (char *)malloc(strlen(G.filename) + 1);
+ if (dirlist->fn == (char *)NULL) {
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(DirlistEntryNoMem)));
+ dirlist = d_entry->next;
+ free(d_entry);
+ if (!error_in_archive)
+ error_in_archive = PK_WARN;
+ continue;
+ }
+ strcpy(dirlist->fn, G.filename);
+ dirlist->perms = G.pInfo->file_attr;
+#ifdef USE_EF_UT_TIME
+ eb_izux_flg = G.extra_field? ef_scan_for_izux(
+ G.extra_field, G.lrec.extra_field_length, 0,
+ G.lrec.last_mod_dos_datetime,
+#ifdef IZ_CHECK_TZ
+ (G.tz_is_valid ? &(dirlist->u.t3) : NULL),
+#else
+ &(dirlist->u.t3),
+#endif
+ dirlist->uidgid)
+ : 0;
+#else /* !USE_EF_UT_TIME */
+ eb_izux_flg = 0;
+#endif /* ?USE_EF_UT_TIME */
+ if (eb_izux_flg & EB_UT_FL_MTIME) {
+ TTrace((stderr,
+ "\nextract: Unix dir e.f. modtime = %ld\n",
+ dirlist->u.t3.mtime));
+ } else {
+ dirlist->u.t3.mtime = dos_to_unix_time(
+ G.lrec.last_mod_dos_datetime);
+ }
+ if (eb_izux_flg & EB_UT_FL_ATIME) {
+ TTrace((stderr,
+ "\nextract: Unix dir e.f. actime = %ld\n",
+ dirlist->u.t3.atime));
+ } else {
+ dirlist->u.t3.atime =
+ dirlist->u.t3.mtime;
+ }
+ dirlist->have_uidgid =
+ (uO.X_flag && (eb_izux_flg & EB_UX2_VALID));
+ ++num_dirs;
+ }
+#endif /* SET_DIR_ATTRIB */
+ } else if (error == IZ_VOL_LABEL) {
+#ifdef DOS_OS2_W32
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(SkipVolumeLabel),
+ FnFilter1(G.filename),
+ uO.volflag? "hard disk " : ""));
+#else
+ Info(slide, 1, ((char *)slide,
+ LoadFarString(SkipVolumeLabel),
+ FnFilter1(G.filename), ""));
+#endif
+ /* if (!error_in_archive)
+ error_in_archive = PK_WARN; */
+ } else if (error > PK_ERR && error_in_archive < PK_ERR)
+ error_in_archive = PK_ERR;
+ Trace((stderr, "mapname(%s) returns error = %d\n",
+ FnFilter1(G.filename), error));
+ continue; /* go on to next file */
+ }
+
+#ifdef QDOS
+ QFilename(__G__ G.filename);
+#endif
+ switch (check_for_newer(__G__ G.filename)) {
+ case DOES_NOT_EXIST:
+#ifdef NOVELL_BUG_FAILSAFE
+ G.dne = TRUE; /* stat() says file DOES NOT EXIST */
+#endif
+ /* if freshening, don't skip if just renamed */
+ if (uO.fflag && !renamed)
+ continue; /* freshen (no new files): skip */
+ break;
+ case EXISTS_AND_OLDER:
+ if (uO.overwrite_none) {
+#ifdef WINDLL
+ char szStr[FILNAMSIZ+40]; /* add. space for text */
+
+ if ((!G.prompt_always) || (done_once)) {
+ sprintf(szStr,
+ "Target file exists.\nSkipping %s\n",
+ FnFilter1(G.filename));
+ win_fprintf((zvoid *)&G, stdout,
+ strlen(szStr), szStr);
+ } else {
+ query = TRUE;
+ break;
+ }
+#endif /* WINDLL */
+ continue; /* never overwrite: skip file */
+ }
+#ifdef UNIXBACKUP
+ if (!uO.overwrite_all && !uO.B_flag)
+#else
+ if (!uO.overwrite_all)
+#endif
+ query = TRUE;
+ break;
+ case EXISTS_AND_NEWER: /* (or equal) */
+ if (uO.overwrite_none || (uO.uflag && !renamed)) {
+#ifdef WINDLL
+ char szStr[FILNAMSIZ+40]; /* add. space for text */
+
+ if ((!G.prompt_always) || (done_once)) {
+ sprintf(szStr,
+ "Target file newer.\nSkipping %s\n",
+ FnFilter1(G.filename));
+ win_fprintf((zvoid *)&G, stdout,
+ strlen(szStr), szStr);
+ } else {
+ query = TRUE;
+ break;
+ }
+#endif /* WINDLL */
+ continue; /* skip if update/freshen & orig name */
+ }
+#ifdef UNIXBACKUP
+ if (!uO.overwrite_all && !uO.B_flag)
+#else
+ if (!uO.overwrite_all)
+#endif
+ query = TRUE;
+ break;
+ }
+ if (query) {
+#ifdef WINDLL
+ switch (G.lpUserFunctions->replace != NULL ?
+ (*G.lpUserFunctions->replace)(G.filename) :
+ IDM_REPLACE_NONE) {
+ case IDM_REPLACE_RENAME:
+ _ISO_INTERN(G.filename);
+ renamed = TRUE;
+ goto startover;
+ case IDM_REPLACE_YES:
+ break;
+ case IDM_REPLACE_ALL:
+ uO.overwrite_all = TRUE;
+ uO.overwrite_none = FALSE; /* just to make sure */
+ break;
+ case IDM_REPLACE_NONE:
+ uO.overwrite_none = TRUE;
+ uO.overwrite_all = FALSE; /* make sure */
+ done_once = TRUE;
+ /* FALL THROUGH, skip */
+ case IDM_REPLACE_NO:
+ {
+ char szStr[FILNAMSIZ+40];
+
+ sprintf(szStr,
+ "Target file newer.\nSkipping %s\n",
+ FnFilter1(G.filename));
+ win_fprintf((zvoid *)&G, stdout,
+ strlen(szStr), szStr);
+ }
+ continue;
+ }
+#else /* !WINDLL */
+reprompt:
+ Info(slide, 0x81, ((char *)slide,
+ LoadFarString(ReplaceQuery),
+ FnFilter1(G.filename)));
+ if (fgets(G.answerbuf, 9, stdin) == (char *)NULL) {
+ Info(slide, 1, ((char *)slide,
+ LoadFarString(AssumeNone)));
+ *G.answerbuf = 'N';
+ if (!error_in_archive)
+ error_in_archive = 1; /* not extracted: warning */
+ }
+ switch (*G.answerbuf) {
+ case 'A': /* dangerous option: force caps */
+ uO.overwrite_all = TRUE;
+ uO.overwrite_none = FALSE; /* just to make sure */
+ break;
+ case 'r':
+ case 'R':
+ do {
+ Info(slide, 0x81, ((char *)slide,
+ LoadFarString(NewNameQuery)));
+ fgets(G.filename, FILNAMSIZ, stdin);
+ /* usually get \n here: better check for it */
+ len = strlen(G.filename);
+ if (G.filename[len-1] == '\n')
+ G.filename[--len] = '\0';
+ } while (len == 0);
+#ifdef WIN32 /* WIN32 fgets( ... , stdin) returns OEM coded strings */
+ _OEM_INTERN(G.filename);
+#endif
+ renamed = TRUE;
+ goto startover; /* sorry for a goto */
+ case 'y':
+ case 'Y':
+ break;
+ case 'N':
+ uO.overwrite_none = TRUE;
+ uO.overwrite_all = FALSE; /* make sure */
+ /* FALL THROUGH, skip */
+ case 'n':
+ continue; /* skip file */
+ default:
+ Info(slide, 1, ((char *)slide,
+ LoadFarString(InvalidResponse), *G.answerbuf));
+ goto reprompt; /* yet another goto? */
+ } /* end switch (*answerbuf) */
+#endif /* ?WINDLL */
+ } /* end if (query) */
+ } /* end if (extracting to disk) */
+
+#ifdef DLL
+ if ((G.statreportcb != NULL) &&
+ (*G.statreportcb)(__G__ UZ_ST_START_EXTRACT, G.zipfn,
+ G.filename, NULL)) {
+ if (fn_matched)
+ free((zvoid *)fn_matched);
+ if (xn_matched)
+ free((zvoid *)xn_matched);
+ return IZ_CTRLC; /* cancel operation by user request */
+ }
+#endif
+#ifdef MACOS /* MacOS is no preemptive OS, thus call event-handling by hand */
+ UserStop();
+#endif
+#ifdef AMIGA
+ G.filenote_slot = i;
+#endif
+ G.disk_full = 0;
+ if ((error = extract_or_test_member(__G)) != PK_COOL) {
+ if (error > error_in_archive)
+ error_in_archive = error; /* ...and keep going */
+#ifdef DLL
+ if (G.disk_full > 1 || error_in_archive == IZ_CTRLC) {
+#else
+ if (G.disk_full > 1) {
+#endif
+ if (fn_matched)
+ free((zvoid *)fn_matched);
+ if (xn_matched)
+ free((zvoid *)xn_matched);
+ return error_in_archive; /* (unless disk full) */
+ }
+ }
+#ifdef DLL
+ if ((G.statreportcb != NULL) &&
+ (*G.statreportcb)(__G__ UZ_ST_FINISH_MEMBER, G.zipfn,
+ G.filename, (zvoid *)&G.lrec.ucsize)) {
+ if (fn_matched)
+ free((zvoid *)fn_matched);
+ if (xn_matched)
+ free((zvoid *)xn_matched);
+ return IZ_CTRLC; /* cancel operation by user request */
+ }
+#endif
+#ifdef MACOS /* MacOS is no preemptive OS, thus call event-handling by hand */
+ UserStop();
+#endif
+ } /* end for-loop (i: files in current block) */
+
+
+ /*
+ * Jump back to where we were in the central directory, then go and do
+ * the next batch of files.
+ */
+
+#ifdef USE_STRM_INPUT
+ fseek((FILE *)G.zipfd, (LONGINT)cd_bufstart, SEEK_SET);
+ G.cur_zipfile_bufstart = ftell((FILE *)G.zipfd);
+#else /* !USE_STRM_INPUT */
+ G.cur_zipfile_bufstart = lseek(G.zipfd,(LONGINT)cd_bufstart,SEEK_SET);
+#endif /* ?USE_STRM_INPUT */
+ read(G.zipfd, (char *)G.inbuf, INBUFSIZ); /* been here before... */
+ G.inptr = cd_inptr;
+ G.incnt = cd_incnt;
+ ++blknum;
+
+#ifdef TEST
+ printf("\ncd_bufstart = %ld (%.8lXh)\n", cd_bufstart, cd_bufstart);
+ printf("cur_zipfile_bufstart = %ld (%.8lXh)\n", cur_zipfile_bufstart,
+ cur_zipfile_bufstart);
+ printf("inptr-inbuf = %d\n", G.inptr-G.inbuf);
+ printf("incnt = %d\n\n", G.incnt);
+#endif
+
+ } /* end while-loop (blocks of files in central directory) */
+
+/*---------------------------------------------------------------------------
+ Go back through saved list of directories, sort and set times/perms/UIDs
+ and GIDs from the deepest level on up.
+ ---------------------------------------------------------------------------*/
+
+#ifdef SET_DIR_ATTRIB
+ if (num_dirs > 0) {
+ sorted_dirlist = (dirtime **)malloc(num_dirs*sizeof(dirtime *));
+ if (sorted_dirlist == (dirtime **)NULL) {
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(DirlistSortNoMem)));
+ while (dirlist != (dirtime *)NULL) {
+ dirtime *d = dirlist;
+
+ dirlist = dirlist->next;
+ free(d);
+ }
+ } else {
+ if (num_dirs == 1)
+ sorted_dirlist[0] = dirlist;
+ else {
+ for (i = 0; i < num_dirs; ++i) {
+ sorted_dirlist[i] = dirlist;
+ dirlist = dirlist->next;
+ }
+ qsort((char *)sorted_dirlist, num_dirs, sizeof(dirtime *),
+ dircomp);
+ }
+
+ Trace((stderr, "setting directory times/perms/attributes\n"));
+ for (i = 0; i < num_dirs; ++i) {
+ dirtime *d = sorted_dirlist[i];
+
+ Trace((stderr, "dir = %s\n", d->fn));
+ if ((error = set_direc_attribs(__G__ d)) != PK_OK) {
+ Info(slide, 0x201, ((char *)slide,
+ LoadFarString(DirlistSetAttrFailed), d->fn));
+ if (!error_in_archive)
+ error_in_archive = error;
+ }
+ free(d->fn);
+ free(d);
+ }
+ free(sorted_dirlist);
+ }
+ }
+#endif /* SET_DIR_ATTRIB */
+
+#if (defined(WIN32) && defined(NTSD_EAS))
+ process_defer_NT(__G); /* process any deferred items for this .zip file */
+#endif
+
+/*---------------------------------------------------------------------------
+ Check for unmatched filespecs on command line and print warning if any
+ found. Free allocated memory.
+ ---------------------------------------------------------------------------*/
+
+ if (fn_matched) {
+ for (i = 0; i < G.filespecs; ++i)
+ if (!fn_matched[i]) {
+#ifdef DLL
+ if (!G.redirect_data && !G.redirect_text)
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(FilenameNotMatched), G.pfnames[i]));
+ else
+ setFileNotFound(__G);
+#else
+ Info(slide, 1, ((char *)slide,
+ LoadFarString(FilenameNotMatched), G.pfnames[i]));
+#endif
+ if (error_in_archive <= PK_WARN)
+ error_in_archive = PK_FIND; /* some files not found */
+ }
+ free((zvoid *)fn_matched);
+ }
+ if (xn_matched) {
+ for (i = 0; i < G.xfilespecs; ++i)
+ if (!xn_matched[i])
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(ExclFilenameNotMatched), G.pxnames[i]));
+ free((zvoid *)xn_matched);
+ }
+
+/*---------------------------------------------------------------------------
+ Double-check that we're back at the end-of-central-directory record, and
+ print quick summary of results, if we were just testing the archive. We
+ send the summary to stdout so that people doing the testing in the back-
+ ground and redirecting to a file can just do a "tail" on the output file.
+ ---------------------------------------------------------------------------*/
+
+#ifndef SFX
+ if (readbuf(__G__ G.sig, 4) == 0)
+ error_in_archive = PK_EOF;
+ if (strncmp(G.sig, end_central_sig, 4)) { /* just to make sure */
+ Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg)));
+ Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg)));
+ if (!error_in_archive) /* don't overwrite stronger error */
+ error_in_archive = PK_WARN;
+ }
+#endif /* !SFX */
+ if (uO.tflag) {
+ unsigned num = filnum - num_bad_pwd;
+
+ if (uO.qflag < 2) { /* GRR 930710: was (uO.qflag == 1) */
+ if (error_in_archive)
+ Info(slide, 0, ((char *)slide, LoadFarString(ErrorInArchive),
+ (error_in_archive == 1)? "warning-" : "", G.zipfn));
+ else if (num == 0)
+ Info(slide, 0, ((char *)slide, LoadFarString(ZeroFilesTested),
+ G.zipfn));
+ else if (G.process_all_files && (num_skipped+num_bad_pwd == 0))
+ Info(slide, 0, ((char *)slide, LoadFarString(NoErrInCompData),
+ G.zipfn));
+ else
+ Info(slide, 0, ((char *)slide, LoadFarString(NoErrInTestedFiles)
+ , G.zipfn, num, (num==1)? "":"s"));
+ if (num_skipped > 0)
+ Info(slide, 0, ((char *)slide, LoadFarString(FilesSkipped),
+ num_skipped, (num_skipped==1)? "":"s"));
+#if CRYPT
+ if (num_bad_pwd > 0)
+ Info(slide, 0, ((char *)slide, LoadFarString(FilesSkipBadPasswd)
+ , num_bad_pwd, (num_bad_pwd==1)? "":"s"));
+#endif /* CRYPT */
+ } else if ((uO.qflag == 0) && !error_in_archive && (num == 0))
+ Info(slide, 0, ((char *)slide, LoadFarString(ZeroFilesTested),
+ G.zipfn));
+ }
+
+ /* give warning if files not tested or extracted (first condition can still
+ * happen if zipfile is empty and no files specified on command line) */
+
+ if ((filnum == 0) && error_in_archive <= PK_WARN) {
+ if (num_skipped > 0)
+ error_in_archive = IZ_UNSUP; /* unsupport. compression/encryption */
+ else
+ error_in_archive = PK_FIND; /* no files found at all */
+ }
+#if CRYPT
+ else if ((filnum == num_bad_pwd) && error_in_archive <= PK_WARN)
+ error_in_archive = IZ_BADPWD; /* bad passwd => all files skipped */
+#endif
+ else if ((num_skipped > 0) && error_in_archive <= PK_WARN)
+ error_in_archive = IZ_UNSUP; /* was PK_WARN; Jean-loup complained */
+#if CRYPT
+ else if ((num_bad_pwd > 0) && !error_in_archive)
+ error_in_archive = PK_WARN;
+#endif
+
+ return error_in_archive;
+
+} /* end function extract_or_test_files() */
+
+
+
+
+
+/***************************/
+/* Function store_info() */
+/***************************/
+
+static int store_info(__G) /* return 0 if skipping, 1 if OK */
+ __GDEF
+{
+#ifdef SFX
+# define UNKN_COMPR \
+ (G.crec.compression_method!=STORED && G.crec.compression_method!=DEFLATED)
+#else
+# ifdef COPYRIGHT_CLEAN /* no reduced files */
+# define UNKN_RED (G.crec.compression_method >= REDUCED1 && \
+ G.crec.compression_method <= REDUCED4)
+# else
+# define UNKN_RED FALSE /* reducing not unknown */
+# endif
+# ifdef LZW_CLEAN /* no shrunk files */
+# define UNKN_SHR (G.crec.compression_method == SHRUNK)
+# else
+# define UNKN_SHR FALSE /* unshrinking not unknown */
+# endif
+# define UNKN_COMPR (UNKN_RED || UNKN_SHR || \
+ G.crec.compression_method==TOKENIZED || G.crec.compression_method>DEFLATED)
+#endif
+
+/*---------------------------------------------------------------------------
+ Check central directory info for version/compatibility requirements.
+ ---------------------------------------------------------------------------*/
+
+ G.pInfo->encrypted = G.crec.general_purpose_bit_flag & 1; /* bit field */
+ G.pInfo->ExtLocHdr = (G.crec.general_purpose_bit_flag & 8) == 8; /* bit */
+ G.pInfo->textfile = G.crec.internal_file_attributes & 1; /* bit field */
+ G.pInfo->crc = G.crec.crc32;
+ G.pInfo->compr_size = G.crec.csize;
+ G.pInfo->uncompr_size = G.crec.ucsize;
+
+ switch (uO.aflag) {
+ case 0:
+ G.pInfo->textmode = FALSE; /* bit field */
+ break;
+ case 1:
+ G.pInfo->textmode = G.pInfo->textfile; /* auto-convert mode */
+ break;
+ default: /* case 2: */
+ G.pInfo->textmode = TRUE;
+ break;
+ }
+
+ if (G.crec.version_needed_to_extract[1] == VMS_) {
+ if (G.crec.version_needed_to_extract[0] > VMS_UNZIP_VERSION) {
+ if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))
+ Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg),
+ FnFilter1(G.filename), "VMS",
+ G.crec.version_needed_to_extract[0] / 10,
+ G.crec.version_needed_to_extract[0] % 10,
+ VMS_UNZIP_VERSION / 10, VMS_UNZIP_VERSION % 10));
+ return 0;
+ }
+#ifndef VMS /* won't be able to use extra field, but still have data */
+ else if (!uO.tflag && !uO.overwrite_all) { /* if -o, extract anyway */
+ Info(slide, 0x481, ((char *)slide, LoadFarString(VMSFormatQuery),
+ FnFilter1(G.filename)));
+ fgets(G.answerbuf, 9, stdin);
+ if ((*G.answerbuf != 'y') && (*G.answerbuf != 'Y'))
+ return 0;
+ }
+#endif /* !VMS */
+ /* usual file type: don't need VMS to extract */
+ } else if (G.crec.version_needed_to_extract[0] > UNZIP_VERSION) {
+ if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))
+ Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg),
+ FnFilter1(G.filename), "PK",
+ G.crec.version_needed_to_extract[0] / 10,
+ G.crec.version_needed_to_extract[0] % 10,
+ UNZIP_VERSION / 10, UNZIP_VERSION % 10));
+ return 0;
+ }
+
+ if UNKN_COMPR {
+ if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) {
+#ifndef SFX
+ if (G.crec.compression_method < NUM_METHODS)
+ Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgName),
+ FnFilter1(G.filename),
+ LoadFarStringSmall(ComprNames[G.crec.compression_method])));
+ else
+#endif
+ Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgNum),
+ FnFilter1(G.filename),
+ G.crec.compression_method));
+ }
+ return 0;
+ }
+#if (!CRYPT)
+ if (G.pInfo->encrypted) {
+ if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))
+ Info(slide, 0x401, ((char *)slide, LoadFarString(SkipEncrypted),
+ FnFilter1(G.filename)));
+ return 0;
+ }
+#endif /* !CRYPT */
+
+ /* map whatever file attributes we have into the local format */
+ mapattr(__G); /* GRR: worry about return value later */
+
+ G.pInfo->offset = (long)G.crec.relative_offset_local_header;
+ return 1;
+
+} /* end function store_info() */
+
+
+
+
+
+/***************************************/
+/* Function extract_or_test_member() */
+/***************************************/
+
+static int extract_or_test_member(__G) /* return PK-type error code */
+ __GDEF
+{
+ char *nul="[empty] ", *txt="[text] ", *bin="[binary]";
+#ifdef CMS_MVS
+ char *ebc="[ebcdic]";
+#endif
+ register int b;
+ int r, error=PK_COOL;
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+ ulg wsize;
+#else
+# define wsize WSIZE
+#endif
+
+
+/*---------------------------------------------------------------------------
+ Initialize variables, buffers, etc.
+ ---------------------------------------------------------------------------*/
+
+ G.bits_left = 0;
+ G.bitbuf = 0L; /* unreduce and unshrink only */
+ G.zipeof = 0;
+ G.newfile = TRUE;
+ G.crc32val = CRCVAL_INITIAL;
+
+#ifdef SYMLINKS
+ /* if file came from Unix and is a symbolic link and we are extracting
+ * to disk, prepare to restore the link */
+ if (S_ISLNK(G.pInfo->file_attr) &&
+ (G.pInfo->hostnum == UNIX_ || G.pInfo->hostnum == ATARI_ ||
+ G.pInfo->hostnum == BEOS_) &&
+ !uO.tflag && !uO.cflag && (G.lrec.ucsize > 0))
+ G.symlnk = TRUE;
+ else
+ G.symlnk = FALSE;
+#endif /* SYMLINKS */
+
+ if (uO.tflag) {
+ if (!uO.qflag)
+ Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), "test",
+ FnFilter1(G.filename), "", ""));
+ } else {
+#ifdef DLL
+ if (uO.cflag && !G.redirect_data)
+#else
+ if (uO.cflag)
+#endif
+ {
+#if (defined(OS2) && defined(__IBMC__) && (__IBMC__ >= 200))
+ G.outfile = freopen("", "wb", stdout); /* VAC++ ignores setmode */
+#else
+ G.outfile = stdout;
+#endif
+#ifdef DOS_FLX_H68_OS2_W32
+#if (defined(__HIGHC__) && !defined(FLEXOS))
+ setmode(G.outfile, _BINARY);
+#else /* !(defined(__HIGHC__) && !defined(FLEXOS)) */
+ setmode(fileno(G.outfile), O_BINARY);
+#endif /* ?(defined(__HIGHC__) && !defined(FLEXOS)) */
+# define NEWLINE "\r\n"
+#else /* !DOS_FLX_H68_OS2_W32 */
+# define NEWLINE "\n"
+#endif /* ?DOS_FLX_H68_OS2_W32 */
+#ifdef VMS
+ if (open_outfile(__G)) /* VMS: required even for stdout! */
+ return PK_DISK;
+#endif
+ } else if (open_outfile(__G))
+ return PK_DISK;
+ }
+
+/*---------------------------------------------------------------------------
+ Unpack the file.
+ ---------------------------------------------------------------------------*/
+
+ defer_leftover_input(__G); /* so NEXTBYTE bounds check will work */
+ switch (G.lrec.compression_method) {
+ case STORED:
+ if (!uO.tflag && QCOND2) {
+#ifdef SYMLINKS
+ if (G.symlnk) /* can also be deflated, but rarer... */
+ Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
+ "link", FnFilter1(G.filename), "", ""));
+ else
+#endif /* SYMLINKS */
+ Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
+ "extract", FnFilter1(G.filename),
+ (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
+ "" : (G.lrec.ucsize == 0L? nul : (G.pInfo->textfile? txt :
+ bin)), uO.cflag? NEWLINE : ""));
+ }
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+ if (G.redirect_slide) {
+ wsize = G.redirect_size; redirSlide = G.redirect_buffer;
+ } else {
+ wsize = WSIZE; redirSlide = slide;
+ }
+#endif
+ G.outptr = redirSlide;
+ G.outcnt = 0L;
+ while ((b = NEXTBYTE) != EOF && !G.disk_full) {
+ *G.outptr++ = (uch)b;
+ if (++G.outcnt == wsize) {
+ flush(__G__ redirSlide, G.outcnt, 0);
+ G.outptr = redirSlide;
+ G.outcnt = 0L;
+ }
+ }
+ if (G.outcnt) /* flush final (partial) buffer */
+ flush(__G__ redirSlide, G.outcnt, 0);
+ break;
+
+#ifndef SFX
+#ifndef LZW_CLEAN
+ case SHRUNK:
+ if (!uO.tflag && QCOND2) {
+ Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
+ LoadFarStringSmall(Unshrink), FnFilter1(G.filename),
+ (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
+ "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : ""));
+ }
+ if ((r = unshrink(__G)) != PK_COOL) {
+ if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarStringSmall(ErrUnzipFile),
+ LoadFarString(NotEnoughMem),
+ LoadFarStringSmall2(Unshrink),
+ FnFilter1(G.filename)));
+ else
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarStringSmall(ErrUnzipNoFile),
+ LoadFarString(NotEnoughMem),
+ LoadFarStringSmall2(Unshrink)));
+ error = r;
+ }
+ break;
+#endif /* !LZW_CLEAN */
+
+#ifndef COPYRIGHT_CLEAN
+ case REDUCED1:
+ case REDUCED2:
+ case REDUCED3:
+ case REDUCED4:
+ if (!uO.tflag && QCOND2) {
+ Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
+ "unreduc", FnFilter1(G.filename),
+ (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
+ "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : ""));
+ }
+ unreduce(__G);
+ break;
+#endif /* !COPYRIGHT_CLEAN */
+
+ case IMPLODED:
+ if (!uO.tflag && QCOND2) {
+ Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
+ "explod", FnFilter1(G.filename),
+ (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
+ "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : ""));
+ }
+ if (((r = explode(__G)) != 0) && (r != 5)) { /* treat 5 specially */
+ if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarStringSmall(ErrUnzipFile), r == 3?
+ LoadFarString(NotEnoughMem) :
+ LoadFarString(InvalidComprData),
+ LoadFarStringSmall2(Explode),
+ FnFilter1(G.filename)));
+ else
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarStringSmall(ErrUnzipNoFile), r == 3?
+ LoadFarString(NotEnoughMem) :
+ LoadFarString(InvalidComprData),
+ LoadFarStringSmall2(Explode)));
+ error = (r == 3)? PK_MEM3 : PK_ERR;
+ }
+ if (r == 5) {
+ int warning = ((ulg)G.used_csize <= G.lrec.csize);
+
+ if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
+ Info(slide, 0x401, ((char *)slide, LoadFarString(LengthMsg),
+ "", warning? "warning" : "error", G.used_csize,
+ G.lrec.ucsize, warning? " " : "", G.lrec.csize,
+ " [", FnFilter1(G.filename), "]"));
+ else
+ Info(slide, 0x401, ((char *)slide, LoadFarString(LengthMsg),
+ "\n", warning? "warning" : "error", G.used_csize,
+ G.lrec.ucsize, warning? " ":"", G.lrec.csize,
+ "", "", "."));
+ error = warning? PK_WARN : PK_ERR;
+ }
+ break;
+#endif /* !SFX */
+
+ case DEFLATED:
+ if (!uO.tflag && QCOND2) {
+ Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
+ "inflat", FnFilter1(G.filename),
+ (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
+ "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : ""));
+ }
+#ifndef USE_ZLIB /* zlib's function is called inflate(), too */
+# define UZinflate inflate
+#endif
+ if ((r = UZinflate(__G)) != 0) {
+ if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarStringSmall(ErrUnzipFile), r == 3?
+ LoadFarString(NotEnoughMem) :
+ LoadFarString(InvalidComprData),
+ LoadFarStringSmall2(Inflate),
+ FnFilter1(G.filename)));
+ else
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarStringSmall(ErrUnzipNoFile), r == 3?
+ LoadFarString(NotEnoughMem) :
+ LoadFarString(InvalidComprData),
+ LoadFarStringSmall2(Inflate)));
+ error = (r == 3)? PK_MEM3 : PK_ERR;
+ }
+ break;
+
+ default: /* should never get to this point */
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(FileUnknownCompMethod), FnFilter1(G.filename)));
+ /* close and delete file before return? */
+ undefer_input(__G);
+ return PK_WARN;
+
+ } /* end switch (compression method) */
+
+/*---------------------------------------------------------------------------
+ Close the file and set its date and time (not necessarily in that order),
+ and make sure the CRC checked out OK. Logical-AND the CRC for 64-bit
+ machines (redundant on 32-bit machines).
+ ---------------------------------------------------------------------------*/
+
+#ifdef VMS /* VMS: required even for stdout! (final flush) */
+ if (!uO.tflag) /* don't close NULL file */
+ close_outfile(__G);
+#else
+#ifdef DLL
+ if (!uO.tflag && (!uO.cflag || G.redirect_data)) {
+ if (G.redirect_data)
+ FINISH_REDIRECT();
+ else
+ close_outfile(__G);
+ }
+#else
+ if (!uO.tflag && !uO.cflag) /* don't close NULL file or stdout */
+ close_outfile(__G);
+#endif
+#endif /* VMS */
+
+ /* GRR: CONVERT close_outfile() TO NON-VOID: CHECK FOR ERRORS! */
+
+
+ if (G.disk_full) { /* set by flush() */
+ if (G.disk_full > 1) {
+#if (defined(DELETE_IF_FULL) && defined(HAVE_UNLINK))
+ /* delete the incomplete file if we can */
+ if (unlink(G.filename) != 0)
+ Trace((stderr, "extract.c: could not delete %s\n",
+ FnFilter1(G.filename)));
+#else
+ /* warn user about the incomplete file */
+ Info(slide, 0x421, ((char *)slide, LoadFarString(FileTruncated),
+ FnFilter1(G.filename)));
+#endif
+ error = PK_DISK;
+ } else {
+ error = PK_WARN;
+ }
+ }
+
+ if (error > PK_WARN) {/* don't print redundant CRC error if error already */
+ undefer_input(__G);
+ return error;
+ }
+ if (G.crc32val != G.lrec.crc32) {
+ /* if quiet enough, we haven't output the filename yet: do it */
+ if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
+ Info(slide, 0x401, ((char *)slide, "%-22s ",
+ FnFilter1(G.filename)));
+ Info(slide, 0x401, ((char *)slide, LoadFarString(BadCRC), G.crc32val,
+ G.lrec.crc32));
+#if CRYPT
+ if (G.pInfo->encrypted)
+ Info(slide, 0x401, ((char *)slide, LoadFarString(MaybeBadPasswd)));
+#endif
+ error = PK_ERR;
+ } else if (uO.tflag) {
+#ifndef SFX
+ if (G.extra_field) {
+ if ((r = TestExtraField(__G__ G.extra_field,
+ G.lrec.extra_field_length)) > error)
+ error = r;
+ } else
+#endif /* !SFX */
+ if (!uO.qflag)
+ Info(slide, 0, ((char *)slide, " OK\n"));
+ } else {
+ if (QCOND2 && !error) /* GRR: is stdout reset to text mode yet? */
+ Info(slide, 0, ((char *)slide, "\n"));
+ }
+
+ undefer_input(__G);
+ return error;
+
+} /* end function extract_or_test_member() */
+
+
+
+
+
+#ifndef SFX
+
+/*******************************/
+/* Function TestExtraField() */
+/*******************************/
+
+static int TestExtraField(__G__ ef, ef_len)
+ __GDEF
+ uch *ef;
+ unsigned ef_len;
+{
+ ush ebID;
+ unsigned ebLen;
+ unsigned eb_cmpr_offs = 0;
+ int r;
+
+ /* we know the regular compressed file data tested out OK, or else we
+ * wouldn't be here ==> print filename if any extra-field errors found
+ */
+ while (ef_len >= EB_HEADSIZE) {
+ ebID = makeword(ef);
+ ebLen = (unsigned)makeword(ef+EB_LEN);
+
+ if (ebLen > (ef_len - EB_HEADSIZE)) {
+ /* Discovered some extra field inconsistency! */
+ if (uO.qflag)
+ Info(slide, 1, ((char *)slide, "%-22s ",
+ FnFilter1(G.filename)));
+ Info(slide, 1, ((char *)slide, LoadFarString(InconsistEFlength),
+ ebLen, (ef_len - EB_HEADSIZE)));
+ return PK_ERR;
+ }
+
+ switch (ebID) {
+ case EF_OS2:
+ case EF_ACL:
+ case EF_MAC3:
+ case EF_BEOS:
+ switch (ebID) {
+ case EF_OS2:
+ case EF_ACL:
+ eb_cmpr_offs = EB_OS2_HLEN;
+ break;
+ case EF_MAC3:
+ if (ebLen >= EB_MAC3_HLEN &&
+ (makeword(ef+(EB_HEADSIZE+EB_FLGS_OFFS))
+ & EB_M3_FL_UNCMPR) &&
+ (makelong(ef+EB_HEADSIZE) == ebLen - EB_MAC3_HLEN))
+ eb_cmpr_offs = 0;
+ else
+ eb_cmpr_offs = EB_MAC3_HLEN;
+ break;
+ case EF_BEOS:
+ if (ebLen >= EB_BEOS_HLEN &&
+ (*(ef+(EB_HEADSIZE+EB_FLGS_OFFS)) & EB_BE_FL_UNCMPR) &&
+ (makelong(ef+EB_HEADSIZE) == ebLen - EB_BEOS_HLEN))
+ eb_cmpr_offs = 0;
+ else
+ eb_cmpr_offs = EB_BEOS_HLEN;
+ break;
+ }
+ if ((r = test_compr_eb(__G__ ef, ebLen, eb_cmpr_offs, NULL))
+ != PK_OK) {
+ if (uO.qflag)
+ Info(slide, 1, ((char *)slide, "%-22s ",
+ FnFilter1(G.filename)));
+ switch (r) {
+ case IZ_EF_TRUNC:
+ Info(slide, 1, ((char *)slide,
+ LoadFarString(TruncEAs),
+ ebLen-(eb_cmpr_offs+EB_CMPRHEADLEN), "\n"));
+ break;
+ case PK_ERR:
+ Info(slide, 1, ((char *)slide,
+ LoadFarString(InvalidComprDataEAs)));
+ break;
+ case PK_MEM3:
+ case PK_MEM4:
+ Info(slide, 1, ((char *)slide,
+ LoadFarString(NotEnoughMemEAs)));
+ break;
+ default:
+ if ((r & 0xff) != PK_ERR)
+ Info(slide, 1, ((char *)slide,
+ LoadFarString(UnknErrorEAs)));
+ else {
+ ush m = (ush)(r >> 8);
+ if (m == DEFLATED) /* GRR KLUDGE! */
+ Info(slide, 1, ((char *)slide,
+ LoadFarString(BadCRC_EAs)));
+ else
+ Info(slide, 1, ((char *)slide,
+ LoadFarString(UnknComprMethodEAs), m));
+ }
+ break;
+ }
+ return r;
+ }
+ break;
+
+ case EF_NTSD:
+ Trace((stderr, "ebID: %i / ebLen: %u\n", ebID, ebLen));
+ r = ebLen < EB_NTSD_L_LEN ? IZ_EF_TRUNC :
+ ((ef[EB_HEADSIZE+EB_NTSD_VERSION] > EB_NTSD_MAX_VER) ?
+ (PK_WARN | 0x4000) :
+ test_compr_eb(__G__ ef, ebLen, EB_NTSD_L_LEN, TEST_NTSD));
+ if (r != PK_OK) {
+ if (uO.qflag)
+ Info(slide, 1, ((char *)slide, "%-22s ",
+ FnFilter1(G.filename)));
+ switch (r) {
+ case IZ_EF_TRUNC:
+ Info(slide, 1, ((char *)slide,
+ LoadFarString(TruncNTSD),
+ ebLen-(EB_NTSD_L_LEN+EB_CMPRHEADLEN), "\n"));
+ break;
+#if (defined(WIN32) && defined(NTSD_EAS))
+ case PK_WARN:
+ Info(slide, 1, ((char *)slide,
+ LoadFarString(InvalidSecurityEAs)));
+ break;
+#endif
+ case PK_ERR:
+ Info(slide, 1, ((char *)slide,
+ LoadFarString(InvalidComprDataEAs)));
+ break;
+ case PK_MEM3:
+ case PK_MEM4:
+ Info(slide, 1, ((char *)slide,
+ LoadFarString(NotEnoughMemEAs)));
+ break;
+ case (PK_WARN | 0x4000):
+ Info(slide, 1, ((char *)slide,
+ LoadFarString(UnsuppNTSDVersEAs),
+ (int)ef[EB_HEADSIZE+EB_NTSD_VERSION]));
+ r = PK_WARN;
+ break;
+ default:
+ if ((r & 0xff) != PK_ERR)
+ Info(slide, 1, ((char *)slide,
+ LoadFarString(UnknErrorEAs)));
+ else {
+ ush m = (ush)(r >> 8);
+ if (m == DEFLATED) /* GRR KLUDGE! */
+ Info(slide, 1, ((char *)slide,
+ LoadFarString(BadCRC_EAs)));
+ else
+ Info(slide, 1, ((char *)slide,
+ LoadFarString(UnknComprMethodEAs), m));
+ }
+ break;
+ }
+ return r;
+ }
+ break;
+ case EF_PKVMS:
+ case EF_PKW32:
+ case EF_PKUNIX:
+ case EF_ASIUNIX:
+ case EF_IZVMS:
+ case EF_IZUNIX:
+ case EF_VMCMS:
+ case EF_MVS:
+ case EF_SPARK:
+ case EF_AV:
+ default:
+ break;
+ }
+ ef_len -= (ebLen + EB_HEADSIZE);
+ ef += (ebLen + EB_HEADSIZE);
+ }
+
+ if (!uO.qflag)
+ Info(slide, 0, ((char *)slide, " OK\n"));
+
+ return PK_COOL;
+
+} /* end function TestExtraField() */
+
+
+
+
+
+/******************************/
+/* Function test_compr_eb() */
+/******************************/
+
+#ifdef PROTO
+static int test_compr_eb(
+ __GPRO__
+ uch *eb,
+ unsigned eb_size,
+ unsigned compr_offset,
+ int (*test_uc_ebdata)(__GPRO__ uch *eb, unsigned eb_size,
+ uch *eb_ucptr, ulg eb_ucsize))
+#else /* !PROTO */
+static int test_compr_eb(__G__ eb, eb_size, compr_offset, test_uc_ebdata)
+ __GDEF
+ uch *eb;
+ unsigned eb_size;
+ unsigned compr_offset;
+ int (*test_uc_ebdata)();
+#endif /* ?PROTO */
+{
+ ulg eb_ucsize;
+ uch *eb_ucptr;
+ int r;
+
+ if (compr_offset < 4) /* field is not compressed: */
+ return PK_OK; /* do nothing and signal OK */
+
+ if ((eb_size < (EB_UCSIZE_P + 4)) ||
+ ((eb_ucsize = makelong(eb+(EB_HEADSIZE+EB_UCSIZE_P))) > 0L &&
+ eb_size <= (compr_offset + EB_CMPRHEADLEN)))
+ return IZ_EF_TRUNC; /* no compressed data! */
+
+ if ((eb_ucptr = (uch *)malloc((extent)eb_ucsize)) == (uch *)NULL)
+ return PK_MEM4;
+
+ r = memextract(__G__ eb_ucptr, eb_ucsize,
+ eb + (EB_HEADSIZE + compr_offset),
+ (ulg)(eb_size - compr_offset));
+
+ if (r == PK_OK && test_uc_ebdata != NULL)
+ r = (*test_uc_ebdata)(__G__ eb, eb_size, eb_ucptr, eb_ucsize);
+
+ free(eb_ucptr);
+ return r;
+
+} /* end function test_compr_eb() */
+
+#endif /* !SFX */
+
+
+
+
+
+/***************************/
+/* Function memextract() */
+/***************************/
+
+int memextract(__G__ tgt, tgtsize, src, srcsize) /* extract compressed */
+ __GDEF /* extra field block; */
+ uch *tgt, *src; /* return PK-type error */
+ ulg tgtsize, srcsize; /* level */
+{
+ long old_csize=G.csize;
+ uch *old_inptr=G.inptr;
+ int old_incnt=G.incnt;
+ int r, error=PK_OK;
+ ush method;
+ ulg extra_field_crc;
+
+
+ method = makeword(src);
+ extra_field_crc = makelong(src+2);
+
+ /* compressed extra field exists completely in memory at this location: */
+ G.inptr = src + 2 + 4; /* method and extra_field_crc */
+ G.incnt = (int)(G.csize = (long)(srcsize - (2 + 4)));
+ G.mem_mode = TRUE;
+ G.outbufptr = tgt;
+ G.outsize = tgtsize;
+
+ switch (method) {
+ case STORED:
+ memcpy((char *)tgt, (char *)G.inptr, (extent)G.incnt);
+ G.outcnt = G.csize; /* for CRC calculation */
+ break;
+ case DEFLATED:
+ G.outcnt = 0L;
+ if ((r = UZinflate(__G)) != 0) {
+ if (!uO.tflag)
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarStringSmall(ErrUnzipNoFile), r == 3?
+ LoadFarString(NotEnoughMem) :
+ LoadFarString(InvalidComprData),
+ LoadFarStringSmall2(Inflate)));
+ error = (r == 3)? PK_MEM3 : PK_ERR;
+ }
+ if (G.outcnt == 0L) /* inflate's final FLUSH sets outcnt */
+ break;
+ break;
+ default:
+ if (uO.tflag)
+ error = PK_ERR | ((int)method << 8);
+ else {
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(UnsupportedExtraField), method));
+ error = PK_ERR; /* GRR: should be passed on up via SetEAs() */
+ }
+ break;
+ }
+
+ G.inptr = old_inptr;
+ G.incnt = old_incnt;
+ G.csize = old_csize;
+ G.mem_mode = FALSE;
+
+ if (!error) {
+ register ulg crcval = crc32(CRCVAL_INITIAL, tgt, (extent)G.outcnt);
+
+ if (crcval != extra_field_crc) {
+ if (uO.tflag)
+ error = PK_ERR | (DEFLATED << 8); /* kludge for now */
+ else {
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(BadExtraFieldCRC), G.zipfn, crcval,
+ extra_field_crc));
+ error = PK_ERR;
+ }
+ }
+ }
+ return error;
+
+} /* end function memextract() */
+
+
+
+
+
+/*************************/
+/* Function memflush() */
+/*************************/
+
+int memflush(__G__ rawbuf, size)
+ __GDEF
+ uch *rawbuf;
+ ulg size;
+{
+ if (size > G.outsize)
+ return 50; /* more data than output buffer can hold */
+
+ memcpy((char *)G.outbufptr, (char *)rawbuf, (extent)size);
+ G.outbufptr += (unsigned int)size;
+ G.outsize -= size;
+ G.outcnt += size;
+
+ return 0;
+
+} /* end function memflush() */
+
+
+
+
+
+/*************************/
+/* Function fnfilter() */ /* here instead of in list.c for SFX */
+/*************************/
+
+char *fnfilter(raw, space) /* convert name to safely printable form */
+ ZCONST char *raw;
+ uch *space;
+{
+#ifndef NATIVE /* ASCII: filter ANSI escape codes, etc. */
+ uch *r=(uch *)raw, *s=space;
+
+ while (*r) {
+#ifdef QDOS
+ if (qlflag & 2) {
+ if (*r == '/' || *r == '.') {
+ ++r;
+ *s++ = '_';
+ continue;
+ }
+ } else
+#endif
+ if (*r < 32)
+ *s++ = '^', *s++ = (uch)(64 + *r++);
+ else
+ *s++ = *r++;
+ }
+ *s = 0;
+
+#ifdef WINDLL
+ INTERN_TO_ISO((char *)space, (char *)space); /* translate to ANSI */
+#else
+#ifdef WIN32
+ /* Win9x console always uses OEM character coding, and
+ WinNT console is set to OEM charset by default, too */
+ INTERN_TO_OEM((char *)space, (char *)space);
+#endif /* WIN32 */
+#endif /* ?WINDLL */
+
+ return (char *)space;
+
+#else /* NATIVE: EBCDIC or whatever */
+ return (char *)raw;
+#endif
+
+} /* end function fnfilter() */
+
+
+
+
+
+#ifdef SET_DIR_ATTRIB
+/* must sort saved directories so can set perms from bottom up */
+
+/************************/
+/* Function dircomp() */
+/************************/
+
+static int dircomp(a, b) /* used by qsort(); swiped from Zip */
+ ZCONST zvoid *a, *b;
+{
+ /* order is significant: this sorts in reverse order (deepest first) */
+ return strcmp((*(dirtime **)b)->fn, (*(dirtime **)a)->fn);
+ /* return namecmp((*(dirtime **)b)->fn, (*(dirtime **)a)->fn); */
+}
+
+
+
+#if 0 /* not used in Unix, but maybe for future OSes? */
+
+/************************/
+/* Function namecmp() */
+/************************/
+
+static int namecmp(s1, s2) /* [not] used by dircomp(); swiped from Zip */
+ ZCONST char *s1, *s2;
+{
+ int d;
+
+ for (;;) {
+ d = (int)(uch)case_map(*s1)
+ - (int)(uch)case_map(*s2);
+
+ if (d || *s1 == 0 || *s2 == 0)
+ return d;
+
+ s1++;
+ s2++;
+ }
+}
+
+#endif /* 0 */
+#endif /* SET_DIR_ATTRIB */
diff --git a/Build/source/libs/unzip/fileio.c b/Build/source/libs/unzip/fileio.c
new file mode 100644
index 00000000000..97001b579df
--- /dev/null
+++ b/Build/source/libs/unzip/fileio.c
@@ -0,0 +1,2151 @@
+/*---------------------------------------------------------------------------
+
+ fileio.c
+
+ This file contains routines for doing direct but relatively generic input/
+ output, file-related sorts of things, plus some miscellaneous stuff. Most
+ of the stuff has to do with opening, closing, reading and/or writing files.
+
+ Contains: open_input_file()
+ open_outfile() (non-VMS, non-AOS/VS, non-CMS_MVS)
+ undefer_input()
+ defer_leftover_input()
+ readbuf()
+ readbyte()
+ fillinbuf()
+ flush() (non-VMS)
+ disk_error() (non-VMS)
+ UzpMessagePrnt()
+ UzpMessageNull() (DLL only)
+ UzpInput()
+ UzpMorePause()
+ UzpPassword() (non-WINDLL)
+ handler()
+ dos_to_unix_time() (non-VMS, non-VM/CMS, non-MVS)
+ check_for_newer() (non-VMS, non-OS/2, non-VM/CMS, non-MVS)
+ do_string()
+ makeword()
+ makelong()
+ str2iso() (CRYPT && NEED_STR2ISO, only)
+ str2oem() (CRYPT && NEED_STR2OEM, only)
+ memset() (ZMEM only)
+ memcpy() (ZMEM only)
+ zstrnicmp()
+ zstat() (REGULUS only)
+ fLoadFarString() (SMALL_MEM only)
+ fLoadFarStringSmall() (SMALL_MEM only)
+ fLoadFarStringSmall2() (SMALL_MEM only)
+ zfstrcpy() (SMALL_MEM only)
+
+ ---------------------------------------------------------------------------*/
+
+
+#define FILEIO_C
+#define UNZIP_INTERNAL
+#include "unzip.h"
+#ifdef WINDLL
+# include "windll/windll.h"
+# include <setjmp.h>
+#endif
+#include "crypt.h"
+#include "ttyio.h"
+
+/* setup of codepage conversion for decryption passwords */
+#if CRYPT
+# if (defined(CRYP_USES_ISO2OEM) && !defined(IZ_ISO2OEM_ARRAY))
+# define IZ_ISO2OEM_ARRAY /* pull in iso2oem[] table */
+# endif
+# if (defined(CRYP_USES_OEM2ISO) && !defined(IZ_OEM2ISO_ARRAY))
+# define IZ_OEM2ISO_ARRAY /* pull in oem2iso[] table */
+# endif
+#endif
+#include "ebcdic.h" /* definition/initialization of ebcdic[] */
+
+
+/*
+ Note: Under Windows, the maximum size of the buffer that can be used
+ with any of the *printf calls is 16,384, so win_fprintf was used to
+ feed the fprintf clone no more than 16K chunks at a time. This should
+ be valid for anything up to 64K (and probably beyond, assuming your
+ buffers are that big).
+*/
+#ifdef WINDLL
+# define WriteError(buf,len,strm) \
+ (win_fprintf(pG, strm, (extent)len, (char far *)buf) != (int)(len))
+#else /* !WINDLL */
+# ifdef USE_FWRITE
+# define WriteError(buf,len,strm) \
+ ((extent)fwrite((char *)(buf),1,(extent)(len),strm) != (extent)(len))
+# else
+# define WriteError(buf,len,strm) \
+ ((extent)write(fileno(strm),(char *)(buf),(extent)(len)) != (extent)(len))
+# endif
+#endif /* ?WINDLL */
+
+static int disk_error OF((__GPRO));
+
+
+/****************************/
+/* Strings used in fileio.c */
+/****************************/
+
+#if (defined(UNIX) || defined(DOS_FLX_OS2_W32) || defined(__BEOS__))
+ static ZCONST char Far CannotDeleteOldFile[] =
+ "error: cannot delete old %s\n";
+#ifdef UNIXBACKUP
+ static ZCONST char Far CannotRenameOldFile[] =
+ "error: cannot rename old %s\n";
+ static ZCONST char Far BackupSuffix[] = "~";
+#endif
+#endif /* UNIX || DOS_FLX_OS2_W32 || __BEOS__ */
+
+static ZCONST char Far CannotOpenZipfile[] =
+ "error: cannot open zipfile [ %s ]\n";
+#if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS))
+ static ZCONST char Far CannotCreateFile[] = "error: cannot create %s\n";
+#endif
+#ifdef NOVELL_BUG_FAILSAFE
+ static ZCONST char Far NovellBug[] =
+ "error: %s: stat() says does not exist, but fopen() found anyway\n";
+#endif
+static ZCONST char Far ReadError[] = "error: zipfile read error\n";
+static ZCONST char Far FilenameTooLongTrunc[] =
+ "warning: filename too long--truncating.\n";
+static ZCONST char Far ExtraFieldTooLong[] =
+ "warning: extra field too long (%d). Ignoring...\n";
+
+#ifdef WINDLL
+ static ZCONST char Far DiskFullQuery[] =
+ "%s: write error (disk full?).\n";
+#else
+ static ZCONST char Far DiskFullQuery[] =
+ "%s: write error (disk full?). Continue? (y/n/^C) ";
+ static ZCONST char Far ZipfileCorrupt[] =
+ "error: zipfile probably corrupt (%s)\n";
+# ifdef SYMLINKS
+ static ZCONST char Far FileIsSymLink[] =
+ "%s exists and is a symbolic link%s.\n";
+# endif
+# ifdef MORE
+ static ZCONST char Far MorePrompt[] = "--More--(%lu)";
+# endif
+ static ZCONST char Far QuitPrompt[] =
+ "--- Press `Q' to quit, or any other key to continue ---";
+ static ZCONST char Far HidePrompt[] = /* "\r \r"; */
+ "\r \r";
+# if CRYPT
+# ifdef MACOS
+ /* SPC: are names on MacOS REALLY so much longer than elsewhere ??? */
+ static ZCONST char Far PasswPrompt[] = "[%s]\n %s password: ";
+# else
+ static ZCONST char Far PasswPrompt[] = "[%s] %s password: ";
+# endif
+ static ZCONST char Far PasswPrompt2[] = "Enter password: ";
+ static ZCONST char Far PasswRetry[] = "password incorrect--reenter: ";
+# endif /* CRYPT */
+#endif /* !WINDLL */
+
+
+
+
+
+/******************************/
+/* Function open_input_file() */
+/******************************/
+
+int open_input_file(__G) /* return 1 if open failed */
+ __GDEF
+{
+ /*
+ * open the zipfile for reading and in BINARY mode to prevent cr/lf
+ * translation, which would corrupt the bitstreams
+ */
+
+#if (defined(UNIX) || defined(TOPS20) || defined(AOS_VS) || defined(__BEOS__))
+ G.zipfd = open(G.zipfn, O_RDONLY);
+#else /* !(UNIX || TOPS20 || AOS_VS || __BEOS__) */
+#ifdef VMS
+ G.zipfd = open(G.zipfn, O_RDONLY, 0, "ctx=stm");
+#else /* !VMS */
+#ifdef MACOS
+ G.zipfd = open(G.zipfn, 0);
+#else /* !MACOS */
+#ifdef RISCOS
+ G.zipfd = fopen(G.zipfn, "rb");
+#else /* !RISCOS */
+#ifdef CMS_MVS
+ G.zipfd = vmmvs_open_infile(__G);
+#else /* !CMS_MVS */
+ G.zipfd = open(G.zipfn, O_RDONLY | O_BINARY);
+#endif /* ?CMS_MVS */
+#endif /* ?RISCOS */
+#endif /* ?MACOS */
+#endif /* ?VMS */
+#endif /* ?(UNIX || TOPS20 || AOS_VS || __BEOS__) */
+
+#ifdef USE_STRM_INPUT
+ if (G.zipfd == NULL)
+#else
+ /* if (G.zipfd < 0) */ /* no good for Windows CE port */
+ if (G.zipfd == -1)
+#endif
+ {
+ Info(slide, 0x401, ((char *)slide, LoadFarString(CannotOpenZipfile),
+ G.zipfn));
+ return 1;
+ }
+ return 0;
+
+} /* end function open_input_file() */
+
+
+
+
+#if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS))
+
+/***************************/
+/* Function open_outfile() */
+/***************************/
+
+int open_outfile(__G) /* return 1 if fail */
+ __GDEF
+{
+#ifdef DLL
+ if (G.redirect_data)
+ return (redirect_outfile(__G) == FALSE);
+#endif
+#ifdef QDOS
+ QFilename(__G__ G.filename);
+#endif
+#if (defined(DOS_FLX_OS2_W32) || defined(UNIX) || defined(__BEOS__))
+#ifdef BORLAND_STAT_BUG
+ /* Borland 5.0's stat() barfs if the filename has no extension and the
+ * file doesn't exist. */
+ if (access(G.filename, 0) == -1) {
+ FILE *tmp = fopen(G.filename, "wb+");
+
+ /* file doesn't exist, so create a dummy file to keep stat() from
+ * failing (will be over-written anyway) */
+ fputc('0', tmp); /* just to have something in the file */
+ fclose(tmp);
+ }
+#endif /* BORLAND_STAT_BUG */
+#ifdef SYMLINKS
+ if (SSTAT(G.filename, &G.statbuf) == 0 || lstat(G.filename,&G.statbuf) == 0)
+#else
+ if (SSTAT(G.filename, &G.statbuf) == 0)
+#endif /* ?SYMLINKS */
+ {
+ Trace((stderr, "open_outfile: stat(%s) returns 0: file exists\n",
+ FnFilter1(G.filename)));
+#ifdef UNIXBACKUP
+ if (uO.B_flag) { /* do backup */
+ char *tname;
+ int blen, flen, tlen;
+
+ blen = strlen(BackupSuffix);
+ flen = strlen(G.filename);
+ tlen = flen + blen + 1;
+ if (tlen >= FILNAMSIZ) { /* in case name is too long, truncate */
+ tname = (char *)malloc(FILNAMSIZ);
+ if (tname == NULL)
+ return 1; /* in case we run out of space */
+ tlen = FILNAMSIZ - 1 - blen;
+ strcpy(tname, G.filename); /* make backup name */
+ tname[tlen] = '\0';
+ } else {
+ tname = (char *)malloc(tlen);
+ if (tname == NULL)
+ return 1; /* in case we run out of space */
+ strcpy(tname, G.filename); /* make backup name */
+ }
+ strcpy(tname+flen, BackupSuffix);
+
+ /* GRR: should check if backup file exists, apply -n/-o to that */
+ if (rename(G.filename, tname) < 0) { /* move file */
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(CannotRenameOldFile), FnFilter1(G.filename)));
+ free(tname);
+ return 1;
+ }
+ free(tname);
+ } else
+#endif /* UNIXBACKUP */
+#ifdef DOS_FLX_OS2_W32
+ if (!(G.statbuf.st_mode & S_IWRITE)) {
+ Trace((stderr, "open_outfile: existing file %s is read-only\n",
+ FnFilter1(G.filename)));
+ chmod(G.filename, S_IREAD | S_IWRITE);
+ Trace((stderr, "open_outfile: %s now writable\n",
+ FnFilter1(G.filename)));
+ }
+#endif /* DOS_FLX_OS2_W32 */
+ if (unlink(G.filename) != 0) {
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(CannotDeleteOldFile), FnFilter1(G.filename)));
+ return 1;
+ }
+ Trace((stderr, "open_outfile: %s now deleted\n",
+ FnFilter1(G.filename)));
+ }
+#endif /* DOS_FLX_OS2_W32 || UNIX || __BEOS__ */
+#ifdef RISCOS
+ if (SWI_OS_File_7(G.filename,0xDEADDEAD,0xDEADDEAD,G.lrec.ucsize)!=NULL) {
+ Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile),
+ FnFilter1(G.filename)));
+ return 1;
+ }
+#endif /* RISCOS */
+#ifdef TOPS20
+ char *tfilnam;
+
+ if ((tfilnam = (char *)malloc(2*strlen(G.filename)+1)) == (char *)NULL)
+ return 1;
+ strcpy(tfilnam, G.filename);
+ upper(tfilnam);
+ enquote(tfilnam);
+ if ((G.outfile = fopen(tfilnam, FOPW)) == (FILE *)NULL) {
+ Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile),
+ tfilnam));
+ free(tfilnam);
+ return 1;
+ }
+ free(tfilnam);
+#else /* !TOPS20 */
+#ifdef MTS
+ if (uO.aflag)
+ G.outfile = fopen(G.filename, FOPWT);
+ else
+ G.outfile = fopen(G.filename, FOPW);
+ if (G.outfile == (FILE *)NULL) {
+ Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile),
+ FnFilter1(G.filename)));
+ return 1;
+ }
+#else /* !MTS */
+#ifdef TANDEM
+ if (SSTAT(G.filename, &G.statbuf) == 0) {
+ Trace((stderr, "open_outfile: stat(%s) returns 0 (file exists)\n",
+ FnFilter1(G.filename)));
+ if (unlink(G.filename) != 0) {
+ Trace((stderr, "open_outfile: existing file %s is read-only\n",
+ FnFilter1(G.filename)));
+ chmod(G.filename, S_IRUSR | S_IWUSR);
+ Trace((stderr, "open_outfile: %s now writable\n",
+ FnFilter1(G.filename)));
+ if (unlink(G.filename) != 0)
+ return 1;
+ }
+ Trace((stderr, "open_outfile: %s now deleted\n",
+ FnFilter1(G.filename)));
+ }
+ if (G.pInfo->textmode)
+ G.outfile = fopen(G.filename, FOPWT);
+ else
+ G.outfile = fopen(G.filename, FOPW);
+ if (G.outfile == (FILE *)NULL) {
+ Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile),
+ FnFilter1(G.filename)));
+ return 1;
+ }
+#else /* !TANDEM */
+#ifdef DEBUG
+ Info(slide, 1, ((char *)slide,
+ "open_outfile: doing fopen(%s) for reading\n", FnFilter1(G.filename)));
+ if ((G.outfile = fopen(G.filename, FOPR)) == (FILE *)NULL)
+ Info(slide, 1, ((char *)slide,
+ "open_outfile: fopen(%s) for reading failed: does not exist\n",
+ FnFilter1(G.filename)));
+ else {
+ Info(slide, 1, ((char *)slide,
+ "open_outfile: fopen(%s) for reading succeeded: file exists\n",
+ FnFilter1(G.filename)));
+ fclose(G.outfile);
+ }
+#endif /* DEBUG */
+#ifdef NOVELL_BUG_FAILSAFE
+ if (G.dne && ((G.outfile = fopen(G.filename, FOPR)) != (FILE *)NULL)) {
+ Info(slide, 0x401, ((char *)slide, LoadFarString(NovellBug),
+ FnFilter1(G.filename)));
+ fclose(G.outfile);
+ return 1; /* with "./" fix in checkdir(), should never reach here */
+ }
+#endif /* NOVELL_BUG_FAILSAFE */
+ Trace((stderr, "open_outfile: doing fopen(%s) for writing\n",
+ FnFilter1(G.filename)));
+ if ((G.outfile = fopen(G.filename, FOPW)) == (FILE *)NULL) {
+ Info(slide, 0x401, ((char *)slide, LoadFarString(CannotCreateFile),
+ FnFilter1(G.filename)));
+ return 1;
+ }
+ Trace((stderr, "open_outfile: fopen(%s) for writing succeeded\n",
+ FnFilter1(G.filename)));
+#endif /* !TANDEM */
+#endif /* !MTS */
+#endif /* !TOPS20 */
+
+#ifdef USE_FWRITE
+#ifdef DOS_OS2_W32
+ /* 16-bit MSC: buffer size must be strictly LESS than 32K (WSIZE): bogus */
+ setbuf(G.outfile, (char *)NULL); /* make output unbuffered */
+#else /* !DOS_OS2_W32 */
+#ifndef RISCOS
+#ifdef _IOFBF /* make output fully buffered (works just about like write()) */
+ setvbuf(G.outfile, (char *)slide, _IOFBF, WSIZE);
+#else
+ setbuf(G.outfile, (char *)slide);
+#endif
+#endif /* !RISCOS */
+#endif /* ?DOS_OS2_W32 */
+#endif /* USE_FWRITE */
+ return 0;
+
+} /* end function open_outfile() */
+
+#endif /* !VMS && !AOS_VS && !CMS_MVS && !MACOS */
+
+
+
+
+
+/*
+ * These functions allow NEXTBYTE to function without needing two bounds
+ * checks. Call defer_leftover_input() if you ever have filled G.inbuf
+ * by some means other than readbyte(), and you then want to start using
+ * NEXTBYTE. When going back to processing bytes without NEXTBYTE, call
+ * undefer_input(). For example, extract_or_test_member brackets its
+ * central section that does the decompression with these two functions.
+ * If you need to check the number of bytes remaining in the current
+ * file while using NEXTBYTE, check (G.csize + G.incnt), not G.csize.
+ */
+
+/****************************/
+/* function undefer_input() */
+/****************************/
+
+void undefer_input(__G)
+ __GDEF
+{
+ if (G.incnt > 0)
+ G.csize += G.incnt;
+ if (G.incnt_leftover > 0) {
+ /* We know that "(G.csize < MAXINT)" so we can cast G.csize to int:
+ * This condition was checked when G.incnt_leftover was set > 0 in
+ * defer_leftover_input(), and it is NOT allowed to touch G.csize
+ * before calling undefer_input() when (G.incnt_leftover > 0)
+ * (single exception: see read_byte()'s "G.csize <= 0" handling) !!
+ */
+ G.incnt = G.incnt_leftover + (int)G.csize;
+ G.inptr = G.inptr_leftover - (int)G.csize;
+ G.incnt_leftover = 0;
+ } else if (G.incnt < 0)
+ G.incnt = 0;
+} /* end function undefer_input() */
+
+
+
+
+
+/***********************************/
+/* function defer_leftover_input() */
+/***********************************/
+
+void defer_leftover_input(__G)
+ __GDEF
+{
+ if ((long)G.incnt > G.csize) {
+ /* (G.csize < MAXINT), we can safely cast it to int !! */
+ if (G.csize < 0L)
+ G.csize = 0L;
+ G.inptr_leftover = G.inptr + (int)G.csize;
+ G.incnt_leftover = G.incnt - (int)G.csize;
+ G.incnt = (int)G.csize;
+ } else
+ G.incnt_leftover = 0;
+ G.csize -= G.incnt;
+} /* end function defer_leftover_input() */
+
+
+
+
+
+/**********************/
+/* Function readbuf() */
+/**********************/
+
+unsigned readbuf(__G__ buf, size) /* return number of bytes read into buf */
+ __GDEF
+ char *buf;
+ register unsigned size;
+{
+ register unsigned count;
+ unsigned n;
+
+ n = size;
+ while (size) {
+ if (G.incnt <= 0) {
+ if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) == 0)
+ return (n-size);
+ else if (G.incnt < 0) {
+ /* another hack, but no real harm copying same thing twice */
+ (*G.message)((zvoid *)&G,
+ (uch *)LoadFarString(ReadError), /* CANNOT use slide */
+ (ulg)strlen(LoadFarString(ReadError)), 0x401);
+ return 0; /* discarding some data; better than lock-up */
+ }
+ /* buffer ALWAYS starts on a block boundary: */
+ G.cur_zipfile_bufstart += INBUFSIZ;
+ G.inptr = G.inbuf;
+ }
+ count = MIN(size, (unsigned)G.incnt);
+ memcpy(buf, G.inptr, count);
+ buf += count;
+ G.inptr += count;
+ G.incnt -= count;
+ size -= count;
+ }
+ return n;
+
+} /* end function readbuf() */
+
+
+
+
+
+/***********************/
+/* Function readbyte() */
+/***********************/
+
+int readbyte(__G) /* refill inbuf and return a byte if available, else EOF */
+ __GDEF
+{
+ if (G.mem_mode)
+ return EOF;
+ if (G.csize <= 0) {
+ G.csize--; /* for tests done after exploding */
+ G.incnt = 0;
+ return EOF;
+ }
+ if (G.incnt <= 0) {
+ if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) == 0) {
+ G.incnt = 0; /* do not allow negative value to affect stuff */
+ return EOF;
+ } else if (G.incnt < 0) { /* "fail" (abort, retry, ...) returns this */
+ /* another hack, but no real harm copying same thing twice */
+ (*G.message)((zvoid *)&G,
+ (uch *)LoadFarString(ReadError),
+ (ulg)strlen(LoadFarString(ReadError)), 0x401);
+ echon();
+#ifdef WINDLL
+ longjmp(dll_error_return, 1);
+#else
+ DESTROYGLOBALS()
+ EXIT(PK_BADERR); /* totally bailing; better than lock-up */
+#endif
+ }
+ G.cur_zipfile_bufstart += INBUFSIZ; /* always starts on block bndry */
+ G.inptr = G.inbuf;
+ defer_leftover_input(__G); /* decrements G.csize */
+ }
+
+#if CRYPT
+ if (G.pInfo->encrypted) {
+ uch *p;
+ int n;
+
+ /* This was previously set to decrypt one byte beyond G.csize, when
+ * incnt reached that far. GRR said, "but it's required: why?" This
+ * was a bug in fillinbuf() -- was it also a bug here?
+ */
+ for (n = G.incnt, p = G.inptr; n--; p++)
+ zdecode(*p);
+ }
+#endif /* CRYPT */
+
+ --G.incnt;
+ return *G.inptr++;
+
+} /* end function readbyte() */
+
+
+
+
+
+#ifdef USE_ZLIB
+
+/************************/
+/* Function fillinbuf() */
+/************************/
+
+int fillinbuf(__G) /* like readbyte() except returns number of bytes in inbuf */
+ __GDEF
+{
+ if (G.mem_mode ||
+ (G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) <= 0)
+ return 0;
+ G.cur_zipfile_bufstart += INBUFSIZ; /* always starts on a block boundary */
+ G.inptr = G.inbuf;
+ defer_leftover_input(__G); /* decrements G.csize */
+
+#if CRYPT
+ if (G.pInfo->encrypted) {
+ uch *p;
+ int n;
+
+ for (n = G.incnt, p = G.inptr; n--; p++)
+ zdecode(*p);
+ }
+#endif /* CRYPT */
+
+ return G.incnt;
+
+} /* end function fillinbuf() */
+
+#endif /* USE_ZLIB */
+
+
+
+
+
+#ifndef VMS /* for VMS use code in vms.c */
+
+/********************/
+/* Function flush() */ /* returns PK error codes: */
+/********************/ /* if cflag => always 0; PK_DISK if write error */
+
+int flush(__G__ rawbuf, size, unshrink)
+ __GDEF
+ uch *rawbuf;
+ ulg size;
+ int unshrink;
+{
+ register uch *p, *q;
+ uch *transbuf;
+#if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV))
+ ulg transbufsiz;
+#endif
+ /* static int didCRlast = FALSE; moved to globals.h */
+
+
+/*---------------------------------------------------------------------------
+ Compute the CRC first; if testing or if disk is full, that's it.
+ ---------------------------------------------------------------------------*/
+
+ G.crc32val = crc32(G.crc32val, rawbuf, (extent)size);
+
+#ifdef DLL
+ if ((G.statreportcb != NULL) &&
+ (*G.statreportcb)(__G__ UZ_ST_IN_PROGRESS, G.zipfn, G.filename, NULL))
+ return IZ_CTRLC; /* cancel operation by user request */
+#endif
+
+ if (uO.tflag || size == 0L) /* testing or nothing to write: all done */
+ return PK_OK;
+
+ if (G.disk_full)
+ return PK_DISK; /* disk already full: ignore rest of file */
+
+/*---------------------------------------------------------------------------
+ Write the bytes rawbuf[0..size-1] to the output device, first converting
+ end-of-lines and ASCII/EBCDIC as needed. If SMALL_MEM or MED_MEM are NOT
+ defined, outbuf is assumed to be at least as large as rawbuf and is not
+ necessarily checked for overflow.
+ ---------------------------------------------------------------------------*/
+
+ if (!G.pInfo->textmode) { /* write raw binary data */
+ /* GRR: note that for standard MS-DOS compilers, size argument to
+ * fwrite() can never be more than 65534, so WriteError macro will
+ * have to be rewritten if size can ever be that large. For now,
+ * never more than 32K. Also note that write() returns an int, which
+ * doesn't necessarily limit size to 32767 bytes if write() is used
+ * on 16-bit systems but does make it more of a pain; however, because
+ * at least MSC 5.1 has a lousy implementation of fwrite() (as does
+ * DEC Ultrix cc), write() is used anyway.
+ */
+#ifdef DLL
+ if (G.redirect_data)
+ writeToMemory(__G__ rawbuf, size);
+ else
+#endif
+ if (!uO.cflag && WriteError(rawbuf, size, G.outfile))
+ return disk_error(__G);
+ else if (uO.cflag && (*G.message)((zvoid *)&G, rawbuf, size, 0))
+ return 0;
+ } else { /* textmode: aflag is true */
+ if (unshrink) {
+ /* rawbuf = outbuf */
+ transbuf = G.outbuf2;
+#if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV))
+ transbufsiz = TRANSBUFSIZ;
+#endif
+ } else {
+ /* rawbuf = slide */
+ transbuf = G.outbuf;
+#if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV))
+ transbufsiz = OUTBUFSIZ;
+ Trace((stderr, "\ntransbufsiz = OUTBUFSIZ = %u\n", OUTBUFSIZ));
+#endif
+ }
+ if (G.newfile) {
+#ifdef VMS_TEXT_CONV
+ /* GRR: really want to check if -aa (or -aaa?) was given... */
+ if (rawbuf[1]) { /* first line is more than 255 chars long */
+ Trace((stderr,
+ "\nfirst line of VMS `text' too long; switching to normal extraction\n"));
+ G.VMS_line_state = -1; /* -1: don't treat as VMS text */
+ } else
+ G.VMS_line_state = 0; /* 0: ready to read line length */
+#endif
+ G.didCRlast = FALSE; /* no previous buffers written */
+ G.newfile = FALSE;
+ }
+
+#ifdef VMS_TEXT_CONV
+ if (G.pInfo->hostnum == VMS_ && G.extra_field && G.VMS_line_state >= 0)
+ {
+ /* GRR: really want to check for actual VMS extra field, and
+ * ideally for variable-length record format */
+/*
+ printf("\n>>>>>> GRR: file is VMS text and has an extra field\n");
+ */
+
+ p = rawbuf;
+ q = transbuf;
+ while(p < rawbuf+(unsigned)size) {
+ switch (G.VMS_line_state) {
+
+ /* 0: ready to read line length */
+ case 0:
+ G.VMS_line_length = 0;
+ G.VMS_line_pad = 0;
+ if (p == rawbuf+(unsigned)size-1) { /* last char */
+ G.VMS_line_length = (int)((uch)(*p++));
+ G.VMS_line_state = 1;
+ } else {
+ G.VMS_line_length = makeword(p);
+ p += 2;
+ G.VMS_line_state = 2;
+ }
+ if (G.VMS_line_length & 1) /* odd */
+ G.VMS_line_pad = 1;
+ break;
+
+ /* 1: read one byte of length, need second */
+ case 1:
+ G.VMS_line_length += ((int)((uch)(*p++)) << 8);
+ G.VMS_line_state = 2;
+ break;
+
+ /* 2: ready to read VMS_line_length chars */
+ case 2:
+ if (G.VMS_line_length < rawbuf+(unsigned)size-p) {
+ if (G.VMS_line_length >=
+ transbuf+(unsigned)transbufsiz-q)
+ {
+ int outroom = transbuf+(unsigned)transbufsiz-q;
+
+/* GRR: need to change this to *q++ = native(*p++); loop or something */
+ memcpy(q, p, outroom);
+#ifdef DLL
+ if (G.redirect_data)
+ writeToMemory(__G__ transbuf,
+ (unsigned)outroom);
+ else
+#endif
+ if (!uO.cflag && WriteError(transbuf,
+ (unsigned)outroom, G.outfile))
+ return disk_error(__G);
+ else if (uO.cflag && (*G.message)((zvoid *)&G,
+ transbuf, (ulg)outroom, 0))
+ return 0;
+ q = transbuf;
+ p += outroom;
+ G.VMS_line_length -= outroom;
+ /* fall through to normal case */
+ }
+/* GRR: need to change this to *q++ = native(*p++); loop or something */
+ memcpy(q, p, G.VMS_line_length);
+ q += G.VMS_line_length;
+ p += G.VMS_line_length;
+ G.VMS_line_length = 0; /* necessary?? */
+ G.VMS_line_state = 3;
+
+ } else { /* remaining input is less than full line */
+ int remaining = rawbuf+(unsigned)size-p;
+
+ if (remaining <
+ transbuf+(unsigned)transbufsiz-q)
+ {
+ int outroom = transbuf+(unsigned)transbufsiz-q;
+
+/* GRR: need to change this to *q++ = native(*p++); loop or something */
+ memcpy(q, p, outroom);
+#ifdef DLL
+ if (G.redirect_data)
+ writeToMemory(__G__ transbuf,
+ (unsigned)(outroom));
+ else
+#endif
+ if (!uO.cflag && WriteError(transbuf,
+ (unsigned)outroom, G.outfile))
+ return disk_error(__G);
+ else if (uO.cflag && (*G.message)((zvoid *)&G,
+ transbuf, (ulg)outroom, 0))
+ return 0;
+ q = transbuf;
+ p += outroom;
+ remaining -= outroom;
+ }
+/* GRR: need to change this to *q++ = native(*p++); loop or something */
+ memcpy(q, p, remaining);
+ q += remaining;
+ p += remaining;
+ G.VMS_line_length -= remaining;
+ /* no change in G.VMS_line_state */
+ }
+ break;
+
+ /* 3: ready to PutNativeEOL */
+ case 3:
+ if (q > transbuf+(unsigned)transbufsiz-lenEOL) {
+#ifdef DLL
+ if (G.redirect_data)
+ writeToMemory(__G__ transbuf,
+ (unsigned)(q-transbuf));
+ else
+#endif
+ if (!uO.cflag &&
+ WriteError(transbuf, (unsigned)(q-transbuf),
+ G.outfile))
+ return disk_error(__G);
+ else if (uO.cflag && (*G.message)((zvoid *)&G,
+ transbuf, (ulg)(q-transbuf), 0))
+ return 0;
+ q = transbuf;
+ }
+ PutNativeEOL
+ if (G.VMS_line_pad)
+ if (p < rawbuf+(unsigned)size) {
+ ++p;
+ G.VMS_line_state = 0;
+ } else
+ G.VMS_line_state = 4;
+ else
+ G.VMS_line_state = 0;
+ break;
+
+ /* 4: ready to read pad byte */
+ case 4:
+ ++p;
+ G.VMS_line_state = 0;
+ break;
+ }
+ } /* end while */
+
+ } else
+#endif /* VMS_TEXT_CONV */
+
+ /*-----------------------------------------------------------------------
+ Algorithm: CR/LF => native; lone CR => native; lone LF => native.
+ This routine is only for non-raw-VMS, non-raw-VM/CMS files (i.e.,
+ stream-oriented files, not record-oriented).
+ -----------------------------------------------------------------------*/
+
+ /* else not VMS text */ {
+ p = rawbuf;
+ if (*p == LF && G.didCRlast)
+ ++p;
+ G.didCRlast = FALSE;
+ for (q = transbuf; p < rawbuf+(unsigned)size; ++p) {
+ if (*p == CR) { /* lone CR or CR/LF: EOL either way */
+ PutNativeEOL
+ if (p == rawbuf+(unsigned)size-1) /* last char in buffer */
+ G.didCRlast = TRUE;
+ else if (p[1] == LF) /* get rid of accompanying LF */
+ ++p;
+ } else if (*p == LF) /* lone LF */
+ PutNativeEOL
+ else
+#ifndef DOS_FLX_OS2_W32
+ if (*p != CTRLZ) /* lose all ^Z's */
+#endif
+ *q++ = native(*p);
+
+#if (defined(SMALL_MEM) || defined(MED_MEM))
+# if (lenEOL == 1) /* don't check unshrink: both buffers small but equal */
+ if (!unshrink)
+# endif
+ /* check for danger of buffer overflow and flush */
+ if (q > transbuf+(unsigned)transbufsiz-lenEOL) {
+ Trace((stderr,
+ "p - rawbuf = %u q-transbuf = %u size = %lu\n",
+ (unsigned)(p-rawbuf), (unsigned)(q-transbuf), size));
+ if (!uO.cflag && WriteError(transbuf,
+ (unsigned)(q-transbuf), G.outfile))
+ return disk_error(__G);
+ else if (uO.cflag && (*G.message)((zvoid *)&G,
+ transbuf, (ulg)(q-transbuf), 0))
+ return 0;
+ q = transbuf;
+ continue;
+ }
+#endif /* SMALL_MEM || MED_MEM */
+ }
+ }
+
+ /*-----------------------------------------------------------------------
+ Done translating: write whatever we've got to file (or screen).
+ -----------------------------------------------------------------------*/
+
+ Trace((stderr, "p - rawbuf = %u q-transbuf = %u size = %lu\n",
+ (unsigned)(p-rawbuf), (unsigned)(q-transbuf), size));
+ if (q > transbuf) {
+#ifdef DLL
+ if (G.redirect_data)
+ writeToMemory(__G__ transbuf, (unsigned)(q-transbuf));
+ else
+#endif
+ if (!uO.cflag && WriteError(transbuf, (unsigned)(q-transbuf),
+ G.outfile))
+ return disk_error(__G);
+ else if (uO.cflag && (*G.message)((zvoid *)&G, transbuf,
+ (ulg)(q-transbuf), 0))
+ return 0;
+ }
+ }
+
+ return 0;
+
+} /* end function flush() */
+
+
+
+
+
+/*************************/
+/* Function disk_error() */
+/*************************/
+
+static int disk_error(__G)
+ __GDEF
+{
+ /* OK to use slide[] here because this file is finished regardless */
+ Info(slide, 0x4a1, ((char *)slide, LoadFarString(DiskFullQuery),
+ FnFilter1(G.filename)));
+
+#ifndef WINDLL
+ fgets(G.answerbuf, 9, stdin);
+ if (*G.answerbuf == 'y') /* stop writing to this file */
+ G.disk_full = 1; /* (outfile bad?), but new OK */
+ else
+#endif
+ G.disk_full = 2; /* no: exit program */
+
+ return PK_DISK;
+
+} /* end function disk_error() */
+
+#endif /* !VMS */
+
+
+
+
+
+/*****************************/
+/* Function UzpMessagePrnt() */
+/*****************************/
+
+int UZ_EXP UzpMessagePrnt(pG, buf, size, flag)
+ zvoid *pG; /* globals struct: always passed */
+ uch *buf; /* preformatted string to be printed */
+ ulg size; /* length of string (may include nulls) */
+ int flag; /* flag bits */
+{
+ /* IMPORTANT NOTE:
+ * The name of the first parameter of UzpMessagePrnt(), which passes
+ * the "Uz_Globs" address, >>> MUST <<< be identical to the string
+ * expansion of the __G__ macro in the REENTRANT case (see globals.h).
+ * This name identity is mandatory for the LoadFarString() macro
+ * (in the SMALL_MEM case) !!!
+ */
+ int error;
+ uch *q=buf, *endbuf=buf+(unsigned)size;
+#ifdef MORE
+ uch *p=buf-1;
+#endif
+ FILE *outfp;
+
+
+/*---------------------------------------------------------------------------
+ These tests are here to allow fine-tuning of UnZip's output messages,
+ but none of them will do anything without setting the appropriate bit
+ in the flag argument of every Info() statement which is to be turned
+ *off*. That is, all messages are currently turned on for all ports.
+ To turn off *all* messages, use the UzpMessageNull() function instead
+ of this one.
+ ---------------------------------------------------------------------------*/
+
+#if (defined(OS2) && defined(DLL))
+ if (MSG_NO_DLL2(flag)) /* if OS/2 DLL bit is set, do NOT print this msg */
+ return 0;
+#endif
+#ifdef WINDLL
+ if (MSG_NO_WDLL(flag))
+ return 0;
+#endif
+#ifdef WINDLL
+ if (MSG_NO_WGUI(flag))
+ return 0;
+#endif
+/*
+#ifdef ACORN_GUI
+ if (MSG_NO_AGUI(flag))
+ return 0;
+#endif
+ */
+#ifdef DLL /* don't display message if data is redirected */
+ if (((Uz_Globs *)pG)->redirect_data &&
+ !((Uz_Globs *)pG)->redirect_text)
+ return 0;
+#endif
+
+ if (MSG_STDERR(flag) && !((Uz_Globs *)pG)->UzO.tflag)
+ outfp = (FILE *)stderr;
+ else
+ outfp = (FILE *)stdout;
+
+#ifdef QUERY_TRNEWLN
+ /* some systems require termination of query prompts with '\n' to force
+ * immediate display */
+ if (MSG_MNEWLN(flag)) { /* assumes writable buffer (e.g., slide[]) */
+ *endbuf++ = '\n'; /* with room for one more char at end of buf */
+ ++size; /* (safe assumption: only used for four */
+ } /* short queries in extract.c and fileio.c) */
+#endif
+
+ if (MSG_TNEWLN(flag)) { /* again assumes writable buffer: fragile... */
+ if ((!size && !((Uz_Globs *)pG)->sol) ||
+ (size && (endbuf[-1] != '\n')))
+ {
+ *endbuf++ = '\n';
+ ++size;
+ }
+ }
+
+#ifdef MORE
+ /* room for --More-- and one line of overlap: */
+ ((Uz_Globs *)pG)->height = SCREENLINES - 2;
+#endif
+
+ if (MSG_LNEWLN(flag) && !((Uz_Globs *)pG)->sol) {
+ /* not at start of line: want newline */
+#ifdef OS2DLL
+ if (!((Uz_Globs *)pG)->redirect_text) {
+#endif
+ putc('\n', outfp);
+ fflush(outfp);
+#ifdef MORE
+ if (((Uz_Globs *)pG)->M_flag)
+ {
+ ++((Uz_Globs *)pG)->numlines;
+ if (((Uz_Globs *)pG)->numlines %
+ ((Uz_Globs *)pG)->height == 0L) /* GRR: fix */
+ (*((Uz_Globs *)pG)->mpause)((zvoid *)pG,
+ LoadFarString(MorePrompt), 1);
+ }
+#endif /* MORE */
+ if (MSG_STDERR(flag) && ((Uz_Globs *)pG)->UzO.tflag &&
+ !isatty(1) && isatty(2))
+ {
+ /* error output from testing redirected: also send to stderr */
+ putc('\n', stderr);
+ fflush(stderr);
+ }
+#ifdef OS2DLL
+ } else
+ REDIRECTC('\n');
+#endif
+ ((Uz_Globs *)pG)->sol = TRUE;
+ }
+
+ /* put zipfile name, filename and/or error/warning keywords here */
+
+#ifdef MORE
+ if (((Uz_Globs *)pG)->M_flag
+#ifdef OS2DLL
+ && !((Uz_Globs *)pG)->redirect_text
+#endif
+ )
+ {
+ while (++p < endbuf) {
+ if (*p == '\n') {
+ ++((Uz_Globs *)pG)->numlines;
+ if (((Uz_Globs *)pG)->numlines %
+ ((Uz_Globs *)pG)->height == 0L) /* GRR: fix */
+ {
+ if ((error = WriteError(q, p-q+1, outfp)) != 0)
+ return error;
+ fflush(outfp);
+ ((Uz_Globs *)pG)->sol = TRUE;
+ q = p + 1;
+ (*((Uz_Globs *)pG)->mpause)((zvoid *)pG,
+ LoadFarString(MorePrompt), 1);
+ }
+ }
+ } /* end while */
+ size = (ulg)(p - q); /* remaining text */
+ }
+#endif /* MORE */
+
+ if (size) {
+#ifdef OS2DLL
+ if (!((Uz_Globs *)pG)->redirect_text) {
+#endif
+ if ((error = WriteError(q, size, outfp)) != 0)
+ return error;
+ fflush(outfp);
+ if (MSG_STDERR(flag) && ((Uz_Globs *)pG)->UzO.tflag &&
+ !isatty(1) && isatty(2))
+ {
+ /* error output from testing redirected: also send to stderr */
+ if ((error = WriteError(q, size, stderr)) != 0)
+ return error;
+ fflush(stderr);
+ }
+#ifdef OS2DLL
+ } else { /* GRR: this is ugly: hide with macro */
+ if ((error = REDIRECTPRINT(q, size)) != 0)
+ return error;
+ }
+#endif
+ ((Uz_Globs *)pG)->sol = (endbuf[-1] == '\n');
+ }
+ return 0;
+
+} /* end function UzpMessagePrnt() */
+
+
+
+
+
+#ifdef DLL
+
+/*****************************/
+/* Function UzpMessageNull() */ /* convenience routine for no output at all */
+/*****************************/
+
+int UZ_EXP UzpMessageNull(pG, buf, size, flag)
+ zvoid *pG; /* globals struct: always passed */
+ uch *buf; /* preformatted string to be printed */
+ ulg size; /* length of string (may include nulls) */
+ int flag; /* flag bits */
+{
+ return 0;
+
+} /* end function UzpMessageNull() */
+
+#endif /* DLL */
+
+
+
+
+
+/***********************/
+/* Function UzpInput() */ /* GRR: this is a placeholder for now */
+/***********************/
+
+int UZ_EXP UzpInput(pG, buf, size, flag)
+ zvoid *pG; /* globals struct: always passed */
+ uch *buf; /* preformatted string to be printed */
+ int *size; /* (address of) size of buf and of returned string */
+ int flag; /* flag bits (bit 0: no echo) */
+{
+ /* tell picky compilers to shut up about "unused variable" warnings */
+ pG = pG; buf = buf; flag = flag;
+
+ *size = 0;
+ return 0;
+
+} /* end function UzpInput() */
+
+
+
+
+
+#if (!defined(WINDLL) && !defined(MACOS))
+
+/***************************/
+/* Function UzpMorePause() */
+/***************************/
+
+void UZ_EXP UzpMorePause(pG, prompt, flag)
+ zvoid *pG; /* globals struct: always passed */
+ ZCONST char *prompt; /* "--More--" prompt */
+ int flag; /* 0 = any char OK; 1 = accept only '\n', ' ', q */
+{
+ uch c;
+
+/*---------------------------------------------------------------------------
+ Print a prompt and wait for the user to press a key, then erase prompt
+ if possible.
+ ---------------------------------------------------------------------------*/
+
+ if (!((Uz_Globs *)pG)->sol)
+ fprintf(stderr, "\n");
+ /* numlines may or may not be used: */
+ fprintf(stderr, prompt, ((Uz_Globs *)pG)->numlines);
+ fflush(stderr);
+ if (flag & 1) {
+ do {
+ c = (uch)FGETCH(0);
+ } while (c != '\r' && c != '\n' && c != ' ' && c != 'q' && c != 'Q');
+ } else
+ c = (uch)FGETCH(0);
+
+ /* newline was not echoed, so cover up prompt line */
+ fprintf(stderr, LoadFarString(HidePrompt));
+ fflush(stderr);
+
+ if (ToLower(c) == 'q') {
+ DESTROYGLOBALS()
+ EXIT(PK_COOL);
+ }
+
+ ((Uz_Globs *)pG)->sol = TRUE;
+
+} /* end function UzpMorePause() */
+
+#endif /* !WINDLL && !MACOS */
+
+
+
+
+#ifndef WINDLL
+
+/**************************/
+/* Function UzpPassword() */
+/**************************/
+
+int UZ_EXP UzpPassword (pG, rcnt, pwbuf, size, zfn, efn)
+ zvoid *pG; /* pointer to UnZip's internal global vars */
+ int *rcnt; /* retry counter */
+ char *pwbuf; /* buffer for password */
+ int size; /* size of password buffer */
+ ZCONST char *zfn; /* name of zip archive */
+ ZCONST char *efn; /* name of archive entry being processed */
+{
+#if CRYPT
+ int r = IZ_PW_ENTERED;
+ char *m;
+ char *prompt;
+
+#ifndef REENTRANT
+ /* tell picky compilers to shut up about "unused variable" warnings */
+ pG = pG;
+#endif
+
+ if (*rcnt == 0) { /* First call for current entry */
+ *rcnt = 2;
+ if ((prompt = (char *)malloc(2*FILNAMSIZ + 15)) != (char *)NULL) {
+ sprintf(prompt, LoadFarString(PasswPrompt),
+ FnFilter1(zfn), FnFilter2(efn));
+ m = prompt;
+ } else
+ m = (char *)LoadFarString(PasswPrompt2);
+ } else { /* Retry call, previous password was wrong */
+ (*rcnt)--;
+ prompt = NULL;
+ m = (char *)LoadFarString(PasswRetry);
+ }
+
+ m = getp(__G__ m, pwbuf, size);
+ if (prompt != (char *)NULL) {
+ free(prompt);
+ }
+ if (m == (char *)NULL) {
+ r = IZ_PW_ERROR;
+ }
+ else if (*pwbuf == '\0') {
+ r = IZ_PW_CANCELALL;
+ }
+ return r;
+
+#else /* !CRYPT */
+ /* tell picky compilers to shut up about "unused variable" warnings */
+ pG = pG; rcnt = rcnt; pwbuf = pwbuf; size = size; zfn = zfn; efn = efn;
+
+ return IZ_PW_ERROR; /* internal error; function should never get called */
+#endif /* ?CRYPT */
+
+} /* end function UzpPassword() */
+
+
+
+
+
+/**********************/
+/* Function handler() */
+/**********************/
+
+void handler(signal) /* upon interrupt, turn on echo and exit cleanly */
+ int signal;
+{
+ GETGLOBALS();
+
+#if !(defined(SIGBUS) || defined(SIGSEGV)) /* add a newline if not at */
+ (*G.message)((zvoid *)&G, slide, 0L, 0x41); /* start of line (to stderr; */
+#endif /* slide[] should be safe) */
+
+ echon();
+
+#ifdef SIGBUS
+ if (signal == SIGBUS) {
+ Info(slide, 0x421, ((char *)slide, LoadFarString(ZipfileCorrupt),
+ "bus error"));
+ DESTROYGLOBALS()
+ EXIT(PK_BADERR);
+ }
+#endif /* SIGBUS */
+
+#ifdef SIGSEGV
+ if (signal == SIGSEGV) {
+ Info(slide, 0x421, ((char *)slide, LoadFarString(ZipfileCorrupt),
+ "segmentation violation"));
+ DESTROYGLOBALS()
+ EXIT(PK_BADERR);
+ }
+#endif /* SIGSEGV */
+
+ /* probably ctrl-C */
+ DESTROYGLOBALS()
+#if defined(AMIGA) && defined(__SASC)
+ _abort();
+#endif
+ EXIT(IZ_CTRLC); /* was EXIT(0), then EXIT(PK_ERR) */
+}
+
+#endif /* !WINDLL */
+
+
+
+
+#if (!defined(VMS) && !defined(CMS_MVS))
+#if (!defined(OS2) || defined(TIMESTAMP))
+
+#if (!defined(HAVE_MKTIME) || defined(AMIGA) || defined(WIN32))
+/* also used in amiga/filedate.c and win32/win32.c */
+ZCONST ush ydays[] =
+ { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
+#endif
+
+/*******************************/
+/* Function dos_to_unix_time() */ /* used for freshening/updating/timestamps */
+/*******************************/
+
+time_t dos_to_unix_time(dosdatetime)
+ ulg dosdatetime;
+{
+ time_t m_time;
+
+#ifdef HAVE_MKTIME
+
+ ZCONST time_t now = time(NULL);
+ struct tm *tm;
+# define YRBASE 1900
+
+ tm = localtime(&now);
+ tm->tm_isdst = -1; /* let mktime determine if DST is in effect */
+
+ /* dissect date */
+ tm->tm_year = ((int)(dosdatetime >> 25) & 0x7f) + (1980 - YRBASE);
+ tm->tm_mon = ((int)(dosdatetime >> 21) & 0x0f) - 1;
+ tm->tm_mday = ((int)(dosdatetime >> 16) & 0x1f);
+
+ /* dissect time */
+ tm->tm_hour = (int)((unsigned)dosdatetime >> 11) & 0x1f;
+ tm->tm_min = (int)((unsigned)dosdatetime >> 5) & 0x3f;
+ tm->tm_sec = (int)((unsigned)dosdatetime << 1) & 0x3e;
+
+ m_time = mktime(tm);
+ NATIVE_TO_TIMET(m_time) /* NOP unless MSC 7.0 or Macintosh */
+ TTrace((stderr, " final m_time = %lu\n", (ulg)m_time));
+
+#else /* !HAVE_MKTIME */
+
+ int yr, mo, dy, hh, mm, ss;
+#ifdef TOPS20
+# define YRBASE 1900
+ struct tmx *tmx;
+ char temp[20];
+#else /* !TOPS20 */
+# define YRBASE 1970
+ int leap;
+ unsigned days;
+ struct tm *tm;
+#if (!defined(MACOS) && !defined(RISCOS) && !defined(QDOS) && !defined(TANDEM))
+#ifdef WIN32
+ TIME_ZONE_INFORMATION tzinfo;
+ DWORD res;
+#else /* ! WIN32 */
+#ifndef BSD4_4 /* GRR: change to !defined(MODERN) ? */
+#if (defined(BSD) || defined(MTS) || defined(__GO32__))
+ struct timeb tbp;
+#else /* !(BSD || MTS || __GO32__) */
+#ifdef DECLARE_TIMEZONE
+ extern time_t timezone;
+#endif
+#endif /* ?(BSD || MTS || __GO32__) */
+#endif /* !BSD4_4 */
+#endif /* ?WIN32 */
+#endif /* !MACOS && !RISCOS && !QDOS && !TANDEM */
+#endif /* ?TOPS20 */
+
+
+ /* dissect date */
+ yr = ((int)(dosdatetime >> 25) & 0x7f) + (1980 - YRBASE);
+ mo = ((int)(dosdatetime >> 21) & 0x0f) - 1;
+ dy = ((int)(dosdatetime >> 16) & 0x1f) - 1;
+
+ /* dissect time */
+ hh = (int)((unsigned)dosdatetime >> 11) & 0x1f;
+ mm = (int)((unsigned)dosdatetime >> 5) & 0x3f;
+ ss = (int)((unsigned)dosdatetime & 0x1f) * 2;
+
+#ifdef TOPS20
+ tmx = (struct tmx *)malloc(sizeof(struct tmx));
+ sprintf (temp, "%02d/%02d/%02d %02d:%02d:%02d", mo+1, dy+1, yr, hh, mm, ss);
+ time_parse(temp, tmx, (char *)0);
+ m_time = time_make(tmx);
+ free(tmx);
+
+#else /* !TOPS20 */
+
+/*---------------------------------------------------------------------------
+ Calculate the number of seconds since the epoch, usually 1 January 1970.
+ ---------------------------------------------------------------------------*/
+
+ /* leap = # of leap yrs from YRBASE up to but not including current year */
+ leap = ((yr + YRBASE - 1) / 4); /* leap year base factor */
+
+ /* calculate days from BASE to this year and add expired days this year */
+ days = (yr * 365) + (leap - 492) + ydays[mo];
+
+ /* if year is a leap year and month is after February, add another day */
+ if ((mo > 1) && ((yr+YRBASE)%4 == 0) && ((yr+YRBASE) != 2100))
+ ++days; /* OK through 2199 */
+
+ /* convert date & time to seconds relative to 00:00:00, 01/01/YRBASE */
+ m_time = (time_t)((unsigned long)(days + dy) * 86400L +
+ (unsigned long)hh * 3600L +
+ (unsigned long)(mm * 60 + ss));
+ /* - 1; MS-DOS times always rounded up to nearest even second */
+ TTrace((stderr, "dos_to_unix_time:\n"));
+ TTrace((stderr, " m_time before timezone = %lu\n", (ulg)m_time));
+
+/*---------------------------------------------------------------------------
+ Adjust for local standard timezone offset.
+ ---------------------------------------------------------------------------*/
+
+#if (!defined(MACOS) && !defined(RISCOS) && !defined(QDOS) && !defined(TANDEM))
+#ifdef WIN32
+ /* account for timezone differences */
+ res = GetTimeZoneInformation(&tzinfo);
+ if (res != TIME_ZONE_ID_UNKNOWN)
+ {
+ m_time += 60*(tzinfo.Bias);
+#else /* !WIN32 */
+#if (defined(BSD) || defined(MTS) || defined(__GO32__))
+#ifdef BSD4_4
+ if ( (dosdatetime >= DOSTIME_2038_01_18) &&
+ (m_time < (time_t)0x70000000L) )
+ m_time = U_TIME_T_MAX; /* saturate in case of (unsigned) overflow */
+ if (m_time < (time_t)0L) /* a converted DOS time cannot be negative */
+ m_time = S_TIME_T_MAX; /* -> saturate at max signed time_t value */
+ if ((tm = localtime(&m_time)) != (struct tm *)NULL)
+ m_time -= tm->tm_gmtoff; /* sec. EAST of GMT: subtr. */
+#else /* !(BSD4_4 */
+ ftime(&tbp); /* get `timezone' */
+ m_time += tbp.timezone * 60L; /* seconds WEST of GMT: add */
+#endif /* ?(BSD4_4 || __EMX__) */
+#else /* !(BSD || MTS || __GO32__) */
+ /* tzset was already called at start of process_zipfiles() */
+ /* tzset(); */ /* set `timezone' variable */
+#ifndef __BEOS__ /* BeOS DR8 has no timezones... */
+ m_time += timezone; /* seconds WEST of GMT: add */
+#endif
+#endif /* ?(BSD || MTS || __GO32__) */
+#endif /* ?WIN32 */
+ TTrace((stderr, " m_time after timezone = %lu\n", (ulg)m_time));
+
+/*---------------------------------------------------------------------------
+ Adjust for local daylight savings (summer) time.
+ ---------------------------------------------------------------------------*/
+
+#ifndef BSD4_4 /* (DST already added to tm_gmtoff, so skip tm_isdst) */
+ if ( (dosdatetime >= DOSTIME_2038_01_18) &&
+ (m_time < (time_t)0x70000000L) )
+ m_time = U_TIME_T_MAX; /* saturate in case of (unsigned) overflow */
+ if (m_time < (time_t)0L) /* a converted DOS time cannot be negative */
+ m_time = S_TIME_T_MAX; /* -> saturate at max signed time_t value */
+ TIMET_TO_NATIVE(m_time) /* NOP unless MSC 7.0 or Macintosh */
+ if (((tm = localtime((time_t *)&m_time)) != NULL) && tm->tm_isdst)
+#ifdef WIN32
+ m_time += 60L * tzinfo.DaylightBias; /* adjust with DST bias */
+ else
+ m_time += 60L * tzinfo.StandardBias; /* add StdBias (normally 0) */
+#else
+ m_time -= 60L * 60L; /* adjust for daylight savings time */
+#endif
+ NATIVE_TO_TIMET(m_time) /* NOP unless MSC 7.0 or Macintosh */
+ TTrace((stderr, " m_time after DST = %lu\n", (ulg)m_time));
+#endif /* !BSD4_4 */
+#ifdef WIN32
+ }
+#endif
+#endif /* !MACOS && !RISCOS && !QDOS && !TANDEM */
+#endif /* ?TOPS20 */
+
+#endif /* ?HAVE_MKTIME */
+
+ if ( (dosdatetime >= DOSTIME_2038_01_18) &&
+ (m_time < (time_t)0x70000000L) )
+ m_time = U_TIME_T_MAX; /* saturate in case of (unsigned) overflow */
+ if (m_time < (time_t)0L) /* a converted DOS time cannot be negative */
+ m_time = S_TIME_T_MAX; /* -> saturate at max signed time_t value */
+
+ return m_time;
+
+} /* end function dos_to_unix_time() */
+
+#endif /* !OS2 || TIMESTAMP */
+#endif /* !VMS && !CMS_MVS */
+
+
+
+#if (!defined(VMS) && !defined(OS2) && !defined(CMS_MVS))
+
+/******************************/
+/* Function check_for_newer() */ /* used for overwriting/freshening/updating */
+/******************************/
+
+int check_for_newer(__G__ filename) /* return 1 if existing file is newer */
+ __GDEF /* or equal; 0 if older; -1 if doesn't */
+ char *filename; /* exist yet */
+{
+ time_t existing, archive;
+#ifdef USE_EF_UT_TIME
+ iztimes z_utime;
+#endif
+#ifdef AOS_VS
+ long dyy, dmm, ddd, dhh, dmin, dss;
+
+
+ dyy = (lrec.last_mod_dos_datetime >> 25) + 1980;
+ dmm = (lrec.last_mod_dos_datetime >> 21) & 0x0f;
+ ddd = (lrec.last_mod_dos_datetime >> 16) & 0x1f;
+ dhh = (lrec.last_mod_dos_datetime >> 11) & 0x1f;
+ dmin = (lrec.last_mod_dos_datetime >> 5) & 0x3f;
+ dss = (lrec.last_mod_dos_datetime & 0x1f) * 2;
+
+ /* under AOS/VS, file times can only be set at creation time,
+ * with the info in a special DG format. Make sure we can create
+ * it here - we delete it later & re-create it, whether or not
+ * it exists now.
+ */
+ if (!zvs_create(filename, (((ulg)dgdate(dmm, ddd, dyy)) << 16) |
+ (dhh*1800L + dmin*30L + dss/2L), -1L, -1L, (char *) -1, -1, -1, -1))
+ return DOES_NOT_EXIST;
+#endif /* AOS_VS */
+
+ Trace((stderr, "check_for_newer: doing stat(%s)\n", FnFilter1(filename)));
+ if (SSTAT(filename, &G.statbuf)) {
+ Trace((stderr,
+ "check_for_newer: stat(%s) returns %d: file does not exist\n",
+ FnFilter1(filename), SSTAT(filename, &G.statbuf)));
+#ifdef SYMLINKS
+ Trace((stderr, "check_for_newer: doing lstat(%s)\n",
+ FnFilter1(filename)));
+ /* GRR OPTION: could instead do this test ONLY if G.symlnk is true */
+ if (lstat(filename, &G.statbuf) == 0) {
+ Trace((stderr,
+ "check_for_newer: lstat(%s) returns 0: symlink does exist\n",
+ FnFilter1(filename)));
+ if (QCOND2 && !uO.overwrite_all)
+ Info(slide, 0, ((char *)slide, LoadFarString(FileIsSymLink),
+ FnFilter1(filename), " with no real file"));
+ return EXISTS_AND_OLDER; /* symlink dates are meaningless */
+ }
+#endif /* SYMLINKS */
+ return DOES_NOT_EXIST;
+ }
+ Trace((stderr, "check_for_newer: stat(%s) returns 0: file exists\n",
+ FnFilter1(filename)));
+
+#ifdef SYMLINKS
+ /* GRR OPTION: could instead do this test ONLY if G.symlnk is true */
+ if (lstat(filename, &G.statbuf) == 0 && S_ISLNK(G.statbuf.st_mode)) {
+ Trace((stderr, "check_for_newer: %s is a symbolic link\n",
+ FnFilter1(filename)));
+ if (QCOND2 && !uO.overwrite_all)
+ Info(slide, 0, ((char *)slide, LoadFarString(FileIsSymLink),
+ FnFilter1(filename), ""));
+ return EXISTS_AND_OLDER; /* symlink dates are meaningless */
+ }
+#endif /* SYMLINKS */
+
+ NATIVE_TO_TIMET(G.statbuf.st_mtime) /* NOP unless MSC 7.0 or Macintosh */
+
+#ifdef USE_EF_UT_TIME
+ /* The `Unix extra field mtime' should be used for comparison with the
+ * time stamp of the existing file >>>ONLY<<< when the EF info is also
+ * used to set the modification time of the extracted file.
+ */
+ if (G.extra_field &&
+#ifdef IZ_CHECK_TZ
+ G.tz_is_valid &&
+#endif
+ (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0,
+ G.lrec.last_mod_dos_datetime, &z_utime, NULL)
+ & EB_UT_FL_MTIME))
+ {
+ TTrace((stderr, "check_for_newer: using Unix extra field mtime\n"));
+ existing = G.statbuf.st_mtime;
+ archive = z_utime.mtime;
+ } else {
+ /* round up existing filetime to nearest 2 seconds for comparison,
+ * but saturate in case of arithmetic overflow
+ */
+ existing = ((G.statbuf.st_mtime & 1) &&
+ (G.statbuf.st_mtime + 1 > G.statbuf.st_mtime)) ?
+ G.statbuf.st_mtime + 1 : G.statbuf.st_mtime;
+ archive = dos_to_unix_time(G.lrec.last_mod_dos_datetime);
+ }
+#else /* !USE_EF_UT_TIME */
+ /* round up existing filetime to nearest 2 seconds for comparison,
+ * but saturate in case of arithmetic overflow
+ */
+ existing = ((G.statbuf.st_mtime & 1) &&
+ (G.statbuf.st_mtime + 1 > G.statbuf.st_mtime)) ?
+ G.statbuf.st_mtime + 1 : G.statbuf.st_mtime;
+ archive = dos_to_unix_time(G.lrec.last_mod_dos_datetime);
+#endif /* ?USE_EF_UT_TIME */
+
+ TTrace((stderr, "check_for_newer: existing %lu, archive %lu, e-a %ld\n",
+ (ulg)existing, (ulg)archive, (long)(existing-archive)));
+
+ return (existing >= archive);
+
+} /* end function check_for_newer() */
+
+#endif /* !VMS && !OS2 && !CMS_MVS */
+
+
+
+
+
+/************************/
+/* Function do_string() */
+/************************/
+
+int do_string(__G__ len, option) /* return PK-type error code */
+ __GDEF
+ unsigned int len; /* without prototype, ush converted to this */
+ int option;
+{
+ long comment_bytes_left, block_length;
+ int error=PK_OK;
+ ush extra_len;
+#ifdef AMIGA
+ char tmp_fnote[2 * AMIGA_FILENOTELEN]; /* extra room for squozen chars */
+#endif
+
+
+/*---------------------------------------------------------------------------
+ This function processes arbitrary-length (well, usually) strings. Four
+ options are allowed: SKIP, wherein the string is skipped (pretty logical,
+ eh?); DISPLAY, wherein the string is printed to standard output after un-
+ dergoing any necessary or unnecessary character conversions; DS_FN,
+ wherein the string is put into the filename[] array after undergoing ap-
+ propriate conversions (including case-conversion, if that is indicated:
+ see the global variable pInfo->lcflag); and EXTRA_FIELD, wherein the
+ `string' is assumed to be an extra field and is copied to the (freshly
+ malloced) buffer G.extra_field. The third option should be OK since
+ filename is dimensioned at 1025, but we check anyway.
+
+ The string, by the way, is assumed to start at the current file-pointer
+ position; its length is given by len. So start off by checking length
+ of string: if zero, we're already done.
+ ---------------------------------------------------------------------------*/
+
+ if (!len)
+ return PK_COOL;
+
+ switch (option) {
+
+ /*
+ * First case: print string on standard output. First set loop vari-
+ * ables, then loop through the comment in chunks of OUTBUFSIZ bytes,
+ * converting formats and printing as we go. The second half of the
+ * loop conditional was added because the file might be truncated, in
+ * which case comment_bytes_left will remain at some non-zero value for
+ * all time. outbuf and slide are used as scratch buffers because they
+ * are available (we should be either before or in between any file pro-
+ * cessing).
+ */
+
+ case DISPLAY:
+ case DISPL_8:
+ comment_bytes_left = len;
+ block_length = OUTBUFSIZ; /* for the while statement, first time */
+ while (comment_bytes_left > 0 && block_length > 0) {
+ register uch *p = G.outbuf;
+ register uch *q = G.outbuf;
+
+ if ((block_length = readbuf(__G__ (char *)G.outbuf,
+ (unsigned) MIN((long)OUTBUFSIZ, comment_bytes_left))) == 0)
+ return PK_EOF;
+ comment_bytes_left -= block_length;
+
+ /* this is why we allocated an extra byte for outbuf: terminate
+ * with zero (ASCIIZ) */
+ G.outbuf[(unsigned)block_length] = '\0';
+
+ /* remove all ASCII carriage returns from comment before printing
+ * (since used before A_TO_N(), check for CR instead of '\r')
+ */
+ while (*p) {
+ while (*p == CR)
+ ++p;
+ *q++ = *p++;
+ }
+ /* could check whether (p - outbuf) == block_length here */
+ *q = '\0';
+
+ if (option == DISPL_8) {
+ /* translate the text coded in the entry's host-dependent
+ "extended ASCII" charset into the compiler's (system's)
+ internal text code page */
+ Ext_ASCII_TO_Native((char *)G.outbuf, G.pInfo->hostnum,
+ G.crec.version_made_by[0]);
+#ifdef WINDLL
+ /* translate to ANSI (RTL internal codepage may be OEM) */
+ INTERN_TO_ISO((char *)G.outbuf, (char *)G.outbuf);
+#else /* !WINDLL */
+#ifdef WIN32
+ /* Win9x console always uses OEM character coding, and
+ WinNT console is set to OEM charset by default, too */
+ INTERN_TO_OEM((char *)G.outbuf, (char *)G.outbuf);
+#endif /* WIN32 */
+#endif /* ?WINDLL */
+ } else {
+ A_TO_N(G.outbuf); /* translate string to native */
+ }
+
+#ifdef WINDLL
+ /* ran out of local mem -- had to cheat */
+ win_fprintf((zvoid *)&G, stdout, len, (char *)G.outbuf);
+ win_fprintf((zvoid *)&G, stdout, 2, (char *)"\n\n");
+#else /* !WINDLL */
+#ifdef NOANSIFILT /* GRR: can ANSI be used with EBCDIC? */
+ (*G.message)((zvoid *)&G, G.outbuf, (ulg)(q-G.outbuf), 0);
+#else /* ASCII, filter out ANSI escape sequences and handle ^S (pause) */
+ p = G.outbuf - 1;
+ q = slide;
+ while (*++p) {
+ int pause = FALSE;
+
+ if (*p == 0x1B) { /* ASCII escape char */
+ *q++ = '^';
+ *q++ = '[';
+ } else if (*p == 0x13) { /* ASCII ^S (pause) */
+ pause = TRUE;
+ if (p[1] == LF) /* ASCII LF */
+ *q++ = *++p;
+ else if (p[1] == CR && p[2] == LF) { /* ASCII CR LF */
+ *q++ = *++p;
+ *q++ = *++p;
+ }
+ } else
+ *q++ = *p;
+ if ((unsigned)(q-slide) > WSIZE-3 || pause) { /* flush */
+ (*G.message)((zvoid *)&G, slide, (ulg)(q-slide), 0);
+ q = slide;
+ if (pause && G.extract_flag) /* don't pause for list/test */
+ (*G.mpause)((zvoid *)&G, LoadFarString(QuitPrompt), 0);
+ }
+ }
+ (*G.message)((zvoid *)&G, slide, (ulg)(q-slide), 0);
+#endif /* ?NOANSIFILT */
+#endif /* ?WINDLL */
+ }
+ /* add '\n' if not at start of line */
+ (*G.message)((zvoid *)&G, slide, 0L, 0x40);
+ break;
+
+ /*
+ * Second case: read string into filename[] array. The filename should
+ * never ever be longer than FILNAMSIZ-1 (1024), but for now we'll check,
+ * just to be sure.
+ */
+
+ case DS_FN:
+ extra_len = 0;
+ if (len >= FILNAMSIZ) {
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(FilenameTooLongTrunc)));
+ error = PK_WARN;
+ extra_len = (ush)(len - FILNAMSIZ + 1);
+ len = FILNAMSIZ - 1;
+ }
+ if (readbuf(__G__ G.filename, len) == 0)
+ return PK_EOF;
+ G.filename[len] = '\0'; /* terminate w/zero: ASCIIZ */
+
+ /* translate the Zip entry filename coded in host-dependent "extended
+ ASCII" into the compiler's (system's) internal text code page */
+ Ext_ASCII_TO_Native(G.filename, G.pInfo->hostnum,
+ G.crec.version_made_by[0]);
+
+ if (G.pInfo->lcflag) /* replace with lowercase filename */
+ TOLOWER(G.filename, G.filename);
+
+ if (G.pInfo->vollabel && len > 8 && G.filename[8] == '.') {
+ char *p = G.filename+8;
+ while (*p++)
+ p[-1] = *p; /* disk label, and 8th char is dot: remove dot */
+ }
+
+ if (!extra_len) /* we're done here */
+ break;
+
+ /*
+ * We truncated the filename, so print what's left and then fall
+ * through to the SKIP routine.
+ */
+ Info(slide, 0x401, ((char *)slide, "[ %s ]\n", FnFilter1(G.filename)));
+ len = extra_len;
+ /* FALL THROUGH... */
+
+ /*
+ * Third case: skip string, adjusting readbuf's internal variables
+ * as necessary (and possibly skipping to and reading a new block of
+ * data).
+ */
+
+ case SKIP:
+ /* cur_zipfile_bufstart already takes account of extra_bytes, so don't
+ * correct for it twice: */
+ ZLSEEK(G.cur_zipfile_bufstart - G.extra_bytes +
+ (G.inptr-G.inbuf) + len)
+ break;
+
+ /*
+ * Fourth case: assume we're at the start of an "extra field"; malloc
+ * storage for it and read data into the allocated space.
+ */
+
+ case EXTRA_FIELD:
+ if (G.extra_field != (uch *)NULL)
+ free(G.extra_field);
+ if ((G.extra_field = (uch *)malloc(len)) == (uch *)NULL) {
+ Info(slide, 0x401, ((char *)slide, LoadFarString(ExtraFieldTooLong),
+ len));
+ /* cur_zipfile_bufstart already takes account of extra_bytes,
+ * so don't correct for it twice: */
+ ZLSEEK(G.cur_zipfile_bufstart - G.extra_bytes +
+ (G.inptr-G.inbuf) + len)
+ } else
+ if (readbuf(__G__ (char *)G.extra_field, len) == 0)
+ return PK_EOF;
+ break;
+
+#ifdef AMIGA
+ /*
+ * Fifth case, for the Amiga only: take the comment that would ordinarily
+ * be skipped over, and turn it into a 79 character string that will be
+ * attached to the file as a "filenote" after it is extracted.
+ */
+
+ case FILENOTE:
+ if ((extra_len = readbuf(__G__ tmp_fnote, (unsigned)
+ MIN(len, 2 * AMIGA_FILENOTELEN - 1))) == 0)
+ return PK_EOF;
+ if ((len -= extra_len) > 0) /* treat remainder as in case SKIP: */
+ ZLSEEK(G.cur_zipfile_bufstart - G.extra_bytes
+ + (G.inptr - G.inbuf) + len)
+ /* convert multi-line text into single line with no ctl-chars: */
+ tmp_fnote[extra_len] = '\0';
+ while ((short int) --extra_len >= 0)
+ if ((unsigned) tmp_fnote[extra_len] < ' ')
+ if (tmp_fnote[extra_len+1] == ' ') /* no excess */
+ strcpy(tmp_fnote+extra_len, tmp_fnote+extra_len+1);
+ else
+ tmp_fnote[extra_len] = ' ';
+ tmp_fnote[AMIGA_FILENOTELEN - 1] = '\0';
+ if (G.filenotes[G.filenote_slot])
+ free(G.filenotes[G.filenote_slot]); /* should not happen */
+ G.filenotes[G.filenote_slot] = NULL;
+ if (tmp_fnote[0]) {
+ if (!(G.filenotes[G.filenote_slot] = malloc(strlen(tmp_fnote)+1)))
+ return PK_MEM;
+ strcpy(G.filenotes[G.filenote_slot], tmp_fnote);
+ }
+ break;
+#endif /* AMIGA */
+
+ } /* end switch (option) */
+
+ return error;
+
+} /* end function do_string() */
+
+
+
+
+
+/***********************/
+/* Function makeword() */
+/***********************/
+
+ush makeword(b)
+ ZCONST uch *b;
+{
+ /*
+ * Convert Intel style 'short' integer to non-Intel non-16-bit
+ * host format. This routine also takes care of byte-ordering.
+ */
+ return (ush)((b[1] << 8) | b[0]);
+}
+
+
+
+
+
+/***********************/
+/* Function makelong() */
+/***********************/
+
+ulg makelong(sig)
+ ZCONST uch *sig;
+{
+ /*
+ * Convert intel style 'long' variable to non-Intel non-16-bit
+ * host format. This routine also takes care of byte-ordering.
+ */
+ return (((ulg)sig[3]) << 24)
+ + (((ulg)sig[2]) << 16)
+ + (((ulg)sig[1]) << 8)
+ + ((ulg)sig[0]);
+}
+
+
+
+#if CRYPT
+
+#ifdef NEED_STR2ISO
+/**********************/
+/* Function str2iso() */
+/**********************/
+
+char *str2iso(dst, src)
+ char *dst; /* destination buffer */
+ register ZCONST char *src; /* source string */
+{
+#ifdef INTERN_TO_ISO
+ INTERN_TO_ISO(src, dst);
+#else
+ register uch c;
+ register char *dstp = dst;
+
+ do {
+ c = (uch)foreign(*src++);
+ *dstp++ = (char)ASCII2ISO(c);
+ } while (c != '\0');
+#endif
+
+ return dst;
+}
+#endif /* NEED_STR2ISO */
+
+
+#ifdef NEED_STR2OEM
+/**********************/
+/* Function str2oem() */
+/**********************/
+
+char *str2oem(dst, src)
+ char *dst; /* destination buffer */
+ register ZCONST char *src; /* source string */
+{
+#ifdef INTERN_TO_OEM
+ INTERN_TO_OEM(src, dst);
+#else
+ register uch c;
+ register char *dstp = dst;
+
+ do {
+ c = (uch)foreign(*src++);
+ *dstp++ = (char)ASCII2OEM(c);
+ } while (c != '\0');
+#endif
+
+ return dst;
+}
+#endif /* NEED_STR2OEM */
+
+#endif /* CRYPT */
+
+
+#ifdef ZMEM /* memset/memcmp/memcpy for systems without either them or */
+ /* bzero/bcmp/bcopy */
+ /* (no known systems as of 960211) */
+
+/*********************/
+/* Function memset() */
+/*********************/
+
+zvoid *memset(buf, init, len)
+ register zvoid *buf; /* buffer location */
+ register int init; /* initializer character */
+ register unsigned int len; /* length of the buffer */
+{
+ zvoid *start;
+
+ start = buf;
+ while (len--)
+ *((char *)buf++) = (char)init;
+ return start;
+}
+
+
+
+/*********************/
+/* Function memcmp() */
+/*********************/
+
+int memcmp(b1, b2, len)
+ register ZCONST zvoid *b1;
+ register ZCONST zvoid *b2;
+ register unsigned int len;
+{
+ register int c;
+
+ if (len > 0) do {
+ if ((c = (int)(*((ZCONST unsigned char *)b1)++) -
+ (int)(*((ZCONST unsigned char *)b2)++)) != 0)
+ return c;
+ } while (--len > 0)
+ return 0;
+}
+
+
+
+/*********************/
+/* Function memcpy() */
+/*********************/
+
+zvoid *memcpy(dst, src, len)
+ register zvoid *dst;
+ register ZCONST zvoid *src;
+ register unsigned int len;
+{
+ zvoid *start;
+
+ start = dst;
+ while (len-- > 0)
+ *((char *)dst)++ = *((ZCONST char *)src)++;
+ return start;
+}
+
+#endif /* ZMEM */
+
+
+
+
+
+/************************/
+/* Function zstrnicmp() */
+/************************/
+
+int zstrnicmp(s1, s2, n)
+ register ZCONST char *s1, *s2;
+ register unsigned n;
+{
+ for (; n > 0; --n, ++s1, ++s2) {
+
+ if (ToLower(*s1) != ToLower(*s2))
+ /* test includes early termination of one string */
+ return (ToLower(*s1) < ToLower(*s2))? -1 : 1;
+
+ if (*s1 == '\0') /* both strings terminate early */
+ return 0;
+ }
+ return 0;
+}
+
+
+
+
+
+#ifdef REGULUS /* returns the inode number on success(!)...argh argh argh */
+# undef stat
+
+/********************/
+/* Function zstat() */
+/********************/
+
+int zstat(p, s)
+ char *p;
+ struct stat *s;
+{
+ return (stat(p,s) >= 0? 0 : (-1));
+}
+
+#endif /* REGULUS */
+
+
+
+
+
+#ifdef SMALL_MEM
+
+/*******************************/
+/* Function fLoadFarString() */ /* (and friends...) */
+/*******************************/
+
+char *fLoadFarString(__GPRO__ const char Far *sz)
+{
+ (void)zfstrcpy(G.rgchBigBuffer, sz);
+ return G.rgchBigBuffer;
+}
+
+char *fLoadFarStringSmall(__GPRO__ const char Far *sz)
+{
+ (void)zfstrcpy(G.rgchSmallBuffer, sz);
+ return G.rgchSmallBuffer;
+}
+
+char *fLoadFarStringSmall2(__GPRO__ const char Far *sz)
+{
+ (void)zfstrcpy(G.rgchSmallBuffer2, sz);
+ return G.rgchSmallBuffer2;
+}
+
+
+
+
+#if (!defined(_MSC_VER) || (_MSC_VER < 600))
+/*************************/
+/* Function zfstrcpy() */ /* portable clone of _fstrcpy() */
+/*************************/
+
+char Far * Far zfstrcpy(char Far *s1, const char Far *s2)
+{
+ char Far *p = s1;
+
+ while ((*s1++ = *s2++) != '\0');
+ return p;
+}
+#endif /* !_MSC_VER || (_MSC_VER < 600) */
+
+#endif /* SMALL_MEM */
diff --git a/Build/source/libs/unzip/globals.c b/Build/source/libs/unzip/globals.c
new file mode 100644
index 00000000000..d795090b983
--- /dev/null
+++ b/Build/source/libs/unzip/globals.c
@@ -0,0 +1,204 @@
+/*---------------------------------------------------------------------------
+
+ globals.c
+
+ Routines to allocate and initialize globals, with or without threads.
+
+ Contents: registerGlobalPointer()
+ deregisterGlobalPointer()
+ getGlobalPointer()
+ globalsCtor()
+
+ ---------------------------------------------------------------------------*/
+
+
+#define UNZIP_INTERNAL
+#include "unzip.h"
+
+#ifndef FUNZIP
+/* initialization of sigs is completed at runtime so unzip(sfx) executable
+ * won't look like a zipfile
+ */
+char central_hdr_sig[4] = {0, 0, 0x01, 0x02};
+char local_hdr_sig[4] = {0, 0, 0x03, 0x04};
+char end_central_sig[4] = {0, 0, 0x05, 0x06};
+/* extern char extd_local_sig[4] = {0, 0, 0x07, 0x08}; NOT USED YET */
+
+ZCONST char *fnames[2] = {"*", NULL}; /* default filenames vector */
+#endif
+
+
+#ifndef REENTRANT
+ Uz_Globs G;
+#else /* REENTRANT */
+
+# ifndef USETHREADID
+ Uz_Globs *GG;
+# else /* USETHREADID */
+# define THREADID_ENTRIES 0x40
+
+ int lastScan;
+ Uz_Globs *threadPtrTable[THREADID_ENTRIES];
+ ulg threadIdTable [THREADID_ENTRIES] = {
+ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
+ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* Make sure there are */
+ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* THREADID_ENTRIES 0s */
+ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0
+ };
+
+ static ZCONST char Far TooManyThreads[] =
+ "error: more than %d simultaneous threads.\n\
+ Some threads are probably not calling DESTROYTHREAD()\n";
+ static ZCONST char Far EntryNotFound[] =
+ "error: couldn't find global pointer in table.\n\
+ Maybe somebody accidentally called DESTROYTHREAD() twice.\n";
+ static ZCONST char Far GlobalPointerMismatch[] =
+ "error: global pointer in table does not match pointer passed as\
+ parameter\n";
+
+static void registerGlobalPointer OF((__GPRO));
+
+
+
+static void registerGlobalPointer(__G)
+ __GDEF
+{
+ int scan=0;
+ ulg tid = GetThreadId();
+
+ while (threadIdTable[scan] && scan < THREADID_ENTRIES)
+ scan++;
+
+ if (scan == THREADID_ENTRIES) {
+ ZCONST char *tooMany = LoadFarString(TooManyThreads);
+ Info(slide, 0x421, ((char *)slide, tooMany, THREADID_ENTRIES));
+ free(pG);
+ EXIT(PK_MEM); /* essentially memory error before we've started */
+ }
+
+ threadIdTable [scan] = tid;
+ threadPtrTable[scan] = pG;
+ lastScan = scan;
+}
+
+
+
+void deregisterGlobalPointer(__G)
+ __GDEF
+{
+ int scan=0;
+ ulg tid = GetThreadId();
+
+
+ while (threadIdTable[scan] != tid && scan < THREADID_ENTRIES)
+ scan++;
+
+/*---------------------------------------------------------------------------
+ There are two things we can do if we can't find the entry: ignore it or
+ scream. The most likely reason for it not to be here is the user calling
+ this routine twice. Since this could cause BIG problems if any globals
+ are accessed after the first call, we'd better scream.
+ ---------------------------------------------------------------------------*/
+
+ if (scan == THREADID_ENTRIES || threadPtrTable[scan] != pG) {
+ ZCONST char *noEntry;
+ if (scan == THREADID_ENTRIES)
+ noEntry = LoadFarString(EntryNotFound);
+ else
+ noEntry = LoadFarString(GlobalPointerMismatch);
+ Info(slide, 0x421, ((char *)slide, noEntry));
+ EXIT(PK_WARN); /* programming error, but after we're all done */
+ }
+
+ threadIdTable [scan] = 0;
+ lastScan = scan;
+ free(threadPtrTable[scan]);
+}
+
+
+
+Uz_Globs *getGlobalPointer()
+{
+ int scan=0;
+ ulg tid = GetThreadId();
+
+ while (threadIdTable[scan] != tid && scan < THREADID_ENTRIES)
+ scan++;
+
+/*---------------------------------------------------------------------------
+ There are two things we can do if we can't find the entry: ignore it or
+ scream. The most likely reason for it not to be here is the user calling
+ this routine twice. Since this could cause BIG problems if any globals
+ are accessed after the first call, we'd better scream.
+ ---------------------------------------------------------------------------*/
+
+ if (scan == THREADID_ENTRIES) {
+ ZCONST char *noEntry = LoadFarString(EntryNotFound);
+ fprintf(stderr, noEntry); /* can't use Info w/o a global pointer */
+ EXIT(PK_ERR); /* programming error while still working */
+ }
+
+ return threadPtrTable[scan];
+}
+
+# endif /* ?USETHREADID */
+#endif /* ?REENTRANT */
+
+
+
+Uz_Globs *globalsCtor()
+{
+#ifdef REENTRANT
+ Uz_Globs *pG = (Uz_Globs *)malloc(sizeof(Uz_Globs));
+
+ if (!pG)
+ return (Uz_Globs *)NULL;
+#endif /* REENTRANT */
+
+ /* for REENTRANT version, G is defined as (*pG) */
+
+ memzero(&G, sizeof(Uz_Globs));
+
+#ifndef FUNZIP
+#ifdef CMS_MVS
+ uO.aflag=1;
+ uO.C_flag=1;
+#endif
+
+ uO.lflag=(-1);
+ G.wildzipfn = "";
+ G.pfnames = (char **)fnames;
+ G.pxnames = (char **)&fnames[1];
+ G.pInfo = G.info;
+ G.sol = TRUE; /* at start of line */
+
+ G.message = UzpMessagePrnt;
+ G.input = UzpInput; /* not used by anyone at the moment... */
+#if defined(WINDLL) || defined(MACOS)
+ G.mpause = NULL; /* has scrollbars: no need for pausing */
+#else
+ G.mpause = UzpMorePause;
+#endif
+ G.decr_passwd = UzpPassword;
+#endif /* !FUNZIP */
+
+#if (!defined(DOS_FLX_H68_OS2_W32) && !defined(AMIGA) && !defined(RISCOS))
+#if (!defined(MACOS) && !defined(ATARI) && !defined(VMS))
+ G.echofd = -1;
+#endif /* !(MACOS || ATARI || VMS) */
+#endif /* !(DOS_FLX_H68_OS2_W32 || AMIGA || RISCOS) */
+
+#ifdef SYSTEM_SPECIFIC_CTOR
+ SYSTEM_SPECIFIC_CTOR(__G);
+#endif
+
+#ifdef REENTRANT
+#ifdef USETHREADID
+ registerGlobalPointer(__G);
+#else
+ GG = &G;
+#endif /* ?USETHREADID */
+#endif /* REENTRANT */
+
+ return &G;
+}
diff --git a/Build/source/libs/unzip/globals.h b/Build/source/libs/unzip/globals.h
new file mode 100644
index 00000000000..49439cffe7f
--- /dev/null
+++ b/Build/source/libs/unzip/globals.h
@@ -0,0 +1,395 @@
+/*---------------------------------------------------------------------------
+
+ globals.h
+
+ There is usually no need to include this file since unzip.h includes it.
+
+ This header file is used by all of the UnZip source files. It contains
+ a struct definition that is used to "house" all of the global variables.
+ This is done to allow for multithreaded environments (OS/2, NT, Win95,
+ Unix) to call UnZip through an API without a semaphore. REENTRANT should
+ be defined for all platforms that require this.
+
+ GLOBAL CONSTRUCTOR AND DESTRUCTOR (API WRITERS READ THIS!!!)
+ ------------------------------------------------------------
+
+ No, it's not C++, but it's as close as we can get with K&R.
+
+ The main() of each process that uses these globals must include the
+ CONSTRUCTGLOBALS; statement. This will malloc enough memory for the
+ structure and initialize any variables that require it. This must
+ also be done by any API function that jumps into the middle of the
+ code.
+
+ The DESTROYGLOBALS; statement should be inserted before EVERY "EXIT(n)".
+ Naturally, it also needs to be put before any API returns as well.
+ In fact, it's much more important in API functions since the process
+ will NOT end, and therefore the memory WON'T automatically be freed
+ by the operating system.
+
+ USING VARIABLES FROM THE STRUCTURE
+ ----------------------------------
+
+ All global variables must now be prefixed with `G.' which is either a
+ global struct (in which case it should be the only global variable) or
+ a macro for the value of a local pointer variable that is passed from
+ function to function. Yes, this is a pain. But it's the only way to
+ allow full reentrancy.
+
+ ADDING VARIABLES TO THE STRUCTURE
+ ---------------------------------
+
+ If you make the inclusion of any variables conditional, be sure to only
+ check macros that are GUARANTEED to be included in every module.
+ For instance, newzip and pwdarg are needed only if CRYPT is TRUE,
+ but this is defined after unzip.h has been read. If you are not careful,
+ some modules will expect your variable to be part of this struct while
+ others won't. This will cause BIG problems. (Inexplicable crashes at
+ strange times, car fires, etc.) When in doubt, always include it!
+
+ Note also that UnZipSFX needs a few variables that UnZip doesn't. However,
+ it also includes some object files from UnZip. If we were to conditionally
+ include the extra variables that UnZipSFX needs, the object files from
+ UnZip would not mesh with the UnZipSFX object files. Result: we just
+ include the UnZipSFX variables every time. (It's only an extra 4 bytes
+ so who cares!)
+
+ ADDING FUNCTIONS
+ ----------------
+
+ To support this new global struct, all functions must now conditionally
+ pass the globals pointer (pG) to each other. This is supported by 5 macros:
+ __GPRO, __GPRO__, __G, __G__ and __GDEF. A function that needs no other
+ parameters would look like this:
+
+ int extract_or_test_files(__G)
+ __GDEF
+ {
+ ... stuff ...
+ }
+
+ A function with other parameters would look like:
+
+ int memextract(__G__ tgt, tgtsize, src, srcsize)
+ __GDEF
+ uch *tgt, *src;
+ ulg tgtsize, srcsize;
+ {
+ ... stuff ...
+ }
+
+ In the Function Prototypes section of unzpriv.h, you should use __GPRO and
+ __GPRO__ instead:
+
+ int uz_opts OF((__GPRO__ int *pargc, char ***pargv));
+ int process_zipfiles OF((__GPRO));
+
+ Note that there is NO comma after __G__ or __GPRO__ and no semi-colon after
+ __GDEF. I wish there was another way but I don't think there is.
+
+
+ TESTING THE CODE
+ -----------------
+
+ Whether your platform requires reentrancy or not, you should always try
+ building with REENTRANT defined if any functions have been added. It is
+ pretty easy to forget a __G__ or a __GDEF and this mistake will only show
+ up if REENTRANT is defined. All platforms should run with REENTRANT
+ defined. Platforms that can't take advantage of it will just be paying
+ a performance penalty needlessly.
+
+ SIGNAL MADNESS
+ --------------
+
+ This whole pointer passing scheme falls apart when it comes to SIGNALs.
+ I handle this situation 2 ways right now. If you define USETHREADID,
+ UnZip will include a 64-entry table. Each entry can hold a global
+ pointer and thread ID for one thread. This should allow up to 64
+ threads to access UnZip simultaneously. Calling DESTROYGLOBALS()
+ will free the global struct and zero the table entry. If somebody
+ forgets to call DESTROYGLOBALS(), this table will eventually fill up
+ and UnZip will exit with an error message. A good way to test your
+ code to make sure you didn't forget a DESTROYGLOBALS() is to change
+ THREADID_ENTRIES to 3 or 4 in globals.c, making the table real small.
+ Then make a small test program that calls your API a dozen times.
+
+ Those platforms that don't have threads still need to be able to compile
+ with REENTRANT defined to test and see if new code is correctly written
+ to work either way. For these platforms, I simply keep a global pointer
+ called GG that points to the Globals structure. Good enough for testing.
+
+ I believe that NT has thread level storage. This could probably be used
+ to store a global pointer for the sake of the signal handler more cleanly
+ than my table approach.
+
+ ---------------------------------------------------------------------------*/
+
+#ifndef __globals_h
+#define __globals_h
+
+#ifdef USE_ZLIB
+# include "zlib.h"
+#endif
+
+
+/*************/
+/* Globals */
+/*************/
+
+typedef struct Globals {
+#ifdef DLL
+ zvoid *callerglobs; /* pointer to structure of pass-through global vars */
+#endif
+
+ /* command options of general use */
+ UzpOpts UzO; /* command options of general use */
+
+#ifndef FUNZIP
+ /* command options specific to the high level command line interface */
+#ifdef MORE
+ int M_flag; /* -M: built-in "more" function */
+#endif
+
+ /* internal flags and general globals */
+#ifdef MORE
+ int height; /* check for SIGWINCH, etc., eventually... */
+#endif /* (take line-wrapping into account?) */
+#if (defined(IZ_CHECK_TZ) && defined(USE_EF_UT_TIME))
+ int tz_is_valid; /* indicates that timezone info can be used */
+#endif
+#ifdef WINDLL
+ int prompt_always; /* prompt to overwrite if TRUE */
+#endif
+ int noargs; /* did true command line have *any* arguments? */
+ unsigned filespecs; /* number of real file specifications to be matched */
+ unsigned xfilespecs; /* number of excluded filespecs to be matched */
+ int process_all_files;
+ int create_dirs; /* used by main(), mapname(), checkdir() */
+ int extract_flag;
+ int newzip; /* reset in extract.c; used in crypt.c */
+ LONGINT real_ecrec_offset;
+ LONGINT expect_ecrec_offset;
+ long csize; /* used by decompr. (NEXTBYTE): must be signed */
+ long ucsize; /* used by unReduce(), explode() */
+ long used_csize; /* used by extract_or_test_member(), explode() */
+
+#ifdef DLL
+ int fValidate; /* true if only validating an archive */
+ int filenotfound;
+ int redirect_data; /* redirect data to memory buffer */
+ int redirect_text; /* redirect text output to buffer */
+# ifndef NO_SLIDE_REDIR
+ int redirect_slide; /* redirect decompression area to mem buffer */
+ unsigned _wsize;
+# endif
+ unsigned redirect_size; /* size of redirected output buffer */
+ uch *redirect_buffer; /* pointer to head of allocated buffer */
+ uch *redirect_pointer; /* pointer past end of written data */
+# ifndef NO_SLIDE_REDIR
+ uch *redirect_sldptr; /* head of decompression slide buffer */
+# endif
+# ifdef OS2DLL
+ cbList(processExternally); /* call-back list */
+# endif
+#endif /* DLL */
+
+ char **pfnames;
+ char **pxnames;
+ char sig[4];
+ char answerbuf[10];
+ min_info info[DIR_BLKSIZ];
+ min_info *pInfo;
+#endif /* !FUNZIP */
+ union work area; /* see unzpriv.h for definition of work */
+
+#ifndef FUNZIP
+# if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB))
+ ZCONST ulg near *crc_32_tab;
+# else
+ ZCONST ulg Far *crc_32_tab;
+# endif
+#endif
+ ulg crc32val; /* CRC shift reg. (was static in funzip) */
+
+#ifdef FUNZIP
+ FILE *in; /* file descriptor of compressed stream */
+#endif
+ uch *inbuf; /* input buffer (any size is OK) */
+ uch *inptr; /* pointer into input buffer */
+ int incnt;
+
+#ifndef FUNZIP
+ ulg bitbuf;
+ int bits_left; /* unreduce and unshrink only */
+ int zipeof;
+ char *argv0; /* used for NT and EXE_EXTENSION */
+ char *wildzipfn;
+ char *zipfn; /* GRR: WINDLL: must nuke any malloc'd zipfn... */
+#ifdef USE_STRM_INPUT
+ FILE *zipfd; /* zipfile file descriptor */
+#else
+ int zipfd; /* zipfile file handle */
+#endif
+ LONGINT ziplen;
+ LONGINT cur_zipfile_bufstart; /* extract_or_test, readbuf, ReadByte */
+ LONGINT extra_bytes; /* used in unzip.c, misc.c */
+ uch *extra_field; /* Unix, VMS, Mac, OS/2, Acorn, ... */
+ uch *hold;
+
+ local_file_hdr lrec; /* used in unzip.c, extract.c */
+ cdir_file_hdr crec; /* used in unzip.c, extract.c, misc.c */
+ ecdir_rec ecrec; /* used in unzip.c, extract.c */
+ struct stat statbuf; /* used by main, mapname, check_for_newer */
+
+ int mem_mode;
+ uch *outbufptr; /* extract.c static */
+ ulg outsize; /* extract.c static */
+ int reported_backslash; /* extract.c static */
+ int disk_full;
+ int newfile;
+
+ int didCRlast; /* fileio static */
+ ulg numlines; /* fileio static: number of lines printed */
+ int sol; /* fileio static: at start of line */
+ int no_ecrec; /* process static */
+#ifdef SYMLINKS
+ int symlnk;
+#endif
+#ifdef NOVELL_BUG_FAILSAFE
+ int dne; /* true if stat() says file doesn't exist */
+#endif
+
+ FILE *outfile;
+ uch *outbuf;
+ uch *realbuf;
+
+#ifndef VMS /* if SMALL_MEM, outbuf2 is initialized in */
+ uch *outbuf2; /* process_zipfiles() (never changes); */
+#endif /* else malloc'd ONLY if unshrink and -a */
+#endif /* !FUNZIP */
+ uch *outptr;
+ ulg outcnt; /* number of chars stored in outbuf */
+#ifndef FUNZIP
+ char filename[FILNAMSIZ]; /* also used by NT for temporary SFX path */
+
+#ifdef CMS_MVS
+ char *tempfn; /* temp file used; erase on close */
+#endif
+
+ char *key; /* crypt static: decryption password or NULL */
+ int nopwd; /* crypt static */
+#endif /* !FUNZIP */
+ ulg keys[3]; /* crypt static: keys defining pseudo-random sequence */
+
+#if (!defined(DOS_FLX_H68_OS2_W32) && !defined(AMIGA) && !defined(RISCOS))
+#if (!defined(MACOS) && !defined(ATARI) && !defined(VMS))
+ int echofd; /* ttyio static: file descriptor whose echo is off */
+#endif /* !(MACOS || ATARI || VMS) */
+#endif /* !(DOS_FLX_H68_OS2_W32 || AMIGA || RISCOS) */
+
+ unsigned hufts; /* track memory usage */
+
+#ifdef USE_ZLIB
+ int inflInit; /* inflate static: zlib inflate() initialized */
+ z_stream dstrm; /* inflate global: decompression stream */
+#else
+ struct huft *fixed_tl; /* inflate static */
+ struct huft *fixed_td; /* inflate static */
+ int fixed_bl, fixed_bd; /* inflate static */
+ unsigned wp; /* inflate static: current position in slide */
+ ulg bb; /* inflate static: bit buffer */
+ unsigned bk; /* inflate static: bits in bit buffer */
+#endif /* ?USE_ZLIB */
+
+#ifndef FUNZIP
+#ifdef SMALL_MEM
+ char rgchBigBuffer[512];
+ char rgchSmallBuffer[96];
+ char rgchSmallBuffer2[160]; /* boosted to 160 for local3[] in unzip.c */
+#endif
+
+ MsgFn *message;
+ InputFn *input;
+ PauseFn *mpause;
+ PasswdFn *decr_passwd;
+ StatCBFn *statreportcb;
+#ifdef WINDLL
+ LPUSERFUNCTIONS lpUserFunctions;
+#endif
+
+ int incnt_leftover; /* so improved NEXTBYTE does not waste input */
+ uch *inptr_leftover;
+
+#ifdef VMS_TEXT_CONV
+ int VMS_line_state; /* so native VMS variable-length text files are */
+ int VMS_line_length; /* readable on other platforms */
+ int VMS_line_pad;
+#endif
+#endif /* !FUNZIP */
+
+#ifdef SYSTEM_SPECIFIC_GLOBALS
+ SYSTEM_SPECIFIC_GLOBALS
+#endif
+
+} Uz_Globs; /* end of struct Globals */
+
+
+/***************************************************************************/
+
+
+#ifdef FUNZIP
+# if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB))
+ extern ZCONST ulg near crc_32_tab[256];
+# else
+ extern ZCONST ulg Far *crc_32_tab;
+# endif
+# define CRC_32_TAB crc_32_tab
+#else
+# define CRC_32_TAB G.crc_32_tab
+#endif
+
+
+Uz_Globs *globalsCtor OF((void));
+
+/* pseudo constant sigs; they are initialized at runtime so unzip executable
+ * won't look like a zipfile
+ */
+extern char local_hdr_sig[4];
+extern char central_hdr_sig[4];
+extern char end_central_sig[4];
+/* extern char extd_local_sig[4]; NOT USED YET */
+
+#ifdef REENTRANT
+# define G (*(Uz_Globs *)pG)
+# define __G pG
+# define __G__ pG,
+# define __GPRO Uz_Globs *pG
+# define __GPRO__ Uz_Globs *pG,
+# define __GDEF Uz_Globs *pG;
+# ifdef USETHREADID
+ extern int lastScan;
+ void deregisterGlobalPointer OF((__GPRO));
+ Uz_Globs *getGlobalPointer OF((void));
+# define GETGLOBALS() Uz_Globs *pG = getGlobalPointer();
+# define DESTROYGLOBALS() {free_G_buffers(pG); deregisterGlobalPointer(pG);}
+# else
+ extern Uz_Globs *GG;
+# define GETGLOBALS() Uz_Globs *pG = GG;
+# define DESTROYGLOBALS() {free_G_buffers(pG); free(pG);}
+# endif /* ?USETHREADID */
+# define CONSTRUCTGLOBALS() Uz_Globs *pG = globalsCtor()
+#else /* !REENTRANT */
+ extern Uz_Globs G;
+# define __G
+# define __G__
+# define __GPRO void
+# define __GPRO__
+# define __GDEF
+# define GETGLOBALS()
+# define CONSTRUCTGLOBALS() globalsCtor()
+# define DESTROYGLOBALS()
+#endif /* ?REENTRANT */
+
+#define uO G.UzO
+
+#endif /* __globals_h */
diff --git a/Build/source/libs/unzip/inflate.c b/Build/source/libs/unzip/inflate.c
new file mode 100644
index 00000000000..93913f15e05
--- /dev/null
+++ b/Build/source/libs/unzip/inflate.c
@@ -0,0 +1,1305 @@
+/* inflate.c -- put in the public domain by Mark Adler
+ version c16b, 29 March 1998 */
+
+
+/* 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
+ ---- --------- -------------- ------------------------------------
+ a ~~ Feb 92 M. Adler used full (large, one-step) lookup table
+ b1 21 Mar 92 M. Adler first version with partial lookup tables
+ b2 21 Mar 92 M. Adler fixed bug in fixed-code blocks
+ b3 22 Mar 92 M. Adler sped up match copies, cleaned up some
+ b4 25 Mar 92 M. Adler added prototypes; removed window[] (now
+ is the responsibility of unzip.h--also
+ changed name to slide[]), so needs diffs
+ for unzip.c and unzip.h (this allows
+ compiling in the small model on MSDOS);
+ fixed cast of q in huft_build();
+ b5 26 Mar 92 M. Adler got rid of unintended macro recursion.
+ b6 27 Mar 92 M. Adler got rid of nextbyte() routine. fixed
+ bug in inflate_fixed().
+ c1 30 Mar 92 M. Adler removed lbits, dbits environment variables.
+ changed BMAX to 16 for explode. Removed
+ OUTB usage, and replaced it with flush()--
+ this was a 20% speed improvement! Added
+ an explode.c (to replace unimplod.c) that
+ uses the huft routines here. Removed
+ register union.
+ c2 4 Apr 92 M. Adler fixed bug for file sizes a multiple of 32k.
+ c3 10 Apr 92 M. Adler reduced memory of code tables made by
+ huft_build significantly (factor of two to
+ three).
+ c4 15 Apr 92 M. Adler added NOMEMCPY do kill use of memcpy().
+ worked around a Turbo C optimization bug.
+ c5 21 Apr 92 M. Adler added the WSIZE #define to allow reducing
+ the 32K window size for specialized
+ applications.
+ c6 31 May 92 M. Adler added some typecasts to eliminate warnings
+ c7 27 Jun 92 G. Roelofs added some more typecasts (444: MSC bug).
+ c8 5 Oct 92 J-l. Gailly added ifdef'd code to deal with PKZIP bug.
+ c9 9 Oct 92 M. Adler removed a memory error message (~line 416).
+ c10 17 Oct 92 G. Roelofs changed ULONG/UWORD/byte to ulg/ush/uch,
+ removed old inflate, renamed inflate_entry
+ to inflate, added Mark's fix to a comment.
+ c10.5 14 Dec 92 M. Adler fix up error messages for incomplete trees.
+ c11 2 Jan 93 M. Adler fixed bug in detection of incomplete
+ tables, and removed assumption that EOB is
+ the longest code (bad assumption).
+ c12 3 Jan 93 M. Adler make tables for fixed blocks only once.
+ c13 5 Jan 93 M. Adler allow all zero length codes (pkzip 2.04c
+ outputs one zero length code for an empty
+ distance tree).
+ c14 12 Mar 93 M. Adler made inflate.c standalone with the
+ introduction of inflate.h.
+ c14b 16 Jul 93 G. Roelofs added (unsigned) typecast to w at 470.
+ c14c 19 Jul 93 J. Bush changed v[N_MAX], l[288], ll[28x+3x] arrays
+ to static for Amiga.
+ c14d 13 Aug 93 J-l. Gailly de-complicatified Mark's c[*p++]++ thing.
+ c14e 8 Oct 93 G. Roelofs changed memset() to memzero().
+ c14f 22 Oct 93 G. Roelofs renamed quietflg to qflag; made Trace()
+ conditional; added inflate_free().
+ c14g 28 Oct 93 G. Roelofs changed l/(lx+1) macro to pointer (Cray bug)
+ c14h 7 Dec 93 C. Ghisler huft_build() optimizations.
+ c14i 9 Jan 94 A. Verheijen set fixed_t{d,l} to NULL after freeing;
+ G. Roelofs check NEXTBYTE macro for EOF.
+ c14j 23 Jan 94 G. Roelofs removed Ghisler "optimizations"; ifdef'd
+ EOF check.
+ c14k 27 Feb 94 G. Roelofs added some typecasts to avoid warnings.
+ c14l 9 Apr 94 G. Roelofs fixed split comments on preprocessor lines
+ to avoid bug in Encore compiler.
+ c14m 7 Jul 94 P. Kienitz modified to allow assembler version of
+ inflate_codes() (define ASM_INFLATECODES)
+ c14n 22 Jul 94 G. Roelofs changed fprintf to macro for DLL versions
+ c14o 23 Aug 94 C. Spieler added a newline to a debug statement;
+ G. Roelofs added another typecast to avoid MSC warning
+ c14p 4 Oct 94 G. Roelofs added (voidp *) cast to free() argument
+ c14q 30 Oct 94 G. Roelofs changed fprintf macro to MESSAGE()
+ c14r 1 Nov 94 G. Roelofs fixed possible redefinition of CHECK_EOF
+ c14s 7 May 95 S. Maxwell OS/2 DLL globals stuff incorporated;
+ P. Kienitz "fixed" ASM_INFLATECODES macro/prototype
+ c14t 18 Aug 95 G. Roelofs added UZinflate() to use zlib functions;
+ changed voidp to zvoid; moved huft_build()
+ and huft_free() to end of file
+ c14u 1 Oct 95 G. Roelofs moved G into definition of MESSAGE macro
+ c14v 8 Nov 95 P. Kienitz changed ASM_INFLATECODES to use a regular
+ call with __G__ instead of a macro
+ c15 3 Aug 96 M. Adler fixed bomb-bug on random input data (Adobe)
+ c15b 24 Aug 96 M. Adler more fixes for random input data
+ c15c 28 Mar 97 G. Roelofs changed USE_ZLIB fatal exit code from
+ PK_MEM2 to PK_MEM3
+ c16 20 Apr 97 J. Altman added memzero(v[]) in huft_build()
+ c16b 29 Mar 98 C. Spieler modified DLL code for slide redirection
+ */
+
+
+/*
+ Inflate deflated (PKZIP's method 8 compressed) data. The compression
+ method searches for as much of the current string of bytes (up to a
+ length of 258) in the previous 32K bytes. If it doesn't find any
+ matches (of at least length 3), it codes the next byte. Otherwise, it
+ codes the length of the matched string and its distance backwards from
+ the current position. There is a single Huffman code that codes both
+ single bytes (called "literals") and match lengths. A second Huffman
+ code codes the distance information, which follows a length code. Each
+ length or distance code actually represents a base value and a number
+ of "extra" (sometimes zero) bits to get to add to the base value. At
+ the end of each deflated block is a special end-of-block (EOB) literal/
+ length code. The decoding process is basically: get a literal/length
+ code; if EOB then done; if a literal, emit the decoded byte; if a
+ length then get the distance and emit the referred-to bytes from the
+ sliding window of previously emitted data.
+
+ There are (currently) three kinds of inflate blocks: stored, fixed, and
+ dynamic. The compressor outputs a chunk of data at a time and decides
+ which method to use on a chunk-by-chunk basis. A chunk might typically
+ be 32K to 64K, uncompressed. If the chunk is uncompressible, then the
+ "stored" method is used. In this case, the bytes are simply stored as
+ is, eight bits per byte, with none of the above coding. The bytes are
+ preceded by a count, since there is no longer an EOB code.
+
+ If the data are compressible, then either the fixed or dynamic methods
+ are used. In the dynamic method, the compressed data are preceded by
+ an encoding of the literal/length and distance Huffman codes that are
+ to be used to decode this block. The representation is itself Huffman
+ coded, and so is preceded by a description of that code. These code
+ descriptions take up a little space, and so for small blocks, there is
+ a predefined set of codes, called the fixed codes. The fixed method is
+ used if the block ends up smaller that way (usually for quite small
+ chunks); otherwise the dynamic method is used. In the latter case, the
+ codes are customized to the probabilities in the current block and so
+ can code it much better than the pre-determined fixed codes can.
+
+ The Huffman codes themselves are decoded using a multi-level table
+ lookup, in order to maximize the speed of decoding plus the speed of
+ building the decoding tables. See the comments below that precede the
+ lbits and dbits tuning parameters.
+
+ GRR: return values(?)
+ 0 OK
+ 1 incomplete table
+ 2 bad input
+ 3 not enough memory
+ */
+
+
+/*
+ Notes beyond the 1.93a appnote.txt:
+
+ 1. Distance pointers never point before the beginning of the output
+ stream.
+ 2. Distance pointers can point back across blocks, up to 32k away.
+ 3. There is an implied maximum of 7 bits for the bit length table and
+ 15 bits for the actual data.
+ 4. If only one code exists, then it is encoded using one bit. (Zero
+ would be more efficient, but perhaps a little confusing.) If two
+ codes exist, they are coded using one bit each (0 and 1).
+ 5. There is no way of sending zero distance codes--a dummy must be
+ sent if there are none. (History: a pre 2.0 version of PKZIP would
+ store blocks with no distance codes, but this was discovered to be
+ too harsh a criterion.) Valid only for 1.93a. 2.04c does allow
+ zero distance codes, which is sent as one code of zero bits in
+ length.
+ 6. There are up to 286 literal/length codes. Code 256 represents the
+ end-of-block. Note however that the static length tree defines
+ 288 codes just to fill out the Huffman codes. Codes 286 and 287
+ cannot be used though, since there is no length base or extra bits
+ defined for them. Similarily, there are up to 30 distance codes.
+ However, static trees define 32 codes (all 5 bits) to fill out the
+ Huffman codes, but the last two had better not show up in the data.
+ 7. Unzip can check dynamic Huffman blocks for complete code sets.
+ The exception is that a single code would not be complete (see #4).
+ 8. The five bits following the block type is really the number of
+ literal codes sent minus 257.
+ 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
+ (1+6+6). Therefore, to output three times the length, you output
+ three codes (1+1+1), whereas to output four times the same length,
+ you only need two codes (1+3). Hmm.
+ 10. In the tree reconstruction algorithm, Code = Code + Increment
+ only if BitLength(i) is not zero. (Pretty obvious.)
+ 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19)
+ 12. Note: length code 284 can represent 227-258, but length code 285
+ really is 258. The last length deserves its own, short code
+ since it gets used a lot in very redundant files. The length
+ 258 is special since 258 - 3 (the min match length) is 255.
+ 13. The literal/length and distance code bit lengths are read as a
+ single stream of lengths. It is possible (and advantageous) for
+ a repeat code (16, 17, or 18) to go across the boundary between
+ the two sets of lengths.
+ */
+
+
+#define PKZIP_BUG_WORKAROUND /* PKZIP 1.93a problem--live with it */
+
+/*
+ inflate.h must supply the uch slide[WSIZE] array, the zvoid typedef
+ (void if (void *) is accepted, else char) and the NEXTBYTE,
+ FLUSH() and memzero macros. If the window size is not 32K, it
+ should also define WSIZE. If INFMOD is defined, it can include
+ compiled functions to support the NEXTBYTE and/or FLUSH() macros.
+ There are defaults for NEXTBYTE and FLUSH() below for use as
+ examples of what those functions need to do. Normally, you would
+ also want FLUSH() to compute a crc on the data. inflate.h also
+ needs to provide these typedefs:
+
+ typedef unsigned char uch;
+ typedef unsigned short ush;
+ typedef unsigned long ulg;
+
+ This module uses the external functions malloc() and free() (and
+ probably memset() or bzero() in the memzero() macro). Their
+ prototypes are normally found in <string.h> and <stdlib.h>.
+ */
+
+/* #define DEBUG */
+#define INFMOD /* tell inflate.h to include code to be compiled */
+#include "inflate.h"
+
+
+#ifndef WSIZE /* default is 32K */
+# define WSIZE 0x8000 /* window size--must be a power of two, and at least */
+#endif /* 32K for zip's deflate method */
+
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+# define wsize G._wsize /* wsize is a variable */
+#else
+# define wsize WSIZE /* wsize is a constant */
+#endif
+
+
+#ifndef NEXTBYTE /* default is to simply get a byte from stdin */
+# define NEXTBYTE getchar()
+#endif
+
+#ifndef MESSAGE /* only used twice, for fixed strings--NOT general-purpose */
+# define MESSAGE(str,len,flag) fprintf(stderr,(char *)(str))
+#endif
+
+#ifndef FLUSH /* default is to simply write the buffer to stdout */
+# define FLUSH(n) fwrite(redirSlide, 1, n, stdout) /* return value not used */
+#endif
+/* Warning: the fwrite above might not work on 16-bit compilers, since
+ 0x8000 might be interpreted as -32,768 by the library function. */
+
+#ifndef Trace
+# ifdef DEBUG
+# define Trace(x) fprintf x
+# else
+# define Trace(x)
+# endif
+#endif
+
+
+/*---------------------------------------------------------------------------*/
+#ifdef USE_ZLIB
+
+
+/*
+ GRR: return values for both original inflate() and UZinflate()
+ 0 OK
+ 1 incomplete table(?)
+ 2 bad input
+ 3 not enough memory
+ */
+
+/**************************/
+/* Function UZinflate() */
+/**************************/
+
+int UZinflate(__G) /* decompress an inflated entry using the zlib routines */
+ __GDEF
+{
+ int err=Z_OK;
+
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+ if (G.redirect_slide)
+ wsize = G.redirect_size, redirSlide = G.redirect_buffer;
+ else
+ wsize = WSIZE, redirSlide = slide;
+#endif
+
+ G.dstrm.next_out = redirSlide;
+ G.dstrm.avail_out = wsize;
+
+ G.dstrm.next_in = G.inptr;
+ G.dstrm.avail_in = G.incnt;
+
+ if (!G.inflInit) {
+ unsigned i;
+ int windowBits;
+
+ /* only need to test this stuff once */
+ if (zlib_version[0] != ZLIB_VERSION[0]) {
+ Info(slide, 0x21, ((char *)slide,
+ "error: incompatible zlib version (expected %s, found %s)\n",
+ ZLIB_VERSION, zlib_version));
+ return 3;
+ } else if (strcmp(zlib_version, ZLIB_VERSION) != 0)
+ Info(slide, 0x21, ((char *)slide,
+ "warning: different zlib version (expected %s, using %s)\n",
+ ZLIB_VERSION, zlib_version));
+
+ /* windowBits = log2(wsize) */
+ for (i = ((unsigned)wsize * 2 - 1), windowBits = 0;
+ !(i & 1); i >>= 1, ++windowBits);
+ if ((unsigned)windowBits > (unsigned)15)
+ windowBits = 15;
+ else if (windowBits < 8)
+ windowBits = 8;
+
+ G.dstrm.zalloc = (alloc_func)Z_NULL;
+ G.dstrm.zfree = (free_func)Z_NULL;
+
+ Trace((stderr, "initializing inflate()\n"));
+ err = inflateInit2(&G.dstrm, -windowBits);
+
+ if (err == Z_MEM_ERROR)
+ return 3;
+ else if (err != Z_OK)
+ Trace((stderr, "oops! (inflateInit2() err = %d)\n", err));
+ G.inflInit = 1;
+ }
+
+#ifdef FUNZIP
+ while (err != Z_STREAM_END) {
+#else /* !FUNZIP */
+ while (G.csize > 0) {
+ Trace((stderr, "first loop: G.csize = %ld\n", G.csize));
+#endif /* ?FUNZIP */
+ while (G.dstrm.avail_out > 0) {
+ err = inflate(&G.dstrm, Z_PARTIAL_FLUSH);
+
+ if (err == Z_DATA_ERROR)
+ return 2;
+ else if (err == Z_MEM_ERROR)
+ return 3;
+ else if (err != Z_OK && err != Z_STREAM_END)
+ Trace((stderr, "oops! (inflate(first loop) err = %d)\n", err));
+
+#ifdef FUNZIP
+ if (err == Z_STREAM_END) /* "END-of-entry-condition" ? */
+#else /* !FUNZIP */
+ if (G.csize <= 0L) /* "END-of-entry-condition" ? */
+#endif /* ?FUNZIP */
+ break;
+
+ if (G.dstrm.avail_in <= 0) {
+ if (fillinbuf(__G) == 0)
+ return 2; /* no "END-condition" yet, but no more data */
+
+ G.dstrm.next_in = G.inptr;
+ G.dstrm.avail_in = G.incnt;
+ }
+ Trace((stderr, " avail_in = %d\n", G.dstrm.avail_in));
+ }
+ FLUSH(wsize - G.dstrm.avail_out); /* flush slide[] */
+ Trace((stderr, "inside loop: flushing %ld bytes (ptr diff = %ld)\n",
+ (long)(wsize - G.dstrm.avail_out),
+ (long)(G.dstrm.next_out-(Bytef *)redirSlide)));
+ G.dstrm.next_out = redirSlide;
+ G.dstrm.avail_out = wsize;
+ }
+
+ /* no more input, so loop until we have all output */
+ Trace((stderr, "beginning final loop: err = %d\n", err));
+ while (err != Z_STREAM_END) {
+ err = inflate(&G.dstrm, Z_PARTIAL_FLUSH);
+ if (err == Z_DATA_ERROR)
+ return 2;
+ else if (err == Z_MEM_ERROR)
+ return 3;
+ else if (err == Z_BUF_ERROR) { /* DEBUG */
+ Trace((stderr, "zlib inflate() did not detect stream end (%s, %s)\n"
+ , G.zipfn, G.filename));
+ break;
+ } else if (err != Z_OK && err != Z_STREAM_END) {
+ Trace((stderr, "oops! (inflate(final loop) err = %d)\n", err));
+ DESTROYGLOBALS()
+ EXIT(PK_MEM3);
+ }
+ FLUSH(wsize - G.dstrm.avail_out); /* final flush of slide[] */
+ Trace((stderr, "final loop: flushing %ld bytes (ptr diff = %ld)\n",
+ (long)(wsize - G.dstrm.avail_out),
+ (long)(G.dstrm.next_out-(Bytef *)redirSlide)));
+ G.dstrm.next_out = redirSlide;
+ G.dstrm.avail_out = wsize;
+ }
+ Trace((stderr, "total in = %ld, total out = %ld\n", G.dstrm.total_in,
+ G.dstrm.total_out));
+
+ G.inptr = (uch *)G.dstrm.next_in;
+ G.incnt = (G.inbuf + INBUFSIZ) - G.inptr; /* reset for other routines */
+
+ err = inflateReset(&G.dstrm);
+ if (err != Z_OK)
+ Trace((stderr, "oops! (inflateReset() err = %d)\n", err));
+
+ return 0;
+}
+
+
+/*---------------------------------------------------------------------------*/
+#else /* !USE_ZLIB */
+
+
+/* Function prototypes */
+#ifndef OF
+# ifdef __STDC__
+# define OF(a) a
+# else
+# define OF(a) ()
+# endif
+#endif /* !OF */
+int inflate_codes OF((__GPRO__ struct huft *tl, struct huft *td,
+ int bl, int bd));
+static int inflate_stored OF((__GPRO));
+static int inflate_fixed OF((__GPRO));
+static int inflate_dynamic OF((__GPRO));
+static int inflate_block OF((__GPRO__ int *e));
+
+
+/* The inflate algorithm uses a sliding 32K byte window on the uncompressed
+ stream to find repeated byte strings. This is implemented here as a
+ circular buffer. The index is updated simply by incrementing and then
+ and'ing with 0x7fff (32K-1). */
+/* It is left to other modules to supply the 32K area. It is assumed
+ to be usable as if it were declared "uch slide[32768];" or as just
+ "uch *slide;" and then malloc'ed in the latter case. The definition
+ must be in unzip.h, included above. */
+
+
+/* unsigned wp; moved to globals.h */ /* current position in slide */
+
+
+/* Tables for deflate from PKZIP's appnote.txt. */
+static ZCONST unsigned border[] = { /* Order of the bit length code lengths */
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+static ZCONST ush cplens[] = { /* Copy lengths for literal codes 257..285 */
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+ /* note: see note #13 above about the 258 in this list. */
+static ZCONST ush cplext[] = { /* Extra bits for literal codes 257..285 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99}; /* 99==invalid */
+static ZCONST ush cpdist[] = { /* Copy offsets for distance codes 0..29 */
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577};
+static ZCONST ush cpdext[] = { /* Extra bits for distance codes */
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+ 12, 12, 13, 13};
+
+
+/* moved to consts.h (included in unzip.c), resp. funzip.c */
+#if 0
+/* And'ing with mask_bits[n] masks the lower n bits */
+ZCONST ush near mask_bits[] = {
+ 0x0000,
+ 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+ 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+#endif /* 0 */
+
+
+/* Macros for inflate() bit peeking and grabbing.
+ The usage is:
+
+ NEEDBITS(j)
+ x = b & mask_bits[j];
+ DUMPBITS(j)
+
+ where NEEDBITS makes sure that b has at least j bits in it, and
+ DUMPBITS removes the bits from b. The macros use the variable k
+ for the number of bits in b. Normally, b and k are register
+ variables for speed and are initialized at the begining of a
+ routine that uses these macros from a global bit buffer and count.
+
+ In order to not ask for more bits than there are in the compressed
+ stream, the Huffman tables are constructed to only ask for just
+ enough bits to make up the end-of-block code (value 256). Then no
+ bytes need to be "returned" to the buffer at the end of the last
+ block. See the huft_build() routine.
+ */
+
+/* These have been moved to globals.h */
+#if 0
+ulg bb; /* bit buffer */
+unsigned bk; /* bits in bit buffer */
+#endif
+
+#ifndef CHECK_EOF
+# define CHECK_EOF /* default as of 5.13/5.2 */
+#endif
+
+#ifndef CHECK_EOF
+# define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE)<<k;k+=8;}}
+#else
+# define NEEDBITS(n) {while(k<(n)){int c=NEXTBYTE;if(c==EOF)return 1;\
+ b|=((ulg)c)<<k;k+=8;}}
+#endif /* Piet Plomp: change "return 1" to "break" */
+
+#define DUMPBITS(n) {b>>=(n);k-=(n);}
+
+
+/*
+ Huffman code decoding is performed using a multi-level table lookup.
+ The fastest way to decode is to simply build a lookup table whose
+ size is determined by the longest code. However, the time it takes
+ to build this table can also be a factor if the data being decoded
+ are not very long. The most common codes are necessarily the
+ shortest codes, so those codes dominate the decoding time, and hence
+ the speed. The idea is you can have a shorter table that decodes the
+ shorter, more probable codes, and then point to subsidiary tables for
+ the longer codes. The time it costs to decode the longer codes is
+ then traded against the time it takes to make longer tables.
+
+ This results of this trade are in the variables lbits and dbits
+ below. lbits is the number of bits the first level table for literal/
+ length codes can decode in one step, and dbits is the same thing for
+ the distance codes. Subsequent tables are also less than or equal to
+ those sizes. These values may be adjusted either when all of the
+ codes are shorter than that, in which case the longest code length in
+ bits is used, or when the shortest code is *longer* than the requested
+ table size, in which case the length of the shortest code in bits is
+ used.
+
+ There are two different values for the two tables, since they code a
+ different number of possibilities each. The literal/length table
+ codes 286 possible values, or in a flat code, a little over eight
+ bits. The distance table codes 30 possible values, or a little less
+ than five bits, flat. The optimum values for speed end up being
+ about one bit more than those, so lbits is 8+1 and dbits is 5+1.
+ The optimum values may differ though from machine to machine, and
+ possibly even between compilers. Your mileage may vary.
+ */
+
+
+static ZCONST int lbits = 9; /* bits in base literal/length lookup table */
+static ZCONST int dbits = 6; /* bits in base distance lookup table */
+
+
+#ifndef ASM_INFLATECODES
+
+int inflate_codes(__G__ tl, td, bl, bd)
+ __GDEF
+struct huft *tl, *td; /* literal/length and distance decoder tables */
+int bl, bd; /* number of bits decoded by tl[] and td[] */
+/* inflate (decompress) the codes in a deflated (compressed) block.
+ Return an error code or zero if it all goes ok. */
+{
+ register unsigned e; /* table entry flag/number of extra bits */
+ unsigned n, d; /* length and index for copy */
+ unsigned w; /* current window position */
+ struct huft *t; /* pointer to table entry */
+ unsigned ml, md; /* masks for bl and bd bits */
+ register ulg b; /* bit buffer */
+ register unsigned k; /* number of bits in bit buffer */
+
+
+ /* make local copies of globals */
+ b = G.bb; /* initialize bit buffer */
+ k = G.bk;
+ w = G.wp; /* initialize window position */
+
+
+ /* inflate the coded data */
+ ml = mask_bits[bl]; /* precompute masks for speed */
+ md = mask_bits[bd];
+ while (1) /* do until end of block */
+ {
+ NEEDBITS((unsigned)bl)
+ if ((e = (t = tl + ((unsigned)b & ml))->e) > 16)
+ do {
+ if (e == 99)
+ return 1;
+ DUMPBITS(t->b)
+ e -= 16;
+ NEEDBITS(e)
+ } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16);
+ DUMPBITS(t->b)
+ if (e == 16) /* then it's a literal */
+ {
+ redirSlide[w++] = (uch)t->v.n;
+ if (w == wsize)
+ {
+ FLUSH(w);
+ w = 0;
+ }
+ }
+ else /* it's an EOB or a length */
+ {
+ /* exit if end of block */
+ if (e == 15)
+ break;
+
+ /* get length of block to copy */
+ NEEDBITS(e)
+ n = t->v.n + ((unsigned)b & mask_bits[e]);
+ DUMPBITS(e);
+
+ /* decode distance of block to copy */
+ NEEDBITS((unsigned)bd)
+ if ((e = (t = td + ((unsigned)b & md))->e) > 16)
+ do {
+ if (e == 99)
+ return 1;
+ DUMPBITS(t->b)
+ e -= 16;
+ NEEDBITS(e)
+ } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16);
+ DUMPBITS(t->b)
+ NEEDBITS(e)
+ d = w - t->v.n - ((unsigned)b & mask_bits[e]);
+ DUMPBITS(e)
+
+ /* do the copy */
+ do {
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+ if (G.redirect_slide) {/* &= w/ wsize unnecessary & wrong if redirect */
+ if (d >= wsize)
+ return 1; /* invalid compressed data */
+ n -= (e = (e = wsize - (d > w ? d : w)) > n ? n : e);
+ }
+ else
+#endif
+ n -= (e = (e = wsize - ((d &= wsize-1) > w ? d : w)) > n ? n : e);
+#ifndef NOMEMCPY
+ if (w - d >= e) /* (this test assumes unsigned comparison) */
+ {
+ memcpy(redirSlide + w, redirSlide + d, e);
+ w += e;
+ d += e;
+ }
+ else /* do it slowly to avoid memcpy() overlap */
+#endif /* !NOMEMCPY */
+ do {
+ redirSlide[w++] = redirSlide[d++];
+ } while (--e);
+ if (w == wsize)
+ {
+ FLUSH(w);
+ w = 0;
+ }
+ } while (n);
+ }
+ }
+
+
+ /* restore the globals from the locals */
+ G.wp = w; /* restore global window pointer */
+ G.bb = b; /* restore global bit buffer */
+ G.bk = k;
+
+
+ /* done */
+ return 0;
+}
+
+#endif /* ASM_INFLATECODES */
+
+
+
+static int inflate_stored(__G)
+ __GDEF
+/* "decompress" an inflated type 0 (stored) block. */
+{
+ unsigned n; /* number of bytes in block */
+ unsigned w; /* current window position */
+ register ulg b; /* bit buffer */
+ register unsigned k; /* number of bits in bit buffer */
+
+
+ /* make local copies of globals */
+ Trace((stderr, "\nstored block"));
+ b = G.bb; /* initialize bit buffer */
+ k = G.bk;
+ w = G.wp; /* initialize window position */
+
+
+ /* go to byte boundary */
+ n = k & 7;
+ DUMPBITS(n);
+
+
+ /* get the length and its complement */
+ NEEDBITS(16)
+ n = ((unsigned)b & 0xffff);
+ DUMPBITS(16)
+ NEEDBITS(16)
+ if (n != (unsigned)((~b) & 0xffff))
+ return 1; /* error in compressed data */
+ DUMPBITS(16)
+
+
+ /* read and output the compressed data */
+ while (n--)
+ {
+ NEEDBITS(8)
+ redirSlide[w++] = (uch)b;
+ if (w == wsize)
+ {
+ FLUSH(w);
+ w = 0;
+ }
+ DUMPBITS(8)
+ }
+
+
+ /* restore the globals from the locals */
+ G.wp = w; /* restore global window pointer */
+ G.bb = b; /* restore global bit buffer */
+ G.bk = k;
+ return 0;
+}
+
+
+/* Globals for literal tables (built once) */
+/* Moved to globals.h */
+#if 0
+struct huft *fixed_tl = (struct huft *)NULL;
+struct huft *fixed_td;
+int fixed_bl, fixed_bd;
+#endif
+
+static int inflate_fixed(__G)
+ __GDEF
+/* decompress an inflated type 1 (fixed Huffman codes) block. We should
+ either replace this with a custom decoder, or at least precompute the
+ Huffman tables. */
+{
+ /* if first time, set up tables for fixed blocks */
+ Trace((stderr, "\nliteral block"));
+ if (G.fixed_tl == (struct huft *)NULL)
+ {
+ int i; /* temporary variable */
+ unsigned l[288]; /* length list for huft_build */
+
+ /* literal table */
+ for (i = 0; i < 144; i++)
+ l[i] = 8;
+ for (; i < 256; i++)
+ l[i] = 9;
+ for (; i < 280; i++)
+ l[i] = 7;
+ for (; i < 288; i++) /* make a complete, but wrong code set */
+ l[i] = 8;
+ G.fixed_bl = 7;
+ if ((i = huft_build(__G__ l, 288, 257, cplens, cplext,
+ &G.fixed_tl, &G.fixed_bl)) != 0)
+ {
+ G.fixed_tl = (struct huft *)NULL;
+ return i;
+ }
+
+ /* distance table */
+ for (i = 0; i < 30; i++) /* make an incomplete code set */
+ l[i] = 5;
+ G.fixed_bd = 5;
+ if ((i = huft_build(__G__ l, 30, 0, cpdist, cpdext,
+ &G.fixed_td, &G.fixed_bd)) > 1)
+ {
+ huft_free(G.fixed_tl);
+ G.fixed_tl = (struct huft *)NULL;
+ return i;
+ }
+ }
+
+ /* decompress until an end-of-block code */
+ return inflate_codes(__G__ G.fixed_tl, G.fixed_td,
+ G.fixed_bl, G.fixed_bd) != 0;
+}
+
+
+
+static int inflate_dynamic(__G)
+ __GDEF
+/* decompress an inflated type 2 (dynamic Huffman codes) block. */
+{
+ int i; /* temporary variables */
+ unsigned j;
+ unsigned l; /* last length */
+ unsigned m; /* mask for bit lengths table */
+ unsigned n; /* number of lengths to get */
+ struct huft *tl; /* literal/length code table */
+ struct huft *td; /* distance code table */
+ int bl; /* lookup bits for tl */
+ int bd; /* lookup bits for td */
+ unsigned nb; /* number of bit length codes */
+ unsigned nl; /* number of literal/length codes */
+ unsigned nd; /* number of distance codes */
+#ifdef PKZIP_BUG_WORKAROUND
+ unsigned ll[288+32]; /* literal/length and distance code lengths */
+#else
+ unsigned ll[286+30]; /* literal/length and distance code lengths */
+#endif
+ register ulg b; /* bit buffer */
+ register unsigned k; /* number of bits in bit buffer */
+
+
+ /* make local bit buffer */
+ Trace((stderr, "\ndynamic block"));
+ b = G.bb;
+ k = G.bk;
+
+
+ /* read in table lengths */
+ NEEDBITS(5)
+ nl = 257 + ((unsigned)b & 0x1f); /* number of literal/length codes */
+ DUMPBITS(5)
+ NEEDBITS(5)
+ nd = 1 + ((unsigned)b & 0x1f); /* number of distance codes */
+ DUMPBITS(5)
+ NEEDBITS(4)
+ nb = 4 + ((unsigned)b & 0xf); /* number of bit length codes */
+ DUMPBITS(4)
+#ifdef PKZIP_BUG_WORKAROUND
+ if (nl > 288 || nd > 32)
+#else
+ if (nl > 286 || nd > 30)
+#endif
+ return 1; /* bad lengths */
+
+
+ /* read in bit-length-code lengths */
+ for (j = 0; j < nb; j++)
+ {
+ NEEDBITS(3)
+ ll[border[j]] = (unsigned)b & 7;
+ DUMPBITS(3)
+ }
+ for (; j < 19; j++)
+ ll[border[j]] = 0;
+
+
+ /* build decoding table for trees--single level, 7 bit lookup */
+ bl = 7;
+ i = huft_build(__G__ ll, 19, 19, NULL, NULL, &tl, &bl);
+ if (bl == 0) /* no bit lengths */
+ i = 1;
+ if (i)
+ {
+ if (i == 1)
+ huft_free(tl);
+ return i; /* incomplete code set */
+ }
+
+
+ /* read in literal and distance code lengths */
+ n = nl + nd;
+ m = mask_bits[bl];
+ i = l = 0;
+ while ((unsigned)i < n)
+ {
+ NEEDBITS((unsigned)bl)
+ j = (td = tl + ((unsigned)b & m))->b;
+ DUMPBITS(j)
+ j = td->v.n;
+ if (j < 16) /* length of code in bits (0..15) */
+ ll[i++] = l = j; /* save last length in l */
+ else if (j == 16) /* repeat last length 3 to 6 times */
+ {
+ NEEDBITS(2)
+ j = 3 + ((unsigned)b & 3);
+ DUMPBITS(2)
+ if ((unsigned)i + j > n)
+ return 1;
+ while (j--)
+ ll[i++] = l;
+ }
+ else if (j == 17) /* 3 to 10 zero length codes */
+ {
+ NEEDBITS(3)
+ j = 3 + ((unsigned)b & 7);
+ DUMPBITS(3)
+ if ((unsigned)i + j > n)
+ return 1;
+ while (j--)
+ ll[i++] = 0;
+ l = 0;
+ }
+ else /* j == 18: 11 to 138 zero length codes */
+ {
+ NEEDBITS(7)
+ j = 11 + ((unsigned)b & 0x7f);
+ DUMPBITS(7)
+ if ((unsigned)i + j > n)
+ return 1;
+ while (j--)
+ ll[i++] = 0;
+ l = 0;
+ }
+ }
+
+
+ /* free decoding table for trees */
+ huft_free(tl);
+
+
+ /* restore the global bit buffer */
+ G.bb = b;
+ G.bk = k;
+
+
+ /* build the decoding tables for literal/length and distance codes */
+ bl = lbits;
+ i = huft_build(__G__ ll, nl, 257, cplens, cplext, &tl, &bl);
+ if (bl == 0) /* no literals or lengths */
+ i = 1;
+ if (i)
+ {
+ if (i == 1) {
+ if (!uO.qflag)
+ MESSAGE((uch *)"(incomplete l-tree) ", 21L, 1);
+ huft_free(tl);
+ }
+ return i; /* incomplete code set */
+ }
+ bd = dbits;
+ i = huft_build(__G__ ll + nl, nd, 0, cpdist, cpdext, &td, &bd);
+ if (bd == 0 && nl > 257) /* lengths but no distances */
+ {
+ if (!uO.qflag)
+ MESSAGE((uch *)"(incomplete d-tree) ", 21L, 1);
+ huft_free(tl);
+ return 1;
+ }
+ if (i == 1) {
+#ifdef PKZIP_BUG_WORKAROUND
+ i = 0;
+#else
+ if (!uO.qflag)
+ MESSAGE((uch *)"(incomplete d-tree) ", 21L, 1);
+ huft_free(td);
+#endif
+ }
+ if (i)
+ {
+ huft_free(tl);
+ return i;
+ }
+
+
+ /* decompress until an end-of-block code */
+ if (inflate_codes(__G__ tl, td, bl, bd))
+ return 1;
+
+
+ /* free the decoding tables, return */
+ huft_free(tl);
+ huft_free(td);
+ return 0;
+}
+
+
+
+static int inflate_block(__G__ e)
+ __GDEF
+ int *e; /* last block flag */
+/* decompress an inflated block */
+{
+ unsigned t; /* block type */
+ register ulg b; /* bit buffer */
+ register unsigned k; /* number of bits in bit buffer */
+
+
+ /* make local bit buffer */
+ b = G.bb;
+ k = G.bk;
+
+
+ /* read in last block bit */
+ NEEDBITS(1)
+ *e = (int)b & 1;
+ DUMPBITS(1)
+
+
+ /* read in block type */
+ NEEDBITS(2)
+ t = (unsigned)b & 3;
+ DUMPBITS(2)
+
+
+ /* restore the global bit buffer */
+ G.bb = b;
+ G.bk = k;
+
+
+ /* inflate that block type */
+ if (t == 2)
+ return inflate_dynamic(__G);
+ if (t == 0)
+ return inflate_stored(__G);
+ if (t == 1)
+ return inflate_fixed(__G);
+
+
+ /* bad block type */
+ return 2;
+}
+
+
+
+int inflate(__G)
+ __GDEF
+/* decompress an inflated entry */
+{
+ int e; /* last block flag */
+ int r; /* result code */
+#ifdef DEBUG
+ unsigned h = 0; /* maximum struct huft's malloc'ed */
+#endif
+
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+ if (G.redirect_slide)
+ wsize = G.redirect_size, redirSlide = G.redirect_buffer;
+ else
+ wsize = WSIZE, redirSlide = slide; /* how they're #defined if !DLL */
+#endif
+
+ /* initialize window, bit buffer */
+ G.wp = 0;
+ G.bk = 0;
+ G.bb = 0;
+
+
+ /* decompress until the last block */
+ do {
+#ifdef DEBUG
+ G.hufts = 0;
+#endif
+ if ((r = inflate_block(__G__ &e)) != 0)
+ return r;
+#ifdef DEBUG
+ if (G.hufts > h)
+ h = G.hufts;
+#endif
+ } while (!e);
+
+
+ /* flush out redirSlide */
+ FLUSH(G.wp);
+
+
+ /* return success */
+ Trace((stderr, "\n%u bytes in Huffman tables (%d/entry)\n",
+ h * sizeof(struct huft), sizeof(struct huft)));
+ return 0;
+}
+
+
+
+int inflate_free(__G)
+ __GDEF
+{
+ if (G.fixed_tl != (struct huft *)NULL)
+ {
+ huft_free(G.fixed_td);
+ huft_free(G.fixed_tl);
+ G.fixed_td = G.fixed_tl = (struct huft *)NULL;
+ }
+ return 0;
+}
+
+#endif /* ?USE_ZLIB */
+
+
+/*
+ * GRR: moved huft_build() and huft_free() down here; used by explode()
+ * and fUnZip regardless of whether USE_ZLIB defined or not
+ */
+
+
+/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
+#define BMAX 16 /* maximum bit length of any code (16 for explode) */
+#define N_MAX 288 /* maximum number of codes in any set */
+
+
+int huft_build(__G__ b, n, s, d, e, t, m)
+ __GDEF
+ ZCONST unsigned *b; /* code lengths in bits (all assumed <= BMAX) */
+ unsigned n; /* number of codes (assumed <= N_MAX) */
+ unsigned s; /* number of simple-valued codes (0..s-1) */
+ ZCONST ush *d; /* list of base values for non-simple codes */
+ ZCONST ush *e; /* list of extra bits for non-simple codes */
+ struct huft **t; /* result: starting table */
+ int *m; /* maximum lookup bits, returns actual */
+/* Given a list of code lengths and a maximum table size, make a set of
+ tables to decode that set of codes. Return zero on success, one if
+ the given code set is incomplete (the tables are still built in this
+ case), two if the input is invalid (all zero length codes or an
+ oversubscribed set of lengths), and three if not enough memory.
+ The code with value 256 is special, and the tables are constructed
+ so that no bits beyond that code are fetched when that code is
+ decoded. */
+{
+ unsigned a; /* counter for codes of length k */
+ unsigned c[BMAX+1]; /* bit length count table */
+ unsigned el; /* length of EOB code (value 256) */
+ unsigned f; /* i repeats in table every f entries */
+ int g; /* maximum code length */
+ int h; /* table level */
+ register unsigned i; /* counter, current code */
+ register unsigned j; /* counter */
+ register int k; /* number of bits in current code */
+ int lx[BMAX+1]; /* memory for l[-1..BMAX-1] */
+ int *l = lx+1; /* stack of bits per table */
+ register unsigned *p; /* pointer into c[], b[], or v[] */
+ register struct huft *q; /* points to current table */
+ struct huft r; /* table entry for structure assignment */
+ struct huft *u[BMAX]; /* table stack */
+ unsigned v[N_MAX]; /* values in order of bit length */
+ register int w; /* bits before this table == (l * h) */
+ unsigned x[BMAX+1]; /* bit offsets, then code stack */
+ unsigned *xp; /* pointer into x */
+ int y; /* number of dummy codes added */
+ unsigned z; /* number of entries in current table */
+
+
+ /* Generate counts for each bit length */
+ el = n > 256 ? b[256] : BMAX; /* set length of EOB code, if any */
+ memzero((char *)c, sizeof(c));
+ p = (unsigned *)b; i = n;
+ do {
+ c[*p]++; p++; /* assume all entries <= BMAX */
+ } while (--i);
+ if (c[0] == n) /* null input--all zero length codes */
+ {
+ *t = (struct huft *)NULL;
+ *m = 0;
+ return 0;
+ }
+
+
+ /* Find minimum and maximum length, bound *m by those */
+ for (j = 1; j <= BMAX; j++)
+ if (c[j])
+ break;
+ k = j; /* minimum code length */
+ if ((unsigned)*m < j)
+ *m = j;
+ for (i = BMAX; i; i--)
+ if (c[i])
+ break;
+ g = i; /* maximum code length */
+ if ((unsigned)*m > i)
+ *m = i;
+
+
+ /* Adjust last length count to fill out codes, if needed */
+ for (y = 1 << j; j < i; j++, y <<= 1)
+ if ((y -= c[j]) < 0)
+ return 2; /* bad input: more codes than bits */
+ if ((y -= c[i]) < 0)
+ return 2;
+ c[i] += y;
+
+
+ /* Generate starting offsets into the value table for each length */
+ x[1] = j = 0;
+ p = c + 1; xp = x + 2;
+ while (--i) { /* note that i == g from above */
+ *xp++ = (j += *p++);
+ }
+
+
+ /* Make a table of values in order of bit lengths */
+ memzero((char *)v, sizeof(v));
+ p = (unsigned *)b; i = 0;
+ do {
+ if ((j = *p++) != 0)
+ v[x[j]++] = i;
+ } while (++i < n);
+ n = x[g]; /* set n to length of v */
+
+
+ /* Generate the Huffman codes and for each, make the table entries */
+ x[0] = i = 0; /* first Huffman code is zero */
+ p = v; /* grab values in bit order */
+ h = -1; /* no tables yet--level -1 */
+ w = l[-1] = 0; /* no bits decoded yet */
+ u[0] = (struct huft *)NULL; /* just to keep compilers happy */
+ q = (struct huft *)NULL; /* ditto */
+ z = 0; /* ditto */
+
+ /* go through the bit lengths (k already is bits in shortest code) */
+ for (; k <= g; k++)
+ {
+ a = c[k];
+ while (a--)
+ {
+ /* here i is the Huffman code of length k bits for value *p */
+ /* make tables up to required level */
+ while (k > w + l[h])
+ {
+ w += l[h++]; /* add bits already decoded */
+
+ /* compute minimum size table less than or equal to *m bits */
+ z = (z = g - w) > (unsigned)*m ? *m : z; /* upper limit */
+ if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */
+ { /* too few codes for k-w bit table */
+ f -= a + 1; /* deduct codes from patterns left */
+ xp = c + k;
+ while (++j < z) /* try smaller tables up to z bits */
+ {
+ if ((f <<= 1) <= *++xp)
+ break; /* enough codes to use up j bits */
+ f -= *xp; /* else deduct codes from patterns */
+ }
+ }
+ if ((unsigned)w + j > el && (unsigned)w < el)
+ j = el - w; /* make EOB code end at table */
+ z = 1 << j; /* table entries for j-bit table */
+ l[h] = j; /* set table size in stack */
+
+ /* allocate and link in new table */
+ if ((q = (struct huft *)malloc((z + 1)*sizeof(struct huft))) ==
+ (struct huft *)NULL)
+ {
+ if (h)
+ huft_free(u[0]);
+ return 3; /* not enough memory */
+ }
+#ifdef DEBUG
+ G.hufts += z + 1; /* track memory usage */
+#endif
+ *t = q + 1; /* link to list for huft_free() */
+ *(t = &(q->v.t)) = (struct huft *)NULL;
+ u[h] = ++q; /* table starts after link */
+
+ /* connect to last table, if there is one */
+ if (h)
+ {
+ x[h] = i; /* save pattern for backing up */
+ r.b = (uch)l[h-1]; /* bits to dump before this table */
+ r.e = (uch)(16 + j); /* bits in this table */
+ r.v.t = q; /* pointer to this table */
+ j = (i & ((1 << w) - 1)) >> (w - l[h-1]);
+ u[h-1][j] = r; /* connect to last table */
+ }
+ }
+
+ /* set up table entry in r */
+ r.b = (uch)(k - w);
+ if (p >= v + n)
+ r.e = 99; /* out of values--invalid code */
+ else if (*p < s)
+ {
+ r.e = (uch)(*p < 256 ? 16 : 15); /* 256 is end-of-block code */
+ r.v.n = (ush)*p++; /* simple code is just the value */
+ }
+ else
+ {
+ r.e = (uch)e[*p - s]; /* non-simple--look up in lists */
+ r.v.n = d[*p++ - s];
+ }
+
+ /* fill code-like entries with r */
+ f = 1 << (k - w);
+ for (j = i >> w; j < z; j += f)
+ q[j] = r;
+
+ /* backwards increment the k-bit code i */
+ for (j = 1 << (k - 1); i & j; j >>= 1)
+ i ^= j;
+ i ^= j;
+
+ /* backup over finished tables */
+ while ((i & ((1 << w) - 1)) != x[h])
+ w -= l[--h]; /* don't need to update q */
+ }
+ }
+
+
+ /* return actual size of base table */
+ *m = l[0];
+
+
+ /* Return true (1) if we were given an incomplete table */
+ return y != 0 && g != 1;
+}
+
+
+
+int huft_free(t)
+struct huft *t; /* table to free */
+/* Free the malloc'ed tables built by huft_build(), which makes a linked
+ list of the tables it made, with the links in a dummy first entry of
+ each table. */
+{
+ register struct huft *p, *q;
+
+
+ /* Go through linked list, freeing from the malloced (t[-1]) address. */
+ p = t;
+ while (p != (struct huft *)NULL)
+ {
+ q = (--p)->v.t;
+ free((zvoid *)p);
+ p = q;
+ }
+ return 0;
+}
diff --git a/Build/source/libs/unzip/inflate.h b/Build/source/libs/unzip/inflate.h
new file mode 100644
index 00000000000..f1d774b7935
--- /dev/null
+++ b/Build/source/libs/unzip/inflate.h
@@ -0,0 +1,24 @@
+/* inflate.h for UnZip -- put in the public domain by Mark Adler
+ version c14f, 23 November 1995 */
+
+
+/* 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
+ ---- --------- -------------- ------------------------------------
+ c14 12 Mar 93 M. Adler made inflate.c standalone with the
+ introduction of inflate.h.
+ c14d 28 Aug 93 G. Roelofs replaced flush/FlushOutput with new version
+ c14e 29 Sep 93 G. Roelofs moved everything into unzip.h; added crypt.h
+ c14f 23 Nov 95 G. Roelofs added UNZIP_INTERNAL to accommodate newly
+ split unzip.h
+ */
+
+#define UNZIP_INTERNAL
+#include "unzip.h" /* provides slide[], typedefs and macros */
+#ifdef FUNZIP
+# include "crypt.h" /* provides NEXTBYTE macro for crypt version of funzip */
+#endif
diff --git a/Build/source/libs/unzip/list.c b/Build/source/libs/unzip/list.c
new file mode 100644
index 00000000000..0dc1e8a1286
--- /dev/null
+++ b/Build/source/libs/unzip/list.c
@@ -0,0 +1,644 @@
+/*---------------------------------------------------------------------------
+
+ list.c
+
+ This file contains the non-ZipInfo-specific listing routines for UnZip.
+
+ Contains: list_files()
+ get_time_stamp() [optional feature]
+ ratio()
+ fnprint()
+
+ ---------------------------------------------------------------------------*/
+
+
+#define UNZIP_INTERNAL
+#include "unzip.h"
+#ifdef WINDLL
+# ifdef POCKET_UNZIP
+# include "wince/intrface.h"
+# else
+# include "windll/windll.h"
+# endif
+#endif
+
+
+#ifdef TIMESTAMP
+ static int fn_is_dir OF((__GPRO));
+#endif
+
+#ifndef WINDLL
+ static ZCONST char Far CompFactorStr[] = "%c%d%%";
+ static ZCONST char Far CompFactor100[] = "100%%";
+
+#ifdef OS2_EAS
+ static ZCONST char Far HeadersS[] =
+ " Length EAs ACLs Date Time Name";
+ static ZCONST char Far HeadersS1[] =
+ " -------- --- ---- ---- ---- ----";
+#else
+ static ZCONST char Far HeadersS[] = " Length Date Time Name";
+ static ZCONST char Far HeadersS1[] = " -------- ---- ---- ----";
+#endif
+
+ static ZCONST char Far HeadersL[] =
+ " Length Method Size Ratio Date Time CRC-32 Name";
+ static ZCONST char Far HeadersL1[] =
+ "-------- ------ ------- ----- ---- ---- ------ ----";
+ static ZCONST char Far *Headers[][2] =
+ { {HeadersS, HeadersS1}, {HeadersL, HeadersL1} };
+
+ static ZCONST char Far CaseConversion[] =
+ "%s (\"^\" ==> case\n%s conversion)\n";
+ static ZCONST char Far LongHdrStats[] =
+ "%8lu %-7s%8lu %4s %02u-%02u-%02u %02u:%02u %08lx %c";
+ static ZCONST char Far LongFileTrailer[] =
+ "-------- ------- --- \
+ -------\n%8lu %8lu %4s %u file%s\n";
+#ifdef OS2_EAS
+ static ZCONST char Far ShortHdrStats[] =
+ "%9lu %6lu %6lu %02u-%02u-%02u %02u:%02u %c";
+ static ZCONST char Far ShortFileTrailer[] = " -------- ----- ----- \
+ -------\n%9lu %6lu %6lu %u file%s\n";
+ static ZCONST char Far OS2ExtAttrTrailer[] =
+ "%ld file%s %ld bytes of OS/2 extended attributes attached.\n";
+ static ZCONST char Far OS2ACLTrailer[] =
+ "%ld file%s %ld bytes of access control lists attached.\n";
+#else
+ static ZCONST char Far ShortHdrStats[] =
+ "%9lu %02u-%02u-%02u %02u:%02u %c";
+ static ZCONST char Far ShortFileTrailer[] =
+ " -------- -------\n%9lu %u file%s\n";
+#endif /* ?OS2_EAS */
+#endif /* !WINDLL */
+
+
+
+
+
+/*************************/
+/* Function list_files() */
+/*************************/
+
+int list_files(__G) /* return PK-type error code */
+ __GDEF
+{
+ int do_this_file=FALSE, cfactor, error, error_in_archive=PK_COOL;
+#ifndef WINDLL
+ char sgn, cfactorstr[10];
+ int longhdr=(uO.vflag>1);
+#endif
+ int date_format;
+ unsigned j, methnum, members=0;
+#ifdef USE_EF_UT_TIME
+ iztimes z_utime;
+ struct tm *t;
+#endif
+ unsigned yr, mo, dy, hh, mm;
+ ulg csiz, tot_csize=0L, tot_ucsize=0L;
+#ifdef OS2_EAS
+ ulg ea_size, tot_easize=0L, tot_eafiles=0L;
+ ulg acl_size, tot_aclsize=0L, tot_aclfiles=0L;
+#endif
+ min_info info;
+ char methbuf[8];
+ static ZCONST char dtype[]="NXFS"; /* see zi_short() */
+ static ZCONST char Far method[NUM_METHODS+1][8] =
+ {"Stored", "Shrunk", "Reduce1", "Reduce2", "Reduce3", "Reduce4",
+ "Implode", "Token", "Defl:#", "EnhDefl", "ImplDCL", "Unk:###"};
+
+
+
+/*---------------------------------------------------------------------------
+ Unlike extract_or_test_files(), this routine confines itself to the cen-
+ tral directory. Thus its structure is somewhat simpler, since we can do
+ just a single loop through the entire directory, listing files as we go.
+
+ So to start off, print the heading line and then begin main loop through
+ the central directory. The results will look vaguely like the following:
+
+ Length Method Size Ratio Date Time CRC-32 Name ("^" ==> case
+-------- ------ ------- ----- ---- ---- ------ ---- conversion)
+ 44004 Implode 13041 71% 11-02-89 19:34 8b4207f7 Makefile.UNIX
+ 3438 Shrunk 2209 36% 09-15-90 14:07 a2394fd8 ^dos-file.ext
+ 16717 Defl:X 5252 69% 11-03-97 06:40 1ce0f189 WHERE
+-------- ------- --- -------
+ 64159 20502 68% 3 files
+ ---------------------------------------------------------------------------*/
+
+ G.pInfo = &info;
+ date_format = DATE_FORMAT;
+
+#ifndef WINDLL
+ if (uO.qflag < 2) {
+ if (uO.L_flag)
+ Info(slide, 0, ((char *)slide, LoadFarString(CaseConversion),
+ LoadFarStringSmall(Headers[longhdr][0]),
+ LoadFarStringSmall2(Headers[longhdr][1])));
+ else
+ Info(slide, 0, ((char *)slide, "%s\n%s\n",
+ LoadFarString(Headers[longhdr][0]),
+ LoadFarStringSmall(Headers[longhdr][1])));
+ }
+#endif /* !WINDLL */
+
+ for (j = 0; j++ < (unsigned)G.ecrec.total_entries_central_dir;) {
+
+ if (readbuf(__G__ G.sig, 4) == 0)
+ return PK_EOF;
+ if (strncmp(G.sig, central_hdr_sig, 4)) { /* just to make sure */
+ Info(slide, 0x401, ((char *)slide, LoadFarString(CentSigMsg), j));
+ Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg)));
+ return PK_BADERR; /* sig not found */
+ }
+ /* process_cdir_file_hdr() sets pInfo->hostnum, pInfo->lcflag, ...: */
+ if ((error = process_cdir_file_hdr(__G)) != PK_COOL)
+ return error; /* only PK_EOF defined */
+
+ /*
+ * We could DISPLAY the filename instead of storing (and possibly trun-
+ * cating, in the case of a very long name) and printing it, but that
+ * has the disadvantage of not allowing case conversion--and it's nice
+ * to be able to see in the listing precisely how you have to type each
+ * filename in order for unzip to consider it a match. Speaking of
+ * which, if member names were specified on the command line, check in
+ * with match() to see if the current file is one of them, and make a
+ * note of it if it is.
+ */
+
+ if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) !=
+ PK_COOL) /* ^--(uses pInfo->lcflag) */
+ {
+ error_in_archive = error;
+ if (error > PK_WARN) /* fatal: can't continue */
+ return error;
+ }
+ if (G.extra_field != (uch *)NULL) {
+ free(G.extra_field);
+ G.extra_field = (uch *)NULL;
+ }
+ if ((error = do_string(__G__ G.crec.extra_field_length, EXTRA_FIELD))
+ != 0)
+ {
+ error_in_archive = error;
+ if (error > PK_WARN) /* fatal */
+ return error;
+ }
+ if (!G.process_all_files) { /* check if specified on command line */
+ unsigned i;
+
+ do_this_file = FALSE;
+ for (i = 0; i < G.filespecs; i++)
+ if (match(G.filename, G.pfnames[i], uO.C_flag)) {
+ do_this_file = TRUE;
+ break; /* found match, so stop looping */
+ }
+ if (do_this_file) { /* check if this is an excluded file */
+ for (i = 0; i < G.xfilespecs; i++)
+ if (match(G.filename, G.pxnames[i], uO.C_flag)) {
+ do_this_file = FALSE; /* ^-- ignore case in match */
+ break;
+ }
+ }
+ }
+ /*
+ * If current file was specified on command line, or if no names were
+ * specified, do the listing for this file. Otherwise, get rid of the
+ * file comment and go back for the next file.
+ */
+
+ if (G.process_all_files || do_this_file) {
+
+#ifdef OS2DLL
+ /* this is used by UzpFileTree() to allow easy processing of lists
+ * of zip directory contents */
+ if (G.processExternally) {
+ if ((G.processExternally)(G.filename, &G.crec))
+ break;
+ ++members;
+ } else {
+#endif
+#ifdef OS2_EAS
+ {
+ uch *ef_ptr = G.extra_field;
+ int ef_size, ef_len = G.crec.extra_field_length;
+ ea_size = acl_size = 0;
+
+ while (ef_len >= EB_HEADSIZE) {
+ ef_size = makeword(&ef_ptr[EB_LEN]);
+ switch (makeword(&ef_ptr[EB_ID])) {
+ case EF_OS2:
+ ea_size = makelong(&ef_ptr[EB_HEADSIZE]);
+ break;
+ case EF_ACL:
+ acl_size = makelong(&ef_ptr[EB_HEADSIZE]);
+ break;
+ }
+ ef_ptr += (ef_size + EB_HEADSIZE);
+ ef_len -= (ef_size + EB_HEADSIZE);
+ }
+ }
+#endif
+#ifdef USE_EF_UT_TIME
+ if (G.extra_field &&
+#ifdef IZ_CHECK_TZ
+ G.tz_is_valid &&
+#endif
+ (ef_scan_for_izux(G.extra_field, G.crec.extra_field_length, 1,
+ G.crec.last_mod_dos_datetime, &z_utime, NULL)
+ & EB_UT_FL_MTIME))
+ {
+ TIMET_TO_NATIVE(z_utime.mtime) /* NOP unless MSC 7.0, Mac */
+ t = localtime(&(z_utime.mtime));
+ } else
+ t = (struct tm *)NULL;
+ if (t != (struct tm *)NULL) {
+ mo = (unsigned)(t->tm_mon + 1);
+ dy = (unsigned)(t->tm_mday);
+ yr = (unsigned)(t->tm_year % 100);
+ hh = (unsigned)(t->tm_hour);
+ mm = (unsigned)(t->tm_min);
+ } else
+#endif /* USE_EF_UT_TIME */
+ {
+ yr = ((((unsigned)(G.crec.last_mod_dos_datetime >> 25) & 0x7f)
+ + 80) % (unsigned)100);
+ mo = ((unsigned)(G.crec.last_mod_dos_datetime >> 21) & 0x0f);
+ dy = ((unsigned)(G.crec.last_mod_dos_datetime >> 16) & 0x1f);
+ hh = (((unsigned)G.crec.last_mod_dos_datetime >> 11) & 0x1f);
+ mm = (((unsigned)G.crec.last_mod_dos_datetime >> 5) & 0x3f);
+ }
+ /* permute date so it displays according to nat'l convention
+ * ('methnum' is not yet set, it is used as temporary buffer) */
+ switch (date_format) {
+ case DF_YMD:
+ methnum = (unsigned)mo;
+ mo = yr; yr = dy; dy = (ush)methnum;
+ break;
+ case DF_DMY:
+ methnum = (unsigned)mo;
+ mo = dy; dy = (ush)methnum;
+ }
+
+ csiz = G.crec.csize;
+ if (G.crec.general_purpose_bit_flag & 1)
+ csiz -= 12; /* if encrypted, don't count encryption header */
+ if ((cfactor = ratio(G.crec.ucsize, csiz)) < 0) {
+#ifndef WINDLL
+ sgn = '-';
+#endif
+ cfactor = (-cfactor + 5) / 10;
+ } else {
+#ifndef WINDLL
+ sgn = ' ';
+#endif
+ cfactor = (cfactor + 5) / 10;
+ }
+
+ methnum = MIN(G.crec.compression_method, NUM_METHODS);
+ zfstrcpy(methbuf, method[methnum]);
+ if (methnum == DEFLATED) {
+ methbuf[5] = dtype[(G.crec.general_purpose_bit_flag>>1) & 3];
+ } else if (methnum >= NUM_METHODS) {
+ sprintf(&methbuf[4], "%03u", G.crec.compression_method);
+ }
+
+#if 0 /* GRR/Euro: add this? */
+#if defined(DOS_FLX_OS2_W32) || defined(UNIX)
+ for (p = G.filename; *p; ++p)
+ if (!isprint(*p))
+ *p = '?'; /* change non-printable chars to '?' */
+#endif /* DOS_FLX_OS2_W32 || UNIX */
+#endif /* 0 */
+
+#ifdef WINDLL
+ /* send data to application for formatting and printing */
+ (*G.lpUserFunctions->SendApplicationMessage)(G.crec.ucsize, csiz,
+ (ush)cfactor, mo, dy, yr, hh, mm,
+ (char)(G.pInfo->lcflag ? '^' : ' '),
+ (LPSTR)fnfilter(G.filename, slide), (LPSTR)methbuf, G.crec.crc32,
+ (char)((G.crec.general_purpose_bit_flag & 1) ? 'E' : ' '));
+#else /* !WINDLL */
+ if (cfactor == 100)
+ sprintf(cfactorstr, LoadFarString(CompFactor100));
+ else
+ sprintf(cfactorstr, LoadFarString(CompFactorStr), sgn, cfactor);
+ if (longhdr)
+ Info(slide, 0, ((char *)slide, LoadFarString(LongHdrStats),
+ G.crec.ucsize, methbuf, csiz, cfactorstr, mo, dy,
+ yr, hh, mm, G.crec.crc32, (G.pInfo->lcflag? '^':' ')));
+ else
+#ifdef OS2_EAS
+ Info(slide, 0, ((char *)slide, LoadFarString(ShortHdrStats),
+ G.crec.ucsize, ea_size, acl_size,
+ mo, dy, yr, hh, mm, (G.pInfo->lcflag? '^':' ')));
+#else
+ Info(slide, 0, ((char *)slide, LoadFarString(ShortHdrStats),
+ G.crec.ucsize,
+ mo, dy, yr, hh, mm, (G.pInfo->lcflag? '^':' ')));
+#endif
+ fnprint(__G);
+#endif /* ?WINDLL */
+
+ if ((error = do_string(__G__ G.crec.file_comment_length,
+ QCOND? DISPL_8 : SKIP)) != 0)
+ {
+ error_in_archive = error; /* might be just warning */
+ if (error > PK_WARN) /* fatal */
+ return error;
+ }
+ tot_ucsize += G.crec.ucsize;
+ tot_csize += csiz;
+ ++members;
+#ifdef OS2_EAS
+ if (ea_size) {
+ tot_easize += ea_size;
+ ++tot_eafiles;
+ }
+ if (acl_size) {
+ tot_aclsize += acl_size;
+ ++tot_aclfiles;
+ }
+#endif
+#ifdef OS2DLL
+ } /* end of "if (G.processExternally) {...} else {..." */
+#endif
+ } else { /* not listing this file */
+ SKIP_(G.crec.file_comment_length)
+ }
+ } /* end for-loop (j: files in central directory) */
+
+/*---------------------------------------------------------------------------
+ Print footer line and totals (compressed size, uncompressed size, number
+ of members in zipfile).
+ ---------------------------------------------------------------------------*/
+
+ if (uO.qflag < 2
+#ifdef OS2DLL
+ && !G.processExternally
+#endif
+ ) {
+ if ((cfactor = ratio(tot_ucsize, tot_csize)) < 0) {
+#ifndef WINDLL
+ sgn = '-';
+#endif
+ cfactor = (-cfactor + 5) / 10;
+ } else {
+#ifndef WINDLL
+ sgn = ' ';
+#endif
+ cfactor = (cfactor + 5) / 10;
+ }
+#ifdef WINDLL
+ /* pass the totals back to the calling application */
+ G.lpUserFunctions->TotalSizeComp = tot_csize;
+ G.lpUserFunctions->TotalSize = tot_ucsize;
+ G.lpUserFunctions->CompFactor = cfactor;
+ G.lpUserFunctions->NumMembers = members;
+
+#else /* !WINDLL */
+ if (cfactor == 100)
+ sprintf(cfactorstr, LoadFarString(CompFactor100));
+ else
+ sprintf(cfactorstr, LoadFarString(CompFactorStr), sgn, cfactor);
+ if (longhdr) {
+ Info(slide, 0, ((char *)slide, LoadFarString(LongFileTrailer),
+ tot_ucsize, tot_csize, cfactorstr, members, members==1? "":"s"));
+#ifdef OS2_EAS
+ if (tot_easize || tot_aclsize)
+ Info(slide, 0, ((char *)slide, "\n"));
+ if (tot_eafiles && tot_easize)
+ Info(slide, 0, ((char *)slide, LoadFarString(OS2ExtAttrTrailer),
+ tot_eafiles, tot_eafiles == 1? " has" : "s have a total of",
+ tot_easize));
+ if (tot_aclfiles && tot_aclsize)
+ Info(slide, 0, ((char *)slide, LoadFarString(OS2ACLTrailer),
+ tot_aclfiles, tot_aclfiles == 1? " has" : "s have a total of",
+ tot_aclsize));
+#endif /* OS2_EAS */
+ } else
+#ifdef OS2_EAS
+ Info(slide, 0, ((char *)slide, LoadFarString(ShortFileTrailer),
+ tot_ucsize, tot_easize, tot_aclsize, members, members == 1?
+ "" : "s"));
+#else
+ Info(slide, 0, ((char *)slide, LoadFarString(ShortFileTrailer),
+ tot_ucsize, members, members == 1? "" : "s"));
+#endif /* OS2_EAS */
+#endif /* ?WINDLL */
+ }
+
+/*---------------------------------------------------------------------------
+ Double check that we're back at the end-of-central-directory record.
+ ---------------------------------------------------------------------------*/
+
+ if (readbuf(__G__ G.sig, 4) == 0) /* disk error? */
+ return PK_EOF;
+ if (strncmp(G.sig, end_central_sig, 4)) { /* just to make sure again */
+ Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg)));
+ error_in_archive = PK_WARN; /* didn't find sig */
+ }
+ if (members == 0 && error_in_archive <= PK_WARN)
+ error_in_archive = PK_FIND;
+
+ return error_in_archive;
+
+} /* end function list_files() */
+
+
+
+
+
+#ifdef TIMESTAMP
+
+/************************/
+/* Function fn_is_dir() */
+/************************/
+
+static int fn_is_dir(__G) /* returns TRUE if G.filename is directory */
+ __GDEF
+{
+ extent fn_len = strlen(G.filename);
+ register char endc;
+
+ return fn_len > 0 &&
+ ((endc = G.filename[fn_len-1]) == '/' ||
+ (G.pInfo->hostnum == FS_FAT_ && !strchr(G.filename, '/') &&
+ endc == '\\'));
+}
+
+
+
+
+
+/*****************************/
+/* Function get_time_stamp() */
+/*****************************/
+
+int get_time_stamp(__G__ last_modtime, nmember) /* return PK-type error code */
+ __GDEF
+ time_t *last_modtime;
+ unsigned *nmember;
+{
+ int do_this_file=FALSE, error, error_in_archive=PK_COOL;
+ unsigned j;
+#ifdef USE_EF_UT_TIME
+ iztimes z_utime;
+#endif
+ min_info info;
+
+
+/*---------------------------------------------------------------------------
+ Unlike extract_or_test_files() but like list_files(), this function works
+ on information in the central directory alone. Thus we have a single,
+ large loop through the entire directory, searching for the latest time
+ stamp.
+ ---------------------------------------------------------------------------*/
+
+ *last_modtime = 0L; /* assuming no zipfile data older than 1970 */
+ *nmember = 0;
+ G.pInfo = &info;
+
+ for (j = 0; j++ < (unsigned)G.ecrec.total_entries_central_dir;) {
+
+ if (readbuf(__G__ G.sig, 4) == 0)
+ return PK_EOF;
+ if (strncmp(G.sig, central_hdr_sig, 4)) { /* just to make sure */
+ Info(slide, 0x401, ((char *)slide, LoadFarString(CentSigMsg), j));
+ Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg)));
+ return PK_BADERR;
+ }
+ /* process_cdir_file_hdr() sets pInfo->lcflag: */
+ if ((error = process_cdir_file_hdr(__G)) != PK_COOL)
+ return error; /* only PK_EOF defined */
+ if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) != PK_OK)
+ { /* ^-- (uses pInfo->lcflag) */
+ error_in_archive = error;
+ if (error > PK_WARN) /* fatal: can't continue */
+ return error;
+ }
+ if (G.extra_field != (uch *)NULL) {
+ free(G.extra_field);
+ G.extra_field = (uch *)NULL;
+ }
+ if ((error = do_string(__G__ G.crec.extra_field_length, EXTRA_FIELD))
+ != 0)
+ {
+ error_in_archive = error;
+ if (error > PK_WARN) /* fatal */
+ return error;
+ }
+ if (!G.process_all_files) { /* check if specified on command line */
+ unsigned i;
+
+ do_this_file = FALSE;
+ for (i = 0; i < G.filespecs; i++)
+ if (match(G.filename, G.pfnames[i], uO.C_flag)) {
+ do_this_file = TRUE;
+ break; /* found match, so stop looping */
+ }
+ if (do_this_file) { /* check if this is an excluded file */
+ for (i = 0; i < G.xfilespecs; i++)
+ if (match(G.filename, G.pxnames[i], uO.C_flag)) {
+ do_this_file = FALSE; /* ^-- ignore case in match */
+ break;
+ }
+ }
+ }
+
+ /* If current file was specified on command line, or if no names were
+ * specified, check the time for this file. Either way, get rid of the
+ * file comment and go back for the next file.
+ * Directory entries are always ignored, to stay compatible with both
+ * Zip and PKZIP.
+ */
+ if ((G.process_all_files || do_this_file) && !fn_is_dir(__G)) {
+#ifdef USE_EF_UT_TIME
+ if (G.extra_field &&
+#ifdef IZ_CHECK_TZ
+ G.tz_is_valid &&
+#endif
+ (ef_scan_for_izux(G.extra_field, G.crec.extra_field_length, 1,
+ G.crec.last_mod_dos_datetime, &z_utime, NULL)
+ & EB_UT_FL_MTIME))
+ {
+ if (*last_modtime < z_utime.mtime)
+ *last_modtime = z_utime.mtime;
+ } else
+#endif /* USE_EF_UT_TIME */
+ {
+ time_t modtime = dos_to_unix_time(G.crec.last_mod_dos_datetime);
+
+ if (*last_modtime < modtime)
+ *last_modtime = modtime;
+ }
+ ++*nmember;
+ }
+ SKIP_(G.crec.file_comment_length)
+
+ } /* end for-loop (j: files in central directory) */
+
+/*---------------------------------------------------------------------------
+ Double check that we're back at the end-of-central-directory record.
+ ---------------------------------------------------------------------------*/
+
+ if (readbuf(__G__ G.sig, 4) == 0)
+ return PK_EOF;
+ if (strncmp(G.sig, end_central_sig, 4)) { /* just to make sure again */
+ Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg)));
+ error_in_archive = PK_WARN;
+ }
+ if (*nmember == 0 && error_in_archive <= PK_WARN)
+ error_in_archive = PK_FIND;
+
+ return error_in_archive;
+
+} /* end function get_time_stamp() */
+
+#endif /* TIMESTAMP */
+
+
+
+
+
+/********************/
+/* Function ratio() */ /* also used by ZipInfo routines */
+/********************/
+
+int ratio(uc, c)
+ ulg uc, c;
+{
+ ulg denom;
+
+ if (uc == 0)
+ return 0;
+ if (uc > 2000000L) { /* risk signed overflow if multiply numerator */
+ denom = uc / 1000L;
+ return ((uc >= c) ?
+ (int) ((uc-c + (denom>>1)) / denom) :
+ -((int) ((c-uc + (denom>>1)) / denom)));
+ } else { /* ^^^^^^^^ rounding */
+ denom = uc;
+ return ((uc >= c) ?
+ (int) ((1000L*(uc-c) + (denom>>1)) / denom) :
+ -((int) ((1000L*(c-uc) + (denom>>1)) / denom)));
+ } /* ^^^^^^^^ rounding */
+}
+
+
+
+
+
+/************************/
+/* Function fnprint() */ /* also used by ZipInfo routines */
+/************************/
+
+void fnprint(__G) /* print filename (after filtering) and newline */
+ __GDEF
+{
+ char *name = fnfilter(G.filename, slide);
+
+ (*G.message)((zvoid *)&G, (uch *)name, (ulg)strlen(name), 0);
+ (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0);
+
+} /* end function fnprint() */
diff --git a/Build/source/libs/unzip/match.c b/Build/source/libs/unzip/match.c
new file mode 100644
index 00000000000..34954742ee0
--- /dev/null
+++ b/Build/source/libs/unzip/match.c
@@ -0,0 +1,294 @@
+/*---------------------------------------------------------------------------
+
+ match.c
+
+ The match() routine recursively compares a string to a "pattern" (regular
+ expression), returning TRUE if a match is found or FALSE if not. This
+ version is specifically for use with unzip.c: as did the previous match()
+ routines from SEA and J. Kercheval, it leaves the case (upper, lower, or
+ mixed) of the string alone, but converts any uppercase characters in the
+ pattern to lowercase if indicated by the global var pInfo->lcflag (which
+ is to say, string is assumed to have been converted to lowercase already,
+ if such was necessary).
+
+ GRR: reversed order of text, pattern in matche() (now same as match());
+ added ignore_case/ic flags, Case() macro.
+
+ PaulK: replaced matche() with recmatch() from Zip, modified to have an
+ ignore_case argument; replaced test frame with simpler one.
+
+ ---------------------------------------------------------------------------
+
+ Copyright on recmatch() from Zip's util.c (although recmatch() was almost
+ certainly written by Mark Adler...ask me how I can tell :-) ):
+
+ Copyright (C) 1990-1992 Mark Adler, Richard B. Wales, Jean-loup Gailly,
+ Kai Uwe Rommel and Igor Mandrichenko.
+
+ Permission is granted to any individual or institution to use, copy,
+ or redistribute this software so long as all of the original files are
+ included unmodified, that it is not sold for profit, and that this copy-
+ right notice is retained.
+
+ ---------------------------------------------------------------------------
+
+ Match the pattern (wildcard) against the string (fixed):
+
+ match(string, pattern, ignore_case);
+
+ returns TRUE if string matches pattern, FALSE otherwise. In the pattern:
+
+ `*' matches any sequence of characters (zero or more)
+ `?' matches any single character
+ [SET] matches any character in the specified set,
+ [!SET] or [^SET] matches any character not in the specified set.
+
+ A set is composed of characters or ranges; a range looks like ``character
+ hyphen character'' (as in 0-9 or A-Z). [0-9a-zA-Z_] is the minimal set of
+ characters allowed in the [..] pattern construct. Other characters are
+ allowed (i.e., 8-bit characters) if your system will support them.
+
+ To suppress the special syntactic significance of any of ``[]*?!^-\'', in-
+ side or outside a [..] construct, and match the character exactly, precede
+ it with a ``\'' (backslash).
+
+ Note that "*.*" and "*." are treated specially under MS-DOS if DOSWILD is
+ defined. See the DOSWILD section below for an explanation. Note also
+ that with VMSWILD defined, '%' is used instead of '?', and sets (ranges)
+ are delimited by () instead of [].
+
+ ---------------------------------------------------------------------------*/
+
+
+
+/* define ToLower() in here (for Unix, define ToLower to be macro (using
+ * isupper()); otherwise just use tolower() */
+#define UNZIP_INTERNAL
+#include "unzip.h"
+
+#if 0 /* this is not useful until it matches Amiga names insensitively */
+#ifdef AMIGA /* some other platforms might also want to use this */
+# define ANSI_CHARSET /* MOVE INTO UNZIP.H EVENTUALLY */
+#endif
+#endif /* 0 */
+
+#ifdef ANSI_CHARSET
+# ifdef ToLower
+# undef ToLower
+# endif
+ /* uppercase letters are values 41 thru 5A, C0 thru D6, and D8 thru DE */
+# define IsUpper(c) (c>=0xC0 ? c<=0xDE && c!=0xD7 : c>=0x41 && c<=0x5A)
+# define ToLower(c) (IsUpper((uch) c) ? (unsigned) c | 0x20 : (unsigned) c)
+#endif
+#define Case(x) (ic? ToLower(x) : (x))
+
+#ifdef VMSWILD
+# define WILDCHAR '%'
+# define BEG_RANGE '('
+# define END_RANGE ')'
+#else
+# define WILDCHAR '?'
+# define BEG_RANGE '['
+# define END_RANGE ']'
+#endif
+
+#if 0 /* GRR: add this to unzip.h someday... */
+#if !(defined(MSDOS) && defined(DOSWILD))
+#define match(s,p,ic) (recmatch((ZCONST uch *)p,(ZCONST uch *)s,ic) == 1)
+int recmatch OF((ZCONST uch *pattern, ZCONST uch *string, int ignore_case));
+#endif
+#endif /* 0 */
+static int recmatch OF((ZCONST uch *pattern, ZCONST uch *string,
+ int ignore_case));
+
+
+
+/* match() is a shell to recmatch() to return only Boolean values. */
+
+int match(string, pattern, ignore_case)
+ ZCONST char *string, *pattern;
+ int ignore_case;
+{
+#if (defined(MSDOS) && defined(DOSWILD))
+ char *dospattern;
+ int j = strlen(pattern);
+
+/*---------------------------------------------------------------------------
+ Optional MS-DOS preprocessing section: compare last three chars of the
+ wildcard to "*.*" and translate to "*" if found; else compare the last
+ two characters to "*." and, if found, scan the non-wild string for dots.
+ If in the latter case a dot is found, return failure; else translate the
+ "*." to "*". In either case, continue with the normal (Unix-like) match
+ procedure after translation. (If not enough memory, default to normal
+ match.) This causes "a*.*" and "a*." to behave as MS-DOS users expect.
+ ---------------------------------------------------------------------------*/
+
+ if ((dospattern = (char *)malloc(j+1)) != NULL) {
+ strcpy(dospattern, pattern);
+ if (!strcmp(dospattern+j-3, "*.*")) {
+ dospattern[j-2] = '\0'; /* nuke the ".*" */
+ } else if (!strcmp(dospattern+j-2, "*.")) {
+ char *p = strchr(string, '.');
+
+ if (p) { /* found a dot: match fails */
+ free(dospattern);
+ return 0;
+ }
+ dospattern[j-1] = '\0'; /* nuke the end "." */
+ }
+ j = recmatch((uch *)dospattern, (uch *)string, ignore_case);
+ free(dospattern);
+ return j == 1;
+ } else
+#endif /* MSDOS && DOSWILD */
+ return recmatch((uch *)pattern, (uch *)string, ignore_case) == 1;
+}
+
+
+
+static int recmatch(p, s, ic)
+ ZCONST uch *p; /* sh pattern to match */
+ ZCONST uch *s; /* string to which to match it */
+ int ic; /* true for case insensitivity */
+/* Recursively compare the sh pattern p with the string s and return 1 if
+ * they match, and 0 or 2 if they don't or if there is a syntax error in the
+ * pattern. This routine recurses on itself no more deeply than the number
+ * of characters in the pattern. */
+{
+ unsigned int c; /* pattern char or start of range in [-] loop */
+
+ /* Get first character, the pattern for new recmatch calls follows */
+ c = *p++;
+
+ /* If that was the end of the pattern, match if string empty too */
+ if (c == 0)
+ return *s == 0;
+
+ /* '?' (or '%') matches any character (but not an empty string) */
+ if (c == WILDCHAR)
+ return *s ? recmatch(p, s + 1, ic) : 0;
+
+ /* '*' matches any number of characters, including zero */
+#ifdef AMIGA
+ if (c == '#' && *p == '?') /* "#?" is Amiga-ese for "*" */
+ c = '*', p++;
+#endif /* AMIGA */
+ if (c == '*') {
+ if (*p == 0)
+ return 1;
+ for (; *s; s++)
+ if ((c = recmatch(p, s, ic)) != 0)
+ return (int)c;
+ return 2; /* 2 means give up--match will return false */
+ }
+
+ /* Parse and process the list of characters and ranges in brackets */
+ if (c == BEG_RANGE) {
+ int e; /* flag true if next char to be taken literally */
+ ZCONST uch *q; /* pointer to end of [-] group */
+ int r; /* flag true to match anything but the range */
+
+ if (*s == 0) /* need a character to match */
+ return 0;
+ p += (r = (*p == '!' || *p == '^')); /* see if reverse */
+ for (q = p, e = 0; *q; q++) /* find closing bracket */
+ if (e)
+ e = 0;
+ else
+ if (*q == '\\') /* GRR: change to ^ for MS-DOS, OS/2? */
+ e = 1;
+ else if (*q == END_RANGE)
+ break;
+ if (*q != END_RANGE) /* nothing matches if bad syntax */
+ return 0;
+ for (c = 0, e = *p == '-'; p < q; p++) { /* go through the list */
+ if (e == 0 && *p == '\\') /* set escape flag if \ */
+ e = 1;
+ else if (e == 0 && *p == '-') /* set start of range if - */
+ c = *(p-1);
+ else {
+ unsigned int cc = Case(*s);
+
+ if (*(p+1) != '-')
+ for (c = c ? c : *p; c <= *p; c++) /* compare range */
+ if ((unsigned)Case(c) == cc) /* typecast for MSC bug */
+ return r ? 0 : recmatch(q + 1, s + 1, ic);
+ c = e = 0; /* clear range, escape flags */
+ }
+ }
+ return r ? recmatch(q + 1, s + 1, ic) : 0; /* bracket match failed */
+ }
+
+ /* if escape ('\'), just compare next character */
+ if (c == '\\' && (c = *p++) == 0) /* if \ at end, then syntax error */
+ return 0;
+
+ /* just a character--compare it */
+#ifdef QDOS
+ return QMatch(Case((uch)c), Case(*s)) ? recmatch(p, ++s, ic) : 0;
+#else
+ return Case((uch)c) == Case(*s) ? recmatch(p, ++s, ic) : 0;
+#endif
+
+} /* end function recmatch() */
+
+
+
+
+
+int iswild(p) /* originally only used for stat()-bug workaround in */
+ ZCONST char *p; /* VAX C, Turbo/Borland C, Watcom C, Atari MiNT libs; */
+{ /* now used in process_zipfiles() as well */
+ for (; *p; ++p)
+ if (*p == '\\' && *(p+1))
+ ++p;
+#ifdef VMS
+ else if (*p == '%' || *p == '*')
+#else /* !VMS */
+#ifdef AMIGA
+ else if (*p == '?' || *p == '*' || (*p=='#' && p[1]=='?') || *p == '[')
+#else /* !AMIGA */
+ else if (*p == '?' || *p == '*' || *p == '[')
+#endif /* ?AMIGA */
+#endif /* ?VMS */
+#ifdef QDOS
+ return (int)p;
+#else
+ return TRUE;
+#endif
+
+ return FALSE;
+
+} /* end function iswild() */
+
+
+
+
+
+#ifdef TEST_MATCH
+
+#define put(s) {fputs(s,stdout); fflush(stdout);}
+
+void main()
+{
+ char pat[256], str[256];
+
+ for (;;) {
+ put("Pattern (return to exit): ");
+ gets(pat);
+ if (!pat[0])
+ break;
+ for (;;) {
+ put("String (return for new pattern): ");
+ gets(str);
+ if (!str[0])
+ break;
+ printf("Case sensitive: %s insensitive: %s\n",
+ match(str, pat, 0) ? "YES" : "NO",
+ match(str, pat, 1) ? "YES" : "NO");
+ }
+ }
+ EXIT(0);
+}
+
+#endif /* TEST_MATCH */
diff --git a/Build/source/libs/unzip/process.c b/Build/source/libs/unzip/process.c
new file mode 100644
index 00000000000..2d8f179e843
--- /dev/null
+++ b/Build/source/libs/unzip/process.c
@@ -0,0 +1,1378 @@
+/*---------------------------------------------------------------------------
+
+ process.c
+
+ This file contains the top-level routines for processing multiple zipfiles.
+
+ Contains: process_zipfiles()
+ free_G_buffers()
+ do_seekable()
+ find_ecrec()
+ uz_end_central()
+ process_cdir_file_hdr()
+ get_cdir_ent()
+ process_local_file_hdr()
+ ef_scan_for_izux()
+
+ ---------------------------------------------------------------------------*/
+
+
+#define UNZIP_INTERNAL
+#include "unzip.h"
+#ifdef WINDLL
+# ifdef POCKET_UNZIP
+# include "wince/intrface.h"
+# else
+# include "windll/windll.h"
+# endif
+#endif
+
+static int do_seekable OF((__GPRO__ int lastchance));
+static int find_ecrec OF((__GPRO__ long searchlen));
+
+static ZCONST char Far CannotAllocateBuffers[] =
+ "error: cannot allocate unzip buffers\n";
+
+#ifdef SFX
+ static ZCONST char Far CannotFindMyself[] =
+ "unzipsfx: cannot find myself! [%s]\n";
+
+#else /* !SFX */
+ /* process_zipfiles() strings */
+# if (defined(IZ_CHECK_TZ) && defined(USE_EF_UT_TIME))
+ static ZCONST char Far WarnInvalidTZ[] =
+ "Warning: TZ environment variable not found, cannot use UTC times!!\n";
+# endif
+ static ZCONST char Far FilesProcessOK[] =
+ "%d archive%s successfully processed.\n";
+ static ZCONST char Far ArchiveWarning[] =
+ "%d archive%s had warnings but no fatal errors.\n";
+ static ZCONST char Far ArchiveFatalError[] =
+ "%d archive%s had fatal errors.\n";
+ static ZCONST char Far FileHadNoZipfileDir[] =
+ "%d file%s had no zipfile directory.\n";
+ static ZCONST char Far ZipfileWasDir[] = "1 \"zipfile\" was a directory.\n";
+ static ZCONST char Far ManyZipfilesWereDir[] =
+ "%d \"zipfiles\" were directories.\n";
+ static ZCONST char Far NoZipfileFound[] = "No zipfiles found.\n";
+
+ /* do_seekable() strings */
+# ifdef UNIX
+ static ZCONST char Far CannotFindZipfileDirMsg[] =
+ "%s: cannot find zipfile directory in one of %s or\n\
+ %s%s.zip, and cannot find %s, period.\n";
+ static ZCONST char Far CannotFindEitherZipfile[] =
+ "%s: cannot find %s, %s.zip or %s.\n"; /* ", so there" removed 970918 */
+# else /* !UNIX */
+# ifndef AMIGA
+ static ZCONST char Far CannotFindWildcardMatch[] =
+ "%s: cannot find any matches for wildcard specification \"%s\".\n";
+# endif /* !AMIGA */
+ static ZCONST char Far CannotFindZipfileDirMsg[] =
+ "%s: cannot find zipfile directory in %s,\n\
+ %sand cannot find %s, period.\n";
+ static ZCONST char Far CannotFindEitherZipfile[] =
+ "%s: cannot find either %s or %s.\n"; /* ", so there" removed 970918 */
+# endif /* ?UNIX */
+ extern ZCONST char Far Zipnfo[]; /* in unzip.c */
+#ifndef WINDLL
+ static ZCONST char Far Unzip[] = "unzip";
+#else
+ static ZCONST char Far Unzip[] = "UnZip DLL";
+#endif
+ static ZCONST char Far MaybeExe[] =
+ "note: %s may be a plain executable, not an archive\n";
+ static ZCONST char Far CentDirNotInZipMsg[] = "\n\
+ [%s]:\n\
+ Zipfile is disk %u of a multi-disk archive, and this is not the disk on\n\
+ which the central zipfile directory begins (disk %u).\n";
+ static ZCONST char Far EndCentDirBogus[] =
+ "\nwarning [%s]: end-of-central-directory record claims this\n\
+ is disk %u but that the central directory starts on disk %u; this is a\n\
+ contradiction. Attempting to process anyway.\n";
+# ifdef NO_MULTIPART
+ static ZCONST char Far NoMultiDiskArcSupport[] =
+ "\nerror [%s]: zipfile is part of multi-disk archive\n\
+ (sorry, not yet supported).\n";
+ static ZCONST char Far MaybePakBug[] = "warning [%s]:\
+ zipfile claims to be 2nd disk of a 2-part archive;\n\
+ attempting to process anyway. If no further errors occur, this archive\n\
+ was probably created by PAK v2.51 or earlier. This bug was reported to\n\
+ NoGate in March 1991 and was supposed to have been fixed by mid-1991; as\n\
+ of mid-1992 it still hadn't been. (If further errors do occur, archive\n\
+ was probably created by PKZIP 2.04c or later; UnZip does not yet support\n\
+ multi-part archives.)\n";
+# else
+ static ZCONST char Far MaybePakBug[] = "warning [%s]:\
+ zipfile claims to be last disk of a multi-part archive;\n\
+ attempting to process anyway, assuming all parts have been concatenated\n\
+ together in order. Expect \"errors\" and warnings...true multi-part support\
+\n doesn't exist yet (coming soon).\n";
+# endif
+ static ZCONST char Far ExtraBytesAtStart[] =
+ "warning [%s]: %ld extra byte%s at beginning or within zipfile\n\
+ (attempting to process anyway)\n";
+#endif /* ?SFX */
+
+static ZCONST char Far MissingBytes[] =
+ "error [%s]: missing %ld bytes in zipfile\n\
+ (attempting to process anyway)\n";
+static ZCONST char Far NullCentDirOffset[] =
+ "error [%s]: NULL central directory offset\n\
+ (attempting to process anyway)\n";
+static ZCONST char Far ZipfileEmpty[] = "warning [%s]: zipfile is empty\n";
+static ZCONST char Far CentDirStartNotFound[] =
+ "error [%s]: start of central directory not found;\n\
+ zipfile corrupt.\n%s";
+#ifndef SFX
+ static ZCONST char Far CentDirTooLong[] =
+ "error [%s]: reported length of central directory is\n\
+ %ld bytes too long (Atari STZip zipfile? J.H.Holm ZIPSPLIT 1.1\n\
+ zipfile?). Compensating...\n";
+ static ZCONST char Far CentDirEndSigNotFound[] = "\
+ End-of-central-directory signature not found. Either this file is not\n\
+ a zipfile, or it constitutes one disk of a multi-part archive. In the\n\
+ latter case the central directory and zipfile comment will be found on\n\
+ the last disk(s) of this archive.\n";
+#else /* SFX */
+ static ZCONST char Far CentDirEndSigNotFound[] =
+ " End-of-central-directory signature not found.\n";
+#endif /* ?SFX */
+static ZCONST char Far ZipfileCommTrunc1[] =
+ "\ncaution: zipfile comment truncated\n";
+
+
+
+
+/*******************************/
+/* Function process_zipfiles() */
+/*******************************/
+
+int process_zipfiles(__G) /* return PK-type error code */
+ __GDEF
+{
+#ifndef SFX
+ char *lastzipfn = (char *)NULL;
+ int NumWinFiles, NumLoseFiles, NumWarnFiles;
+ int NumMissDirs, NumMissFiles;
+#endif
+ int error=0, error_in_archive=0;
+
+
+/*---------------------------------------------------------------------------
+ Start by allocating buffers and (re)constructing the various PK signature
+ strings.
+ ---------------------------------------------------------------------------*/
+
+ G.inbuf = (uch *)malloc(INBUFSIZ + 4); /* 4 extra for hold[] (below) */
+ G.outbuf = (uch *)malloc(OUTBUFSIZ + 1); /* 1 extra for string term. */
+
+ if ((G.inbuf == (uch *)NULL) || (G.outbuf == (uch *)NULL)) {
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(CannotAllocateBuffers)));
+ return(PK_MEM);
+ }
+ G.hold = G.inbuf + INBUFSIZ; /* to check for boundary-spanning sigs */
+#ifndef VMS /* VMS uses its own buffer scheme for textmode flush(). */
+#ifdef SMALL_MEM
+ G.outbuf2 = G.outbuf+RAWBUFSIZ; /* never changes */
+#endif
+#endif /* !VMS */
+
+#if 0 /* CRC_32_TAB has been NULLified by CONSTRUCTGLOBALS !!!! */
+ /* allocate the CRC table only later when we know we have a zipfile */
+ CRC_32_TAB = NULL;
+#endif /* 0 */
+
+ /* finish up initialization of magic signature strings */
+ local_hdr_sig[0] /* = extd_local_sig[0] */ = 0x50; /* ASCII 'P', */
+ central_hdr_sig[0] = end_central_sig[0] = 0x50; /* not EBCDIC */
+
+ local_hdr_sig[1] /* = extd_local_sig[1] */ = 0x4B; /* ASCII 'K', */
+ central_hdr_sig[1] = end_central_sig[1] = 0x4B; /* not EBCDIC */
+
+/*---------------------------------------------------------------------------
+ Make sure timezone info is set correctly; localtime() returns GMT on
+ some OSes (e.g., Solaris 2.x) if this isn't done first. The ifdefs were
+ initially copied from dos_to_unix_time() in fileio.c. probably, they are
+ still too strict; any listed OS that supplies tzset(), regardless of
+ whether the function does anything, should be removed from the ifdefs.
+ ---------------------------------------------------------------------------*/
+
+#if (defined(IZ_CHECK_TZ) && defined(USE_EF_UT_TIME))
+# ifndef VALID_TIMEZONE
+# define VALID_TIMEZONE(tmp) \
+ (((tmp = getenv("TZ")) != NULL) && (*tmp != '\0'))
+# endif
+ {
+ char *p;
+ G.tz_is_valid = VALID_TIMEZONE(p);
+# ifndef SFX
+ if (!G.tz_is_valid) {
+ Info(slide, 0x401, ((char *)slide, LoadFarString(WarnInvalidTZ)));
+ error_in_archive = error = PK_WARN;
+ }
+# endif /* !SFX */
+ }
+#endif /* IZ_CHECK_TZ && USE_EF_UT_TIME */
+
+/* For systems that do not have tzset() but supply this function using another
+ name (_tzset() or something similar), an appropiate "#define tzset ..."
+ should be added to the system specifc configuration section. */
+#if (!defined(T20_VMS) && !defined(MACOS) && !defined(RISCOS) && !defined(QDOS))
+#if (!defined(BSD) && !defined(MTS) && !defined(CMS_MVS) && !defined(TANDEM))
+ tzset();
+#endif
+#endif
+
+/*---------------------------------------------------------------------------
+ Match (possible) wildcard zipfile specification with existing files and
+ attempt to process each. If no hits, try again after appending ".zip"
+ suffix. If still no luck, give up.
+ ---------------------------------------------------------------------------*/
+
+#ifdef SFX
+ if ((error = do_seekable(__G__ 0)) == PK_NOZIP) {
+#ifdef EXE_EXTENSION
+ int len=strlen(G.argv0);
+
+ /* append .exe if appropriate; also .sfx? */
+ if ( (G.zipfn = (char *)malloc(len+sizeof(EXE_EXTENSION))) !=
+ (char *)NULL ) {
+ strcpy(G.zipfn, G.argv0);
+ strcpy(G.zipfn+len, EXE_EXTENSION);
+ error = do_seekable(__G__ 0);
+ free(G.zipfn);
+ G.zipfn = G.argv0; /* for "cannot find myself" message only */
+ }
+#endif /* EXE_EXTENSION */
+#ifdef WIN32
+ G.zipfn = G.argv0; /* for "cannot find myself" message only */
+#endif
+ }
+ if (error) {
+ if (error == IZ_DIR)
+ error_in_archive = PK_NOZIP;
+ else
+ error_in_archive = error;
+ if (error == PK_NOZIP)
+ Info(slide, 1, ((char *)slide, LoadFarString(CannotFindMyself),
+ G.zipfn));
+ }
+
+#else /* !SFX */
+ NumWinFiles = NumLoseFiles = NumWarnFiles = 0;
+ NumMissDirs = NumMissFiles = 0;
+
+ while ((G.zipfn = do_wild(__G__ G.wildzipfn)) != (char *)NULL) {
+ Trace((stderr, "do_wild( %s ) returns %s\n", G.wildzipfn, G.zipfn));
+
+ lastzipfn = G.zipfn;
+
+ /* print a blank line between the output of different zipfiles */
+ if (!uO.qflag && error != PK_NOZIP && error != IZ_DIR
+#ifdef TIMESTAMP
+ && (!uO.T_flag || uO.zipinfo_mode)
+#endif
+ && (NumWinFiles+NumLoseFiles+NumWarnFiles+NumMissFiles) > 0)
+ (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0);
+
+ if ((error = do_seekable(__G__ 0)) == PK_WARN)
+ ++NumWarnFiles;
+ else if (error == IZ_DIR)
+ ++NumMissDirs;
+ else if (error == PK_NOZIP)
+ ++NumMissFiles;
+ else if (error)
+ ++NumLoseFiles;
+ else
+ ++NumWinFiles;
+
+ if (error != IZ_DIR && error > error_in_archive)
+ error_in_archive = error;
+ Trace((stderr, "do_seekable(0) returns %d\n", error));
+#ifdef WINDLL
+ if (error == IZ_CTRLC) {
+ free_G_buffers(__G);
+ return error;
+ }
+#endif
+
+ } /* end while-loop (wildcard zipfiles) */
+
+ if ((NumWinFiles + NumWarnFiles + NumLoseFiles) == 0 &&
+ (NumMissDirs + NumMissFiles) == 1 && lastzipfn != (char *)NULL)
+ {
+ NumMissDirs = NumMissFiles = 0;
+ if (error_in_archive == PK_NOZIP)
+ error_in_archive = PK_COOL;
+
+#if (!defined(UNIX) && !defined(AMIGA)) /* filenames with wildcard characters */
+ if (iswild(G.wildzipfn))
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(CannotFindWildcardMatch), uO.zipinfo_mode?
+ LoadFarStringSmall(Zipnfo) : LoadFarStringSmall(Unzip),
+ G.wildzipfn));
+ else
+#endif
+ {
+ char *p = lastzipfn + strlen(lastzipfn);
+
+ G.zipfn = lastzipfn;
+ strcpy(p, ZSUFX);
+
+#if defined(UNIX) || defined(QDOS)
+ /* only Unix has case-sensitive filesystems */
+ /* Well FlexOS (sometimes) also has them, but support is per media */
+ /* and a pig to code for, so treat as case insensitive for now */
+ /* we do this under QDOS to check for .zip as well as _zip */
+ if ((error = do_seekable(__G__ 0)) == PK_NOZIP || error == IZ_DIR) {
+ if (error == IZ_DIR)
+ ++NumMissDirs;
+ strcpy(p, ALT_ZSUFX);
+ error = do_seekable(__G__ 1);
+ }
+#else
+ error = do_seekable(__G__ 1);
+#endif
+ if (error == PK_WARN) /* GRR: make this a switch/case stmt ... */
+ ++NumWarnFiles;
+ else if (error == IZ_DIR)
+ ++NumMissDirs;
+ else if (error == PK_NOZIP)
+ /* increment again => bug: "1 file had no zipfile directory." */
+ /* ++NumMissFiles */ ;
+ else if (error)
+ ++NumLoseFiles;
+ else
+ ++NumWinFiles;
+
+ if (error > error_in_archive)
+ error_in_archive = error;
+ Trace((stderr, "do_seekable(1) returns %d\n", error));
+#ifdef WINDLL
+ if (error == IZ_CTRLC) {
+ free_G_buffers(__G);
+ return error;
+ }
+#endif
+ }
+ }
+#endif /* ?SFX */
+
+/*---------------------------------------------------------------------------
+ Print summary of all zipfiles, assuming zipfile spec was a wildcard (no
+ need for a summary if just one zipfile).
+ ---------------------------------------------------------------------------*/
+
+#ifndef SFX
+ if (iswild(G.wildzipfn) && uO.qflag < 3
+#ifdef TIMESTAMP
+ && !(uO.T_flag && uO.qflag && !uO.zipinfo_mode)
+#endif
+ )
+ {
+ if ((NumMissFiles + NumLoseFiles + NumWarnFiles > 0 || NumWinFiles != 1)
+#ifdef TIMESTAMP
+ && !(uO.T_flag && !uO.zipinfo_mode)
+#endif
+ && !(uO.tflag && uO.qflag > 1))
+ (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0x401);
+ if ((NumWinFiles > 1) || (NumWinFiles == 1 &&
+ NumMissDirs + NumMissFiles + NumLoseFiles + NumWarnFiles > 0))
+ Info(slide, 0x401, ((char *)slide, LoadFarString(FilesProcessOK),
+ NumWinFiles, (NumWinFiles == 1)? " was" : "s were"));
+ if (NumWarnFiles > 0)
+ Info(slide, 0x401, ((char *)slide, LoadFarString(ArchiveWarning),
+ NumWarnFiles, (NumWarnFiles == 1)? "" : "s"));
+ if (NumLoseFiles > 0)
+ Info(slide, 0x401, ((char *)slide, LoadFarString(ArchiveFatalError),
+ NumLoseFiles, (NumLoseFiles == 1)? "" : "s"));
+ if (NumMissFiles > 0)
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(FileHadNoZipfileDir), NumMissFiles,
+ (NumMissFiles == 1)? "" : "s"));
+ if (NumMissDirs == 1)
+ Info(slide, 0x401, ((char *)slide, LoadFarString(ZipfileWasDir)));
+ else if (NumMissDirs > 0)
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(ManyZipfilesWereDir), NumMissDirs));
+ if (NumWinFiles + NumLoseFiles + NumWarnFiles == 0)
+ Info(slide, 0x401, ((char *)slide, LoadFarString(NoZipfileFound)));
+ }
+#endif /* !SFX */
+
+ /* free allocated memory */
+ free_G_buffers(__G);
+
+ return error_in_archive;
+
+} /* end function process_zipfiles() */
+
+
+
+
+
+/*****************************/
+/* Function free_G_buffers() */
+/*****************************/
+
+void free_G_buffers(__G) /* releases all memory allocated in global vars */
+ __GDEF
+{
+ inflate_free(__G);
+ checkdir(__G__ (char *)NULL, END);
+
+#ifdef DYNALLOC_CRCTAB
+ if (CRC_32_TAB) {
+ free_crc_table();
+ CRC_32_TAB = NULL;
+ }
+#endif
+
+ if (G.key != (char *)NULL) {
+ free(G.key);
+ G.key = (char *)NULL;
+ }
+
+#if (!defined(VMS) && !defined(SMALL_MEM))
+ /* VMS uses its own buffer scheme for textmode flush() */
+ if (G.outbuf2) {
+ free(G.outbuf2); /* malloc'd ONLY if unshrink and -a */
+ G.outbuf2 = (uch *)NULL;
+ }
+#endif
+
+ if (G.outbuf)
+ free(G.outbuf);
+ if (G.inbuf)
+ free(G.inbuf);
+ G.inbuf = G.outbuf = (uch *)NULL;
+
+#ifdef MALLOC_WORK
+ if (G.area.Slide) {
+ free(G.area.Slide);
+ G.area.Slide = (uch *)NULL;
+ }
+#endif
+
+} /* end function free_G_buffers() */
+
+
+
+
+
+/**************************/
+/* Function do_seekable() */
+/**************************/
+
+static int do_seekable(__G__ lastchance) /* return PK-type error code */
+ __GDEF
+ int lastchance;
+{
+#ifndef SFX
+ /* static int no_ecrec = FALSE; SKM: moved to globals.h */
+ int maybe_exe=FALSE;
+ int too_weird_to_continue=FALSE;
+#ifdef TIMESTAMP
+ time_t uxstamp;
+ unsigned nmember = 0;
+#endif
+#endif
+ int error=0, error_in_archive;
+
+
+/*---------------------------------------------------------------------------
+ Open the zipfile for reading in BINARY mode to prevent CR/LF translation,
+ which would corrupt the bit streams.
+ ---------------------------------------------------------------------------*/
+
+ if (SSTAT(G.zipfn, &G.statbuf) ||
+ (error = S_ISDIR(G.statbuf.st_mode)) != 0)
+ {
+#ifndef SFX
+ if (lastchance) {
+#if defined(UNIX) || defined(QDOS)
+ if (G.no_ecrec)
+ Info(slide, 1, ((char *)slide,
+ LoadFarString(CannotFindZipfileDirMsg), uO.zipinfo_mode?
+ LoadFarStringSmall(Zipnfo) : LoadFarStringSmall(Unzip),
+ G.wildzipfn, uO.zipinfo_mode? " " : "", G.wildzipfn,
+ G.zipfn));
+ else
+ Info(slide, 1, ((char *)slide,
+ LoadFarString(CannotFindEitherZipfile), uO.zipinfo_mode?
+ LoadFarStringSmall(Zipnfo) : LoadFarStringSmall(Unzip),
+ G.wildzipfn, G.wildzipfn, G.zipfn));
+#else /* !UNIX */
+ if (G.no_ecrec)
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(CannotFindZipfileDirMsg), uO.zipinfo_mode?
+ LoadFarStringSmall(Zipnfo) : LoadFarStringSmall(Unzip),
+ G.wildzipfn, uO.zipinfo_mode? " " : "", G.zipfn));
+ else
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(CannotFindEitherZipfile), uO.zipinfo_mode?
+ LoadFarStringSmall(Zipnfo) : LoadFarStringSmall(Unzip),
+ G.wildzipfn, G.zipfn));
+#endif /* ?UNIX */
+ }
+#endif /* !SFX */
+ return error? IZ_DIR : PK_NOZIP;
+ }
+ G.ziplen = G.statbuf.st_size;
+
+#ifndef SFX
+#if defined(UNIX) || defined(DOS_OS2_W32)
+ if (G.statbuf.st_mode & S_IEXEC) /* no extension on Unix exes: might */
+ maybe_exe = TRUE; /* find unzip, not unzip.zip; etc. */
+#endif
+#endif /* !SFX */
+
+#ifdef VMS
+ if (check_format(__G)) /* check for variable-length format */
+ return PK_ERR;
+#endif
+
+ if (open_input_file(__G)) /* this should never happen, given */
+ return PK_NOZIP; /* the stat() test above, but... */
+
+/*---------------------------------------------------------------------------
+ Find and process the end-of-central-directory header. UnZip need only
+ check last 65557 bytes of zipfile: comment may be up to 65535, end-of-
+ central-directory record is 18 bytes, and signature itself is 4 bytes;
+ add some to allow for appended garbage. Since ZipInfo is often used as
+ a debugging tool, search the whole zipfile if zipinfo_mode is true.
+ ---------------------------------------------------------------------------*/
+
+ /* initialize the CRC table pointer (once) */
+ if (CRC_32_TAB == NULL) {
+ if ((CRC_32_TAB = get_crc_table()) == NULL)
+ return PK_MEM;
+ }
+
+#if (!defined(SFX) || defined(SFX_EXDIR))
+ /* check out if specified extraction root directory exists */
+ if (uO.exdir != (char *)NULL && G.extract_flag) {
+ G.create_dirs = !uO.fflag;
+ if ((error = checkdir(__G__ uO.exdir, ROOT)) > 2)
+ return error; /* out of memory, or file in way */
+ }
+#endif /* !SFX || SFX_EXDIR */
+
+ G.cur_zipfile_bufstart = 0;
+ G.inptr = G.inbuf;
+
+#if (!defined(WINDLL) && !defined(SFX))
+#ifdef TIMESTAMP
+ if (!uO.zipinfo_mode && !uO.qflag && !uO.T_flag)
+#else
+ if (!uO.zipinfo_mode && !uO.qflag)
+#endif
+#ifdef WIN32 /* Win32 console may require codepage conversion for G.zipfn */
+ Info(slide, 0, ((char *)slide, "Archive: %s\n", FnFilter1(G.zipfn)));
+#else
+ Info(slide, 0, ((char *)slide, "Archive: %s\n", G.zipfn));
+#endif
+#endif /* !WINDLL && !SFX */
+
+ if ((
+#ifndef NO_ZIPINFO
+ uO.zipinfo_mode &&
+ ((error_in_archive = find_ecrec(__G__ G.ziplen)) != 0 ||
+ (error_in_archive = zi_end_central(__G)) > PK_WARN))
+ || (!uO.zipinfo_mode &&
+#endif
+ ((error_in_archive = find_ecrec(__G__ MIN(G.ziplen,66000L))) != 0 ||
+ (error_in_archive = uz_end_central(__G)) > PK_WARN)))
+ {
+ CLOSE_INFILE();
+
+#ifdef SFX
+ ++lastchance; /* avoid picky compiler warnings */
+ return error_in_archive;
+#else
+ if (maybe_exe)
+ Info(slide, 0x401, ((char *)slide, LoadFarString(MaybeExe),
+ G.zipfn));
+ if (lastchance)
+ return error_in_archive;
+ else {
+ G.no_ecrec = TRUE; /* assume we found wrong file: e.g., */
+ return PK_NOZIP; /* unzip instead of unzip.zip */
+ }
+#endif /* ?SFX */
+ }
+
+ if ((uO.zflag > 0) && !uO.zipinfo_mode) { /* unzip: zflag = comment ONLY */
+ CLOSE_INFILE();
+ return error_in_archive;
+ }
+
+/*---------------------------------------------------------------------------
+ Test the end-of-central-directory info for incompatibilities (multi-disk
+ archives) or inconsistencies (missing or extra bytes in zipfile).
+ ---------------------------------------------------------------------------*/
+
+#ifdef NO_MULTIPART
+ error = !uO.zipinfo_mode && (G.ecrec.number_this_disk == 1) &&
+ (G.ecrec.num_disk_start_cdir == 1);
+#else
+ error = !uO.zipinfo_mode && (G.ecrec.number_this_disk != 0);
+#endif
+
+#ifndef SFX
+ if (uO.zipinfo_mode &&
+ G.ecrec.number_this_disk != G.ecrec.num_disk_start_cdir)
+ {
+ if (G.ecrec.number_this_disk > G.ecrec.num_disk_start_cdir) {
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(CentDirNotInZipMsg), G.zipfn,
+ G.ecrec.number_this_disk, G.ecrec.num_disk_start_cdir));
+ error_in_archive = PK_FIND;
+ too_weird_to_continue = TRUE;
+ } else {
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(EndCentDirBogus), G.zipfn,
+ G.ecrec.number_this_disk, G.ecrec.num_disk_start_cdir));
+ error_in_archive = PK_WARN;
+ }
+#ifdef NO_MULTIPART /* concatenation of multiple parts works in some cases */
+ } else if (!uO.zipinfo_mode && !error && G.ecrec.number_this_disk != 0) {
+ Info(slide, 0x401, ((char *)slide, LoadFarString(NoMultiDiskArcSupport),
+ G.zipfn));
+ error_in_archive = PK_FIND;
+ too_weird_to_continue = TRUE;
+#endif
+ }
+
+ if (!too_weird_to_continue) { /* (relatively) normal zipfile: go for it */
+ if (error) {
+ Info(slide, 0x401, ((char *)slide, LoadFarString(MaybePakBug),
+ G.zipfn));
+ error_in_archive = PK_WARN;
+ }
+#endif /* !SFX */
+ if ((G.extra_bytes = G.real_ecrec_offset-G.expect_ecrec_offset) <
+ (LONGINT)0)
+ {
+ Info(slide, 0x401, ((char *)slide, LoadFarString(MissingBytes),
+ G.zipfn, (long)(-G.extra_bytes)));
+ error_in_archive = PK_ERR;
+ } else if (G.extra_bytes > 0) {
+ if ((G.ecrec.offset_start_central_directory == 0) &&
+ (G.ecrec.size_central_directory != 0)) /* zip 1.5 -go bug */
+ {
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(NullCentDirOffset), G.zipfn));
+ G.ecrec.offset_start_central_directory = G.extra_bytes;
+ G.extra_bytes = 0;
+ error_in_archive = PK_ERR;
+ }
+#ifndef SFX
+ else {
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(ExtraBytesAtStart), G.zipfn,
+ (long)G.extra_bytes, (G.extra_bytes == 1)? "":"s"));
+ error_in_archive = PK_WARN;
+ }
+#endif /* !SFX */
+ }
+
+ /*-----------------------------------------------------------------------
+ Check for empty zipfile and exit now if so.
+ -----------------------------------------------------------------------*/
+
+ if (G.expect_ecrec_offset==0L && G.ecrec.size_central_directory==0) {
+ if (uO.zipinfo_mode)
+ Info(slide, 0, ((char *)slide, "%sEmpty zipfile.\n",
+ uO.lflag>9? "\n " : ""));
+ else
+ Info(slide, 0x401, ((char *)slide, LoadFarString(ZipfileEmpty),
+ G.zipfn));
+ CLOSE_INFILE();
+ return (error_in_archive > PK_WARN)? error_in_archive : PK_WARN;
+ }
+
+ /*-----------------------------------------------------------------------
+ Compensate for missing or extra bytes, and seek to where the start
+ of central directory should be. If header not found, uncompensate
+ and try again (necessary for at least some Atari archives created
+ with STZip, as well as archives created by J.H. Holm's ZIPSPLIT 1.1).
+ -----------------------------------------------------------------------*/
+
+ ZLSEEK( G.ecrec.offset_start_central_directory )
+#ifdef OLD_SEEK_TEST
+ if (readbuf(G.sig, 4) == 0) {
+ CLOSE_INFILE();
+ return PK_ERR; /* file may be locked, or possibly disk error(?) */
+ }
+ if (strncmp(G.sig, central_hdr_sig, 4))
+#else
+ if ((readbuf(__G__ G.sig, 4) == 0) ||
+ strncmp(G.sig, central_hdr_sig, 4))
+#endif
+ {
+#ifndef SFX
+ long tmp = G.extra_bytes;
+#endif
+
+ G.extra_bytes = 0;
+ ZLSEEK( G.ecrec.offset_start_central_directory )
+ if ((readbuf(__G__ G.sig, 4) == 0) ||
+ strncmp(G.sig, central_hdr_sig, 4))
+ {
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(CentDirStartNotFound), G.zipfn,
+ LoadFarStringSmall(ReportMsg)));
+ CLOSE_INFILE();
+ return PK_BADERR;
+ }
+#ifndef SFX
+ Info(slide, 0x401, ((char *)slide, LoadFarString(CentDirTooLong),
+ G.zipfn, -tmp));
+#endif
+ error_in_archive = PK_ERR;
+ }
+
+ /*-----------------------------------------------------------------------
+ Seek to the start of the central directory one last time, since we
+ have just read the first entry's signature bytes; then list, extract
+ or test member files as instructed, and close the zipfile.
+ -----------------------------------------------------------------------*/
+
+ Trace((stderr, "about to extract/list files (error = %d)\n",
+ error_in_archive));
+
+ ZLSEEK( G.ecrec.offset_start_central_directory )
+
+#ifdef DLL
+ /* G.fValidate is used only to look at an archive to see if
+ it appears to be a valid archive. There is no interest
+ in what the archive contains, nor in validating that the
+ entries in the archive are in good condition. This is
+ currently used only in the Windows DLLs for purposes of
+ checking archives within an archive to determine whether
+ or not to display the inner archives.
+ */
+ if (!G.fValidate)
+#endif
+ {
+#ifndef NO_ZIPINFO
+ if (uO.zipinfo_mode)
+ error = zipinfo(__G); /* ZIPINFO 'EM */
+ else
+#endif
+#ifndef SFX
+#ifdef TIMESTAMP
+ if (uO.T_flag)
+ error = get_time_stamp(__G__ &uxstamp, &nmember);
+ else
+#endif
+ if (uO.vflag && !uO.tflag && !uO.cflag)
+ error = list_files(__G); /* LIST 'EM */
+ else
+#endif /* !SFX */
+ error = extract_or_test_files(__G); /* EXTRACT OR TEST 'EM */
+
+ Trace((stderr, "done with extract/list files (error = %d)\n",
+ error));
+ }
+
+ if (error > error_in_archive) /* don't overwrite stronger error */
+ error_in_archive = error; /* with (for example) a warning */
+#ifndef SFX
+ } /* end if (!too_weird_to_continue) */
+#endif
+
+ CLOSE_INFILE();
+
+#ifdef TIMESTAMP
+ if (uO.T_flag && !uO.zipinfo_mode && (nmember > 0)) {
+# ifdef WIN32
+ if (stamp_file(__G__ G.zipfn, uxstamp)) { /* TIME-STAMP 'EM */
+# else
+ if (stamp_file(G.zipfn, uxstamp)) { /* TIME-STAMP 'EM */
+# endif
+ Info(slide, 0x201, ((char *)slide,
+ "warning: cannot set time for %s\n", G.zipfn));
+ if (error_in_archive < PK_WARN)
+ error_in_archive = PK_WARN;
+ }
+ }
+#endif
+ return error_in_archive;
+
+} /* end function do_seekable() */
+
+
+
+
+
+/*************************/
+/* Function find_ecrec() */
+/*************************/
+
+static int find_ecrec(__G__ searchlen) /* return PK-class error */
+ __GDEF
+ long searchlen;
+{
+ int i, numblks, found=FALSE;
+ LONGINT tail_len;
+ ec_byte_rec byterec;
+
+
+/*---------------------------------------------------------------------------
+ Treat case of short zipfile separately.
+ ---------------------------------------------------------------------------*/
+
+ if (G.ziplen <= INBUFSIZ) {
+ lseek(G.zipfd, 0L, SEEK_SET);
+ if ((G.incnt = read(G.zipfd,(char *)G.inbuf,(unsigned int)G.ziplen))
+ == (int)G.ziplen)
+
+ /* 'P' must be at least 22 bytes from end of zipfile */
+ for (G.inptr = G.inbuf+(int)G.ziplen-22; G.inptr >= G.inbuf;
+ --G.inptr)
+ if ((native(*G.inptr) == 'P') &&
+ !strncmp((char *)G.inptr, end_central_sig, 4)) {
+ G.incnt -= (int)(G.inptr - G.inbuf);
+ found = TRUE;
+ break;
+ }
+
+/*---------------------------------------------------------------------------
+ Zipfile is longer than INBUFSIZ: may need to loop. Start with short
+ block at end of zipfile (if not TOO short).
+ ---------------------------------------------------------------------------*/
+
+ } else {
+ if ((tail_len = G.ziplen % INBUFSIZ) > ECREC_SIZE) {
+#ifdef USE_STRM_INPUT
+ fseek((FILE *)G.zipfd, G.ziplen-tail_len, SEEK_SET);
+ G.cur_zipfile_bufstart = ftell((FILE *)G.zipfd);
+#else /* !USE_STRM_INPUT */
+ G.cur_zipfile_bufstart = lseek(G.zipfd, G.ziplen-tail_len,
+ SEEK_SET);
+#endif /* ?USE_STRM_INPUT */
+ if ((G.incnt = read(G.zipfd, (char *)G.inbuf,
+ (unsigned int)tail_len)) != (int)tail_len)
+ goto fail; /* it's expedient... */
+
+ /* 'P' must be at least 22 bytes from end of zipfile */
+ for (G.inptr = G.inbuf+(int)tail_len-22; G.inptr >= G.inbuf;
+ --G.inptr)
+ if ((native(*G.inptr) == 'P') &&
+ !strncmp((char *)G.inptr, end_central_sig, 4)) {
+ G.incnt -= (int)(G.inptr - G.inbuf);
+ found = TRUE;
+ break;
+ }
+ /* sig may span block boundary: */
+ strncpy((char *)G.hold, (char *)G.inbuf, 3);
+ } else
+ G.cur_zipfile_bufstart = G.ziplen - tail_len;
+
+ /*-----------------------------------------------------------------------
+ Loop through blocks of zipfile data, starting at the end and going
+ toward the beginning. In general, need not check whole zipfile for
+ signature, but may want to do so if testing.
+ -----------------------------------------------------------------------*/
+
+ numblks = (int)((searchlen - tail_len + (INBUFSIZ-1)) / INBUFSIZ);
+ /* ==amount= ==done== ==rounding== =blksiz= */
+
+ for (i = 1; !found && (i <= numblks); ++i) {
+ G.cur_zipfile_bufstart -= INBUFSIZ;
+ lseek(G.zipfd, G.cur_zipfile_bufstart, SEEK_SET);
+ if ((G.incnt = read(G.zipfd,(char *)G.inbuf,INBUFSIZ))
+ != INBUFSIZ)
+ break; /* fall through and fail */
+
+ for (G.inptr = G.inbuf+INBUFSIZ-1; G.inptr >= G.inbuf;
+ --G.inptr)
+ if ((native(*G.inptr) == 'P') &&
+ !strncmp((char *)G.inptr, end_central_sig, 4)) {
+ G.incnt -= (int)(G.inptr - G.inbuf);
+ found = TRUE;
+ break;
+ }
+ /* sig may span block boundary: */
+ strncpy((char *)G.hold, (char *)G.inbuf, 3);
+ }
+ } /* end if (ziplen > INBUFSIZ) */
+
+/*---------------------------------------------------------------------------
+ Searched through whole region where signature should be without finding
+ it. Print informational message and die a horrible death.
+ ---------------------------------------------------------------------------*/
+
+fail:
+ if (!found) {
+ if (uO.qflag || uO.zipinfo_mode)
+ Info(slide, 0x401, ((char *)slide, "[%s]\n", G.zipfn));
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(CentDirEndSigNotFound)));
+ return PK_ERR; /* failed */
+ }
+
+/*---------------------------------------------------------------------------
+ Found the signature, so get the end-central data before returning. Do
+ any necessary machine-type conversions (byte ordering, structure padding
+ compensation) by reading data into character array and copying to struct.
+ ---------------------------------------------------------------------------*/
+
+ G.real_ecrec_offset = G.cur_zipfile_bufstart + (G.inptr-G.inbuf);
+#ifdef TEST
+ printf("\n found end-of-central-dir signature at offset %ld (%.8lXh)\n",
+ G.real_ecrec_offset, G.real_ecrec_offset);
+ printf(" from beginning of file; offset %d (%.4Xh) within block\n",
+ G.inptr-G.inbuf, G.inptr-G.inbuf);
+#endif
+
+ if (readbuf(__G__ (char *)byterec, ECREC_SIZE+4) == 0)
+ return PK_EOF;
+
+ G.ecrec.number_this_disk =
+ makeword(&byterec[NUMBER_THIS_DISK]);
+ G.ecrec.num_disk_start_cdir =
+ makeword(&byterec[NUM_DISK_WITH_START_CENTRAL_DIR]);
+ G.ecrec.num_entries_centrl_dir_ths_disk =
+ makeword(&byterec[NUM_ENTRIES_CENTRL_DIR_THS_DISK]);
+ G.ecrec.total_entries_central_dir =
+ makeword(&byterec[TOTAL_ENTRIES_CENTRAL_DIR]);
+ G.ecrec.size_central_directory =
+ makelong(&byterec[SIZE_CENTRAL_DIRECTORY]);
+ G.ecrec.offset_start_central_directory =
+ makelong(&byterec[OFFSET_START_CENTRAL_DIRECTORY]);
+ G.ecrec.zipfile_comment_length =
+ makeword(&byterec[ZIPFILE_COMMENT_LENGTH]);
+
+ G.expect_ecrec_offset = G.ecrec.offset_start_central_directory +
+ G.ecrec.size_central_directory;
+ return PK_COOL;
+
+} /* end function find_ecrec() */
+
+
+
+
+
+/*****************************/
+/* Function uz_end_central() */
+/*****************************/
+
+int uz_end_central(__G) /* return PK-type error code */
+ __GDEF
+{
+ int error = PK_COOL;
+
+
+/*---------------------------------------------------------------------------
+ Get the zipfile comment (up to 64KB long), if any, and print it out.
+ Then position the file pointer to the beginning of the central directory
+ and fill buffer.
+ ---------------------------------------------------------------------------*/
+
+#ifdef WINDLL
+ /* for comment button: */
+ if ((!G.fValidate) && (G.lpUserFunctions != NULL))
+ G.lpUserFunctions->cchComment = G.ecrec.zipfile_comment_length;
+ if (G.ecrec.zipfile_comment_length && (uO.zflag > 0))
+#else /* !WINDLL */
+ if (G.ecrec.zipfile_comment_length && (uO.zflag > 0 ||
+ (uO.zflag == 0 &&
+#ifdef TIMESTAMP
+ !uO.T_flag &&
+#endif
+ !uO.qflag)))
+#endif /* ?WINDLL */
+ {
+ if (do_string(__G__ G.ecrec.zipfile_comment_length, DISPLAY)) {
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(ZipfileCommTrunc1)));
+ error = PK_WARN;
+ }
+ }
+ return error;
+
+} /* end function uz_end_central() */
+
+
+
+
+
+/************************************/
+/* Function process_cdir_file_hdr() */
+/************************************/
+
+int process_cdir_file_hdr(__G) /* return PK-type error code */
+ __GDEF
+{
+ int error;
+
+
+/*---------------------------------------------------------------------------
+ Get central directory info, save host and method numbers, and set flag
+ for lowercase conversion of filename, depending on the OS from which the
+ file is coming.
+ ---------------------------------------------------------------------------*/
+
+ if ((error = get_cdir_ent(__G)) != 0)
+ return error;
+
+ G.pInfo->hostnum = MIN(G.crec.version_made_by[1], NUM_HOSTS);
+/* extnum = MIN(crec.version_needed_to_extract[1], NUM_HOSTS); */
+
+ G.pInfo->lcflag = 0;
+ if (uO.L_flag) /* user specified case-conversion */
+ switch (G.pInfo->hostnum) {
+ case FS_FAT_: /* PKZIP and zip -k store in uppercase */
+ case CPM_: /* like MS-DOS, right? */
+ case VM_CMS_: /* all caps? */
+ case MVS_: /* all caps? */
+ case TANDEM_:
+ case TOPS20_:
+ case VMS_: /* our Zip uses lowercase, but ASi's doesn't */
+ /* case Z_SYSTEM_: ? */
+ /* case QDOS_: ? */
+ G.pInfo->lcflag = 1; /* convert filename to lowercase */
+ break;
+
+ default: /* AMIGA_, FS_HPFS_, FS_NTFS_, MAC_, UNIX_, ATARI_, */
+ break; /* FS_VFAT_, BEOS_ (Z_SYSTEM_): no conversion */
+ }
+
+ /* do Amigas (AMIGA_) also have volume labels? */
+ if (IS_VOLID(G.crec.external_file_attributes) &&
+ (G.pInfo->hostnum == FS_FAT_ || G.pInfo->hostnum == FS_HPFS_ ||
+ G.pInfo->hostnum == FS_NTFS_ || G.pInfo->hostnum == ATARI_))
+ {
+ G.pInfo->vollabel = TRUE;
+ G.pInfo->lcflag = 0; /* preserve case of volume labels */
+ } else
+ G.pInfo->vollabel = FALSE;
+
+ return PK_COOL;
+
+} /* end function process_cdir_file_hdr() */
+
+
+
+
+
+/***************************/
+/* Function get_cdir_ent() */
+/***************************/
+
+int get_cdir_ent(__G) /* return PK-type error code */
+ __GDEF
+{
+ cdir_byte_hdr byterec;
+
+
+/*---------------------------------------------------------------------------
+ Read the next central directory entry and do any necessary machine-type
+ conversions (byte ordering, structure padding compensation--do so by
+ copying the data from the array into which it was read (byterec) to the
+ usable struct (crec)).
+ ---------------------------------------------------------------------------*/
+
+ if (readbuf(__G__ (char *)byterec, CREC_SIZE) == 0)
+ return PK_EOF;
+
+ G.crec.version_made_by[0] = byterec[C_VERSION_MADE_BY_0];
+ G.crec.version_made_by[1] = byterec[C_VERSION_MADE_BY_1];
+ G.crec.version_needed_to_extract[0] =
+ byterec[C_VERSION_NEEDED_TO_EXTRACT_0];
+ G.crec.version_needed_to_extract[1] =
+ byterec[C_VERSION_NEEDED_TO_EXTRACT_1];
+
+ G.crec.general_purpose_bit_flag =
+ makeword(&byterec[C_GENERAL_PURPOSE_BIT_FLAG]);
+ G.crec.compression_method =
+ makeword(&byterec[C_COMPRESSION_METHOD]);
+ G.crec.last_mod_dos_datetime =
+ makelong(&byterec[C_LAST_MOD_DOS_DATETIME]);
+ G.crec.crc32 =
+ makelong(&byterec[C_CRC32]);
+ G.crec.csize =
+ makelong(&byterec[C_COMPRESSED_SIZE]);
+ G.crec.ucsize =
+ makelong(&byterec[C_UNCOMPRESSED_SIZE]);
+ G.crec.filename_length =
+ makeword(&byterec[C_FILENAME_LENGTH]);
+ G.crec.extra_field_length =
+ makeword(&byterec[C_EXTRA_FIELD_LENGTH]);
+ G.crec.file_comment_length =
+ makeword(&byterec[C_FILE_COMMENT_LENGTH]);
+ G.crec.disk_number_start =
+ makeword(&byterec[C_DISK_NUMBER_START]);
+ G.crec.internal_file_attributes =
+ makeword(&byterec[C_INTERNAL_FILE_ATTRIBUTES]);
+ G.crec.external_file_attributes =
+ makelong(&byterec[C_EXTERNAL_FILE_ATTRIBUTES]); /* LONG, not word! */
+ G.crec.relative_offset_local_header =
+ makelong(&byterec[C_RELATIVE_OFFSET_LOCAL_HEADER]);
+
+ return PK_COOL;
+
+} /* end function get_cdir_ent() */
+
+
+
+
+
+/*************************************/
+/* Function process_local_file_hdr() */
+/*************************************/
+
+int process_local_file_hdr(__G) /* return PK-type error code */
+ __GDEF
+{
+ local_byte_hdr byterec;
+
+
+/*---------------------------------------------------------------------------
+ Read the next local file header and do any necessary machine-type con-
+ versions (byte ordering, structure padding compensation--do so by copy-
+ ing the data from the array into which it was read (byterec) to the
+ usable struct (lrec)).
+ ---------------------------------------------------------------------------*/
+
+ if (readbuf(__G__ (char *)byterec, LREC_SIZE) == 0)
+ return PK_EOF;
+
+ G.lrec.version_needed_to_extract[0] =
+ byterec[L_VERSION_NEEDED_TO_EXTRACT_0];
+ G.lrec.version_needed_to_extract[1] =
+ byterec[L_VERSION_NEEDED_TO_EXTRACT_1];
+
+ G.lrec.general_purpose_bit_flag =
+ makeword(&byterec[L_GENERAL_PURPOSE_BIT_FLAG]);
+ G.lrec.compression_method = makeword(&byterec[L_COMPRESSION_METHOD]);
+ G.lrec.last_mod_dos_datetime = makelong(&byterec[L_LAST_MOD_DOS_DATETIME]);
+ G.lrec.crc32 = makelong(&byterec[L_CRC32]);
+ G.lrec.csize = makelong(&byterec[L_COMPRESSED_SIZE]);
+ G.lrec.ucsize = makelong(&byterec[L_UNCOMPRESSED_SIZE]);
+ G.lrec.filename_length = makeword(&byterec[L_FILENAME_LENGTH]);
+ G.lrec.extra_field_length = makeword(&byterec[L_EXTRA_FIELD_LENGTH]);
+
+ G.csize = (long) G.lrec.csize;
+ G.ucsize = (long) G.lrec.ucsize;
+
+ if ((G.lrec.general_purpose_bit_flag & 8) != 0) {
+ /* can't trust local header, use central directory: */
+ G.lrec.crc32 = G.pInfo->crc;
+ G.csize = (long)(G.lrec.csize = G.pInfo->compr_size);
+ G.ucsize = (long)(G.lrec.ucsize = G.pInfo->uncompr_size);
+ }
+
+ return PK_COOL;
+
+} /* end function process_local_file_hdr() */
+
+
+#ifdef USE_EF_UT_TIME
+
+/*******************************/
+/* Function ef_scan_for_izux() */
+/*******************************/
+
+unsigned ef_scan_for_izux(ef_buf, ef_len, ef_is_c, dos_mdatetime,
+ z_utim, z_uidgid)
+ uch *ef_buf; /* buffer containing extra field */
+ unsigned ef_len; /* total length of extra field */
+ int ef_is_c; /* flag indicating "is central extra field" */
+ ulg dos_mdatetime; /* last_mod_file_date_time in DOS format */
+ iztimes *z_utim; /* return storage: atime, mtime, ctime */
+ ush *z_uidgid; /* return storage: uid and gid */
+{
+ unsigned flags = 0;
+ unsigned eb_id;
+ unsigned eb_len;
+ int have_new_type_eb = FALSE;
+ int ut_zip_unzip_compatible = FALSE;
+
+/*---------------------------------------------------------------------------
+ This function scans the extra field for EF_TIME, EF_IZUNIX2, EF_IZUNIX, or
+ EF_PKUNIX blocks containing Unix-style time_t (GMT) values for the entry's
+ access, creation, and modification time.
+ If a valid block is found, the time stamps are copied to the iztimes
+ structure (provided the z_utim pointer is not NULL).
+ If a IZUNIX2 block is found or the IZUNIX block contains UID/GID fields,
+ and the z_uidgid array pointer is valid (!= NULL), the owner info is
+ transfered as well.
+ The presence of an EF_TIME or EF_IZUNIX2 block results in ignoring all
+ data from probably present obsolete EF_IZUNIX blocks.
+ If multiple blocks of the same type are found, only the information from
+ the last block is used.
+ The return value is a combination of the EF_TIME Flags field with an
+ additional flag bit indicating the presence of valid UID/GID info,
+ or 0 in case of failure.
+ ---------------------------------------------------------------------------*/
+
+ if (ef_len == 0 || ef_buf == NULL || (z_utim == 0 && z_uidgid == NULL))
+ return 0;
+
+ TTrace((stderr,"\nef_scan_for_izux: scanning extra field of length %u\n",
+ ef_len));
+
+ while (ef_len >= EB_HEADSIZE) {
+ eb_id = makeword(EB_ID + ef_buf);
+ eb_len = makeword(EB_LEN + ef_buf);
+
+ if (eb_len > (ef_len - EB_HEADSIZE)) {
+ /* discovered some extra field inconsistency! */
+ TTrace((stderr,
+ "ef_scan_for_izux: block length %u > rest ef_size %u\n", eb_len,
+ ef_len - EB_HEADSIZE));
+ break;
+ }
+
+ switch (eb_id) {
+ case EF_TIME:
+ flags &= ~0x0ff; /* ignore previous IZUNIX or EF_TIME fields */
+ have_new_type_eb = TRUE;
+ if ( eb_len >= EB_UT_MINLEN && z_utim != NULL) {
+ unsigned eb_idx = EB_UT_TIME1;
+ TTrace((stderr,"ef_scan_for_izux: found TIME extra field\n"));
+ flags |= (ef_buf[EB_HEADSIZE+EB_UT_FLAGS] & 0x0ff);
+ if ((flags & EB_UT_FL_MTIME)) {
+ if ((eb_idx+4) <= eb_len) {
+ z_utim->mtime = makelong((EB_HEADSIZE+eb_idx) + ef_buf);
+ eb_idx += 4;
+ TTrace((stderr," UT e.f. modification time = %ld\n",
+ z_utim->mtime));
+
+ if ((ulg)(z_utim->mtime) & (ulg)(0x80000000L)) {
+ ut_zip_unzip_compatible =
+ ((time_t)0x80000000L < (time_t)0L)
+ ? (dos_mdatetime == DOSTIME_MINIMUM)
+ : (dos_mdatetime >= DOSTIME_2038_01_18);
+ if (!ut_zip_unzip_compatible) {
+ /* UnZip interpretes mtime differently than Zip;
+ without modtime: ignore complete UT field */
+ flags &= ~0x0ff; /* no time_t times available */
+ TTrace((stderr,
+ " UT modtime range error; ignore e.f.!\n"));
+ break; /* stop scanning this field */
+ }
+ } else {
+ /* cannot determine, safe assumption is FALSE */
+ ut_zip_unzip_compatible = FALSE;
+ }
+ } else {
+ flags &= ~EB_UT_FL_MTIME;
+ TTrace((stderr," UT e.f. truncated; no modtime\n"));
+ }
+ }
+ if (ef_is_c) {
+ break; /* central version of TIME field ends here */
+ }
+
+ if (flags & EB_UT_FL_ATIME) {
+ if ((eb_idx+4) <= eb_len) {
+ z_utim->atime = makelong((EB_HEADSIZE+eb_idx) + ef_buf);
+ eb_idx += 4;
+ TTrace((stderr," UT e.f. access time = %ld\n",
+ z_utim->atime));
+ if (((ulg)(z_utim->atime) & (ulg)(0x80000000L)) &&
+ !ut_zip_unzip_compatible) {
+ flags &= ~EB_UT_FL_ATIME;
+ TTrace((stderr,
+ " UT access time range error: skip time!\n"));
+ }
+ } else {
+ flags &= ~EB_UT_FL_ATIME;
+ }
+ }
+ if (flags & EB_UT_FL_CTIME) {
+ if ((eb_idx+4) <= eb_len) {
+ z_utim->ctime = makelong((EB_HEADSIZE+eb_idx) + ef_buf);
+ TTrace((stderr," UT e.f. creation time = %ld\n",
+ z_utim->ctime));
+ if (((ulg)(z_utim->ctime) & (ulg)(0x80000000L)) &&
+ !ut_zip_unzip_compatible) {
+ flags &= ~EB_UT_FL_CTIME;
+ TTrace((stderr,
+ " UT creation time range error: skip time!\n"));
+ }
+ } else {
+ flags &= ~EB_UT_FL_CTIME;
+ }
+ }
+ }
+ break;
+
+ case EF_IZUNIX2:
+ if (!have_new_type_eb) {
+ flags &= ~0x0ff; /* ignore any previous IZUNIX field */
+ have_new_type_eb = TRUE;
+ }
+ if (eb_len >= EB_UX2_MINLEN && z_uidgid != NULL) {
+ z_uidgid[0] = makeword((EB_HEADSIZE+EB_UX2_UID) + ef_buf);
+ z_uidgid[1] = makeword((EB_HEADSIZE+EB_UX2_GID) + ef_buf);
+ flags |= EB_UX2_VALID; /* signal success */
+ }
+ break;
+
+ case EF_IZUNIX:
+ case EF_PKUNIX: /* PKUNIX e.f. layout is identical to IZUNIX */
+ if (eb_len >= EB_UX_MINLEN) {
+ TTrace((stderr,"ef_scan_for_izux: found %s extra field\n",
+ (eb_id == EF_IZUNIX ? "IZUNIX" : "PKUNIX")));
+ if (have_new_type_eb) {
+ break; /* Ignore IZUNIX extra field block ! */
+ }
+ if (z_utim != NULL) {
+ z_utim->atime = makelong((EB_HEADSIZE+EB_UX_ATIME)+ef_buf);
+ z_utim->mtime = makelong((EB_HEADSIZE+EB_UX_MTIME)+ef_buf);
+ TTrace((stderr," Unix EF actime = %ld\n", z_utim->atime));
+ TTrace((stderr," Unix EF modtime = %ld\n", z_utim->mtime));
+ flags |= (EB_UT_FL_MTIME | EB_UT_FL_ATIME);
+ if ((ulg)(z_utim->mtime) & (ulg)(0x80000000L)) {
+ ut_zip_unzip_compatible =
+ ((time_t)0x80000000L < (time_t)0L)
+ ? (dos_mdatetime == DOSTIME_MINIMUM)
+ : (dos_mdatetime >= DOSTIME_2038_01_18);
+ if (!ut_zip_unzip_compatible) {
+ /* UnZip interpretes mtime differently than Zip;
+ without modtime: ignore complete UT field */
+ flags &= ~0x0ff; /* no time_t times available */
+ TTrace((stderr,
+ " UX modtime range error: ignore e.f.!\n"));
+ }
+ } else {
+ /* cannot determine, safe assumption is FALSE */
+ ut_zip_unzip_compatible = FALSE;
+ }
+ if ((ulg)(z_utim->atime) & (ulg)(0x80000000L) &&
+ !ut_zip_unzip_compatible && (flags & 0x0ff)) {
+ /* atime not in range of UnZip's time_t */
+ flags &= ~EB_UT_FL_ATIME;
+ TTrace((stderr,
+ " UX access time range error: skip time!\n"));
+ }
+ }
+ if (eb_len >= EB_UX_FULLSIZE && z_uidgid != NULL) {
+ z_uidgid[0] = makeword((EB_HEADSIZE+EB_UX_UID) + ef_buf);
+ z_uidgid[1] = makeword((EB_HEADSIZE+EB_UX_GID) + ef_buf);
+ flags |= EB_UX2_VALID;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* Skip this extra field block */
+ ef_buf += (eb_len + EB_HEADSIZE);
+ ef_len -= (eb_len + EB_HEADSIZE);
+ }
+
+ return flags;
+}
+
+#endif /* USE_EF_UT_TIME */
diff --git a/Build/source/libs/unzip/ttyio.c b/Build/source/libs/unzip/ttyio.c
new file mode 100644
index 00000000000..c755d1c5a37
--- /dev/null
+++ b/Build/source/libs/unzip/ttyio.c
@@ -0,0 +1,625 @@
+/*---------------------------------------------------------------------------
+
+ ttyio.c
+
+ This file contains routines for doing console input/output, including code
+ for non-echoing input. It is used by the encryption/decryption code but
+ does not contain any restricted code itself. This file is shared between
+ Info-ZIP's Zip and UnZip.
+
+ Contains: echo() (VMS only)
+ Echon() (Unix only)
+ Echoff() (Unix only)
+ screenlines() (Unix only)
+ zgetch() (Unix and non-Unix versions)
+ getp() ("PC," Unix/Atari/Be, VMS/VMCMS/MVS)
+
+ ---------------------------------------------------------------------------*/
+
+#define __TTYIO_C /* identifies this source module */
+
+#include "zip.h"
+#include "crypt.h"
+
+#if (CRYPT || (defined(UNZIP) && !defined(FUNZIP)))
+/* Non-echo console/keyboard input is needed for (en/de)cryption's password
+ * entry, and for UnZip(SFX)'s MORE and Pause features.
+ * (The corresponding #endif is found at the end of this module.)
+ */
+
+#include "ttyio.h"
+
+#ifndef PUTC
+# define PUTC putc
+#endif
+
+#ifdef ZIP
+# ifdef GLOBAL /* used in Amiga system headers, maybe others too */
+# undef GLOBAL
+# endif
+# define GLOBAL(g) g
+#else
+# define GLOBAL(g) G.g
+#endif
+
+#ifdef __BEOS__ /* why yes, we do */
+# define HAVE_TERMIOS_H
+#endif
+
+#ifdef _POSIX_VERSION
+# ifndef USE_POSIX_TERMIOS
+# define USE_POSIX_TERMIOS /* use POSIX style termio (termios) */
+# endif
+# ifndef HAVE_TERMIOS_H
+# define HAVE_TERMIOS_H /* POSIX termios.h */
+# endif
+#endif /* _POSIX_VERSION */
+
+#ifdef UNZIP /* Zip handles this with the unix/configure script */
+# ifndef _POSIX_VERSION
+# if (defined(SYSV) || defined(CRAY)) && !defined(__MINT__)
+# ifndef USE_SYSV_TERMIO
+# define USE_SYSV_TERMIO
+# endif
+# ifdef COHERENT
+# ifndef HAVE_TERMIO_H
+# define HAVE_TERMIO_H
+# endif
+# ifdef HAVE_SYS_TERMIO_H
+# undef HAVE_SYS_TERMIO_H
+# endif
+# else /* !COHERENT */
+# ifdef HAVE_TERMIO_H
+# undef HAVE_TERMIO_H
+# endif
+# ifndef HAVE_SYS_TERMIO_H
+# define HAVE_SYS_TERMIO_H
+# endif
+# endif /* ?COHERENT */
+# endif /* (SYSV || CRAY) && !__MINT__ */
+# endif /* !_POSIX_VERSION */
+# if !(defined(BSD4_4) || defined(SYSV) || defined(__convexc__))
+# ifndef NO_FCNTL_H
+# define NO_FCNTL_H
+# endif
+# endif /* !(BSD4_4 || SYSV || __convexc__) */
+#endif /* UNZIP */
+
+#ifdef HAVE_TERMIOS_H
+# ifndef USE_POSIX_TERMIOS
+# define USE_POSIX_TERMIOS
+# endif
+#endif
+
+#if (defined(HAVE_TERMIO_H) || defined(HAVE_SYS_TERMIO_H))
+# ifndef USE_SYSV_TERMIO
+# define USE_SYSV_TERMIO
+# endif
+#endif
+
+#if (defined(UNZIP) && !defined(FUNZIP) && defined(UNIX) && defined(MORE))
+# include <sys/ioctl.h>
+# define GOT_IOCTL_H
+ /* int ioctl OF((int, int, zvoid *)); GRR: may need for some systems */
+#endif
+
+#ifndef HAVE_WORKING_GETCH
+ /* include system support for switching of console echo */
+# ifdef VMS
+# include <descrip.h>
+# include <iodef.h>
+# include <ttdef.h>
+# include <starlet.h>
+# include <ssdef.h>
+# else /* !VMS */
+# ifdef HAVE_TERMIOS_H
+# include <termios.h>
+# define sgttyb termios
+# define sg_flags c_lflag
+# define GTTY(f, s) tcgetattr(f, (zvoid *) s)
+# define STTY(f, s) tcsetattr(f, TCSAFLUSH, (zvoid *) s)
+# else /* !HAVE_TERMIOS_H */
+# ifdef USE_SYSV_TERMIO /* Amdahl, Cray, all SysV? */
+# ifdef HAVE_TERMIO_H
+# include <termio.h>
+# endif
+# ifdef HAVE_SYS_TERMIO_H
+# include <sys/termio.h>
+# endif
+# ifdef NEED_PTEM
+# include <sys/stream.h>
+# include <sys/ptem.h>
+# endif
+# define sgttyb termio
+# define sg_flags c_lflag
+# define GTTY(f,s) ioctl(f,TCGETA,(zvoid *)s)
+# define STTY(f,s) ioctl(f,TCSETAW,(zvoid *)s)
+# else /* !USE_SYSV_TERMIO */
+# ifndef CMS_MVS
+# if (!defined(MINIX) && !defined(GOT_IOCTL_H))
+# include <sys/ioctl.h>
+# endif
+# include <sgtty.h>
+# define GTTY gtty
+# define STTY stty
+# ifdef UNZIP
+ /*
+ * XXX : Are these declarations needed at all ????
+ */
+ /*
+ * GRR: let's find out... Hmmm, appears not...
+ int gtty OF((int, struct sgttyb *));
+ int stty OF((int, struct sgttyb *));
+ */
+# endif
+# endif /* !CMS_MVS */
+# endif /* ?USE_SYSV_TERMIO */
+# endif /* ?HAVE_TERMIOS_H */
+# ifndef NO_FCNTL_H
+# ifndef UNZIP
+# include <fcntl.h>
+# endif
+# else
+ char *ttyname OF((int));
+# endif
+# endif /* ?VMS */
+#endif /* !HAVE_WORKING_GETCH */
+
+
+
+#ifndef HAVE_WORKING_GETCH
+#ifdef VMS
+
+/*
+ * Turn keyboard echoing on or off (VMS). Loosely based on VMSmunch.c
+ * and hence on Joe Meadows' file.c code.
+ */
+int echo(opt)
+ int opt;
+{
+ /*
+ * For VMS v5.x:
+ * IO$_SENSEMODE/SETMODE info: Programming, Vol. 7A, System Programming,
+ * I/O User's: Part I, sec. 8.4.1.1, 8.4.3, 8.4.5, 8.6
+ * sys$assign(), sys$qio() info: Programming, Vol. 4B, System Services,
+ * System Services Reference Manual, pp. sys-23, sys-379
+ * fixed-length descriptor info: Programming, Vol. 3, System Services,
+ * Intro to System Routines, sec. 2.9.2
+ * Greg Roelofs, 15 Aug 91
+ */
+
+ /* SKM: make global? */
+ static struct dsc$descriptor_s DevDesc =
+ {11, DSC$K_DTYPE_T, DSC$K_CLASS_S, "SYS$COMMAND"};
+ /* {dsc$w_length, dsc$b_dtype, dsc$b_class, dsc$a_pointer}; */
+ static short DevChan, iosb[4];
+ static long status;
+ static unsigned long oldmode[2], newmode[2]; /* each = 8 bytes */
+
+
+ /* assign a channel to standard input */
+ status = sys$assign(&DevDesc, &DevChan, 0, 0);
+ if (!(status & 1))
+ return status;
+
+ /* use sys$qio and the IO$_SENSEMODE function to determine the current
+ * tty status (for password reading, could use IO$_READVBLK function
+ * instead, but echo on/off will be more general)
+ */
+ status = sys$qiow(0, DevChan, IO$_SENSEMODE, &iosb, 0, 0,
+ oldmode, 8, 0, 0, 0, 0);
+ if (!(status & 1))
+ return status;
+ status = iosb[0];
+ if (!(status & 1))
+ return status;
+
+ /* copy old mode into new-mode buffer, then modify to be either NOECHO or
+ * ECHO (depending on function argument opt)
+ */
+ newmode[0] = oldmode[0];
+ newmode[1] = oldmode[1];
+ if (opt == 0) /* off */
+ newmode[1] |= TT$M_NOECHO; /* set NOECHO bit */
+ else
+ newmode[1] &= ~((unsigned long) TT$M_NOECHO); /* clear NOECHO bit */
+
+ /* use the IO$_SETMODE function to change the tty status */
+ status = sys$qiow(0, DevChan, IO$_SETMODE, &iosb, 0, 0,
+ newmode, 8, 0, 0, 0, 0);
+ if (!(status & 1))
+ return status;
+ status = iosb[0];
+ if (!(status & 1))
+ return status;
+
+ /* deassign the sys$input channel by way of clean-up */
+ status = sys$dassgn(DevChan);
+ if (!(status & 1))
+ return status;
+
+ return SS$_NORMAL; /* we be happy */
+
+} /* end function echo() */
+
+
+#else /* !VMS: basically Unix */
+
+
+/* For VM/CMS and MVS, non-echo terminal input is not (yet?) supported. */
+#ifndef CMS_MVS
+
+#ifdef ZIP /* moved to globals.h for UnZip */
+ static int echofd=(-1); /* file descriptor whose echo is off */
+#endif
+
+/*
+ * Turn echo off for file descriptor f. Assumes that f is a tty device.
+ */
+void Echoff(__G__ f)
+ __GDEF
+ int f; /* file descriptor for which to turn echo off */
+{
+ struct sgttyb sg; /* tty device structure */
+
+ GLOBAL(echofd) = f;
+ GTTY(f, &sg); /* get settings */
+ sg.sg_flags &= ~ECHO; /* turn echo off */
+ STTY(f, &sg);
+}
+
+/*
+ * Turn echo back on for file descriptor echofd.
+ */
+void Echon(__G)
+ __GDEF
+{
+ struct sgttyb sg; /* tty device structure */
+
+ if (GLOBAL(echofd) != -1) {
+ GTTY(GLOBAL(echofd), &sg); /* get settings */
+ sg.sg_flags |= ECHO; /* turn echo on */
+ STTY(GLOBAL(echofd), &sg);
+ GLOBAL(echofd) = -1;
+ }
+}
+
+#endif /* !CMS_MVS */
+#endif /* ?VMS */
+
+
+#if (defined(UNZIP) && !defined(FUNZIP))
+
+#if (defined(UNIX) || defined(__BEOS__))
+#ifdef MORE
+
+/*
+ * Get the number of lines on the output terminal. SCO Unix apparently
+ * defines TIOCGWINSZ but doesn't support it (!M_UNIX).
+ *
+ * GRR: will need to know width of terminal someday, too, to account for
+ * line-wrapping.
+ */
+
+#if (defined(TIOCGWINSZ) && !defined(M_UNIX))
+
+int screenlines()
+{
+ struct winsize wsz;
+#ifdef DEBUG_WINSZ
+ static int firsttime = TRUE;
+#endif
+
+ /* see termio(4) under, e.g., SunOS */
+ if (ioctl(1, TIOCGWINSZ, &wsz) == 0) {
+#ifdef DEBUG_WINSZ
+ if (firsttime) {
+ firsttime = FALSE;
+ fprintf(stderr, "ttyio.c screenlines(): ws_row = %d\n",
+ wsz.ws_row);
+ }
+#endif
+ /* number of columns = ws_col */
+ return (wsz.ws_row > 0)? wsz.ws_row : 24; /* number of rows */
+
+ } else { /* this happens when piping to more(1), for example */
+#ifdef DEBUG_WINSZ
+ if (firsttime) {
+ firsttime = FALSE;
+ fprintf(stderr,
+ "ttyio.c screenlines(): ioctl(TIOCGWINSZ) failed\n"));
+ }
+#endif
+ return 24; /* VT-100 assumed to be minimal hardware */
+ }
+}
+
+#else /* !TIOCGWINSZ: service not available, fall back to semi-bogus method */
+
+int screenlines()
+{
+ char *envptr, *getenv();
+ int n;
+
+ /* GRR: this is overly simplistic, but don't have access to stty/gtty
+ * system anymore
+ */
+ envptr = getenv("LINES");
+ if (envptr == (char *)NULL || (n = atoi(envptr)) < 5)
+ return 24; /* VT-100 assumed to be minimal hardware */
+ else
+ return n;
+}
+
+#endif /* ?(TIOCGWINSZ && !M_UNIX) */
+#endif /* MORE */
+
+
+/*
+ * Get a character from the given file descriptor without echo or newline.
+ */
+int zgetch(__G__ f)
+ __GDEF
+ int f; /* file descriptor from which to read */
+{
+#if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS))
+ char oldmin, oldtim;
+#endif
+ char c;
+ struct sgttyb sg; /* tty device structure */
+
+ GTTY(f, &sg); /* get settings */
+#if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS))
+ oldmin = sg.c_cc[VMIN]; /* save old values */
+ oldtim = sg.c_cc[VTIME];
+ sg.c_cc[VMIN] = 1; /* need only one char to return read() */
+ sg.c_cc[VTIME] = 0; /* no timeout */
+ sg.sg_flags &= ~ICANON; /* canonical mode off */
+#else
+ sg.sg_flags |= CBREAK; /* cbreak mode on */
+#endif
+ sg.sg_flags &= ~ECHO; /* turn echo off, too */
+ STTY(f, &sg); /* set cbreak mode */
+ GLOBAL(echofd) = f; /* in case ^C hit (not perfect: still CBREAK) */
+
+ read(f, &c, 1); /* read our character */
+
+#if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS))
+ sg.c_cc[VMIN] = oldmin; /* restore old values */
+ sg.c_cc[VTIME] = oldtim;
+ sg.sg_flags |= ICANON; /* canonical mode on */
+#else
+ sg.sg_flags &= ~CBREAK; /* cbreak mode off */
+#endif
+ sg.sg_flags |= ECHO; /* turn echo on */
+ STTY(f, &sg); /* restore canonical mode */
+ GLOBAL(echofd) = -1;
+
+ return (int)c;
+}
+
+
+#else /* !UNIX && !__BEOS__ */
+
+
+int zgetch(__G__ f)
+ __GDEF
+ int f; /* file descriptor from which to read (must be open already) */
+{
+ char c, c2;
+
+/*---------------------------------------------------------------------------
+ Get a character from the given file descriptor without echo; can't fake
+ CBREAK mode (i.e., newline required), but can get rid of all chars up to
+ and including newline.
+ ---------------------------------------------------------------------------*/
+
+ echoff(f);
+ read(f, &c, 1);
+ if (c != '\n')
+ do {
+ read(f, &c2, 1); /* throw away all other chars up thru newline */
+ } while (c2 != '\n');
+ echon();
+ return (int)c;
+}
+
+#endif /* ?(UNIX || __BEOS__) */
+
+#endif /* UNZIP && !FUNZIP */
+#endif /* !HAVE_WORKING_GETCH */
+
+
+#if CRYPT /* getp() is only used with full encryption */
+
+/*
+ * Simple compile-time check for source compatibility between
+ * zcrypt and ttyio:
+ */
+#if (!defined(CR_MAJORVER) || (CR_MAJORVER < 2) || (CR_MINORVER < 7))
+ error: This Info-ZIP tool requires zcrypt 2.7 or later.
+#endif
+
+/*
+ * Get a password of length n-1 or less into *p using the prompt *m.
+ * The entered password is not echoed.
+ */
+
+#ifdef HAVE_WORKING_GETCH
+/*
+ * For the AMIGA, getch() is defined as Agetch(), which is in
+ * amiga/filedate.c; SAS/C 6.x provides a getch(), but since Agetch()
+ * uses the infrastructure that is already in place in filedate.c, it is
+ * smaller. With this function, echoff() and echon() are not needed.
+ *
+ * For the MAC, a non-echo macgetch() function is defined in the MacOS
+ * specific sources which uses the event handling mechanism of the
+ * desktop window manager to get a character from the keyboard.
+ *
+ * For the other systems in this section, a non-echo getch() function
+ * is either contained the C runtime library (conio package), or getch()
+ * is defined as an alias for a similar system specific RTL function.
+ */
+
+#ifndef WINDLL /* WINDLL does not support a console interface */
+#ifndef QDOS /* QDOS supplies a variant of this function */
+
+/* This is the getp() function for all systems (with TTY type user interface)
+ * that supply a working `non-echo' getch() function for "raw" console input.
+ */
+char *getp(__G__ m, p, n)
+ __GDEF
+ ZCONST char *m; /* prompt for password */
+ char *p; /* return value: line input */
+ int n; /* bytes available in p[] */
+{
+ char c; /* one-byte buffer for read() to use */
+ int i; /* number of characters input */
+ char *w; /* warning on retry */
+
+ /* get password */
+ w = "";
+ do {
+ fputs(w, stderr); /* warning if back again */
+ fputs(m, stderr); /* display prompt and flush */
+ fflush(stderr);
+ i = 0;
+ do { /* read line, keeping first n characters */
+ if ((c = (char)getch()) == '\r')
+ c = '\n'; /* until user hits CR */
+ if (c == 8 || c == 127) {
+ if (i > 0) i--; /* the `backspace' and `del' keys works */
+ }
+ else if (i < n)
+ p[i++] = c; /* truncate past n */
+ } while (c != '\n');
+ PUTC('\n', stderr); fflush(stderr);
+ w = "(line too long--try again)\n";
+ } while (p[i-1] != '\n');
+ p[i-1] = 0; /* terminate at newline */
+
+ return p; /* return pointer to password */
+
+} /* end function getp() */
+
+#endif /* !QDOS */
+#endif /* !WINDLL */
+
+
+#else /* !HAVE_WORKING_GETCH */
+
+
+#if (defined(UNIX) || defined(__MINT__) || defined(__BEOS__))
+
+#ifndef _PATH_TTY
+# ifdef __MINT__
+# define _PATH_TTY ttyname(2)
+# else
+# define _PATH_TTY "/dev/tty"
+# endif
+#endif
+
+char *getp(__G__ m, p, n)
+ __GDEF
+ ZCONST char *m; /* prompt for password */
+ char *p; /* return value: line input */
+ int n; /* bytes available in p[] */
+{
+ char c; /* one-byte buffer for read() to use */
+ int i; /* number of characters input */
+ char *w; /* warning on retry */
+ int f; /* file descriptor for tty device */
+
+#ifdef PASSWD_FROM_STDIN
+ /* Read from stdin. This is unsafe if the password is stored on disk. */
+ f = 0;
+#else
+ /* turn off echo on tty */
+
+ if ((f = open(_PATH_TTY, 0)) == -1)
+ return NULL;
+#endif
+ /* get password */
+ w = "";
+ do {
+ fputs(w, stderr); /* warning if back again */
+ fputs(m, stderr); /* prompt */
+ fflush(stderr);
+ i = 0;
+ echoff(f);
+ do { /* read line, keeping n */
+ read(f, &c, 1);
+ if (i < n)
+ p[i++] = c;
+ } while (c != '\n');
+ echon();
+ PUTC('\n', stderr); fflush(stderr);
+ w = "(line too long--try again)\n";
+ } while (p[i-1] != '\n');
+ p[i-1] = 0; /* terminate at newline */
+
+#ifndef PASSWD_FROM_STDIN
+ close(f);
+#endif
+
+ return p; /* return pointer to password */
+
+} /* end function getp() */
+
+#endif /* UNIX || __MINT__ || __BEOS__ */
+
+
+
+#if (defined(VMS) || defined(CMS_MVS))
+
+char *getp(__G__ m, p, n)
+ __GDEF
+ ZCONST char *m; /* prompt for password */
+ char *p; /* return value: line input */
+ int n; /* bytes available in p[] */
+{
+ char c; /* one-byte buffer for read() to use */
+ int i; /* number of characters input */
+ char *w; /* warning on retry */
+ FILE *f; /* file structure for SYS$COMMAND device */
+
+#ifdef PASSWD_FROM_STDIN
+ f = stdin;
+#else
+ if ((f = fopen(ctermid(NULL), "r")) == NULL)
+ return NULL;
+#endif
+
+ /* get password */
+ fflush(stdout);
+ w = "";
+ do {
+ if (*w) /* bug: VMS apparently adds \n to NULL fputs */
+ fputs(w, stderr); /* warning if back again */
+ fputs(m, stderr); /* prompt */
+ fflush(stderr);
+ i = 0;
+ echoff(f);
+ do { /* read line, keeping n */
+ if ((c = (char)getc(f)) == '\r')
+ c = '\n';
+ if (i < n)
+ p[i++] = c;
+ } while (c != '\n');
+ echon();
+ PUTC('\n', stderr); fflush(stderr);
+ w = "(line too long--try again)\n";
+ } while (p[i-1] != '\n');
+ p[i-1] = 0; /* terminate at newline */
+#ifndef PASSWD_FROM_STDIN
+ fclose(f);
+#endif
+
+ return p; /* return pointer to password */
+
+} /* end function getp() */
+
+#endif /* VMS || CMS_MVS */
+#endif /* ?HAVE_WORKING_GETCH */
+#endif /* CRYPT */
+#endif /* CRYPT || (UNZIP && !FUNZIP) */
diff --git a/Build/source/libs/unzip/ttyio.h b/Build/source/libs/unzip/ttyio.h
new file mode 100644
index 00000000000..685e7ace66b
--- /dev/null
+++ b/Build/source/libs/unzip/ttyio.h
@@ -0,0 +1,186 @@
+/*
+ ttyio.h
+ */
+
+#ifndef __ttyio_h /* don't include more than once */
+#define __ttyio_h
+
+#ifndef __crypt_h
+# include "crypt.h" /* ensure that encryption header file has been seen */
+#endif
+
+#if (CRYPT || (defined(UNZIP) && !defined(FUNZIP)))
+/*
+ * Non-echo keyboard/console input support is needed and enabled.
+ */
+
+#ifndef __G /* UnZip only, for now (DLL stuff) */
+# define __G
+# define __G__
+# define __GDEF
+# define __GPRO void
+# define __GPRO__
+#endif
+
+#ifndef ZCONST /* UnZip only (until have configure script like Zip) */
+# define ZCONST const
+#endif
+
+#if (defined(MSDOS) || defined(OS2) || defined(WIN32))
+# ifndef DOS_OS2_W32
+# define DOS_OS2_W32
+# endif
+#endif
+
+#if (defined(DOS_OS2_W32) || defined(__human68k__))
+# ifndef DOS_H68_OS2_W32
+# define DOS_H68_OS2_W32
+# endif
+#endif
+
+#if (defined(DOS_OS2_W32) || defined(FLEXOS))
+# ifndef DOS_FLX_OS2_W32
+# define DOS_FLX_OS2_W32
+# endif
+#endif
+
+#if (defined(DOS_H68_OS2_W32) || defined(FLEXOS))
+# ifndef DOS_FLX_H68_OS2_W32
+# define DOS_FLX_H68_OS2_W32
+# endif
+#endif
+
+#if (defined(VM_CMS) || defined(MVS))
+# ifndef CMS_MVS
+# define CMS_MVS
+# endif
+#endif
+
+
+/* Function prototypes */
+
+/* The following systems supply a `non-echo' character input function "getch()"
+ * (or an alias) and do not need the echoff() / echon() function pair.
+ */
+#ifdef AMIGA
+# define echoff(f)
+# define echon()
+# define getch() Agetch()
+# define HAVE_WORKING_GETCH
+#endif /* AMIGA */
+
+#ifdef ATARI
+# define echoff(f)
+# define echon()
+# include <osbind.h>
+# define getch() (Cnecin() & 0x000000ff)
+# define HAVE_WORKING_GETCH
+#endif
+
+#ifdef MACOS
+# define echoff(f)
+# define echon()
+# define getch() macgetch()
+# define HAVE_WORKING_GETCH
+#endif
+
+#ifdef QDOS
+# define echoff(f)
+# define echon()
+# define HAVE_WORKING_GETCH
+#endif
+
+#ifdef RISCOS
+# define echoff(f)
+# define echon()
+# define getch() SWI_OS_ReadC()
+# define HAVE_WORKING_GETCH
+#endif
+
+#ifdef DOS_H68_OS2_W32
+# define echoff(f)
+# define echon()
+# ifdef WIN32
+# ifndef getch
+# define getch() getch_win32()
+# endif
+# else /* !WIN32 */
+# ifdef __EMX__
+# ifndef getch
+# define getch() _read_kbd(0, 1, 0)
+# endif
+# else /* !__EMX__ */
+# ifdef __GO32__
+# include <pc.h>
+# define getch() getkey()
+# else /* !__GO32__ */
+# include <conio.h>
+# endif /* ?__GO32__ */
+# endif /* ?__EMX__ */
+# endif /* ?WIN32 */
+# define HAVE_WORKING_GETCH
+#endif /* DOS_H68_OS2_W32 */
+
+#ifdef FLEXOS
+# define echoff(f)
+# define echon()
+# define getch() getchar() /* not correct, but may not be on a console */
+# define HAVE_WORKING_GETCH
+#endif
+
+/* For VM/CMS and MVS, we do not (yet) have any support to switch terminal
+ * input echo on and off. The following "fake" definitions allow inclusion
+ * of crypt support and UnZip's "pause prompting" features, but without
+ * any echo suppression.
+ */
+#ifdef CMS_MVS
+# define echoff(f)
+# define echon()
+#endif
+
+/* VMS has a single echo() function in ttyio.c to toggle terminal
+ * input echo on and off.
+ */
+#ifdef VMS
+# define echoff(f) echo(0)
+# define echon() echo(1)
+ int echo OF((int));
+#endif
+
+/* For all other systems, ttyio.c supplies the two functions Echoff() and
+ * Echon() for suppressing and (re)enabling console input echo.
+ */
+#ifndef echoff
+# define echoff(f) Echoff(__G__ f)
+# define echon() Echon(__G)
+ void Echoff OF((__GPRO__ int f));
+ void Echon OF((__GPRO));
+#endif
+
+/* this stuff is used by MORE and also now by the ctrl-S code; fileio.c only */
+#if (defined(UNZIP) && !defined(FUNZIP))
+# ifdef HAVE_WORKING_GETCH
+# define FGETCH(f) getch()
+# endif
+# ifndef FGETCH
+ /* default for all systems where no getch()-like function is available */
+ int zgetch OF((__GPRO__ int f));
+# define FGETCH(f) zgetch(__G__ f)
+# endif
+#endif /* UNZIP && !FUNZIP */
+
+#if (CRYPT && !defined(WINDLL))
+ char *getp OF((__GPRO__ ZCONST char *m, char *p, int n));
+#endif
+
+#else /* !(CRYPT || (UNZIP && !FUNZIP)) */
+
+/*
+ * No need for non-echo keyboard/console input; provide dummy definitions.
+ */
+#define echoff(f)
+#define echon()
+
+#endif /* ?(CRYPT || (UNZIP && !FUNZIP)) */
+
+#endif /* !__ttyio_h */
diff --git a/Build/source/libs/unzip/unreduce.c b/Build/source/libs/unzip/unreduce.c
new file mode 100644
index 00000000000..4cfb3fec6f5
--- /dev/null
+++ b/Build/source/libs/unzip/unreduce.c
@@ -0,0 +1,230 @@
+/*---------------------------------------------------------------------------
+
+ unreduce.c
+
+ The Reducing algorithm is actually a combination of two distinct algorithms.
+ The first algorithm compresses repeated byte sequences, and the second al-
+ gorithm takes the compressed stream from the first algorithm and applies a
+ probabilistic compression method.
+
+ * Copyright 1989 Samuel H. Smith; All rights reserved
+ *
+ * Do not distribute modified versions without my permission.
+ * Do not remove or alter this notice or any other copyright notice.
+ * If you use this in your own program you must distribute source code.
+ * Do not use any of this in a commercial product.
+
+ See the accompanying file "COPYING" in UnZip source and binary distributions
+ for further information. This code is NOT used unless USE_SMITH_CODE is
+ explicitly defined (==> COPYRIGHT_CLEAN is not defined).
+
+ ---------------------------------------------------------------------------*/
+
+
+#define UNZIP_INTERNAL
+#include "unzip.h" /* defines COPYRIGHT_CLEAN by default */
+
+
+#ifndef COPYRIGHT_CLEAN
+
+/**************************************/
+/* UnReduce Defines, Typedefs, etc. */
+/**************************************/
+
+#define DLE 144
+
+typedef uch f_array[64]; /* for followers[256][64] */
+
+
+
+/******************************/
+/* UnReduce Local Functions */
+/******************************/
+
+static void LoadFollowers OF((__GPRO__ f_array *followers, uch *Slen));
+
+
+
+/*******************************/
+/* UnReduce Global Constants */
+/*******************************/
+
+static ZCONST shrint L_table[] =
+{0, 0x7f, 0x3f, 0x1f, 0x0f};
+
+static ZCONST shrint D_shift[] =
+{0, 0x07, 0x06, 0x05, 0x04};
+static ZCONST shrint D_mask[] =
+{0, 0x01, 0x03, 0x07, 0x0f};
+
+static ZCONST shrint B_table[] =
+{8, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8};
+
+
+
+
+
+/*************************/
+/* Function unreduce() */
+/*************************/
+
+void unreduce(__G) /* expand probabilistically reduced data */
+ __GDEF
+{
+ register int lchar = 0;
+ shrint nchar;
+ shrint ExState = 0;
+ shrint V = 0;
+ shrint Len = 0;
+ long s = G.ucsize; /* number of bytes left to decompress */
+ unsigned w = 0; /* position in output window slide[] */
+ unsigned u = 1; /* true if slide[] unflushed */
+ uch Slen[256];
+
+ f_array *followers = (f_array *)(slide + 0x4000);
+ int factor = G.lrec.compression_method - 1;
+
+ LoadFollowers(__G__ followers, Slen);
+
+ while (s > 0 /* && (!zipeof) */) {
+ if (Slen[lchar] == 0)
+ READBITS(8, nchar) /* ; */
+ else {
+ READBITS(1, nchar) /* ; */
+ if (nchar != 0)
+ READBITS(8, nchar) /* ; */
+ else {
+ shrint follower;
+ int bitsneeded = B_table[Slen[lchar]];
+
+ READBITS(bitsneeded, follower) /* ; */
+ nchar = followers[lchar][follower];
+ }
+ }
+ /* expand the resulting byte */
+ switch (ExState) {
+
+ case 0:
+ if (nchar != DLE) {
+ s--;
+ slide[w++] = (uch)nchar;
+ if (w == 0x4000) {
+ flush(__G__ slide, (ulg)w, 0);
+ w = u = 0;
+ }
+ }
+ else
+ ExState = 1;
+ break;
+
+ case 1:
+ if (nchar != 0) {
+ V = nchar;
+ Len = V & L_table[factor];
+ if (Len == L_table[factor])
+ ExState = 2;
+ else
+ ExState = 3;
+ } else {
+ s--;
+ slide[w++] = DLE;
+ if (w == 0x4000)
+ {
+ flush(__G__ slide, (ulg)w, 0);
+ w = u = 0;
+ }
+ ExState = 0;
+ }
+ break;
+
+ case 2:{
+ Len += nchar;
+ ExState = 3;
+ }
+ break;
+
+ case 3:{
+ register unsigned e;
+ register unsigned n = Len + 3;
+ register unsigned d = w - ((((V >> D_shift[factor]) &
+ D_mask[factor]) << 8) + nchar + 1);
+
+ s -= n;
+ do {
+ n -= (e = (e = 0x4000 - ((d &= 0x3fff) > w ? d : w)) > n ?
+ n : e);
+ if (u && w <= d)
+ {
+ memzero(slide + w, e);
+ w += e;
+ d += e;
+ }
+ else
+ if (w - d < e) /* (assume unsigned comparison) */
+ do { /* slow to avoid memcpy() overlap */
+ slide[w++] = slide[d++];
+ } while (--e);
+ else
+ {
+ memcpy(slide + w, slide + d, e);
+ w += e;
+ d += e;
+ }
+ if (w == 0x4000)
+ {
+ flush(__G__ slide, (ulg)w, 0);
+ w = u = 0;
+ }
+ } while (n);
+
+ ExState = 0;
+ }
+ break;
+ }
+
+ /* store character for next iteration */
+ lchar = nchar;
+ }
+
+ /* flush out slide */
+ flush(__G__ slide, (ulg)w, 0);
+}
+
+
+
+
+
+/******************************/
+/* Function LoadFollowers() */
+/******************************/
+
+static void LoadFollowers(__G__ followers, Slen)
+ __GDEF
+ f_array *followers;
+ uch *Slen;
+{
+ register int x;
+ register int i;
+
+ for (x = 255; x >= 0; x--) {
+ READBITS(6, Slen[x]) /* ; */
+ for (i = 0; (uch)i < Slen[x]; i++)
+ READBITS(8, followers[x][i]) /* ; */
+ }
+}
+
+#endif /* !COPYRIGHT_CLEAN */
diff --git a/Build/source/libs/unzip/unshrink.c b/Build/source/libs/unzip/unshrink.c
new file mode 100644
index 00000000000..2b7e6f027f0
--- /dev/null
+++ b/Build/source/libs/unzip/unshrink.c
@@ -0,0 +1,301 @@
+/*---------------------------------------------------------------------------
+
+ unshrink.c version 1.21 23 Nov 95
+
+
+ NOTE: This code may or may not infringe on the so-called "Welch
+ patent" owned by Unisys. (From reading the patent, it appears
+ that a pure LZW decompressor is *not* covered, but this claim has
+ not been tested in court, and Unisys is reported to believe other-
+ wise.) It is therefore the responsibility of the user to acquire
+ whatever license(s) may be required for legal use of this code.
+
+ THE INFO-ZIP GROUP DISCLAIMS ALL LIABILITY FOR USE OF THIS CODE
+ IN VIOLATION OF APPLICABLE PATENT LAW.
+
+
+ Shrinking is basically a dynamic LZW algorithm with allowed code sizes of
+ up to 13 bits; in addition, there is provision for partial clearing of
+ leaf nodes. PKWARE uses the special code 256 (decimal) to indicate a
+ change in code size or a partial clear of the code tree: 256,1 for the
+ former and 256,2 for the latter. [Note that partial clearing can "orphan"
+ nodes: the parent-to-be can be cleared before its new child is added,
+ but the child is added anyway (as an orphan, as though the parent still
+ existed). When the tree fills up to the point where the parent node is
+ reused, the orphan is effectively "adopted." Versions prior to 1.05 were
+ affected more due to greater use of pointers (to children and siblings
+ as well as parents).]
+
+ This replacement version of unshrink.c was written from scratch. It is
+ based only on the algorithms described in Mark Nelson's _The Data Compres-
+ sion Book_ and in Terry Welch's original paper in the June 1984 issue of
+ IEEE _Computer_; no existing source code, including any in Nelson's book,
+ was used.
+
+ Memory requirements have been reduced in this version and are now no more
+ than the original Sam Smith code. This is still larger than any of the
+ other algorithms: at a minimum, 8K+8K+16K (stack+values+parents) assuming
+ 16-bit short ints, and this does not even include the output buffer (the
+ other algorithms leave the uncompressed data in the work area, typically
+ called slide[]). For machines with a 64KB data space this is a problem,
+ particularly when text conversion is required and line endings have more
+ than one character. UnZip's solution is to use two roughly equal halves
+ of outbuf for the ASCII conversion in such a case; the "unshrink" argument
+ to flush() signals that this is the case.
+
+ For large-memory machines, a second outbuf is allocated for translations,
+ but only if unshrinking and only if translations are required.
+
+ | binary mode | text mode
+ ---------------------------------------------------
+ big mem | big outbuf | big outbuf + big outbuf2 <- malloc'd here
+ small mem | small outbuf | half + half small outbuf
+
+ Copyright 1994, 1995 Greg Roelofs. See the accompanying file "COPYING"
+ in UnZip 5.20 (or later) source or binary distributions.
+
+ ---------------------------------------------------------------------------*/
+
+
+#define UNZIP_INTERNAL
+#include "unzip.h" /* defines LZW_CLEAN by default */
+
+
+#ifndef LZW_CLEAN
+
+static void partial_clear OF((__GPRO));
+
+#ifdef DEBUG
+# define OUTDBG(c) \
+ if ((c)<32 || (c)>=127) fprintf(stderr,"\\x%02x",(c)); else putc((c),stderr);
+#else
+# define OUTDBG(c)
+#endif
+
+/* HSIZE is defined as 2^13 (8192) in unzip.h */
+#define BOGUSCODE 256
+#define FLAG_BITS parent /* upper bits of parent[] used as flag bits */
+#define CODE_MASK (HSIZE - 1) /* 0x1fff (lower bits are parent's index) */
+#define FREE_CODE HSIZE /* 0x2000 (code is unused or was cleared) */
+#define HAS_CHILD (HSIZE << 1) /* 0x4000 (code has a child--do not clear) */
+
+#define parent G.area.shrink.Parent
+#define Value G.area.shrink.value /* "value" conflicts with Pyramid ioctl.h */
+#define stack G.area.shrink.Stack
+
+
+/***********************/
+/* Function unshrink() */
+/***********************/
+
+int unshrink(__G)
+ __GDEF
+{
+ int offset = (HSIZE - 1);
+ uch *stacktop = stack + offset;
+ register uch *newstr;
+ int codesize=9, len, KwKwK, error;
+ shrint code, oldcode, freecode, curcode;
+ shrint lastfreecode;
+ unsigned int outbufsiz;
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+ /* Normally realbuf and outbuf will be the same. However, if the data
+ * are redirected to a large memory buffer, realbuf will point to the
+ * new location while outbuf will remain pointing to the malloc'd
+ * memory buffer. */
+ uch *realbuf = G.outbuf;
+#else
+# define realbuf G.outbuf
+#endif
+
+
+/*---------------------------------------------------------------------------
+ Initialize various variables.
+ ---------------------------------------------------------------------------*/
+
+ lastfreecode = BOGUSCODE;
+
+#ifndef VMS /* VMS uses its own buffer scheme for textmode flush(). */
+#ifndef SMALL_MEM
+ /* non-memory-limited machines: allocate second (large) buffer for
+ * textmode conversion in flush(), but only if needed */
+ if (G.pInfo->textmode && !G.outbuf2 &&
+ (G.outbuf2 = (uch *)malloc(TRANSBUFSIZ)) == (uch *)NULL)
+ return PK_MEM3;
+#endif
+#endif /* !VMS */
+
+ for (code = 0; code < BOGUSCODE; ++code) {
+ Value[code] = (uch)code;
+ parent[code] = BOGUSCODE;
+ }
+ for (code = BOGUSCODE+1; code < HSIZE; ++code)
+ parent[code] = FREE_CODE;
+
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+ if (G.redirect_slide) { /* use normal outbuf unless we're a DLL routine */
+ realbuf = G.redirect_buffer;
+ outbufsiz = G.redirect_size;
+ } else
+#endif
+#ifdef DLL
+ if (G.pInfo->textmode && !G.redirect_data)
+#else
+ if (G.pInfo->textmode)
+#endif
+ outbufsiz = RAWBUFSIZ;
+ else
+ outbufsiz = OUTBUFSIZ;
+ G.outptr = realbuf;
+ G.outcnt = 0L;
+
+/*---------------------------------------------------------------------------
+ Get and output first code, then loop over remaining ones.
+ ---------------------------------------------------------------------------*/
+
+ READBITS(codesize, oldcode)
+ if (!G.zipeof) {
+ *G.outptr++ = (uch)oldcode;
+ OUTDBG((uch)oldcode)
+ ++G.outcnt;
+ }
+
+ do {
+ READBITS(codesize, code)
+ if (G.zipeof)
+ break;
+ if (code == BOGUSCODE) { /* possible to have consecutive escapes? */
+ READBITS(codesize, code)
+ if (code == 1) {
+ ++codesize;
+ Trace((stderr, " (codesize now %d bits)\n", codesize));
+ } else if (code == 2) {
+ Trace((stderr, " (partial clear code)\n"));
+ partial_clear(__G); /* clear leafs (nodes with no children) */
+ Trace((stderr, " (done with partial clear)\n"));
+ lastfreecode = BOGUSCODE; /* reset start of free-node search */
+ }
+ continue;
+ }
+
+ /*-----------------------------------------------------------------------
+ Translate code: traverse tree from leaf back to root.
+ -----------------------------------------------------------------------*/
+
+ newstr = stacktop;
+ curcode = code;
+
+ if (parent[curcode] == FREE_CODE) {
+ /* or (FLAG_BITS[curcode] & FREE_CODE)? */
+ KwKwK = TRUE;
+ Trace((stderr, " (found a KwKwK code %d; oldcode = %d)\n", code,
+ oldcode));
+ --newstr; /* last character will be same as first character */
+ curcode = oldcode;
+ } else
+ KwKwK = FALSE;
+
+ do {
+ *newstr-- = Value[curcode];
+ curcode = (shrint)(parent[curcode] & CODE_MASK);
+ } while (curcode != BOGUSCODE);
+
+ len = (int)(stacktop - newstr++);
+ if (KwKwK)
+ *stacktop = *newstr;
+
+ /*-----------------------------------------------------------------------
+ Write expanded string in reverse order to output buffer.
+ -----------------------------------------------------------------------*/
+
+ Trace((stderr, "code %4d; oldcode %4d; char %3d (%c); string [", code,
+ oldcode, (int)(*newstr), (*newstr<32 || *newstr>=127)? ' ':*newstr));
+
+ {
+ register uch *p;
+
+ for (p = newstr; p < newstr+len; ++p) {
+ *G.outptr++ = *p;
+ OUTDBG(*p)
+ if (++G.outcnt == outbufsiz) {
+ Trace((stderr, "doing flush(), outcnt = %lu\n", G.outcnt));
+ if ((error = flush(__G__ realbuf, G.outcnt, TRUE)) != 0)
+ fprintf(stderr, "unshrink: flush() error (%d)\n",
+ error);
+ Trace((stderr, "done with flush()\n"));
+ G.outptr = realbuf;
+ G.outcnt = 0L;
+ }
+ }
+ }
+
+ /*-----------------------------------------------------------------------
+ Add new leaf (first character of newstr) to tree as child of oldcode.
+ -----------------------------------------------------------------------*/
+
+ /* search for freecode */
+ freecode = (shrint)(lastfreecode + 1);
+ /* add if-test before loop for speed? */
+ while (parent[freecode] != FREE_CODE)
+ ++freecode;
+ lastfreecode = freecode;
+ Trace((stderr, "]; newcode %d\n", freecode));
+
+ Value[freecode] = *newstr;
+ parent[freecode] = oldcode;
+ oldcode = code;
+
+ } while (!G.zipeof);
+
+/*---------------------------------------------------------------------------
+ Flush any remaining data and return to sender...
+ ---------------------------------------------------------------------------*/
+
+ if (G.outcnt > 0L) {
+ Trace((stderr, "doing final flush(), outcnt = %lu\n", G.outcnt));
+ if ((error = flush(__G__ realbuf, G.outcnt, TRUE)) != 0)
+ fprintf(stderr, "unshrink: flush() error (%d)\n", error);
+ Trace((stderr, "done with flush()\n"));
+ }
+
+ return PK_OK;
+
+} /* end function unshrink() */
+
+
+
+
+
+/****************************/
+/* Function partial_clear() */ /* no longer recursive... */
+/****************************/
+
+static void partial_clear(__G)
+ __GDEF
+{
+ register shrint code;
+
+ /* clear all nodes which have no children (i.e., leaf nodes only) */
+
+ /* first loop: mark each parent as such */
+ for (code = BOGUSCODE+1; code < HSIZE; ++code) {
+ register shrint cparent = (shrint)(parent[code] & CODE_MASK);
+
+ if (cparent > BOGUSCODE && cparent != FREE_CODE)
+ FLAG_BITS[cparent] |= HAS_CHILD; /* set parent's child-bit */
+ }
+
+ /* second loop: clear all nodes *not* marked as parents; reset flag bits */
+ for (code = BOGUSCODE+1; code < HSIZE; ++code) {
+ if (FLAG_BITS[code] & HAS_CHILD) /* just clear child-bit */
+ FLAG_BITS[code] &= ~HAS_CHILD;
+ else { /* leaf: lose it */
+ Trace((stderr, "%d\n", code));
+ parent[code] = FREE_CODE;
+ }
+ }
+
+ return;
+}
+
+#endif /* !LZW_CLEAN */
diff --git a/Build/source/libs/unzip/unzip.dep b/Build/source/libs/unzip/unzip.dep
new file mode 100644
index 00000000000..bd73bc2bbbd
--- /dev/null
+++ b/Build/source/libs/unzip/unzip.dep
@@ -0,0 +1,191 @@
+# Microsoft Developer Studio Generated Dependency File, included by unzip.mak
+
+.\api.c : \
+ ".\globals.h"\
+ ".\unzip.h"\
+ ".\unzpriv.h"\
+ ".\version.h"\
+ ".\win32\w32cfg.h"\
+ ".\windll\decs.h"\
+ ".\windll\structs.h"\
+ ".\windll\windll.h"\
+ "c:\program files\microsoft visual studio\vc98\include\basetsd.h"\
+
+
+.\crc32.c : \
+ ".\globals.h"\
+ ".\unzip.h"\
+ ".\unzpriv.h"\
+ ".\win32\w32cfg.h"\
+ ".\windll\structs.h"\
+ ".\zip.h"\
+ "c:\program files\microsoft visual studio\vc98\include\basetsd.h"\
+
+
+.\crctab.c : \
+ ".\globals.h"\
+ ".\unzip.h"\
+ ".\unzpriv.h"\
+ ".\win32\w32cfg.h"\
+ ".\windll\structs.h"\
+ ".\zip.h"\
+ "c:\program files\microsoft visual studio\vc98\include\basetsd.h"\
+
+
+.\explode.c : \
+ ".\globals.h"\
+ ".\unzip.h"\
+ ".\unzpriv.h"\
+ ".\win32\w32cfg.h"\
+ ".\windll\structs.h"\
+ "c:\program files\microsoft visual studio\vc98\include\basetsd.h"\
+
+
+.\extract.c : \
+ ".\crypt.h"\
+ ".\globals.h"\
+ ".\unzip.h"\
+ ".\unzpriv.h"\
+ ".\win32\w32cfg.h"\
+ ".\windll\decs.h"\
+ ".\windll\structs.h"\
+ ".\windll\windll.h"\
+ "c:\program files\microsoft visual studio\vc98\include\basetsd.h"\
+
+
+.\fileio.c : \
+ ".\crypt.h"\
+ ".\ebcdic.h"\
+ ".\globals.h"\
+ ".\ttyio.h"\
+ ".\unzip.h"\
+ ".\unzpriv.h"\
+ ".\win32\w32cfg.h"\
+ ".\windll\decs.h"\
+ ".\windll\structs.h"\
+ ".\windll\windll.h"\
+ "c:\program files\microsoft visual studio\vc98\include\basetsd.h"\
+
+
+.\globals.c : \
+ ".\globals.h"\
+ ".\unzip.h"\
+ ".\unzpriv.h"\
+ ".\win32\w32cfg.h"\
+ ".\windll\structs.h"\
+ "c:\program files\microsoft visual studio\vc98\include\basetsd.h"\
+
+
+.\inflate.c : \
+ ".\globals.h"\
+ ".\inflate.h"\
+ ".\unzip.h"\
+ ".\unzpriv.h"\
+ ".\win32\w32cfg.h"\
+ ".\windll\structs.h"\
+ "c:\program files\microsoft visual studio\vc98\include\basetsd.h"\
+
+
+.\list.c : \
+ ".\globals.h"\
+ ".\unzip.h"\
+ ".\unzpriv.h"\
+ ".\win32\w32cfg.h"\
+ ".\windll\decs.h"\
+ ".\windll\structs.h"\
+ ".\windll\windll.h"\
+ "c:\program files\microsoft visual studio\vc98\include\basetsd.h"\
+
+
+.\match.c : \
+ ".\globals.h"\
+ ".\unzip.h"\
+ ".\unzpriv.h"\
+ ".\win32\w32cfg.h"\
+ ".\windll\structs.h"\
+ "c:\program files\microsoft visual studio\vc98\include\basetsd.h"\
+
+
+.\win32\nt.c : \
+ ".\globals.h"\
+ ".\unzip.h"\
+ ".\unzpriv.h"\
+ ".\win32\nt.h"\
+ ".\win32\w32cfg.h"\
+ ".\windll\structs.h"\
+ "c:\program files\microsoft visual studio\vc98\include\basetsd.h"\
+
+
+.\process.c : \
+ ".\globals.h"\
+ ".\unzip.h"\
+ ".\unzpriv.h"\
+ ".\win32\w32cfg.h"\
+ ".\windll\decs.h"\
+ ".\windll\structs.h"\
+ ".\windll\windll.h"\
+ "c:\program files\microsoft visual studio\vc98\include\basetsd.h"\
+
+
+.\ttyio.c : \
+ ".\crypt.h"\
+ ".\globals.h"\
+ ".\ttyio.h"\
+ ".\unzip.h"\
+ ".\unzpriv.h"\
+ ".\win32\w32cfg.h"\
+ ".\windll\structs.h"\
+ ".\zip.h"\
+ "c:\program files\microsoft visual studio\vc98\include\basetsd.h"\
+
+
+.\unreduce.c : \
+ ".\globals.h"\
+ ".\unzip.h"\
+ ".\unzpriv.h"\
+ ".\win32\w32cfg.h"\
+ ".\windll\structs.h"\
+ "c:\program files\microsoft visual studio\vc98\include\basetsd.h"\
+
+
+.\unshrink.c : \
+ ".\globals.h"\
+ ".\unzip.h"\
+ ".\unzpriv.h"\
+ ".\win32\w32cfg.h"\
+ ".\windll\structs.h"\
+ "c:\program files\microsoft visual studio\vc98\include\basetsd.h"\
+
+
+.\win32\win32.c : \
+ ".\globals.h"\
+ ".\unzip.h"\
+ ".\unzpriv.h"\
+ ".\win32\nt.h"\
+ ".\win32\w32cfg.h"\
+ ".\windll\structs.h"\
+ "c:\program files\microsoft visual studio\vc98\include\basetsd.h"\
+
+
+.\windll\windll.c : \
+ ".\consts.h"\
+ ".\crypt.h"\
+ ".\globals.h"\
+ ".\unzip.h"\
+ ".\unzpriv.h"\
+ ".\version.h"\
+ ".\win32\w32cfg.h"\
+ ".\windll\decs.h"\
+ ".\windll\structs.h"\
+ ".\windll\windll.h"\
+ "c:\program files\microsoft visual studio\vc98\include\basetsd.h"\
+
+
+.\zipinfo.c : \
+ ".\globals.h"\
+ ".\unzip.h"\
+ ".\unzpriv.h"\
+ ".\win32\w32cfg.h"\
+ ".\windll\structs.h"\
+ "c:\program files\microsoft visual studio\vc98\include\basetsd.h"\
+
diff --git a/Build/source/libs/unzip/unzip.dsp b/Build/source/libs/unzip/unzip.dsp
new file mode 100644
index 00000000000..51a1f2edbe1
--- /dev/null
+++ b/Build/source/libs/unzip/unzip.dsp
@@ -0,0 +1,258 @@
+# Microsoft Developer Studio Project File - Name="unzip" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=unzip - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "unzip.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "unzip.mak" CFG="unzip - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "unzip - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "unzip - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "unzip - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "./" /I "../" /I "../.." /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "_WINDOWS" /D "WINDLL" /D "USE_EF_UT_TIME" /D "DLL" /D "UNZIPLIB" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x40c /d "NDEBUG"
+# ADD RSC /l 0x40c /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "unzip - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /MTd /W3 /Gm- /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "NDEBUG" /D "_WINDOWS" /D "WINDLL" /D "USE_EF_UT_TIME" /D "DLL" /D "UNZIPLIB" /FD /GZ /c
+# SUBTRACT CPP /nologo /YX
+# ADD BASE RSC /l 0x40c /d "_DEBUG"
+# ADD RSC /l 0x40c /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ENDIF
+
+# Begin Target
+
+# Name "unzip - Win32 Release"
+# Name "unzip - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\api.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\crc32.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\crctab.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\crypt.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\explode.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\extract.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\fileio.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\globals.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\inflate.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\list.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\match.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\win32\nt.c
+
+!IF "$(CFG)" == "unzip - Win32 Release"
+
+!ELSEIF "$(CFG)" == "unzip - Win32 Debug"
+
+# ADD CPP /I "../" /I "./"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\process.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ttyio.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\unreduce.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\unshrink.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\win32\win32.c
+
+!IF "$(CFG)" == "unzip - Win32 Release"
+
+!ELSEIF "$(CFG)" == "unzip - Win32 Debug"
+
+# ADD CPP /I "../" /I "./"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\windll\windll.c
+
+!IF "$(CFG)" == "unzip - Win32 Release"
+
+!ELSEIF "$(CFG)" == "unzip - Win32 Debug"
+
+# ADD CPP /I "../" /I "./"
+# SUBTRACT CPP /nologo /YX /Yc /Yu
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\zipinfo.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\consts.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\crypt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\windll\decs.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ebcdic.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\globals.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\inflate.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\win32\nt.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\windll\structs.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ttyio.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\unzip.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\unzpriv.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\version.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\win32\w32cfg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\windll\windll.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\zip.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/Build/source/libs/unzip/unzip.dsw b/Build/source/libs/unzip/unzip.dsw
new file mode 100644
index 00000000000..43f75699e1b
--- /dev/null
+++ b/Build/source/libs/unzip/unzip.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "unzip"=".\unzip.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/Build/source/libs/unzip/unzip.h b/Build/source/libs/unzip/unzip.h
new file mode 100644
index 00000000000..be12eda7d75
--- /dev/null
+++ b/Build/source/libs/unzip/unzip.h
@@ -0,0 +1,545 @@
+/*---------------------------------------------------------------------------
+
+ unzip.h (new)
+
+ This header file contains the public macros and typedefs required by
+ both the UnZip sources and by any application using the UnZip API. If
+ UNZIP_INTERNAL is defined, it includes unzpriv.h (containing includes,
+ prototypes and extern variables used by the actual UnZip sources).
+
+ ---------------------------------------------------------------------------*/
+
+
+#ifndef __unzip_h /* prevent multiple inclusions */
+#define __unzip_h
+
+/*---------------------------------------------------------------------------
+ Predefined, machine-specific macros.
+ ---------------------------------------------------------------------------*/
+
+#ifdef __GO32__ /* MS-DOS extender: NOT Unix */
+# ifdef unix
+# undef unix
+# endif
+# ifdef __unix
+# undef __unix
+# endif
+# ifdef __unix__
+# undef __unix__
+# endif
+#endif
+
+#if ((defined(__convex__) || defined(__convexc__)) && !defined(CONVEX))
+# define CONVEX
+#endif
+
+#if (defined(unix) || defined(__unix) || defined(__unix__))
+# ifndef UNIX
+# define UNIX
+# endif
+#endif /* unix || __unix || __unix__ */
+#if (defined(M_XENIX) || defined(COHERENT) || defined(__hpux))
+# ifndef UNIX
+# define UNIX
+# endif
+#endif /* M_XENIX || COHERENT || __hpux */
+#if (defined(CONVEX) || defined(MINIX) || defined(_AIX) || defined(__QNX__))
+# ifndef UNIX
+# define UNIX
+# endif
+#endif /* CONVEX || MINIX || _AIX || __QNX__ */
+
+#if (defined(VM_CMS) || defined(MVS))
+# define CMS_MVS
+#endif
+
+#if (defined(__OS2__) && !defined(OS2))
+# define OS2
+#endif
+
+#if (defined(__TANDEM) && !defined(TANDEM))
+# define TANDEM
+#endif
+
+#if (defined(__VMS) && !defined(VMS))
+# define VMS
+#endif
+
+#if ((defined(__WIN32__) || defined(_WIN32)) && !defined(WIN32))
+# define WIN32
+#endif
+#if ((defined(__WINNT__) || defined(__WINNT)) && !defined(WIN32))
+# define WIN32
+#endif
+
+#ifdef __COMPILER_KCC__
+# include <c-env.h>
+# ifdef SYS_T20
+# define TOPS20
+# endif
+#endif /* __COMPILER_KCC__ */
+
+/* Borland C does not define __TURBOC__ if compiling for a 32-bit platform */
+#ifdef __BORLANDC__
+# ifndef __TURBOC__
+# define __TURBOC__
+# endif
+# if (!defined(__MSDOS__) && !defined(OS2) && !defined(WIN32))
+# define __MSDOS__
+# endif
+#endif
+
+/* define MSDOS for Turbo C (unless OS/2) and Power C as well as Microsoft C */
+#ifdef __POWERC
+# define __TURBOC__
+# define MSDOS
+#endif /* __POWERC */
+
+#if (defined(__MSDOS__) && !defined(MSDOS)) /* just to make sure */
+# define MSDOS
+#endif
+
+/* RSXNTDJ (at least up to v1.3) compiles for WIN32 (RSXNT) using a derivate
+ of the EMX environment, but defines MSDOS and __GO32__. ARG !!! */
+#if (defined(MSDOS) && defined(WIN32))
+# undef MSDOS /* WIN32 is >>>not<<< MSDOS */
+#endif
+#if (defined(__GO32__) && defined(__EMX__) && defined(__RSXNT__))
+# undef __GO32__
+#endif
+
+#if (defined(linux) && !defined(LINUX))
+# define LINUX
+#endif
+
+#ifdef __riscos
+# define RISCOS
+#endif
+
+#if (defined(THINK_C) || defined(MPW))
+# define MACOS
+#endif
+#if (defined(__MWERKS__) && defined(macintosh))
+# define MACOS
+#endif
+
+/* use prototypes and ANSI libraries if __STDC__, or Microsoft or Borland C, or
+ * Silicon Graphics, or Convex?, or IBM C Set/2, or GNU gcc/emx, or Watcom C,
+ * or Macintosh, or Windows NT, or Sequent, or Atari or IBM RS/6000.
+ */
+#if (defined(__STDC__) || defined(MSDOS) || defined(WIN32) || defined(__EMX__))
+# ifndef PROTO
+# define PROTO
+# endif
+# ifndef MODERN
+# define MODERN
+# endif
+#endif
+#if (defined(__IBMC__) || defined(__BORLANDC__) || defined(__WATCOMC__))
+# ifndef PROTO
+# define PROTO
+# endif
+# ifndef MODERN
+# define MODERN
+# endif
+#endif
+#if (defined(MACOS) || defined(ATARI_ST) || defined(RISCOS))
+# ifndef PROTO
+# define PROTO
+# endif
+# ifndef MODERN
+# define MODERN
+# endif
+#endif
+/* Sequent running Dynix/ptx: non-modern compiler */
+#if (defined(_AIX) || defined(sgi) || (defined(_SEQUENT_) && !defined(PTX)))
+# ifndef PROTO
+# define PROTO
+# endif
+# ifndef MODERN
+# define MODERN
+# endif
+#endif
+#if (defined(CMS_MVS) || defined(__BEOS__)) /* || defined(CONVEX) */
+# ifndef PROTO
+# define PROTO
+# endif
+# ifndef MODERN
+# define MODERN
+# endif
+#endif
+
+/* turn off prototypes if requested */
+#if (defined(NOPROTO) && defined(PROTO))
+# undef PROTO
+#endif
+
+/* used to remove arguments in function prototypes for non-ANSI C */
+#ifdef PROTO
+# define OF(a) a
+#else
+# define OF(a) ()
+#endif
+
+/* enable the "const" keyword only if MODERN and if not otherwise instructed */
+#ifdef MODERN
+# if (!defined(ZCONST) && (defined(USE_CONST) || !defined(NO_CONST)))
+# define ZCONST const
+# endif
+#endif
+
+#ifndef ZCONST
+# define ZCONST
+#endif
+
+
+/*---------------------------------------------------------------------------
+ Grab system-specific public include headers.
+ ---------------------------------------------------------------------------*/
+
+#ifdef POCKET_UNZIP /* WinCE port */
+# include "wince/punzip.h" /* must appear before windows.h */
+#endif
+
+#ifdef WINDLL
+# include <windows.h>
+# include "windll/structs.h"
+#endif
+
+/*---------------------------------------------------------------------------
+ Grab system-dependent definition of EXPENTRY for prototypes below.
+ ---------------------------------------------------------------------------*/
+
+#if 0
+#if (defined(OS2) && !defined(FUNZIP))
+# ifdef UNZIP_INTERNAL
+# define INCL_NOPM
+# define INCL_DOSNLS
+# define INCL_DOSPROCESS
+# define INCL_DOSDEVICES
+# define INCL_DOSDEVIOCTL
+# define INCL_DOSERRORS
+# define INCL_DOSMISC
+# ifdef OS2DLL
+# define INCL_REXXSAA
+# include <rexxsaa.h>
+# endif
+# endif /* UNZIP_INTERNAL */
+# include <os2.h>
+# define UZ_EXP EXPENTRY
+#endif /* OS2 && !FUNZIP */
+#endif /* 0 */
+
+#if (defined(OS2) && !defined(FUNZIP))
+# if (defined(__IBMC__) || defined(__WATCOMC__))
+# define UZ_EXP _System /* compiler keyword */
+# else
+# define UZ_EXP
+# endif
+#endif /* OS2 && !FUNZIP */
+
+#if (defined(WINDLL) || defined(USE_UNZIP_LIB))
+# ifndef EXPENTRY
+# define UZ_EXP WINAPI
+# else
+# define UZ_EXP EXPENTRY
+# endif
+#endif
+
+#ifndef UZ_EXP
+# define UZ_EXP
+#endif
+
+
+/*---------------------------------------------------------------------------
+ Public typedefs.
+ ---------------------------------------------------------------------------*/
+
+#ifndef _IZ_TYPES_DEFINED
+#ifdef MODERN
+ typedef void zvoid;
+#else /* !MODERN */
+# ifndef AOS_VS /* mostly modern? */
+# ifndef VAXC /* not fully modern, but has knows 'void' */
+# define void int
+# endif /* !VAXC */
+# endif /* !AOS_VS */
+ typedef char zvoid;
+#endif /* ?MODERN */
+typedef unsigned char uch; /* code assumes unsigned bytes; these type- */
+typedef unsigned short ush; /* defs replace byte/UWORD/ULONG (which are */
+typedef unsigned long ulg; /* predefined on some systems) & match zip */
+#define _IZ_TYPES_DEFINED
+#endif /* !_IZ_TYPES_DEFINED */
+
+/* InputFn is not yet used and is likely to change: */
+#ifdef PROTO
+ typedef int (UZ_EXP MsgFn) (zvoid *pG, uch *buf, ulg size, int flag);
+ typedef int (UZ_EXP InputFn) (zvoid *pG, uch *buf, int *size, int flag);
+ typedef void (UZ_EXP PauseFn) (zvoid *pG, ZCONST char *prompt, int flag);
+ typedef int (UZ_EXP PasswdFn) (zvoid *pG, int *rcnt, char *pwbuf,
+ int size, ZCONST char *zfn,
+ ZCONST char *efn);
+ typedef int (UZ_EXP StatCBFn) (zvoid *pG, int fnflag, ZCONST char *zfn,
+ ZCONST char *efn, ZCONST zvoid *details);
+ typedef void (UZ_EXP UsrIniFn) (void);
+#else /* !PROTO */
+ typedef int (UZ_EXP MsgFn) ();
+ typedef int (UZ_EXP InputFn) ();
+ typedef void (UZ_EXP PauseFn) ();
+ typedef int (UZ_EXP PasswdFn) ();
+ typedef int (UZ_EXP StatCBFn) ();
+ typedef void (UZ_EXP UsrIniFn) ();
+#endif /* ?PROTO */
+
+typedef struct _UzpBuffer { /* rxstr */
+ ulg strlength; /* length of string */
+ char *strptr; /* pointer to string */
+} UzpBuffer;
+
+typedef struct _UzpInit {
+ ulg structlen; /* length of the struct being passed */
+
+ /* GRR: can we assume that each of these is a 32-bit pointer? if not,
+ * does it matter? add "far" keyword to make sure? */
+ MsgFn *msgfn;
+ InputFn *inputfn;
+ PauseFn *pausefn;
+ UsrIniFn *userfn; /* user init function to be called after */
+ /* globals constructed and initialized */
+
+ /* pointer to program's environment area or something? */
+ /* hooks for performance testing? */
+ /* hooks for extra unzip -v output? (detect CPU or other hardware?) */
+ /* anything else? let me (Greg) know... */
+} UzpInit;
+
+typedef struct _UzpCB {
+ ulg structlen; /* length of the struct being passed */
+ /* GRR: can we assume that each of these is a 32-bit pointer? if not,
+ * does it matter? add "far" keyword to make sure? */
+ MsgFn *msgfn;
+ InputFn *inputfn;
+ PauseFn *pausefn;
+ PasswdFn *passwdfn;
+ StatCBFn *statrepfn;
+} UzpCB;
+
+/* the collection of general UnZip option flags and option arguments */
+typedef struct _UzpOpts {
+#ifndef FUNZIP
+ char *exdir; /* pointer to extraction root directory (-d option) */
+ char *pwdarg; /* pointer to command-line password (-P option) */
+ int zipinfo_mode; /* behave like ZipInfo or like normal UnZip? */
+ int aflag; /* -a: do ASCII-EBCDIC and/or end-of-line translation */
+#ifdef VMS
+ int bflag; /* -b: force fixed record format for binary files */
+#endif
+#ifdef UNIXBACKUP
+ int B_flag; /* -B: back up existing files by renaming to *~ first */
+#endif
+ int cflag; /* -c: output to stdout */
+ int C_flag; /* -C: match filenames case-insensitively */
+#ifdef MACOS
+ int E_flag; /* -E: [MacOS] show Mac extra field during restoring */
+#endif
+ int fflag; /* -f: "freshen" (extract only newer files) */
+#if (defined(RISCOS) || defined(ACORN_FTYPE_NFS))
+ int acorn_nfs_ext; /* -F: RISC OS types & NFS filetype extensions */
+#endif
+ int hflag; /* -h: header line (zipinfo) */
+#ifdef MACOS
+ int i_flag; /* -i: [MacOS] ignore filenames stored in Mac e.f. */
+#endif
+#ifdef RISCOS
+ int scanimage; /* -I: scan image files */
+#endif
+ int jflag; /* -j: junk pathnames (unzip) */
+#if (defined(__BEOS__) || defined(MACOS))
+ int J_flag; /* -J: ignore BeOS/MacOS extra field info (unzip) */
+#endif
+ int lflag; /* -12slmv: listing format (zipinfo) */
+ int L_flag; /* -L: convert filenames from some OSes to lowercase */
+ int overwrite_none; /* -n: never overwrite files (no prompting) */
+#ifdef AMIGA
+ int N_flag; /* -N: restore comments as AmigaDOS filenotes */
+#endif
+ int overwrite_all; /* -o: OK to overwrite files without prompting */
+#endif /* !FUNZIP */
+ int qflag; /* -q: produce a lot less output */
+#ifndef FUNZIP
+#if (defined(MSDOS) || defined(FLEXOS) || defined(OS2) || defined(WIN32))
+ int sflag; /* -s: convert spaces in filenames to underscores */
+#endif
+#if (defined(MSDOS) || defined(OS2) || defined(WIN32))
+ int volflag; /* -$: extract volume labels */
+#endif
+ int tflag; /* -t: test (unzip) or totals line (zipinfo) */
+ int T_flag; /* -T: timestamps (unzip) or dec. time fmt (zipinfo) */
+ int uflag; /* -u: "update" (extract only newer/brand-new files) */
+ int vflag; /* -v: (verbosely) list directory */
+ int V_flag; /* -V: don't strip VMS version numbers */
+#if (defined(TANDEM) || defined(UNIX) || defined(VMS) || defined(__BEOS__))
+ int X_flag; /* -X: restore owner/protection or UID/GID or ACLs */
+#endif
+#if (defined(OS2) || defined(WIN32))
+ int X_flag; /* -X: restore owner/protection or UID/GID or ACLs */
+#endif
+ int zflag; /* -z: display the zipfile comment (only, for unzip) */
+#endif /* !FUNZIP */
+} UzpOpts;
+
+/* intended to be a private struct: */
+typedef struct _ver {
+ uch major; /* e.g., integer 5 */
+ uch minor; /* e.g., 2 */
+ uch patchlevel; /* e.g., 0 */
+ uch not_used;
+} _version_type;
+
+typedef struct _UzpVer {
+ ulg structlen; /* length of the struct being passed */
+ ulg flag; /* bit 0: is_beta bit 1: uses_zlib */
+ char *betalevel; /* e.g., "g BETA" or "" */
+ char *date; /* e.g., "4 Sep 95" (beta) or "4 September 1995" */
+ char *zlib_version; /* e.g., "0.95" or NULL */
+ _version_type unzip;
+ _version_type zipinfo;
+ _version_type os2dll;
+ _version_type windll;
+} UzpVer;
+
+/* for Visual BASIC access to Windows DLLs: */
+typedef struct _UzpVer2 {
+ ulg structlen; /* length of the struct being passed */
+ ulg flag; /* bit 0: is_beta bit 1: uses_zlib */
+ char betalevel[10]; /* e.g., "g BETA" or "" */
+ char date[20]; /* e.g., "4 Sep 95" (beta) or "4 September 1995" */
+ char zlib_version[10]; /* e.g., "0.95" or NULL */
+ _version_type unzip;
+ _version_type zipinfo;
+ _version_type os2dll;
+ _version_type windll;
+} UzpVer2;
+
+typedef struct central_directory_file_header { /* CENTRAL */
+ uch version_made_by[2];
+ uch version_needed_to_extract[2];
+ ush general_purpose_bit_flag;
+ ush compression_method;
+ ulg last_mod_dos_datetime;
+ ulg crc32;
+ ulg csize;
+ ulg ucsize;
+ ush filename_length;
+ ush extra_field_length;
+ ush file_comment_length;
+ ush disk_number_start;
+ ush internal_file_attributes;
+ ulg external_file_attributes;
+ ulg relative_offset_local_header;
+} cdir_file_hdr;
+
+
+#define UZPINIT_LEN sizeof(UzpInit)
+#define UZPVER_LEN sizeof(UzpVer)
+#define cbList(func) int (* UZ_EXP func)(char *filename, cdir_file_hdr *crec)
+
+
+/*---------------------------------------------------------------------------
+ Return (and exit) values of the public UnZip API functions.
+ ---------------------------------------------------------------------------*/
+
+/* external return codes */
+#define PK_OK 0 /* no error */
+#define PK_COOL 0 /* no error */
+#define PK_GNARLY 0 /* no error */
+#define PK_WARN 1 /* warning error */
+#define PK_ERR 2 /* error in zipfile */
+#define PK_BADERR 3 /* severe error in zipfile */
+#define PK_MEM 4 /* insufficient memory (during initialization) */
+#define PK_MEM2 5 /* insufficient memory (password failure) */
+#define PK_MEM3 6 /* insufficient memory (file decompression) */
+#define PK_MEM4 7 /* insufficient memory (memory decompression) */
+#define PK_MEM5 8 /* insufficient memory (not yet used) */
+#define PK_NOZIP 9 /* zipfile not found */
+#define PK_PARAM 10 /* bad or illegal parameters specified */
+#define PK_FIND 11 /* no files found */
+#define PK_DISK 50 /* disk full */
+#define PK_EOF 51 /* unexpected EOF */
+
+#define IZ_CTRLC 80 /* user hit ^C to terminate */
+#define IZ_UNSUP 81 /* no files found: all unsup. compr/encrypt. */
+#define IZ_BADPWD 82 /* no files found: all had bad password */
+
+/* internal and DLL-only return codes */
+#define IZ_DIR 76 /* potential zipfile is a directory */
+#define IZ_CREATED_DIR 77 /* directory created: set time and permissions */
+#define IZ_VOL_LABEL 78 /* volume label, but can't set on hard disk */
+#define IZ_EF_TRUNC 79 /* local extra field truncated (PKZIP'd) */
+
+/* return codes of password fetches (negative = user abort; positive = error) */
+#define IZ_PW_ENTERED 0 /* got some password string; use/try it */
+#define IZ_PW_CANCEL -1 /* no password available (for this entry) */
+#define IZ_PW_CANCELALL -2 /* no password, skip any further pwd. request */
+#define IZ_PW_ERROR 5 /* = PK_MEM2 : failure (no mem, no tty, ...) */
+
+/* flag values for status callback function */
+#define UZ_ST_START_EXTRACT 1
+#define UZ_ST_IN_PROGRESS 2
+#define UZ_ST_FINISH_MEMBER 3
+
+/* return values of status callback function */
+#define UZ_ST_CONTINUE 0
+#define UZ_ST_BREAK 1
+
+
+/*---------------------------------------------------------------------------
+ Prototypes for public UnZip API (DLL) functions.
+ ---------------------------------------------------------------------------*/
+
+#define UzpMatch match
+
+int UZ_EXP UzpMain OF((int argc, char **argv));
+int UZ_EXP UzpAltMain OF((int argc, char **argv, UzpInit *init));
+UzpVer * UZ_EXP UzpVersion OF((void));
+void UZ_EXP UzpFreeMemBuffer OF((UzpBuffer *retstr));
+#ifndef WINDLL
+int UZ_EXP UzpUnzipToMemory OF((char *zip, char *file, UzpOpts *optflgs,
+ UzpCB *UsrFunc, UzpBuffer *retstr));
+#endif
+#ifndef WINDLL
+ int UZ_EXP UzpGrep OF((char *archive, char *file,
+ char *pattern, int cmd, int SkipBin,
+ UzpCB *UsrFunc));
+#endif
+#ifdef OS2
+int UZ_EXP UzpFileTree OF((char *name, cbList(callBack),
+ char *cpInclude[], char *cpExclude[]));
+#endif
+
+void UZ_EXP UzpVersion2 OF((UzpVer2 *version));
+int UZ_EXP UzpValidate OF((char *archive, int AllCodes));
+
+
+/* default I/O functions (can be swapped out via UzpAltMain() entry point): */
+
+int UZ_EXP UzpMessagePrnt OF((zvoid *pG, uch *buf, ulg size, int flag));
+int UZ_EXP UzpMessageNull OF((zvoid *pG, uch *buf, ulg size, int flag));
+int UZ_EXP UzpInput OF((zvoid *pG, uch *buf, int *size, int flag));
+void UZ_EXP UzpMorePause OF((zvoid *pG, ZCONST char *prompt, int flag));
+int UZ_EXP UzpPassword OF((zvoid *pG, int *rcnt, char *pwbuf,
+ int size, ZCONST char *zfn,
+ ZCONST char *efn));
+
+
+/*---------------------------------------------------------------------------
+ Remaining private stuff for UnZip compilation.
+ ---------------------------------------------------------------------------*/
+
+#ifdef UNZIP_INTERNAL
+# include "unzpriv.h"
+#endif
+
+
+#endif /* !__unzip_h */
diff --git a/Build/source/libs/unzip/unzip.mak b/Build/source/libs/unzip/unzip.mak
new file mode 100644
index 00000000000..9095da86f09
--- /dev/null
+++ b/Build/source/libs/unzip/unzip.mak
@@ -0,0 +1,369 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on unzip.dsp
+!IF "$(CFG)" == ""
+CFG=unzip - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to unzip - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "unzip - Win32 Release" && "$(CFG)" != "unzip - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "unzip.mak" CFG="unzip - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "unzip - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "unzip - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "unzip - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+ALL : "$(OUTDIR)\unzip.lib"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\api.obj"
+ -@erase "$(INTDIR)\crc32.obj"
+ -@erase "$(INTDIR)\crctab.obj"
+ -@erase "$(INTDIR)\crypt.obj"
+ -@erase "$(INTDIR)\explode.obj"
+ -@erase "$(INTDIR)\extract.obj"
+ -@erase "$(INTDIR)\fileio.obj"
+ -@erase "$(INTDIR)\globals.obj"
+ -@erase "$(INTDIR)\inflate.obj"
+ -@erase "$(INTDIR)\list.obj"
+ -@erase "$(INTDIR)\match.obj"
+ -@erase "$(INTDIR)\nt.obj"
+ -@erase "$(INTDIR)\process.obj"
+ -@erase "$(INTDIR)\ttyio.obj"
+ -@erase "$(INTDIR)\unreduce.obj"
+ -@erase "$(INTDIR)\unshrink.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\win32.obj"
+ -@erase "$(INTDIR)\windll.obj"
+ -@erase "$(INTDIR)\zipinfo.obj"
+ -@erase "$(OUTDIR)\unzip.lib"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MT /W3 /GX /O2 /I "./" /I "../" /I "../.." /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "_WINDOWS" /D "WINDLL" /D "USE_EF_UT_TIME" /D "DLL" /D "UNZIPLIB" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\unzip.bsc"
+BSC32_SBRS= \
+
+LIB32=link.exe -lib
+LIB32_FLAGS=/nologo /out:"$(OUTDIR)\unzip.lib"
+LIB32_OBJS= \
+ "$(INTDIR)\api.obj" \
+ "$(INTDIR)\crc32.obj" \
+ "$(INTDIR)\crctab.obj" \
+ "$(INTDIR)\crypt.obj" \
+ "$(INTDIR)\explode.obj" \
+ "$(INTDIR)\extract.obj" \
+ "$(INTDIR)\fileio.obj" \
+ "$(INTDIR)\globals.obj" \
+ "$(INTDIR)\inflate.obj" \
+ "$(INTDIR)\list.obj" \
+ "$(INTDIR)\match.obj" \
+ "$(INTDIR)\nt.obj" \
+ "$(INTDIR)\process.obj" \
+ "$(INTDIR)\ttyio.obj" \
+ "$(INTDIR)\unreduce.obj" \
+ "$(INTDIR)\unshrink.obj" \
+ "$(INTDIR)\win32.obj" \
+ "$(INTDIR)\windll.obj" \
+ "$(INTDIR)\zipinfo.obj"
+
+"$(OUTDIR)\unzip.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS)
+ $(LIB32) @<<
+ $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "unzip - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "$(OUTDIR)\unzip.lib"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\api.obj"
+ -@erase "$(INTDIR)\crc32.obj"
+ -@erase "$(INTDIR)\crctab.obj"
+ -@erase "$(INTDIR)\crypt.obj"
+ -@erase "$(INTDIR)\explode.obj"
+ -@erase "$(INTDIR)\extract.obj"
+ -@erase "$(INTDIR)\fileio.obj"
+ -@erase "$(INTDIR)\globals.obj"
+ -@erase "$(INTDIR)\inflate.obj"
+ -@erase "$(INTDIR)\list.obj"
+ -@erase "$(INTDIR)\match.obj"
+ -@erase "$(INTDIR)\nt.obj"
+ -@erase "$(INTDIR)\process.obj"
+ -@erase "$(INTDIR)\ttyio.obj"
+ -@erase "$(INTDIR)\unreduce.obj"
+ -@erase "$(INTDIR)\unshrink.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(INTDIR)\win32.obj"
+ -@erase "$(INTDIR)\windll.obj"
+ -@erase "$(INTDIR)\zipinfo.obj"
+ -@erase "$(OUTDIR)\unzip.lib"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/MTd /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "NDEBUG" /D "_WINDOWS" /D "WINDLL" /D "USE_EF_UT_TIME" /D "DLL" /D "UNZIPLIB" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\unzip.bsc"
+BSC32_SBRS= \
+
+LIB32=link.exe -lib
+LIB32_FLAGS=/nologo /out:"$(OUTDIR)\unzip.lib"
+LIB32_OBJS= \
+ "$(INTDIR)\api.obj" \
+ "$(INTDIR)\crc32.obj" \
+ "$(INTDIR)\crctab.obj" \
+ "$(INTDIR)\crypt.obj" \
+ "$(INTDIR)\explode.obj" \
+ "$(INTDIR)\extract.obj" \
+ "$(INTDIR)\fileio.obj" \
+ "$(INTDIR)\globals.obj" \
+ "$(INTDIR)\inflate.obj" \
+ "$(INTDIR)\list.obj" \
+ "$(INTDIR)\match.obj" \
+ "$(INTDIR)\nt.obj" \
+ "$(INTDIR)\process.obj" \
+ "$(INTDIR)\ttyio.obj" \
+ "$(INTDIR)\unreduce.obj" \
+ "$(INTDIR)\unshrink.obj" \
+ "$(INTDIR)\win32.obj" \
+ "$(INTDIR)\windll.obj" \
+ "$(INTDIR)\zipinfo.obj"
+
+"$(OUTDIR)\unzip.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS)
+ $(LIB32) @<<
+ $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS)
+<<
+
+!ENDIF
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("unzip.dep")
+!INCLUDE "unzip.dep"
+!ELSE
+!MESSAGE Warning: cannot find "unzip.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "unzip - Win32 Release" || "$(CFG)" == "unzip - Win32 Debug"
+SOURCE=.\api.c
+
+"$(INTDIR)\api.obj" : $(SOURCE) "$(INTDIR)"
+
+
+SOURCE=.\crc32.c
+
+"$(INTDIR)\crc32.obj" : $(SOURCE) "$(INTDIR)"
+
+
+SOURCE=.\crctab.c
+
+"$(INTDIR)\crctab.obj" : $(SOURCE) "$(INTDIR)"
+
+
+SOURCE=.\crypt.c
+
+"$(INTDIR)\crypt.obj" : $(SOURCE) "$(INTDIR)"
+
+
+SOURCE=.\explode.c
+
+"$(INTDIR)\explode.obj" : $(SOURCE) "$(INTDIR)"
+
+
+SOURCE=.\extract.c
+
+"$(INTDIR)\extract.obj" : $(SOURCE) "$(INTDIR)"
+
+
+SOURCE=.\fileio.c
+
+"$(INTDIR)\fileio.obj" : $(SOURCE) "$(INTDIR)"
+
+
+SOURCE=.\globals.c
+
+"$(INTDIR)\globals.obj" : $(SOURCE) "$(INTDIR)"
+
+
+SOURCE=.\inflate.c
+
+"$(INTDIR)\inflate.obj" : $(SOURCE) "$(INTDIR)"
+
+
+SOURCE=.\list.c
+
+"$(INTDIR)\list.obj" : $(SOURCE) "$(INTDIR)"
+
+
+SOURCE=.\match.c
+
+"$(INTDIR)\match.obj" : $(SOURCE) "$(INTDIR)"
+
+
+SOURCE=.\win32\nt.c
+
+!IF "$(CFG)" == "unzip - Win32 Release"
+
+CPP_SWITCHES=/nologo /MT /W3 /GX /O2 /I "./" /I "../" /I "../.." /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "_WINDOWS" /D "WINDLL" /D "USE_EF_UT_TIME" /D "DLL" /D "UNZIPLIB" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+"$(INTDIR)\nt.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) @<<
+ $(CPP_SWITCHES) $(SOURCE)
+<<
+
+
+!ELSEIF "$(CFG)" == "unzip - Win32 Debug"
+
+CPP_SWITCHES=/MTd /W3 /GX /ZI /Od /I "../" /I "./" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "NDEBUG" /D "_WINDOWS" /D "WINDLL" /D "USE_EF_UT_TIME" /D "DLL" /D "UNZIPLIB" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+"$(INTDIR)\nt.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) @<<
+ $(CPP_SWITCHES) $(SOURCE)
+<<
+
+
+!ENDIF
+
+SOURCE=.\process.c
+
+"$(INTDIR)\process.obj" : $(SOURCE) "$(INTDIR)"
+
+
+SOURCE=.\ttyio.c
+
+"$(INTDIR)\ttyio.obj" : $(SOURCE) "$(INTDIR)"
+
+
+SOURCE=.\unreduce.c
+
+"$(INTDIR)\unreduce.obj" : $(SOURCE) "$(INTDIR)"
+
+
+SOURCE=.\unshrink.c
+
+"$(INTDIR)\unshrink.obj" : $(SOURCE) "$(INTDIR)"
+
+
+SOURCE=.\win32\win32.c
+
+!IF "$(CFG)" == "unzip - Win32 Release"
+
+CPP_SWITCHES=/nologo /MT /W3 /GX /O2 /I "./" /I "../" /I "../.." /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "_WINDOWS" /D "WINDLL" /D "USE_EF_UT_TIME" /D "DLL" /D "UNZIPLIB" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+"$(INTDIR)\win32.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) @<<
+ $(CPP_SWITCHES) $(SOURCE)
+<<
+
+
+!ELSEIF "$(CFG)" == "unzip - Win32 Debug"
+
+CPP_SWITCHES=/MTd /W3 /GX /ZI /Od /I "../" /I "./" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "NDEBUG" /D "_WINDOWS" /D "WINDLL" /D "USE_EF_UT_TIME" /D "DLL" /D "UNZIPLIB" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+"$(INTDIR)\win32.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) @<<
+ $(CPP_SWITCHES) $(SOURCE)
+<<
+
+
+!ENDIF
+
+SOURCE=.\windll\windll.c
+
+!IF "$(CFG)" == "unzip - Win32 Release"
+
+CPP_SWITCHES=/nologo /MT /W3 /GX /O2 /I "./" /I "../" /I "../.." /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "_WINDOWS" /D "WINDLL" /D "USE_EF_UT_TIME" /D "DLL" /D "UNZIPLIB" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+"$(INTDIR)\windll.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) @<<
+ $(CPP_SWITCHES) $(SOURCE)
+<<
+
+
+!ELSEIF "$(CFG)" == "unzip - Win32 Debug"
+
+CPP_SWITCHES=/MTd /W3 /GX /ZI /Od /I "../" /I "./" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "NDEBUG" /D "_WINDOWS" /D "WINDLL" /D "USE_EF_UT_TIME" /D "DLL" /D "UNZIPLIB" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+"$(INTDIR)\windll.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) @<<
+ $(CPP_SWITCHES) $(SOURCE)
+<<
+
+
+!ENDIF
+
+SOURCE=.\zipinfo.c
+
+"$(INTDIR)\zipinfo.obj" : $(SOURCE) "$(INTDIR)"
+
+
+
+!ENDIF
+
diff --git a/Build/source/libs/unzip/unzip.plg b/Build/source/libs/unzip/unzip.plg
new file mode 100644
index 00000000000..e35c65cb610
--- /dev/null
+++ b/Build/source/libs/unzip/unzip.plg
@@ -0,0 +1,30 @@
+<html>
+<body>
+<pre>
+<h1>Build Log</h1>
+<h3>
+--------------------Configuration: unzip - Win32 Release--------------------
+</h3>
+<h3>Command Lines</h3>
+Creating temporary file "C:\DOCUME~1\FABRIC~1\LOCALS~1\Temp\RSP54BC.tmp" with contents
+[
+/MT /W3 /GX /O2 /I "./" /I "../" /I "../.." /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "_WINDOWS" /D "WINDLL" /D "USE_EF_UT_TIME" /D "DLL" /D "UNZIPLIB" /Fo"Release/" /Fd"Release/" /FD /c
+"D:\Source\fptex\texk\win32\unzip\win32\nt.c"
+]
+Creating command line "cl.exe @C:\DOCUME~1\FABRIC~1\LOCALS~1\Temp\RSP54BC.tmp"
+<h3>Output Window</h3>
+Compiling...
+Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
+Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
+
+cl "/MT" "/W3" "/GX" "/O2" "/I" "./" "/I" "../" "/I" "../.." "/D" "WIN32" "/D" "NDEBUG" "/D" "_MBCS" "/D" "_LIB" "/D" "_WINDOWS" "/D" "WINDLL" "/D" "USE_EF_UT_TIME" "/D" "DLL" "/D" "UNZIPLIB" "/FoRelease/" "/FdRelease/" "/FD" "/c" "D:\Source\fptex\texk\win32\unzip\win32\nt.c"
+
+nt.c
+
+
+
+<h3>Results</h3>
+nt.obj - 0 error(s), 0 warning(s)
+</pre>
+</body>
+</html>
diff --git a/Build/source/libs/unzip/unzip.vcproj b/Build/source/libs/unzip/unzip.vcproj
new file mode 100644
index 00000000000..151816c4ad8
--- /dev/null
+++ b/Build/source/libs/unzip/unzip.vcproj
@@ -0,0 +1,235 @@
+<?xml version="1.0" encoding = "Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.00"
+ Name="unzip"
+ ProjectGUID="{C1EF4A39-120C-4CD6-B258-B7013A3CCD63}"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\static"
+ IntermediateDirectory=".\static"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="./,../,../.."
+ PreprocessorDefinitions="WIN32,NDEBUG,_LIB,_WINDOWS,WINDLL,USE_EF_UT_TIME,DLL,UNZIPLIB"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ PrecompiledHeaderFile=".\static/unzip.pch"
+ AssemblerListingLocation=".\static/"
+ ObjectFile=".\static/"
+ ProgramDataBaseFileName=".\static/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=".\static\unzip.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1036"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\static-debug"
+ IntermediateDirectory=".\static-debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32,_DEBUG,_LIB,NDEBUG,_WINDOWS,WINDLL,USE_EF_UT_TIME,DLL,UNZIPLIB"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\static-debug/unzip.pch"
+ AssemblerListingLocation=".\static-debug/"
+ ObjectFile=".\static-debug/"
+ ProgramDataBaseFileName=".\static-debug/"
+ WarningLevel="3"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=".\static-debug\unzip.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1036"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath=".\api.c">
+ </File>
+ <File
+ RelativePath=".\crc32.c">
+ </File>
+ <File
+ RelativePath=".\crctab.c">
+ </File>
+ <File
+ RelativePath=".\crypt.c">
+ </File>
+ <File
+ RelativePath=".\explode.c">
+ </File>
+ <File
+ RelativePath=".\extract.c">
+ </File>
+ <File
+ RelativePath=".\fileio.c">
+ </File>
+ <File
+ RelativePath=".\globals.c">
+ </File>
+ <File
+ RelativePath=".\inflate.c">
+ </File>
+ <File
+ RelativePath=".\list.c">
+ </File>
+ <File
+ RelativePath=".\match.c">
+ </File>
+ <File
+ RelativePath=".\win32\nt.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../,./;$(NoInherit)"
+ CompileAs="0"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\process.c">
+ </File>
+ <File
+ RelativePath=".\ttyio.c">
+ </File>
+ <File
+ RelativePath=".\unreduce.c">
+ </File>
+ <File
+ RelativePath=".\unshrink.c">
+ </File>
+ <File
+ RelativePath=".\win32\win32.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../,./;$(NoInherit)"
+ CompileAs="0"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\windll\windll.c">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../,./;$(NoInherit)"
+ CompileAs="0"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\zipinfo.c">
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ <File
+ RelativePath=".\consts.h">
+ </File>
+ <File
+ RelativePath=".\crypt.h">
+ </File>
+ <File
+ RelativePath=".\windll\decs.h">
+ </File>
+ <File
+ RelativePath=".\ebcdic.h">
+ </File>
+ <File
+ RelativePath=".\globals.h">
+ </File>
+ <File
+ RelativePath=".\inflate.h">
+ </File>
+ <File
+ RelativePath=".\win32\nt.h">
+ </File>
+ <File
+ RelativePath=".\windll\structs.h">
+ </File>
+ <File
+ RelativePath=".\ttyio.h">
+ </File>
+ <File
+ RelativePath=".\unzip.h">
+ </File>
+ <File
+ RelativePath=".\unzpriv.h">
+ </File>
+ <File
+ RelativePath=".\version.h">
+ </File>
+ <File
+ RelativePath=".\win32\w32cfg.h">
+ </File>
+ <File
+ RelativePath=".\windll\windll.h">
+ </File>
+ <File
+ RelativePath=".\zip.h">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Build/source/libs/unzip/unzpriv.h b/Build/source/libs/unzip/unzpriv.h
new file mode 100644
index 00000000000..dfac1528b2a
--- /dev/null
+++ b/Build/source/libs/unzip/unzpriv.h
@@ -0,0 +1,2387 @@
+/*---------------------------------------------------------------------------
+
+ unzpriv.h
+
+ This header file contains private (internal) macros, typedefs, prototypes
+ and global-variable declarations used by all of the UnZip source files.
+ In a prior life it was part of the main unzip.h header, but now it is only
+ included by that header if UNZIP_INTERNAL is defined.
+
+ ---------------------------------------------------------------------------*/
+
+
+
+#ifndef __unzpriv_h /* prevent multiple inclusions */
+#define __unzpriv_h
+
+/* First thing: Signal all following code that we compile UnZip utilities! */
+#ifndef UNZIP
+# define UNZIP
+#endif
+
+/* GRR 960204: MORE defined here in preparation for removal altogether */
+#ifndef MORE
+# define MORE
+#endif
+
+/* fUnZip should never need to be reentrant */
+#ifdef FUNZIP
+# ifdef REENTRANT
+# undef REENTRANT
+# endif
+# ifdef DLL
+# undef DLL
+# endif
+#endif
+
+#if (defined(DLL) && !defined(REENTRANT))
+# define REENTRANT
+#endif
+
+#if (!defined(DYNAMIC_CRC_TABLE) && !defined(FUNZIP))
+# define DYNAMIC_CRC_TABLE
+#endif
+
+#if (defined(DYNAMIC_CRC_TABLE) && !defined(REENTRANT))
+# ifndef DYNALLOC_CRCTAB
+# define DYNALLOC_CRCTAB
+# endif
+#endif
+
+/*---------------------------------------------------------------------------
+ OS-dependent configuration for UnZip internals
+ ---------------------------------------------------------------------------*/
+
+/* bad or (occasionally?) missing stddef.h: */
+#if (defined(M_XENIX) || defined(DNIX))
+# define NO_STDDEF_H
+#endif
+
+#if (defined(M_XENIX) && !defined(M_UNIX)) /* SCO Xenix only, not SCO Unix */
+# define SCO_XENIX
+# define NO_LIMITS_H /* no limits.h, but MODERN defined */
+# define NO_UID_GID /* no uid_t/gid_t */
+# define size_t int
+#endif
+
+#ifdef realix /* Modcomp Real/IX, real-time SysV.3 variant */
+# define SYSV
+# define NO_UID_GID /* no uid_t/gid_t */
+#endif
+
+#if (defined(_AIX) && !defined(_ALL_SOURCE))
+# define _ALL_SOURCE
+#endif
+
+#if defined(apollo) /* defines __STDC__ */
+# define NO_STDLIB_H
+#endif
+
+#ifdef DNIX
+# define SYSV
+# define SHORT_NAMES /* 14-char limitation on path components */
+/* # define FILENAME_MAX 14 */
+# define FILENAME_MAX NAME_MAX /* GRR: experiment */
+#endif
+
+#if (defined(SYSTEM_FIVE) || defined(__SYSTEM_FIVE))
+# ifndef SYSV
+# define SYSV
+# endif
+#endif /* SYSTEM_FIVE || __SYSTEM_FIVE */
+#if (defined(M_SYSV) || defined(M_SYS5))
+# ifndef SYSV
+# define SYSV
+# endif
+#endif /* M_SYSV || M_SYS5 */
+/* __SVR4 and __svr4__ catch Solaris on at least some combos of compiler+OS */
+#if (defined(__SVR4) || defined(__svr4__) || defined(sgi) || defined(__hpux))
+# ifndef SYSV
+# define SYSV
+# endif
+#endif /* __SVR4 || __svr4__ || sgi || __hpux */
+#if (defined(LINUX) || defined(__QNX__))
+# ifndef SYSV
+# define SYSV
+# endif
+#endif /* LINUX || __QNX__ */
+
+#if (defined(ultrix) || defined(__ultrix) || defined(bsd4_2))
+# if (!defined(BSD) && !defined(SYSV))
+# define BSD
+# endif
+#endif /* ultrix || __ultrix || bsd4_2 */
+#if (defined(sun) || defined(pyr) || defined(CONVEX))
+# if (!defined(BSD) && !defined(SYSV))
+# define BSD
+# endif
+#endif /* sun || pyr || CONVEX */
+
+#ifdef pyr /* Pyramid: has BSD and AT&T "universes" */
+# ifdef BSD
+# define pyr_bsd
+# define USE_STRINGS_H /* instead of more common string.h */
+# define ZMEM /* ZMEM now uses bcopy/bzero: not in AT&T universe */
+# endif /* (AT&T memcpy claimed to be very slow, though) */
+# define DECLARE_ERRNO
+#endif /* pyr */
+
+/* stat() bug for Borland, VAX C (also GNU?), and Atari ST MiNT on TOS
+ * filesystems: returns 0 for wildcards! (returns 0xffffffff on Minix
+ * filesystem or `U:' drive under Atari MiNT.) Watcom C was previously
+ * included on this list; it would be good to know what version the problem
+ * was fixed at, if it did exist. Watcom 10.6 has a separate stat() problem:
+ * it fails on "." when the current directory is a root. This is covered by
+ * giving it a separate definition of SSTAT in OS-specific header files. */
+#if (defined(__TURBOC__) || defined(VMS) || defined(__MINT__))
+# define WILD_STAT_BUG
+#endif
+
+#ifdef WILD_STAT_BUG
+# define SSTAT(path,pbuf) (iswild(path) || stat(path,pbuf))
+#else
+# define SSTAT stat
+#endif
+
+#ifdef REGULUS /* returns the inode number on success(!)...argh argh argh */
+# define stat(p,s) zstat((p),(s))
+#endif
+
+#define STRNICMP zstrnicmp
+
+/*---------------------------------------------------------------------------
+ OS-dependent includes
+ ---------------------------------------------------------------------------*/
+
+#ifdef EFT
+# define LONGINT off_t /* Amdahl UTS nonsense ("extended file types") */
+#else
+# define LONGINT long
+#endif
+
+#ifdef MODERN
+# ifndef NO_STDDEF_H
+# include <stddef.h>
+# endif
+# ifndef NO_STDLIB_H
+# include <stdlib.h> /* standard library prototypes, malloc(), etc. */
+# endif
+ typedef size_t extent;
+#else /* !MODERN */
+# ifndef AOS_VS /* mostly modern? */
+ LONGINT lseek();
+# ifdef VAXC /* not fully modern, but does have stdlib.h and void */
+# include <stdlib.h>
+# else
+ char *malloc();
+# endif /* ?VAXC */
+# endif /* !AOS_VS */
+ typedef unsigned int extent;
+#endif /* ?MODERN */
+
+
+#ifndef MINIX /* Minix needs it after all the other includes (?) */
+# include <stdio.h>
+#endif
+#include <ctype.h> /* skip for VMS, to use tolower() function? */
+#include <errno.h> /* used in mapname() */
+#ifdef USE_STRINGS_H
+# include <strings.h> /* strcpy, strcmp, memcpy, index/rindex, etc. */
+#else
+# include <string.h> /* strcpy, strcmp, memcpy, strchr/strrchr, etc. */
+#endif
+#if (defined(MODERN) && !defined(NO_LIMITS_H))
+# include <limits.h> /* GRR: EXPERIMENTAL! (can be deleted) */
+#endif
+
+/* this include must be down here for SysV.4, for some reason... */
+#include <signal.h> /* used in unzip.c, fileio.c */
+
+
+/*---------------------------------------------------------------------------
+ API (DLL) section:
+ ---------------------------------------------------------------------------*/
+
+#ifdef DLL
+# define MAIN UZ_EXP UzpMain /* was UzpUnzip */
+# ifdef OS2DLL
+# undef Info
+# define REDIRECTC(c) varputchar(__G__ c)
+# define REDIRECTPRINT(buf,size) varmessage(__G__ buf, size)
+# define FINISH_REDIRECT() finish_REXX_redirect(__G)
+# else
+# define REDIRECTC(c)
+# define REDIRECTPRINT(buf,size) 0
+# define FINISH_REDIRECT() close_redirect(__G)
+# endif
+#endif
+
+/*---------------------------------------------------------------------------
+ Acorn RISCOS section:
+ ---------------------------------------------------------------------------*/
+
+#ifdef RISCOS
+# include "acorn/riscos.h"
+#endif
+
+/*---------------------------------------------------------------------------
+ Amiga section:
+ ---------------------------------------------------------------------------*/
+
+#ifdef AMIGA
+# include "amiga/amiga.h"
+#endif
+
+/*---------------------------------------------------------------------------
+ AOS/VS section (somewhat similar to Unix, apparently):
+ ---------------------------------------------------------------------------*/
+
+#ifdef AOS_VS
+# ifdef FILEIO_C
+# include "aosvs/aosvs.h"
+# endif
+#endif
+
+/*---------------------------------------------------------------------------
+ Atari ST section:
+ ---------------------------------------------------------------------------*/
+
+#ifdef ATARI
+# include <time.h>
+# include <stat.h>
+# include <fcntl.h>
+# include <limits.h>
+# define SYMLINKS
+# define EXE_EXTENSION ".tos"
+# ifndef DATE_FORMAT
+# define DATE_FORMAT DF_DMY
+# endif
+# define DIR_END '/'
+# define INT_SPRINTF
+# define timezone _timezone
+# define lenEOL 2
+# define PutNativeEOL {*q++ = native(CR); *q++ = native(LF);}
+# undef SHORT_NAMES
+# if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP))
+# define TIMESTAMP
+# endif
+#endif
+
+/*---------------------------------------------------------------------------
+ BeOS section:
+ ---------------------------------------------------------------------------*/
+
+#ifdef __BEOS__
+# include <sys/types.h> /* [cjh]: This is pretty much a generic */
+# include <sys/stat.h> /* POSIX 1003.1 system; see beos/ for */
+# include <fcntl.h> /* extra code to deal with our extra file */
+# include <sys/param.h> /* attributes. */
+# include <unistd.h>
+# include <utime.h>
+# define DIRENT
+# include <time.h>
+# ifndef DATE_FORMAT
+# define DATE_FORMAT DF_MDY /* GRR: customize with locale.h somehow? */
+# endif
+# define lenEOL 1
+# define PutNativeEOL *q++ = native(LF);
+# define SCREENLINES screenlines()
+# define USE_EF_UT_TIME
+# define SET_DIR_ATTRIB
+# if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP))
+# define TIMESTAMP
+# endif
+# define RESTORE_UIDGID
+# define NO_GMTIME /* maybe DR10 will have timezones... */
+# define INT_SPRINTF
+# define SYMLINKS
+# define MAIN main_stub /* now that we're using a wrapper... */
+#endif
+
+/*---------------------------------------------------------------------------
+ Human68k/X68000 section:
+ ---------------------------------------------------------------------------*/
+
+#ifdef __human68k__ /* DO NOT DEFINE DOS_OS2 HERE! If Human68k is so much */
+# include <time.h> /* like MS-DOS and/or OS/2, create DOS_H68_OS2 macro. */
+# include <fcntl.h>
+# include <io.h>
+# include <conio.h>
+# include <jctype.h>
+# include <sys/stat.h>
+# ifndef DATE_FORMAT
+# define DATE_FORMAT DF_YMD /* Japanese standard */
+# endif
+ /* GRR: these EOL macros are guesses */
+# define lenEOL 2
+# define PutNativeEOL {*q++ = native(CR); *q++ = native(LF);}
+# define EXE_EXTENSION ".exe" /* just a guess... */
+#endif
+
+/*---------------------------------------------------------------------------
+ Mac section:
+ ---------------------------------------------------------------------------*/
+
+#ifdef MACOS
+# include "maccfg.h"
+#endif /* MACOS */
+
+/*---------------------------------------------------------------------------
+ MS-DOS, OS/2, FLEXOS section:
+ ---------------------------------------------------------------------------*/
+
+#ifdef WINDLL
+# define MSWIN
+# ifdef MORE
+# undef MORE
+# endif
+# ifdef OS2_EAS
+# undef OS2_EAS
+# endif
+#endif
+
+#if (defined(_MSC_VER) || (defined(M_I86) && !defined(__WATCOMC__)))
+# ifndef MSC
+# define MSC /* This should work for older MSC, too! */
+# endif
+#endif
+
+#if (defined(MSDOS) || defined(OS2) || defined(FLEXOS))
+# include <sys/types.h> /* off_t, time_t, dev_t, ... */
+# include <sys/stat.h>
+# include <io.h> /* lseek(), open(), setftime(), dup(), creat() */
+# include <time.h> /* localtime() */
+# include <fcntl.h> /* O_BINARY for open() w/o CR/LF translation */
+
+# ifdef OS2 /* defined for all OS/2 compilers */
+# include "os2/os2cfg.h"
+# else
+# ifdef FLEXOS
+# include "flexos/flxcfg.h"
+# else
+# include "msdos/doscfg.h"
+# endif
+# endif
+
+# if (defined(_MSC_VER) && (_MSC_VER == 700) && !defined(GRR))
+ /*
+ * ARGH. MSC 7.0 libraries think times are based on 1899 Dec 31 00:00, not
+ * 1970 Jan 1 00:00. So we have to diddle time_t's appropriately: add or
+ * subtract 70 years' worth of seconds; i.e., number of days times 86400;
+ * i.e., (70*365 regular days + 17 leap days + 1 1899 day) * 86400 ==
+ * (25550 + 17 + 1) * 86400 == 2209075200 seconds. We know time_t is an
+ * unsigned long (ulg) on the only system with this bug.
+ */
+# define TIMET_TO_NATIVE(x) (x) += (ulg)2209075200L;
+# define NATIVE_TO_TIMET(x) (x) -= (ulg)2209075200L;
+# endif
+# if (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0450))
+# define timezone _timezone
+# endif
+# if (defined(__GO32__) || defined(FLEXOS))
+# define DIR_END '/'
+# else
+# define DIR_END '\\' /* OS uses '\\' as directory separator */
+# define DIR_END2 '/' /* also check for '/' (RTL may convert) */
+# endif
+# ifndef WIN32
+# ifdef DATE_FORMAT
+# undef DATE_FORMAT
+# endif
+# define DATE_FORMAT dateformat()
+# endif
+# define lenEOL 2
+# define PutNativeEOL {*q++ = native(CR); *q++ = native(LF);}
+# define USE_EF_UT_TIME
+#endif /* MSDOS || OS2 || FLEXOS */
+
+/*---------------------------------------------------------------------------
+ MTS section (piggybacks UNIX, I think):
+ ---------------------------------------------------------------------------*/
+
+#ifdef MTS
+# include <sys/types.h> /* off_t, time_t, dev_t, ... */
+# include <sys/stat.h>
+# include <sys/file.h> /* MTS uses this instead of fcntl.h */
+# include <timeb.h>
+# include <time.h>
+# include <unix.h> /* some important non-ANSI routines */
+# define mkdir(s,n) (-1) /* no "make directory" capability */
+# define EBCDIC /* set EBCDIC conversion on */
+# define NO_STRNICMP /* unzip's is as good the one in MTS */
+# define USE_FWRITE
+# define close_outfile() fclose(G.outfile) /* can't set time on files */
+# define umask(n) /* don't have umask() on MTS */
+# define FOPWT "w" /* open file for writing in TEXT mode */
+# ifndef DATE_FORMAT
+# define DATE_FORMAT DF_MDY
+# endif
+# define lenEOL 1
+# define PutNativeEOL *q++ = native(LF);
+#endif /* MTS */
+
+ /*---------------------------------------------------------------------------
+ QDOS section
+ ---------------------------------------------------------------------------*/
+
+#ifdef QDOS
+# define DIRENT
+# include <fcntl.h>
+# include <unistd.h>
+# include <sys/stat.h>
+# include <time.h>
+# include "qdos/izqdos.h"
+# ifndef DATE_FORMAT
+# define DATE_FORMAT DF_MDY
+# endif
+# define lenEOL 1
+# define PutNativeEOL *q++ = native(LF);
+# define DIR_END '_'
+# define RETURN QReturn
+# undef PATH_MAX
+# define PATH_MAX 36
+# if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP))
+# define TIMESTAMP
+# endif
+#endif
+
+/*---------------------------------------------------------------------------
+ Tandem NSK section:
+ ---------------------------------------------------------------------------*/
+
+#ifdef TANDEM
+# include "tandem.h"
+# include <fcntl.h>
+ /* use a single LF delimiter so that writes to 101 text files work */
+# define PutNativeEOL *q++ = native(LF);
+# define lenEOL 1
+# ifndef DATE_FORMAT
+# define DATE_FORMAT DF_DMY
+# endif
+# define USE_EF_UT_TIME
+# define RESTORE_UIDGID
+#endif
+
+/*---------------------------------------------------------------------------
+ TOPS-20 section:
+ ---------------------------------------------------------------------------*/
+
+#ifdef TOPS20
+# include <sys/types.h> /* off_t, time_t, dev_t, ... */
+# include <sys/stat.h>
+# include <sys/param.h>
+# include <sys/time.h>
+# include <sys/timeb.h>
+# include <sys/file.h>
+# include <timex.h>
+# include <monsym.h> /* get amazing monsym() macro */
+ extern int open(), close(), read();
+ extern int stat(), unlink(), jsys(), fcntl();
+ extern long lseek(), dup(), creat();
+# define strchr index /* GRR: necessary? */
+# define strrchr rindex
+# define REALLY_SHORT_SYMS
+# define NO_MKDIR
+# define DIR_BEG '<'
+# define DIR_END '>'
+# define DIR_EXT ".directory"
+# ifndef DATE_FORMAT
+# define DATE_FORMAT DF_MDY
+# endif
+# define EXE_EXTENSION ".exe" /* just a guess... */
+#endif /* TOPS20 */
+
+/*---------------------------------------------------------------------------
+ Unix section:
+ ---------------------------------------------------------------------------*/
+
+#ifdef UNIX
+# include <sys/types.h> /* off_t, time_t, dev_t, ... */
+# include <sys/stat.h>
+
+# ifndef COHERENT
+# include <fcntl.h> /* O_BINARY for open() w/o CR/LF translation */
+# else /* COHERENT */
+# ifdef _I386
+# include <fcntl.h> /* Coherent 4.0.x, Mark Williams C */
+# else
+# include <sys/fcntl.h> /* Coherent 3.10, Mark Williams C */
+# endif
+# define SHORT_SYMS
+# ifndef __COHERENT__ /* Coherent 4.2 has tzset() */
+# define tzset settz
+# endif
+# endif /* ?COHERENT */
+
+# ifndef NO_PARAM_H
+# ifdef NGROUPS_MAX
+# undef NGROUPS_MAX /* SCO bug: defined again in <sys/param.h> */
+# endif
+# ifdef BSD
+# define TEMP_BSD /* may be defined again in <sys/param.h> */
+# undef BSD
+# endif
+# include <sys/param.h> /* conflict with <sys/types.h>, some systems? */
+# ifdef TEMP_BSD
+# undef TEMP_BSD
+# ifndef BSD
+# define BSD
+# endif
+# endif
+# endif /* !NO_PARAM_H */
+
+# ifdef __osf__
+# define DIRENT
+# ifdef BSD
+# undef BSD
+# endif
+# endif /* __osf__ */
+
+# ifdef BSD
+# include <sys/time.h>
+# include <sys/timeb.h>
+# ifdef _AIX
+# include <time.h>
+# endif
+# else
+# include <time.h>
+ struct tm *gmtime(), *localtime();
+# endif
+
+# if (defined(BSD4_4) || (defined(SYSV) && defined(MODERN)))
+# include <unistd.h> /* this includes utime.h on SGIs */
+# if (defined(BSD4_4) || defined(linux))
+# include <utime.h>
+# define GOT_UTIMBUF
+# endif
+# endif
+
+# if (defined(V7) || defined(pyr_bsd))
+# define strchr index
+# define strrchr rindex
+# endif
+# ifdef V7
+# define O_RDONLY 0
+# define O_WRONLY 1
+# define O_RDWR 2
+# endif
+
+# ifdef MINIX
+# include <stdio.h>
+# endif
+# ifndef DATE_FORMAT
+# define DATE_FORMAT DF_MDY /* GRR: customize with locale.h somehow? */
+# endif
+# define lenEOL 1
+# ifdef EBCDIC
+# define PutNativeEOL *q++ = '\n';
+# else
+# define PutNativeEOL *q++ = native(LF);
+# endif
+# define SCREENLINES screenlines()
+# define USE_EF_UT_TIME
+# define SET_DIR_ATTRIB
+# if (!defined(TIMESTAMP) && !defined(NOTIMESTAMP)) /* GRR 970513 */
+# define TIMESTAMP
+# endif
+# define RESTORE_UIDGID
+#endif /* UNIX */
+
+/*---------------------------------------------------------------------------
+ VM/CMS and MVS section:
+ ---------------------------------------------------------------------------*/
+
+#ifdef CMS_MVS
+# include "vmmvs.h"
+# define CLOSE_INFILE() close_infile(__G)
+#endif
+
+/*---------------------------------------------------------------------------
+ VMS section:
+ ---------------------------------------------------------------------------*/
+
+#ifdef VMS
+# include <types.h> /* GRR: experimenting... */
+# include <stat.h>
+# include <time.h> /* the usual non-BSD time functions */
+# include <file.h> /* same things as fcntl.h has */
+# include <unixio.h>
+# include <rms.h>
+# define _MAX_PATH (NAM$C_MAXRSS+1) /* to define FILNAMSIZ below */
+# ifdef RETURN_CODES /* VMS interprets standard PK return codes incorrectly */
+# define RETURN(ret) return_VMS(__G__ (ret)) /* verbose version */
+# define EXIT(ret) return_VMS(__G__ (ret))
+# else
+# define RETURN return_VMS /* quiet version */
+# define EXIT return_VMS
+# endif
+# ifdef VMSCLI
+# define USAGE(ret) VMSCLI_usage(__G__ (ret))
+# endif
+# define DIR_BEG '['
+# define DIR_END ']'
+# define DIR_EXT ".dir"
+# ifndef DATE_FORMAT
+# define DATE_FORMAT DF_MDY
+# endif
+# define lenEOL 1
+# define PutNativeEOL *q++ = native(LF);
+# define SCREENLINES screenlines()
+# if (defined(__VMS_VERSION) && !defined(VMS_VERSION))
+# define VMS_VERSION __VMS_VERSION
+# endif
+# if (defined(__VMS_VER) && !defined(__CRTL_VER))
+# define __CRTL_VER __VMS_VER
+# endif
+# if ((!defined(__CRTL_VER)) || (__CRTL_VER < 70000000))
+# define NO_GMTIME /* gmtime() of earlier VMS C RTLs is broken */
+# else
+# if (!defined(NO_EF_UT_TIME) && !defined(USE_EF_UT_TIME))
+# define USE_EF_UT_TIME
+# endif
+# endif
+# if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP))
+# define TIMESTAMP
+# endif
+# define RESTORE_UIDGID
+#endif /* VMS */
+
+/*---------------------------------------------------------------------------
+ Win32 (Windows 95/NT) section:
+ ---------------------------------------------------------------------------*/
+#if defined(FPTEX)
+#include <win32lib.h>
+/* We don't want to use fpTeX's stat() version */
+#undef stat
+#define stat _stat
+#endif
+
+#if (defined(WIN32) && !defined(POCKET_UNZIP))
+# include "win32/w32cfg.h"
+#endif
+
+
+
+
+
+/*************/
+/* Defines */
+/*************/
+
+#define UNZIP_VERSION 20 /* compatible with PKUNZIP 2.0 */
+#define VMS_UNZIP_VERSION 42 /* if OS-needed-to-extract is VMS: can do */
+
+#if (defined(MSDOS) || defined(OS2))
+# define DOS_OS2
+#endif
+
+#if (defined(OS2) || defined(WIN32))
+# define OS2_W32
+#endif
+
+#if (defined(DOS_OS2) || defined(WIN32))
+# define DOS_OS2_W32
+# define DOS_W32_OS2 /* historical: don't use */
+#endif
+
+#if (defined(DOS_OS2_W32) || defined(__human68k__))
+# define DOS_H68_OS2_W32
+#endif
+
+#if (defined(DOS_OS2) || defined(FLEXOS))
+# define DOS_FLX_OS2
+#endif
+
+#if (defined(DOS_OS2_W32) || defined(FLEXOS))
+# define DOS_FLX_OS2_W32
+#endif
+
+#if (defined(DOS_H68_OS2_W32) || defined(FLEXOS))
+# define DOS_FLX_H68_OS2_W32
+#endif
+
+#if (defined(TOPS20) || defined(VMS))
+# define T20_VMS
+#endif
+
+#if (defined(MSDOS) || defined(T20_VMS))
+# define DOS_T20_VMS
+#endif
+
+/* clean up with a few defaults */
+#ifndef DIR_END
+# define DIR_END '/' /* last char before program name or filename */
+#endif
+#ifndef DATE_FORMAT
+# define DATE_FORMAT DF_MDY /* defaults to US convention */
+#endif
+#ifndef CLOSE_INFILE
+# define CLOSE_INFILE() close(G.zipfd)
+#endif
+#ifndef RETURN
+# define RETURN return /* only used in main() */
+#endif
+#ifndef EXIT
+# define EXIT exit
+#endif
+#ifndef USAGE
+# define USAGE(ret) usage(__G__ (ret)) /* used in unzip.c, zipinfo.c */
+#endif
+#ifndef TIMET_TO_NATIVE /* everybody but MSC 7.0 and Macintosh */
+# define TIMET_TO_NATIVE(x)
+# define NATIVE_TO_TIMET(x)
+#endif
+
+#if (defined(DOS_FLX_OS2_W32) || defined(UNIX) || defined(RISCOS))
+# ifndef HAVE_UNLINK
+# define HAVE_UNLINK
+# endif
+#endif
+#if (defined(AOS_VS) || defined(ATARI) || defined(__BEOS__)) /* GRR: others? */
+# ifndef HAVE_UNLINK
+# define HAVE_UNLINK
+# endif
+#endif
+
+/* OS-specific exceptions to the "ANSI <--> INT_SPRINTF" rule */
+
+#if (!defined(PCHAR_SPRINTF) && !defined(INT_SPRINTF))
+# if (defined(SYSV) || defined(CONVEX) || defined(NeXT) || defined(BSD4_4))
+# define INT_SPRINTF /* sprintf() returns int: SysVish/Posix */
+# endif
+# if (defined(DOS_FLX_OS2_W32) || defined(VMS) || defined(AMIGA))
+# define INT_SPRINTF /* sprintf() returns int: ANSI */
+# endif
+# if (defined(ultrix) || defined(__ultrix)) /* Ultrix 4.3 and newer */
+# if (defined(POSIX) || defined(__POSIX))
+# define INT_SPRINTF /* sprintf() returns int: ANSI/Posix */
+# endif
+# ifdef __GNUC__
+# define PCHAR_SPRINTF /* undetermined actual return value */
+# endif
+# endif
+# if (defined(__osf__) || defined(_AIX) || defined(CMS_MVS))
+# define INT_SPRINTF /* sprintf() returns int: ANSI/Posix */
+# endif
+# if defined(sun)
+# define PCHAR_SPRINTF /* sprintf() returns char *: SunOS cc *and* gcc */
+# endif
+#endif
+
+/* defaults that we hope will take care of most machines in the future */
+
+#if (!defined(PCHAR_SPRINTF) && !defined(INT_SPRINTF))
+# ifdef __STDC__
+# define INT_SPRINTF /* sprintf() returns int: ANSI */
+# endif
+# ifndef INT_SPRINTF
+# define PCHAR_SPRINTF /* sprintf() returns char *: BSDish */
+# endif
+#endif
+
+#define MSG_STDERR(f) (f & 1) /* bit 0: 0 = stdout, 1 = stderr */
+#define MSG_INFO(f) ((f & 6) == 0) /* bits 1 and 2: 0 = info */
+#define MSG_WARN(f) ((f & 6) == 2) /* bits 1 and 2: 1 = warning */
+#define MSG_ERROR(f) ((f & 6) == 4) /* bits 1 and 2: 2 = error */
+#define MSG_FATAL(f) ((f & 6) == 6) /* bits 1 and 2: (3 = fatal error) */
+#define MSG_ZFN(f) (f & 0x0008) /* bit 3: 1 = print zipfile name */
+#define MSG_FN(f) (f & 0x0010) /* bit 4: 1 = print filename */
+#define MSG_LNEWLN(f) (f & 0x0020) /* bit 5: 1 = leading newline if !SOL */
+#define MSG_TNEWLN(f) (f & 0x0040) /* bit 6: 1 = trailing newline if !SOL */
+#define MSG_MNEWLN(f) (f & 0x0080) /* bit 7: 1 = trailing NL for prompts */
+/* the following are subject to change */
+#define MSG_NO_WGUI(f) (f & 0x0100) /* bit 8: 1 = skip if Windows GUI */
+#define MSG_NO_AGUI(f) (f & 0x0200) /* bit 9: 1 = skip if Acorn GUI */
+#define MSG_NO_DLL2(f) (f & 0x0400) /* bit 10: 1 = skip if OS/2 DLL */
+#define MSG_NO_NDLL(f) (f & 0x0800) /* bit 11: 1 = skip if WIN32 DLL */
+#define MSG_NO_WDLL(f) (f & 0x1000) /* bit 12: 1 = skip if Windows DLL */
+
+#if (defined(MORE) && !defined(SCREENLINES))
+# ifdef DOS_FLX_OS2_W32
+# define SCREENLINES 25 /* can be (should be) a function instead */
+# else
+# define SCREENLINES 24 /* VT-100s are assumed to be minimal hardware */
+# endif
+#endif
+
+#define DIR_BLKSIZ 64 /* number of directory entries per block
+ * (should fit in 4096 bytes, usually) */
+#ifndef WSIZE
+# define WSIZE 0x8000 /* window size--must be a power of two, and */
+#endif /* at least 32K for zip's deflate method */
+
+#ifndef INBUFSIZ
+# if (defined(MED_MEM) || defined(SMALL_MEM))
+# define INBUFSIZ 2048 /* works for MS-DOS small model */
+# else
+# define INBUFSIZ 8192 /* larger buffers for real OSes */
+# endif
+#endif
+
+#ifndef __16BIT__
+# define nearmalloc malloc
+# define nearfree free
+# if (!defined(__IBMC__) || !defined(OS2))
+# ifndef near
+# define near
+# endif
+# ifndef far
+# define far
+# endif
+# endif
+#endif
+
+#if (defined(DYNALLOC_CRCTAB) && !defined(DYNAMIC_CRC_TABLE))
+# undef DYNALLOC_CRCTAB
+#endif
+
+#if (defined(DYNALLOC_CRCTAB) && defined(REENTRANT))
+# undef DYNALLOC_CRCTAB /* not safe with reentrant code */
+#endif
+
+#if (defined(USE_ZLIB) && !defined(USE_OWN_CRCTAB))
+# ifdef DYNALLOC_CRCTAB
+# undef DYNALLOC_CRCTAB
+# endif
+#endif
+
+#if (defined(USE_ZLIB) && defined(ASM_CRC))
+# undef ASM_CRC
+#endif
+
+/* Logic for case of small memory, length of EOL > 1: if OUTBUFSIZ == 2048,
+ * OUTBUFSIZ>>1 == 1024 and OUTBUFSIZ>>7 == 16; therefore rawbuf is 1008 bytes
+ * and transbuf 1040 bytes. Have room for 32 extra EOL chars; 1008/32 == 31.5
+ * chars/line, smaller than estimated 35-70 characters per line for C source
+ * and normal text. Hence difference is sufficient for most "average" files.
+ * (Argument scales for larger OUTBUFSIZ.)
+ */
+#ifdef SMALL_MEM /* i.e., 16-bit OSes: MS-DOS, OS/2 1.x, etc. */
+# define LoadFarString(x) fLoadFarString(__G__ (x))
+# define LoadFarStringSmall(x) fLoadFarStringSmall(__G__ (x))
+# define LoadFarStringSmall2(x) fLoadFarStringSmall2(__G__ (x))
+# if (defined(_MSC_VER) && (_MSC_VER >= 600))
+# define zfstrcpy(dest, src) _fstrcpy((dest), (src))
+# endif
+# ifndef Far
+# define Far far /* __far only works for MSC 6.00, not 6.0a or Borland */
+# endif
+# define OUTBUFSIZ INBUFSIZ
+# if (lenEOL == 1)
+# define RAWBUFSIZ (OUTBUFSIZ>>1)
+# else
+# define RAWBUFSIZ ((OUTBUFSIZ>>1) - (OUTBUFSIZ>>7))
+# endif
+# define TRANSBUFSIZ (OUTBUFSIZ-RAWBUFSIZ)
+ typedef short shrint; /* short/int or "shrink int" (unshrink) */
+#else
+# define zfstrcpy(dest, src) strcpy((dest), (src))
+# ifdef QDOS
+# define LoadFarString(x) Qstrfix(x) /* fix up _ for '.' */
+# define LoadFarStringSmall(x) Qstrfix(x)
+# define LoadFarStringSmall2(x) Qstrfix(x)
+# else
+# define LoadFarString(x) x
+# define LoadFarStringSmall(x) x
+# define LoadFarStringSmall2(x) x
+# endif
+# ifdef MED_MEM
+# define OUTBUFSIZ 0xFF80 /* can't malloc arrays of 0xFFE8 or more */
+# define TRANSBUFSIZ 0xFF80
+ typedef short shrint;
+# else
+# define OUTBUFSIZ (lenEOL*WSIZE) /* more efficient text conversion */
+# define TRANSBUFSIZ (lenEOL*OUTBUFSIZ)
+# ifdef AMIGA
+ typedef short shrint;
+# else
+ typedef int shrint; /* for efficiency/speed, we hope... */
+# endif
+# endif /* ?MED_MEM */
+# define RAWBUFSIZ OUTBUFSIZ
+#endif /* ?SMALL_MEM */
+
+#ifndef Far
+# define Far
+#endif
+
+#ifndef MAIN
+# define MAIN main
+#endif
+
+#ifdef SFX /* disable some unused features for SFX executables */
+# ifndef NO_ZIPINFO
+# define NO_ZIPINFO
+# endif
+# ifdef TIMESTAMP
+# undef TIMESTAMP
+# endif
+#endif
+
+/* user may have defined both by accident... NOTIMESTAMP takes precedence */
+#if (defined(TIMESTAMP) && defined(NOTIMESTAMP))
+# undef TIMESTAMP
+#endif
+
+#if (!defined(COPYRIGHT_CLEAN) && !defined(USE_SMITH_CODE))
+# define COPYRIGHT_CLEAN
+#endif
+
+#if (!defined(LZW_CLEAN) && !defined(USE_UNSHRINK))
+# define LZW_CLEAN
+#endif
+
+#ifndef O_BINARY
+# define O_BINARY 0
+#endif
+
+#ifndef PIPE_ERROR
+# define PIPE_ERROR (errno == EPIPE)
+#endif
+
+/* File operations--use "b" for binary if allowed or fixed length 512 on VMS */
+#ifdef VMS
+# define FOPR "r","ctx=stm"
+# define FOPM "r+","ctx=stm","rfm=fix","mrs=512"
+# define FOPW "w","ctx=stm","rfm=fix","mrs=512"
+#endif /* VMS */
+
+#ifdef CMS_MVS
+/* Binary files must be RECFM=F,LRECL=1 for ftell() to get correct pos */
+/* ...unless byteseek is used. Let's try that for a while. */
+# define FOPR "rb,byteseek"
+# define FOPM "r+b,byteseek"
+# define FOPW "wb,recfm=v,lrecl=32760"
+# ifdef MVS
+# define FOPWT "w,lrecl=133"
+# else
+# define FOPWT "w"
+# endif
+#endif /* CMS_MVS */
+
+#ifdef TOPS20 /* TOPS-20 MODERN? You kidding? */
+# define FOPW "w8"
+#endif /* TOPS20 */
+
+/* Defaults when nothing special has been defined previously. */
+#ifdef MODERN
+# ifndef FOPR
+# define FOPR "rb"
+# endif
+# ifndef FOPM
+# define FOPM "r+b"
+# endif
+# ifndef FOPW
+# define FOPW "wb"
+# endif
+# ifndef FOPWT
+# define FOPWT "wt"
+# endif
+#else /* !MODERN */
+# ifndef FOPR
+# define FOPR "r"
+# endif
+# ifndef FOPM
+# define FOPM "r+"
+# endif
+# ifndef FOPW
+# define FOPW "w"
+# endif
+# ifndef FOPWT
+# define FOPWT "w"
+# endif
+#endif /* ?MODERN */
+
+/*
+ * If <limits.h> exists on most systems, should include that, since it may
+ * define some or all of the following: NAME_MAX, PATH_MAX, _POSIX_NAME_MAX,
+ * _POSIX_PATH_MAX.
+ */
+#ifdef DOS_FLX_OS2
+# include <limits.h>
+#endif
+
+#ifndef PATH_MAX
+# ifdef MAXPATHLEN
+# define PATH_MAX MAXPATHLEN /* in <sys/param.h> on some systems */
+# else
+# ifdef _MAX_PATH
+# define PATH_MAX _MAX_PATH
+# else
+# if FILENAME_MAX > 255
+# define PATH_MAX FILENAME_MAX /* used like PATH_MAX on some systems */
+# else
+# define PATH_MAX 1024
+# endif
+# endif /* ?_MAX_PATH */
+# endif /* ?MAXPATHLEN */
+#endif /* !PATH_MAX */
+
+#define FILNAMSIZ PATH_MAX
+
+#ifdef SHORT_SYMS /* Mark Williams C, ...? */
+# define extract_or_test_files xtr_or_tst_files
+# define extract_or_test_member xtr_or_tst_member
+#endif
+
+#ifdef REALLY_SHORT_SYMS /* TOPS-20 linker: first 6 chars */
+# define process_cdir_file_hdr XXpcdfh
+# define process_local_file_hdr XXplfh
+# define extract_or_test_files XXxotf /* necessary? */
+# define extract_or_test_member XXxotm /* necessary? */
+# define check_for_newer XXcfn
+# define overwrite_all XXoa
+# define process_all_files XXpaf
+# define extra_field XXef
+# define explode_lit8 XXel8
+# define explode_lit4 XXel4
+# define explode_nolit8 XXnl8
+# define explode_nolit4 XXnl4
+# define cpdist8 XXcpdist8
+# define inflate_codes XXic
+# define inflate_stored XXis
+# define inflate_fixed XXif
+# define inflate_dynamic XXid
+# define inflate_block XXib
+# define maxcodemax XXmax
+#endif
+
+#ifndef S_TIME_T_MAX /* max value of signed (>= 32-bit) time_t */
+# define S_TIME_T_MAX ((time_t)(ulg)0x7fffffffL)
+#endif
+#ifndef U_TIME_T_MAX /* max value of unsigned (>= 32-bit) time_t */
+# define U_TIME_T_MAX ((time_t)(ulg)0xffffffffL)
+#endif
+#ifdef DOSTIME_MINIMUM /* min DOSTIME value (1980-01-01) */
+# undef DOSTIME_MINIMUM
+#endif
+#define DOSTIME_MINIMUM ((ulg)0x00210000L)
+#ifdef DOSTIME_2038_01_18 /* approximate DOSTIME equivalent of */
+# undef DOSTIME_2038_01_18 /* the signed-32-bit time_t limit */
+#endif
+#define DOSTIME_2038_01_18 ((ulg)0x74320000L)
+
+#ifdef QDOS
+# define ZSUFX "_zip"
+# define ALT_ZSUFX ".zip"
+#else
+# ifdef RISCOS
+# define ZSUFX "/zip"
+# else
+# define ZSUFX ".zip"
+# endif
+# define ALT_ZSUFX ".ZIP" /* Unix-only so far (only case-sensitive fs) */
+#endif
+
+#define CENTRAL_HDR_SIG "\001\002" /* the infamous "PK" signature bytes, */
+#define LOCAL_HDR_SIG "\003\004" /* sans "PK" (so unzip executable not */
+#define END_CENTRAL_SIG "\005\006" /* mistaken for zipfile itself) */
+#define EXTD_LOCAL_SIG "\007\010" /* [ASCII "\113" == EBCDIC "\080" ??] */
+
+/* choice of activities for do_string() */
+#define SKIP 0 /* skip header block */
+#define DISPLAY 1 /* display archive comment (ASCII) */
+#define DISPL_8 5 /* display file comment (ext. ASCII) */
+#define DS_FN 2 /* read filename (ext. ASCII) */
+#define EXTRA_FIELD 3 /* copy extra field into buffer */
+#define DS_EF 3
+#ifdef AMIGA
+# define FILENOTE 4
+#endif
+
+#define DOES_NOT_EXIST -1 /* return values for check_for_newer() */
+#define EXISTS_AND_OLDER 0
+#define EXISTS_AND_NEWER 1
+
+#define ROOT 0 /* checkdir() extract-to path: called once */
+#define INIT 1 /* allocate buildpath: called once per member */
+#define APPEND_DIR 2 /* append a dir comp.: many times per member */
+#define APPEND_NAME 3 /* append actual filename: once per member */
+#define GETPATH 4 /* retrieve the complete path and free it */
+#define END 5 /* free root path prior to exiting program */
+
+/* version_made_by codes (central dir): make sure these */
+/* are not defined on their respective systems!! */
+#define FS_FAT_ 0 /* filesystem used by MS-DOS, OS/2, Win32 */
+#define AMIGA_ 1
+#define VMS_ 2
+#define UNIX_ 3
+#define VM_CMS_ 4
+#define ATARI_ 5 /* what if it's a minix filesystem? [cjh] */
+#define FS_HPFS_ 6 /* filesystem used by OS/2 (and NT 3.x) */
+#define MAC_ 7 /* HFS filesystem used by MacOS */
+#define Z_SYSTEM_ 8
+#define CPM_ 9
+#define TOPS20_ 10
+#define FS_NTFS_ 11 /* filesystem used by Windows NT */
+#define QDOS_ 12
+#define ACORN_ 13 /* Archimedes Acorn RISC OS */
+#define FS_VFAT_ 14 /* filesystem used by Windows 95, NT */
+#define MVS_ 15
+#define BEOS_ 16 /* hybrid POSIX/database filesystem */
+#define TANDEM_ 17 /* Tandem/NSK */
+#define NUM_HOSTS 18 /* index of last system + 1 */
+
+#define STORED 0 /* compression methods */
+#define SHRUNK 1
+#define REDUCED1 2
+#define REDUCED2 3
+#define REDUCED3 4
+#define REDUCED4 5
+#define IMPLODED 6
+#define TOKENIZED 7
+#define DEFLATED 8
+#define ENHDEFLATED 9
+#define DCLIMPLODED 10
+#define NUM_METHODS 11 /* index of last method + 1 */
+/* don't forget to update list_files(), extract.c and zipinfo.c appropriately
+ * if NUM_METHODS changes */
+
+/* (the PK-class error codes are public and have been moved into unzip.h) */
+
+#define DF_MDY 0 /* date format 10/26/91 (USA only) */
+#define DF_DMY 1 /* date format 26/10/91 (most of the world) */
+#define DF_YMD 2 /* date format 91/10/26 (a few countries) */
+
+/*---------------------------------------------------------------------------
+ Extra-field block ID values and offset info.
+ ---------------------------------------------------------------------------*/
+/* extra-field ID values, all little-endian: */
+#define EF_AV 0x0007 /* PKWARE's authenticity verification */
+#define EF_OS2 0x0009 /* OS/2 extended attributes */
+#define EF_PKW32 0x000a /* PKWARE's Win95/98/WinNT filetimes */
+#define EF_PKVMS 0x000c /* PKWARE's VMS */
+#define EF_PKUNIX 0x000d /* PKWARE's Unix */
+#define EF_IZVMS 0x4d49 /* Info-ZIP's VMS ("IM") */
+#define EF_IZUNIX 0x5855 /* Info-ZIP's old Unix[1] ("UX") */
+#define EF_IZUNIX2 0x7855 /* Info-ZIP's new Unix[2] ("Ux") */
+#define EF_TIME 0x5455 /* universal timestamp ("UT") */
+#define EF_MAC3 0x334d /* Info-ZIP's new Macintosh (= "M3") */
+#define EF_JLMAC 0x07c8 /* Johnny Lee's old Macintosh (= 1992) */
+#define EF_ZIPIT 0x2605 /* Thomas Brown's Macintosh (ZipIt) */
+#define EF_ZIPIT2 0x2705 /* T. Brown's Mac (ZipIt) v 1.3.8 and newer ? */
+#define EF_VMCMS 0x4704 /* Info-ZIP's VM/CMS ("\004G") */
+#define EF_MVS 0x470f /* Info-ZIP's MVS ("\017G") */
+#define EF_ACL 0x4c41 /* (OS/2) access control list ("AL") */
+#define EF_NTSD 0x4453 /* NT security descriptor ("SD") */
+#define EF_BEOS 0x6542 /* BeOS ("Be") */
+#define EF_QDOS 0xfb4a /* SMS/QDOS ("J\373") */
+#define EF_AOSVS 0x5356 /* AOS/VS ("VS") */
+#define EF_SPARK 0x4341 /* David Pilling's Acorn/SparkFS ("AC") */
+#define EF_MD5 0x4b46 /* Fred Kantor's MD5 ("FK") */
+#define EF_ASIUNIX 0x756e /* ASi's Unix ("nu") */
+
+#define EB_HEADSIZE 4 /* length of extra field block header */
+#define EB_ID 0 /* offset of block ID in header */
+#define EB_LEN 2 /* offset of data length field in header */
+#define EB_UCSIZE_P 0 /* offset of ucsize field in compr. data */
+#define EB_CMPRHEADLEN 6 /* lenght of compression header */
+
+#define EB_UX_MINLEN 8 /* minimal "UX" field contains atime, mtime */
+#define EB_UX_FULLSIZE 12 /* full "UX" field (atime, mtime, uid, gid) */
+#define EB_UX_ATIME 0 /* offset of atime in "UX" extra field data */
+#define EB_UX_MTIME 4 /* offset of mtime in "UX" extra field data */
+#define EB_UX_UID 8 /* byte offset of UID in "UX" field data */
+#define EB_UX_GID 10 /* byte offset of GID in "UX" field data */
+
+#define EB_UX2_MINLEN 4 /* minimal "Ux" field contains UID/GID */
+#define EB_UX2_UID 0 /* byte offset of UID in "Ux" field data */
+#define EB_UX2_GID 2 /* byte offset of GID in "Ux" field data */
+#define EB_UX2_VALID (1 << 8) /* UID/GID present */
+
+#define EB_UT_MINLEN 1 /* minimal UT field contains Flags byte */
+#define EB_UT_FLAGS 0 /* byte offset of Flags field */
+#define EB_UT_TIME1 1 /* byte offset of 1st time value */
+#define EB_UT_FL_MTIME (1 << 0) /* mtime present */
+#define EB_UT_FL_ATIME (1 << 1) /* atime present */
+#define EB_UT_FL_CTIME (1 << 2) /* ctime present */
+
+#define EB_FLGS_OFFS 4 /* offset of flags area in generic compressed
+ extra field blocks (OS2, NT, and others) */
+#define EB_OS2_HLEN 4 /* size of OS2/ACL compressed data header */
+#define EB_BEOS_HLEN 5 /* length of BeOS e.f attribute header */
+#define EB_BE_FL_UNCMPR 0x01 /* "BeOS attributes uncompressed" bit flag */
+#define EB_MAC3_HLEN 14 /* length of Mac3 attribute block header */
+#define EB_M3_FL_DATFRK 0x01 /* "this entry is data fork" flag */
+#define EB_M3_FL_UNCMPR 0x04 /* "Mac3 attributes uncompressed" bit flag */
+#define EB_M3_FL_TIME64 0x08 /* "Mac3 time fields are 64 bit wide" flag */
+#define EB_M3_FL_NOUTC 0x10 /* "Mac3 timezone offset fields missing" flag */
+
+#define EB_NTSD_C_LEN 4 /* length of central NT security data */
+#define EB_NTSD_L_LEN 5 /* length of minimal local NT security data */
+#define EB_NTSD_VERSION 4 /* offset of NTSD version byte */
+#define EB_NTSD_MAX_VER (0) /* maximum version # we know how to handle */
+
+#define EB_ASI_CRC32 0 /* offset of ASI Unix field's crc32 checksum */
+#define EB_ASI_MODE 4 /* offset of ASI Unix permission mode field */
+
+/*---------------------------------------------------------------------------
+ True sizes of the various headers, as defined by PKWARE--so it is not
+ likely that these will ever change. But if they do, make sure both these
+ defines AND the typedefs below get updated accordingly.
+ ---------------------------------------------------------------------------*/
+#define LREC_SIZE 26 /* lengths of local file headers, central */
+#define CREC_SIZE 42 /* directory headers, and the end-of- */
+#define ECREC_SIZE 18 /* central-dir record, respectively */
+
+#define MAX_BITS 13 /* used in unshrink() */
+#define HSIZE (1 << MAX_BITS) /* size of global work area */
+
+#define LF 10 /* '\n' on ASCII machines; must be 10 due to EBCDIC */
+#define CR 13 /* '\r' on ASCII machines; must be 13 due to EBCDIC */
+#define CTRLZ 26 /* DOS & OS/2 EOF marker (used in fileio.c, vms.c) */
+
+#ifdef EBCDIC
+# define foreign(c) ascii[(uch)(c)]
+# define native(c) ebcdic[(uch)(c)]
+# define NATIVE "EBCDIC"
+# define NOANSIFILT
+#endif
+
+#if (defined(CRAY) && defined(ZMEM))
+# undef ZMEM
+#endif
+
+#ifdef ZMEM
+# undef ZMEM
+# define memcmp(b1,b2,len) bcmp(b2,b1,len)
+# define memcpy(dest,src,len) bcopy(src,dest,len)
+# define memzero bzero
+#else
+# define memzero(dest,len) memset(dest,0,len)
+#endif
+
+#ifdef VMS
+# define ENV_UNZIP "UNZIP_OPTS" /* names of environment variables */
+# define ENV_ZIPINFO "ZIPINFO_OPTS"
+#endif /* VMS */
+#ifdef RISCOS
+# define ENV_UNZIP "Unzip$Options"
+# define ENV_ZIPINFO "Zipinfo$Options"
+# define ENV_UNZIPEXTS "Unzip$Exts"
+#endif /* RISCOS */
+#ifndef ENV_UNZIP
+# define ENV_UNZIP "UNZIP" /* the standard names */
+# define ENV_ZIPINFO "ZIPINFO"
+#endif
+#define ENV_UNZIP2 "UNZIPOPT" /* alternate names, for zip compat. */
+#define ENV_ZIPINFO2 "ZIPINFOOPT"
+
+#if (!defined(QQ) && !defined(NOQQ))
+# define QQ
+#endif
+
+#ifdef QQ /* Newtware version: no file */
+# define QCOND (!uO.qflag) /* comments with -vq or -vqq */
+#else /* Bill Davidsen version: no way to */
+# define QCOND (longhdr) /* kill file comments when listing */
+#endif
+
+#ifdef OLD_QQ
+# define QCOND2 (uO.qflag < 2)
+#else
+# define QCOND2 (!uO.qflag)
+#endif
+
+#ifndef TRUE
+# define TRUE 1 /* sort of obvious */
+#endif
+#ifndef FALSE
+# define FALSE 0
+#endif
+
+#ifndef SEEK_SET
+# define SEEK_SET 0
+# define SEEK_CUR 1
+# define SEEK_END 2
+#endif
+
+#if (defined(UNIX) && defined(S_IFLNK) && !defined(MTS))
+# define SYMLINKS
+# ifndef S_ISLNK
+# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
+# endif
+#endif /* UNIX && S_IFLNK && !MTS */
+
+#ifndef S_ISDIR
+# ifdef CMS_MVS
+# define S_ISDIR(m) (FALSE)
+# else
+# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+# endif
+#endif
+
+#ifndef IS_VOLID
+# define IS_VOLID(m) ((m) & 0x08)
+#endif
+
+
+
+
+
+/**************/
+/* Typedefs */
+/**************/
+
+#ifdef NO_UID_GID
+# ifdef UID_USHORT
+ typedef unsigned short uid_t; /* TI SysV.3 */
+ typedef unsigned short gid_t;
+# else
+ typedef unsigned int uid_t; /* SCO Xenix */
+ typedef unsigned int gid_t;
+# endif
+#endif
+
+#if (defined(WIN32) || defined(sgi) || defined(GOT_UTIMBUF) || defined(ATARI))
+ typedef struct utimbuf ztimbuf;
+#else
+ typedef struct ztimbuf {
+ time_t actime; /* new access time */
+ time_t modtime; /* new modification time */
+ } ztimbuf;
+#endif
+
+typedef struct iztimes {
+ time_t atime; /* new access time */
+ time_t mtime; /* new modification time */
+ time_t ctime; /* used for creation time; NOT same as st_ctime */
+} iztimes;
+
+#ifdef SET_DIR_ATTRIB
+ typedef struct dirtime { /* temporary struct for holding directory info */
+ struct dirtime *next; /* until can be sorted and set at end */
+ char *fn; /* filename of directory */
+ union {
+ iztimes t3; /* mtime, atime, ctime */
+ ztimbuf t2; /* modtime, actime */
+ } u;
+ unsigned perms; /* same as min_info.file_attr */
+ int have_uidgid; /* flag */
+ ush uidgid[2];
+ } dirtime;
+#endif /* SET_DIR_ATTRIB */
+
+typedef struct min_info {
+ long offset;
+ ulg crc; /* crc (needed if extended header) */
+ ulg compr_size; /* compressed size (needed if extended header) */
+ ulg uncompr_size; /* uncompressed size (needed if extended header) */
+ int hostnum;
+ unsigned file_attr; /* local flavor, as used by creat(), chmod()... */
+ unsigned encrypted : 1; /* file encrypted: decrypt before uncompressing */
+ unsigned ExtLocHdr : 1; /* use time instead of CRC for decrypt check */
+ unsigned textfile : 1; /* file is text (according to zip) */
+ unsigned textmode : 1; /* file is to be extracted as text */
+ unsigned lcflag : 1; /* convert filename to lowercase */
+ unsigned vollabel : 1; /* "file" is an MS-DOS volume (disk) label */
+} min_info;
+
+typedef struct VMStimbuf {
+ char *revdate; /* (both roughly correspond to Unix modtime/st_mtime) */
+ char *credate;
+} VMStimbuf;
+
+/*---------------------------------------------------------------------------
+ Zipfile work area declarations.
+ ---------------------------------------------------------------------------*/
+
+#ifdef MALLOC_WORK
+ union work {
+ struct { /* unshrink(): */
+ shrint *Parent; /* (8193 * sizeof(shrint)) */
+ uch *value;
+ uch *Stack;
+ } shrink;
+ uch *Slide; /* explode(), inflate(), unreduce() */
+ };
+#else /* !MALLOC_WORK */
+ union work {
+ struct { /* unshrink(): */
+ shrint Parent[HSIZE]; /* (8192 * sizeof(shrint)) == 16KB minimum */
+ uch value[HSIZE]; /* 8KB */
+ uch Stack[HSIZE]; /* 8KB */
+ } shrink; /* total = 32KB minimum; 80KB on Cray/Alpha */
+ uch Slide[WSIZE]; /* explode(), inflate(), unreduce() */
+ };
+#endif /* ?MALLOC_WORK */
+
+#define slide G.area.Slide
+
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+# define redirSlide G.redirect_sldptr
+#else
+# define redirSlide G.area.Slide
+#endif
+
+/*---------------------------------------------------------------------------
+ Zipfile layout declarations. If these headers ever change, make sure the
+ xxREC_SIZE defines (above) change with them!
+ ---------------------------------------------------------------------------*/
+
+ typedef uch local_byte_hdr[ LREC_SIZE ];
+# define L_VERSION_NEEDED_TO_EXTRACT_0 0
+# define L_VERSION_NEEDED_TO_EXTRACT_1 1
+# define L_GENERAL_PURPOSE_BIT_FLAG 2
+# define L_COMPRESSION_METHOD 4
+# define L_LAST_MOD_DOS_DATETIME 6
+# define L_CRC32 10
+# define L_COMPRESSED_SIZE 14
+# define L_UNCOMPRESSED_SIZE 18
+# define L_FILENAME_LENGTH 22
+# define L_EXTRA_FIELD_LENGTH 24
+
+ typedef uch cdir_byte_hdr[ CREC_SIZE ];
+# define C_VERSION_MADE_BY_0 0
+# define C_VERSION_MADE_BY_1 1
+# define C_VERSION_NEEDED_TO_EXTRACT_0 2
+# define C_VERSION_NEEDED_TO_EXTRACT_1 3
+# define C_GENERAL_PURPOSE_BIT_FLAG 4
+# define C_COMPRESSION_METHOD 6
+# define C_LAST_MOD_DOS_DATETIME 8
+# define C_CRC32 12
+# define C_COMPRESSED_SIZE 16
+# define C_UNCOMPRESSED_SIZE 20
+# define C_FILENAME_LENGTH 24
+# define C_EXTRA_FIELD_LENGTH 26
+# define C_FILE_COMMENT_LENGTH 28
+# define C_DISK_NUMBER_START 30
+# define C_INTERNAL_FILE_ATTRIBUTES 32
+# define C_EXTERNAL_FILE_ATTRIBUTES 34
+# define C_RELATIVE_OFFSET_LOCAL_HEADER 38
+
+ typedef uch ec_byte_rec[ ECREC_SIZE+4 ];
+/* define SIGNATURE 0 space-holder only */
+# define NUMBER_THIS_DISK 4
+# define NUM_DISK_WITH_START_CENTRAL_DIR 6
+# define NUM_ENTRIES_CENTRL_DIR_THS_DISK 8
+# define TOTAL_ENTRIES_CENTRAL_DIR 10
+# define SIZE_CENTRAL_DIRECTORY 12
+# define OFFSET_START_CENTRAL_DIRECTORY 16
+# define ZIPFILE_COMMENT_LENGTH 20
+
+
+ typedef struct local_file_header { /* LOCAL */
+ uch version_needed_to_extract[2];
+ ush general_purpose_bit_flag;
+ ush compression_method;
+ ulg last_mod_dos_datetime;
+ ulg crc32;
+ ulg csize;
+ ulg ucsize;
+ ush filename_length;
+ ush extra_field_length;
+ } local_file_hdr;
+
+#if 0
+ typedef struct central_directory_file_header { /* CENTRAL */
+ uch version_made_by[2];
+ uch version_needed_to_extract[2];
+ ush general_purpose_bit_flag;
+ ush compression_method;
+ ulg last_mod_dos_datetime;
+ ulg crc32;
+ ulg csize;
+ ulg ucsize;
+ ush filename_length;
+ ush extra_field_length;
+ ush file_comment_length;
+ ush disk_number_start;
+ ush internal_file_attributes;
+ ulg external_file_attributes;
+ ulg relative_offset_local_header;
+ } cdir_file_hdr;
+#endif /* 0 */
+
+ typedef struct end_central_dir_record { /* END CENTRAL */
+ ush number_this_disk;
+ ush num_disk_start_cdir;
+ ush num_entries_centrl_dir_ths_disk;
+ ush total_entries_central_dir;
+ ulg size_central_directory;
+ ulg offset_start_central_directory;
+ ush zipfile_comment_length;
+ } ecdir_rec;
+
+
+/* Huffman code lookup table entry--this entry is four bytes for machines
+ that have 16-bit pointers (e.g. PC's in the small or medium model).
+ Valid extra bits are 0..13. e == 15 is EOB (end of block), e == 16
+ means that v is a literal, 16 < e < 32 means that v is a pointer to
+ the next table, which codes e - 16 bits, and lastly e == 99 indicates
+ an unused code. If a code with e == 99 is looked up, this implies an
+ error in the data. */
+
+struct huft {
+ uch e; /* number of extra bits or operation */
+ uch b; /* number of bits in this code or subcode */
+ union {
+ ush n; /* literal, length base, or distance base */
+ struct huft *t; /* pointer to next level of table */
+ } v;
+};
+
+
+typedef struct _APIDocStruct {
+ char *compare;
+ char *function;
+ char *syntax;
+ char *purpose;
+} APIDocStruct;
+
+
+
+
+/*************/
+/* Globals */
+/*************/
+
+#if (defined(OS2) && !defined(FUNZIP))
+# include "os2/os2data.h"
+#endif
+
+#include "globals.h"
+
+
+
+/*************************/
+/* Function Prototypes */
+/*************************/
+
+/*---------------------------------------------------------------------------
+ Functions in unzip.c (initialization routines):
+ ---------------------------------------------------------------------------*/
+
+#ifndef WINDLL
+ int MAIN OF((int argc, char **argv));
+ int unzip OF((__GPRO__ int argc, char **argv));
+ int uz_opts OF((__GPRO__ int *pargc, char ***pargv));
+ int usage OF((__GPRO__ int error));
+#endif /* !WINDLL */
+
+/*---------------------------------------------------------------------------
+ Functions in process.c (main driver routines):
+ ---------------------------------------------------------------------------*/
+
+int process_zipfiles OF((__GPRO));
+void free_G_buffers OF((__GPRO));
+/* static int do_seekable OF((__GPRO__ int lastchance)); */
+/* static int find_ecrec OF((__GPRO__ long searchlen)); */
+int uz_end_central OF((__GPRO));
+int process_cdir_file_hdr OF((__GPRO));
+int get_cdir_ent OF((__GPRO));
+int process_local_file_hdr OF((__GPRO));
+unsigned ef_scan_for_izux OF((uch *ef_buf, unsigned ef_len, int ef_is_c,
+ ulg dos_mdatetime,
+ iztimes *z_utim, ush *z_uidgid));
+
+#ifndef SFX
+
+/*---------------------------------------------------------------------------
+ Functions in zipinfo.c (`zipinfo-style' listing routines):
+ ---------------------------------------------------------------------------*/
+
+#ifndef NO_ZIPINFO
+#ifndef WINDLL
+ int zi_opts OF((__GPRO__ int *pargc, char ***pargv));
+#endif
+int zi_end_central OF((__GPRO));
+int zipinfo OF((__GPRO));
+/* static int zi_long OF((__GPRO__ ulg *pEndprev)); */
+/* static int zi_short OF((__GPRO)); */
+/* static char *zi_time OF((__GPRO__ ZCONST ulg *datetimez,
+ ZCONST time_t *modtimez, char *d_t_str));*/
+#endif /* !NO_ZIPINFO */
+
+/*---------------------------------------------------------------------------
+ Functions in list.c (generic zipfile-listing routines):
+ ---------------------------------------------------------------------------*/
+
+int list_files OF((__GPRO));
+#ifdef TIMESTAMP
+ int get_time_stamp OF((__GPRO__ time_t *last_modtime,
+ unsigned *nmember));
+#endif
+int ratio OF((ulg uc, ulg c));
+void fnprint OF((__GPRO));
+
+#endif /* !SFX */
+
+/*---------------------------------------------------------------------------
+ Functions in fileio.c:
+ ---------------------------------------------------------------------------*/
+
+int open_input_file OF((__GPRO));
+int open_outfile OF((__GPRO)); /* also vms.c */
+void undefer_input OF((__GPRO));
+void defer_leftover_input OF((__GPRO));
+unsigned readbuf OF((__GPRO__ char *buf, register unsigned len));
+int readbyte OF((__GPRO));
+int fillinbuf OF((__GPRO));
+#ifdef FUNZIP
+ int flush OF((__GPRO__ ulg size)); /* actually funzip.c */
+#else
+ int flush OF((__GPRO__ uch *buf, ulg size, int unshrink));
+#endif
+/* static int disk_error OF((__GPRO)); */
+void handler OF((int signal));
+time_t dos_to_unix_time OF((ulg dos_datetime));
+int check_for_newer OF((__GPRO__ char *filename)); /* os2,vmcms,vms */
+int do_string OF((__GPRO__ unsigned int len, int option));
+ush makeword OF((ZCONST uch *b));
+ulg makelong OF((ZCONST uch *sig));
+#if (!defined(STR_TO_ISO) || defined(NEED_STR2ISO))
+ char *str2iso OF((char *dst, ZCONST char *src));
+#endif
+#if (!defined(STR_TO_OEM) || defined(NEED_STR2OEM))
+ char *str2oem OF((char *dst, ZCONST char *src));
+#endif
+int zstrnicmp OF((register ZCONST char *s1,
+ register ZCONST char *s2,
+ register unsigned n));
+#ifdef REGULUS
+ int zstat OF((char *p, struct stat *s));
+#endif
+#ifdef ZMEM /* MUST be ifdef'd because of conflicts with the standard def. */
+ zvoid *memset OF((register zvoid *, register int, register unsigned int));
+ int memcmp OF((register ZCONST zvoid*, register ZCONST zvoid *,
+ register unsigned int));
+ zvoid *memcpy OF((register zvoid *, register ZCONST zvoid *,
+ register unsigned int));
+#endif
+#ifdef SMALL_MEM
+ char *fLoadFarString OF((__GPRO__ const char Far *sz));
+ char *fLoadFarStringSmall OF((__GPRO__ const char Far *sz));
+ char *fLoadFarStringSmall2 OF((__GPRO__ const char Far *sz));
+ #ifndef zfstrcpy
+ char Far * Far zfstrcpy OF((char Far *s1, const char Far *s2));
+ #endif
+#endif
+
+
+/*---------------------------------------------------------------------------
+ Functions in extract.c:
+ ---------------------------------------------------------------------------*/
+
+int extract_or_test_files OF((__GPRO));
+/* static int store_info OF((void)); */
+/* static int extract_or_test_member OF((__GPRO)); */
+/* static int TestExtraField OF((__GPRO__ uch *ef, unsigned ef_len)); */
+/* static int test_OS2 OF((__GPRO__ uch *eb, unsigned eb_size)); */
+/* static int test_NT OF((__GPRO__ uch *eb, unsigned eb_size)); */
+int memextract OF((__GPRO__ uch *tgt, ulg tgtsize,
+ uch *src, ulg srcsize));
+int memflush OF((__GPRO__ uch *rawbuf, ulg size));
+char *fnfilter OF((ZCONST char *raw, uch *space));
+
+/*---------------------------------------------------------------------------
+ Decompression functions:
+ ---------------------------------------------------------------------------*/
+
+#if (!defined(SFX) && !defined(FUNZIP))
+int explode OF((__GPRO)); /* explode.c */
+#endif
+int huft_free OF((struct huft *t)); /* inflate.c */
+int huft_build OF((__GPRO__ ZCONST unsigned *b, unsigned n,
+ unsigned s, ZCONST ush *d, ZCONST ush *e,
+ struct huft **t, int *m));
+#ifdef USE_ZLIB
+ int UZinflate OF((__GPRO)); /* inflate.c */
+# define inflate_free(x) inflateEnd(&((Uz_Globs *)(&G))->dstrm)
+#else
+ int inflate OF((__GPRO)); /* inflate.c */
+ int inflate_free OF((__GPRO)); /* inflate.c */
+#endif /* ?USE_ZLIB */
+#if (!defined(SFX) && !defined(FUNZIP))
+void unreduce OF((__GPRO)); /* unreduce.c */
+/* static void LoadFollowers OF((__GPRO__ f_array *follower, uch *Slen));
+ * unreduce.c */
+int unshrink OF((__GPRO)); /* unshrink.c */
+/* static void partial_clear OF((__GPRO)); * unshrink.c */
+#endif /* !SFX && !FUNZIP */
+
+/*---------------------------------------------------------------------------
+ Internal API functions (only included in DLL versions):
+ ---------------------------------------------------------------------------*/
+
+#ifdef DLL
+ void setFileNotFound OF((__GPRO)); /* api.c */
+ int unzipToMemory OF((__GPRO__ char *zip, char *file,
+ UzpBuffer *retstr)); /* api.c */
+ int redirect_outfile OF((__GPRO)); /* api.c */
+ int writeToMemory OF((__GPRO__ uch *rawbuf, ulg size));
+ int close_redirect OF((__GPRO)); /* api.c */
+ /* this obsolescent entry point kept for compatibility: */
+ int UzpUnzip OF((int argc, char **argv));/* use UzpMain */
+#ifdef OS2DLL
+ int varmessage OF((__GPRO__ uch *buf, ulg size));
+ int varputchar OF((__GPRO__ int c)); /* rexxapi.c */
+ int finish_REXX_redirect OF((__GPRO)); /* rexxapi.c */
+#endif
+#ifdef API_DOC
+ void APIhelp OF((__GPRO__ int argc, char **argv));
+#endif /* apihelp.c */
+#endif /* DLL */
+
+/*---------------------------------------------------------------------------
+ Acorn RISC OS-only functions:
+ ---------------------------------------------------------------------------*/
+
+#ifdef RISCOS
+ int isRISCOSexfield OF((void *extra_field)); /* acorn.c */
+ void setRISCOSexfield OF((char *path, void *extra_field)); /* acorn.c */
+ void printRISCOSexfield OF((int isdir, void *extra_field)); /* acorn.c */
+#endif
+
+/*---------------------------------------------------------------------------
+ Human68K-only functions:
+ ---------------------------------------------------------------------------*/
+
+#ifdef __human68k__
+ void InitTwentyOne OF((void));
+#endif
+
+/*---------------------------------------------------------------------------
+ Macintosh-only functions:
+ ---------------------------------------------------------------------------*/
+
+#ifdef MACOS
+ void screenOpen OF((char *)); /* macscreen.c */
+ void screenControl OF((char *, int)); /* macscreen.c */
+ void screenDump OF((char *, long)); /* macscreen.c */
+ void screenUpdate OF((WindowPtr)); /* macscreen.c */
+ void screenClose OF((void)); /* macscreen.c */
+ int macgetch OF((void)); /* macscreen.c */
+
+ int macmkdir OF((char *)); /* mac.c */
+ short macopen OF((char *, short)); /* mac.c */
+ short maccreat OF((char *)); /* mac.c */
+ short macread OF((short, char *, unsigned)); /* mac.c */
+ long macwrite OF((short, char *, unsigned)); /* mac.c */
+ short macclose OF((short)); /* mac.c */
+ long maclseek OF((short, long, short)); /* mac.c */
+ char *macfgets OF((char *, int, FILE *)); /* mac.c */
+ int macfprintf OF((FILE *, char *, ...)); /* mac.c */
+ int macprintf OF((char *, ...)); /* mac.c */
+#endif
+
+/*---------------------------------------------------------------------------
+ MSDOS-only functions:
+ ---------------------------------------------------------------------------*/
+
+#if (defined(MSDOS) && (defined(__GO32__) || defined(__EMX__)))
+ unsigned _dos_getcountryinfo(void *); /* msdos.c */
+#if (!defined(__DJGPP__) || (__DJGPP__ < 2))
+ unsigned _dos_setftime(int, unsigned short, unsigned short); /* msdos.c */
+ unsigned _dos_setfileattr(char *, unsigned); /* msdos.c */
+ unsigned _dos_creat(char *, unsigned, int *); /* msdos.c */
+ void _dos_getdrive(unsigned *); /* msdos.c */
+ unsigned _dos_close(int); /* msdos.c */
+#endif /* !__DJGPP__ || (__DJGPP__ < 2) */
+#endif
+
+/*---------------------------------------------------------------------------
+ OS/2-only functions:
+ ---------------------------------------------------------------------------*/
+
+#ifdef OS2 /* GetFileTime conflicts with something in Win32 header files */
+#if (defined(REENTRANT) && defined(USETHREADID))
+ ulg GetThreadId OF((void));
+#endif
+ int GetCountryInfo OF((void)); /* os2.c */
+ long GetFileTime OF((ZCONST char *name)); /* os2.c */
+/* static void SetPathAttrTimes OF((__GPRO__ int flags, int dir)); os2.c */
+/* static int SetEAs OF((__GPRO__ const char *path,
+ void *eablock)); os2.c */
+/* static int SetACL OF((__GPRO__ const char *path,
+ void *eablock)); os2.c */
+/* static int IsFileNameValid OF((const char *name)); os2.c */
+/* static void map2fat OF((char *pathcomp, char **pEndFAT)); os2.c */
+/* static int SetLongNameEA OF((char *name, char *longname)); os2.c */
+/* static void InitNLS OF((void)); os2.c */
+ int IsUpperNLS OF((int nChr)); /* os2.c */
+ int ToLowerNLS OF((int nChr)); /* os2.c */
+ void DebugMalloc OF((void)); /* os2.c */
+#endif
+
+/*---------------------------------------------------------------------------
+ QDOS-only functions:
+ ---------------------------------------------------------------------------*/
+
+#ifdef QDOS
+ int QMatch (uch, uch);
+ void QFilename (__GPRO__ char *);
+ char *Qstrfix (char *);
+ int QReturn (int zip_error);
+#endif
+
+/*---------------------------------------------------------------------------
+ TOPS20-only functions:
+ ---------------------------------------------------------------------------*/
+
+#ifdef TOPS20
+ int upper OF((char *s)); /* tops20.c */
+ int enquote OF((char *s)); /* tops20.c */
+ int dequote OF((char *s)); /* tops20.c */
+ int fnlegal OF(()); /* error if prototyped? */ /* tops20.c */
+#endif
+
+/*---------------------------------------------------------------------------
+ VM/CMS- and MVS-only functions:
+ ---------------------------------------------------------------------------*/
+
+#ifdef CMS_MVS
+ extent getVMMVSexfield OF((char *type, uch *ef_block, unsigned datalen));
+ FILE *vmmvs_open_infile OF((__GPRO)); /* vmmvs.c */
+ void close_infile OF((__GPRO)); /* vmmvs.c */
+#endif
+
+/*---------------------------------------------------------------------------
+ VMS-only functions:
+ ---------------------------------------------------------------------------*/
+
+#ifdef VMS
+ int check_format OF((__GPRO)); /* vms.c */
+/* int open_outfile OF((__GPRO)); * (see fileio.c) vms.c */
+/* int flush OF((__GPRO__ uch *rawbuf, unsigned size,
+ int final_flag)); * (see fileio.c) vms.c */
+#ifdef RETURN_CODES
+ void return_VMS OF((__GPRO__ int zip_error)); /* vms.c */
+#else
+ void return_VMS OF((int zip_error)); /* vms.c */
+#endif
+#ifdef VMSCLI
+ ulg vms_unzip_cmdline OF((int *, char ***)); /* cmdline.c */
+ int VMSCLI_usage OF((__GPRO__ int error)); /* cmdline.c */
+#endif
+#endif
+
+/*---------------------------------------------------------------------------
+ WIN32-only functions:
+ ---------------------------------------------------------------------------*/
+
+#ifdef WIN32
+ int IsWinNT OF((void)); /* win32.c */
+#ifdef NTSD_EAS
+ void process_defer_NT OF((__GPRO)); /* win32.c */
+ int test_NTSD OF((__GPRO__ uch *eb, unsigned eb_size,
+ uch *eb_ucptr, ulg eb_ucsize)); /* win32.c */
+# define TEST_NTSD test_NTSD
+#endif
+#ifdef W32_STAT_BANDAID
+ int zstat_win32 OF((__W32STAT_GLOBALS__
+ const char *path, struct stat *buf)); /* win32.c */
+#endif
+#endif
+
+/*---------------------------------------------------------------------------
+ Miscellaneous/shared functions:
+ ---------------------------------------------------------------------------*/
+
+Uz_Globs *globalsCtor OF((void)); /* globals.c */
+
+void envargs OF((__GPRO__ int *Pargc, char ***Pargv,
+ ZCONST char *envstr, ZCONST char *envstr2));
+ /* envargs.c */
+void mksargs OF((int *argcp, char ***argvp)); /* envargs.c */
+
+int match OF((ZCONST char *s, ZCONST char *p,
+ int ic)); /* match.c */
+int iswild OF((ZCONST char *p)); /* match.c */
+
+#ifdef DYNALLOC_CRCTAB
+ void free_crc_table OF((void)); /* crctab.c */
+#endif
+#ifndef USE_ZLIB
+ ZCONST ulg near *get_crc_table OF((void)); /* funzip.c, crctab.c */
+ ulg crc32 OF((ulg crc, ZCONST uch *buf, extent len));
+#endif /* !USE_ZLIB */ /* assembler source or crc32.c */
+
+int dateformat OF((void)); /* currently, only msdos.c */
+#ifndef WINDLL
+ void version OF((__GPRO)); /* local */
+#endif
+int mapattr OF((__GPRO)); /* local */
+int mapname OF((__GPRO__ int renamed)); /* local */
+int checkdir OF((__GPRO__ char *pathcomp, int flag)); /* local */
+char *do_wild OF((__GPRO__ char *wildzipfn)); /* local */
+char *GetLoadPath OF((__GPRO)); /* local */
+#if (defined(MORE) && (defined(UNIX) || defined(VMS) || defined(__BEOS__)))
+ int screenlines OF((void)); /* local */
+#endif
+#ifndef MTS /* macro in MTS */
+ void close_outfile OF((__GPRO)); /* local */
+#endif
+#ifdef SET_DIR_ATTRIB
+ int set_direc_attribs OF((__GPRO__ dirtime *d)); /* local */
+#endif
+#ifdef TIMESTAMP
+# ifdef WIN32
+ int stamp_file OF((__GPRO__
+ ZCONST char *fname, time_t modtime)); /* local */
+# else
+ int stamp_file OF((ZCONST char *fname, time_t modtime)); /* local */
+# endif
+#endif
+#ifdef SYSTEM_SPECIFIC_CTOR
+ void SYSTEM_SPECIFIC_CTOR OF((__GPRO)); /* local */
+#endif
+
+
+
+
+
+/************/
+/* Macros */
+/************/
+
+#ifndef MAX
+# define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+#ifndef MIN
+# define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+#ifdef DEBUG
+# define Trace(x) fprintf x
+#else
+# define Trace(x)
+#endif
+
+#ifdef DEBUG_TIME
+# define TTrace(x) fprintf x
+#else
+# define TTrace(x)
+#endif
+
+#ifdef NO_DEBUG_IN_MACROS
+# define MTrace(x)
+#else
+# define MTrace(x) Trace(x)
+#endif
+
+#if (defined(UNIX) || defined(T20_VMS)) /* generally old systems */
+# define ToLower(x) ((char)(isupper((int)x)? tolower((int)x) : x))
+#else
+# define ToLower tolower /* assumed "smart"; used in match() */
+#endif
+
+#ifdef USE_STRM_INPUT
+ /* ``Replace'' the unbuffered UNIX style I/O function with similar
+ * standard C functions from <stdio.h>.
+ */
+# define read(fd,buf,n) fread((buf),1,(n),(FILE *)(fd))
+# define lseek(fd,o,w) fseek((FILE *)(fd),(o),(w))
+# define close(fd) fclose((FILE *)(fd))
+#endif /* USE_STRM_INPUT */
+
+/* The return value of the Info() "macro function" is never checked in
+ * UnZip. Otherwise, to get the same behaviour as for (*G.message)(), the
+ * Info() definition for "FUNZIP" would have to be corrected:
+ * #define Info(buf,flag,sprf_arg) \
+ * (fprintf((flag)&1? stderr : stdout, \
+ * (char *)(sprintf sprf_arg, (buf))) == EOF)
+ */
+#ifndef Info /* may already have been defined for redirection */
+# ifdef FUNZIP
+# define Info(buf,flag,sprf_arg) \
+ fprintf((flag)&1? stderr : stdout, (char *)(sprintf sprf_arg, (buf)))
+# else
+# ifdef INT_SPRINTF /* optimized version for "int sprintf()" flavour */
+# define Info(buf,flag,sprf_arg) \
+ (*G.message)((zvoid *)&G, (uch *)(buf), (ulg)sprintf sprf_arg, (flag))
+# else /* generic version, does not use sprintf() return value */
+# define Info(buf,flag,sprf_arg) \
+ (*G.message)((zvoid *)&G, (uch *)(buf), \
+ (ulg)(sprintf sprf_arg, strlen((char *)(buf))), (flag))
+# endif
+# endif
+#endif /* !Info */
+
+/* The following macros wrappers around the fnfilter function are used many
+ * times to prepare archive entry names or name components for displaying
+ * listings and (warning/error) messages. They use sections in the upper half
+ * of 'slide' as buffer, since their output is normally fed through the
+ * Info() macro with 'slide' (the start of this area) as message buffer.
+ */
+#define FnFilter1(fname) fnfilter((fname), slide + (WSIZE>>1))
+#define FnFilter2(fname) fnfilter((fname), slide + ((WSIZE>>1) + (WSIZE>>2)))
+
+#ifndef FUNZIP /* used only in inflate.c */
+# define MESSAGE(str,len,flag) (*G.message)((zvoid *)&G,(str),(len),(flag))
+#endif
+
+#if 0 /* Optimization: use the (const) result of crc32(0L,NULL,0) */
+# define CRCVAL_INITIAL crc32(0L, NULL, 0)
+#else
+# define CRCVAL_INITIAL 0L
+#endif
+
+#ifndef TEST_NTSD /* "NTSD valid?" checking function */
+# define TEST_NTSD NULL /* ... is not available */
+#endif
+
+/*
+ * Seek to the block boundary of the block which includes abs_offset,
+ * then read block into input buffer and set pointers appropriately.
+ * If block is already in the buffer, just set the pointers. This macro
+ * is used by uz_end_central (process.c), zi_end_central (zipinfo.c) and
+ * do_string (fileio.c). A slightly modified version is embedded within
+ * extract_or_test_files (extract.c). readbyte() and readbuf() (fileio.c)
+ * are compatible. NOTE THAT abs_offset is intended to be the "proper off-
+ * set" (i.e., if there were no extra bytes prepended); cur_zipfile_bufstart
+ * contains the corrected offset.
+ *
+ * Since ZLSEEK is never used during decompression, it is safe to use the
+ * slide[] buffer for the error message.
+ *
+ * The awkward "%cbs_offset" construct is provided for the obnoxious Solaris
+ * compiler, which wants to do macro substitution inside strings.
+ */
+
+#ifndef ZLSEEK
+# ifdef USE_STRM_INPUT
+# define _ZLS_RELOAD(abs_offset) {\
+ MTrace((stderr, "ZLSEEK: %cbs_offset = %ld, G.extra_bytes = %ld\n",\
+ 'a', (abs_offset), G.extra_bytes));\
+ fseek(G.zipfd,(LONGINT)bufstart,SEEK_SET);\
+ G.cur_zipfile_bufstart = ftell(G.zipfd);\
+ MTrace((stderr,\
+ " request = %ld, (abs+extra) = %ld, inbuf_offset = %ld\n",\
+ request, ((abs_offset)+G.extra_bytes), inbuf_offset));\
+ MTrace((stderr, " bufstart = %ld, cur_zipfile_bufstart = %ld\n",\
+ bufstart, G.cur_zipfile_bufstart));\
+ if ((G.incnt = fread((char *)G.inbuf,1,INBUFSIZ,G.zipfd)) <= 0)\
+ return(PK_EOF);\
+ G.inptr = G.inbuf + (int)inbuf_offset;\
+ G.incnt -= (int)inbuf_offset;\
+ }
+# else /* !USE_STRM_INPUT */
+# define _ZLS_RELOAD(abs_offset) {\
+ MTrace((stderr, "ZLSEEK: %cbs_offset = %ld, G.extra_bytes = %ld\n",\
+ 'a', (abs_offset), G.extra_bytes));\
+ G.cur_zipfile_bufstart = lseek(G.zipfd,(LONGINT)bufstart,SEEK_SET);\
+ MTrace((stderr,\
+ " request = %ld, (abs+extra) = %ld, inbuf_offset = %ld\n",\
+ request, ((abs_offset)+G.extra_bytes), inbuf_offset));\
+ MTrace((stderr, " bufstart = %ld, cur_zipfile_bufstart = %ld\n",\
+ bufstart, G.cur_zipfile_bufstart));\
+ if ((G.incnt = read(G.zipfd,(char *)G.inbuf,INBUFSIZ)) <= 0)\
+ return(PK_EOF);\
+ G.inptr = G.inbuf + (int)inbuf_offset;\
+ G.incnt -= (int)inbuf_offset;\
+ }
+# endif /* ?USE_STRM_INPUT */
+
+# define ZLSEEK(abs_offset) {\
+ LONGINT request = (abs_offset) + G.extra_bytes;\
+ LONGINT inbuf_offset = request % INBUFSIZ;\
+ LONGINT bufstart = request - inbuf_offset;\
+\
+ if (request < 0) {\
+ Info(slide, 1, ((char *)slide, LoadFarStringSmall(SeekMsg),\
+ G.zipfn, LoadFarString(ReportMsg)));\
+ return(PK_BADERR);\
+ } else if (bufstart != G.cur_zipfile_bufstart)\
+ _ZLS_RELOAD(abs_offset)\
+ else {\
+ G.incnt += (G.inptr-G.inbuf) - (int)inbuf_offset;\
+ G.inptr = G.inbuf + (int)inbuf_offset;\
+ }\
+ }
+#endif /* !ZLSEEK */
+
+#define SKIP_(length) if(length&&((error=do_string(__G__ length,SKIP))!=0))\
+ {error_in_archive=error; if(error>1) return error;}
+
+/*
+ * Skip a variable-length field, and report any errors. Used in zipinfo.c
+ * and unzip.c in several functions.
+ *
+ * macro SKIP_(length)
+ * ush length;
+ * {
+ * if (length && ((error = do_string(length, SKIP)) != 0)) {
+ * error_in_archive = error; /-* might be warning *-/
+ * if (error > 1) /-* fatal *-/
+ * return (error);
+ * }
+ * }
+ *
+ */
+
+
+#ifdef FUNZIP
+# define FLUSH(w) flush(__G__ (ulg)(w))
+# define NEXTBYTE getc(G.in) /* redefined in crypt.h if full version */
+#else
+# define FLUSH(w) if (G.mem_mode) memflush(__G__ redirSlide,(ulg)(w)); \
+ else flush(__G__ redirSlide,(ulg)(w),0)
+# define NEXTBYTE (--G.incnt >= 0 ? (int)(*G.inptr++) : readbyte(__G))
+#endif
+
+
+#define READBITS(nbits,zdest) {if(nbits>G.bits_left) {int temp; G.zipeof=1;\
+ while (G.bits_left<=8*(int)(sizeof(G.bitbuf)-1) && (temp=NEXTBYTE)!=EOF) {\
+ G.bitbuf|=(ulg)temp<<G.bits_left; G.bits_left+=8; G.zipeof=0;}}\
+ zdest=(shrint)((ush)G.bitbuf&mask_bits[nbits]);G.bitbuf>>=nbits;\
+ G.bits_left-=nbits;}
+
+/*
+ * macro READBITS(nbits,zdest) * only used by unreduce and unshrink *
+ * {
+ * if (nbits > G.bits_left) { * fill G.bitbuf, 8*sizeof(ulg) bits *
+ * int temp;
+ *
+ * G.zipeof = 1;
+ * while (G.bits_left <= 8*(int)(sizeof(G.bitbuf)-1) &&
+ * (temp = NEXTBYTE) != EOF) {
+ * G.bitbuf |= (ulg)temp << G.bits_left;
+ * G.bits_left += 8;
+ * G.zipeof = 0;
+ * }
+ * }
+ * zdest = (shrint)((ush)G.bitbuf & mask_bits[nbits]);
+ * G.bitbuf >>= nbits;
+ * G.bits_left -= nbits;
+ * }
+ *
+ */
+
+
+/* GRR: should change name to STRLOWER and use StringLower if possible */
+
+/*
+ * Copy the zero-terminated string in str1 into str2, converting any
+ * uppercase letters to lowercase as we go. str2 gets zero-terminated
+ * as well, of course. str1 and str2 may be the same character array.
+ */
+#ifdef __human68k__
+# define TOLOWER(str1, str2) \
+ { \
+ char *p=(str1), *q=(str2); \
+ uch c; \
+ while ((c = *p++) != '\0') { \
+ if (iskanji(c)) { \
+ if (*p == '\0') \
+ break; \
+ *q++ = c; \
+ *q++ = *p++; \
+ } else \
+ *q++ = isupper(c) ? tolower(c) : c; \
+ } \
+ *q = '\0'; \
+ }
+#else
+# define TOLOWER(str1, str2) \
+ { \
+ char *p, *q; \
+ p = (str1) - 1; \
+ q = (str2); \
+ while (*++p) \
+ *q++ = (char)(isupper((int)(*p))? tolower((int)(*p)) : *p); \
+ *q = '\0'; \
+ }
+#endif
+/*
+ * NOTES: This macro makes no assumptions about the characteristics of
+ * the tolower() function or macro (beyond its existence), nor does it
+ * make assumptions about the structure of the character set (i.e., it
+ * should work on EBCDIC machines, too). The fact that either or both
+ * of isupper() and tolower() may be macros has been taken into account;
+ * watch out for "side effects" (in the C sense) when modifying this
+ * macro.
+ */
+
+#ifndef foreign
+# define foreign(c) (c)
+#endif
+
+#ifndef native
+# define native(c) (c)
+# define A_TO_N(str1)
+#else
+# ifndef NATIVE
+# define NATIVE "native chars"
+# endif
+# define A_TO_N(str1) {register uch *p;\
+ for (p=(uch *)(str1); *p; p++) *p=native(*p);}
+#endif
+/*
+ * Translate the zero-terminated string in str1 from ASCII to the native
+ * character set. The translation is performed in-place and uses the
+ * "native" macro to translate each character.
+ *
+ * NOTE: Using the "native" macro means that is it the only part of unzip
+ * which knows which translation table (if any) is actually in use to
+ * produce the native character set. This makes adding new character set
+ * translation tables easy, insofar as all that is needed is an appropriate
+ * "native" macro definition and the translation table itself. Currently,
+ * the only non-ASCII native character set implemented is EBCDIC, but this
+ * may not always be so.
+ */
+
+
+/* default setup for internal codepage: assume ISO 8859-1 compatibility!! */
+#if (!defined(NATIVE) && !defined(CRTL_CP_IS_ISO) && !defined(CRTL_CP_IS_OEM))
+# define CRTL_CP_IS_ISO
+#endif
+
+
+/* Translate "extended ASCII" chars (OEM coding for DOS and OS/2; else
+ * ISO-8859-1 [ISO Latin 1, Win Ansi,...]) into the internal "native"
+ * code page. As with A_TO_N(), conversion is done in place.
+ */
+#ifndef _ISO_INTERN
+# ifdef CRTL_CP_IS_OEM
+# ifndef IZ_ISO2OEM_ARRAY
+# define IZ_ISO2OEM_ARRAY
+# endif
+# define _ISO_INTERN(str1) {register uch *p;\
+ for (p=(uch *)(str1); *p; p++)\
+ *p = native((*p & 0x80) ? iso2oem[*p & 0x7f] : *p);}
+# else
+# define _ISO_INTERN(str1) A_TO_N(str1)
+# endif
+#endif
+
+#ifndef _OEM_INTERN
+# ifdef CRTL_CP_IS_OEM
+# define _OEM_INTERN(str1) A_TO_N(str1)
+# else
+# ifndef IZ_OEM2ISO_ARRAY
+# define IZ_OEM2ISO_ARRAY
+# endif
+# define _OEM_INTERN(str1) {register uch *p;\
+ for (p=(uch *)(str1); *p; p++)\
+ *p = native((*p & 0x80) ? oem2iso[*p & 0x7f] : *p);}
+# endif
+#endif
+
+#ifndef STR_TO_ISO
+# ifdef CRTL_CP_IS_ISO
+# define STR_TO_ISO strcpy
+# else
+# define STR_TO_ISO str2iso
+# define NEED_STR2ISO
+# endif
+#endif
+
+#ifndef STR_TO_OEM
+# ifdef CRTL_CP_IS_OEM
+# define STR_TO_OEM strcpy
+# else
+# define STR_TO_OEM str2oem
+# define NEED_STR2OEM
+# endif
+#endif
+
+#if (!defined(INTERN_TO_ISO) && !defined(ASCII2ISO))
+# ifdef CRTL_CP_IS_OEM
+ /* know: "ASCII" is "OEM" */
+# define ASCII2ISO(c) (((c) & 0x80) ? oem2iso[(c) & 0x7f] : (c))
+# if (defined(NEED_STR2ISO) && !defined(CRYP_USES_OEM2ISO))
+# define CRYP_USES_OEM2ISO
+# endif
+# else
+ /* assume: "ASCII" is "ISO-ANSI" */
+# define ASCII2ISO(c) (c)
+# endif
+#endif
+
+#if (!defined(INTERN_TO_OEM) && !defined(ASCII2OEM))
+# ifdef CRTL_CP_IS_OEM
+ /* know: "ASCII" is "OEM" */
+# define ASCII2OEM(c) (c)
+# else
+ /* assume: "ASCII" is "ISO-ANSI" */
+# define ASCII2OEM(c) (((c) & 0x80) ? iso2oem[(c) & 0x7f] : (c))
+# if (defined(NEED_STR2OEM) && !defined(CRYP_USES_ISO2OEM))
+# define CRYP_USES_ISO2OEM
+# endif
+# endif
+#endif
+
+/* codepage conversion setup for testp() in crypt.c */
+#ifdef CRTL_CP_IS_ISO
+# ifndef STR_TO_CP2
+# define STR_TO_CP2 STR_TO_OEM
+# endif
+#else
+# ifdef CRTL_CP_IS_OEM
+# ifndef STR_TO_CP2
+# define STR_TO_CP2 STR_TO_ISO
+# endif
+# else /* native internal CP is neither ISO nor OEM */
+# ifndef STR_TO_CP1
+# define STR_TO_CP1 STR_TO_ISO
+# endif
+# ifndef STR_TO_CP2
+# define STR_TO_CP2 STR_TO_OEM
+# endif
+# endif
+#endif
+
+
+/* Convert filename (and file comment string) into "internal" charset.
+ * This macro assumes that Zip entry filenames are coded in OEM (IBM DOS)
+ * codepage when made on
+ * -> DOS (this includes 16-bit Windows 3.1) (FS_FAT_)
+ * -> OS/2 (FS_HPFS_)
+ * -> Win95/WinNT with Nico Mak's WinZip (FS_NTFS_ && hostver == "5.0")
+ *
+ * All other ports are assumed to code zip entry filenames in ISO 8859-1.
+ */
+#ifndef Ext_ASCII_TO_Native
+# define Ext_ASCII_TO_Native(string, hostnum, hostver) \
+ if ((hostnum) == FS_FAT_ || (hostnum) == FS_HPFS_ || \
+ ((hostnum) == FS_NTFS_ && (hostver) == 50)) { \
+ _OEM_INTERN((string)); \
+ } else { \
+ _ISO_INTERN((string)); \
+ }
+#endif
+
+
+
+/**********************/
+/* Global constants */
+/**********************/
+
+ extern ZCONST ush near mask_bits[];
+ extern ZCONST char *fnames[2];
+
+#ifdef EBCDIC
+ extern ZCONST uch ebcdic[];
+#endif
+#ifdef IZ_ISO2OEM_ARRAY
+ extern ZCONST uch Far iso2oem[];
+#endif
+#ifdef IZ_OEM2ISO_ARRAY
+ extern ZCONST uch Far oem2iso[];
+#endif
+
+ extern ZCONST char Far VersionDate[];
+ extern ZCONST char Far CentSigMsg[];
+ extern ZCONST char Far EndSigMsg[];
+ extern ZCONST char Far SeekMsg[];
+ extern ZCONST char Far FilenameNotMatched[];
+ extern ZCONST char Far ExclFilenameNotMatched[];
+ extern ZCONST char Far ReportMsg[];
+
+#ifndef SFX
+ extern ZCONST char Far CompiledWith[];
+#endif /* !SFX */
+
+
+
+/***********************************/
+/* Global (shared?) RTL variables */
+/***********************************/
+
+#ifdef DECLARE_ERRNO
+ extern int errno;
+#endif
+
+
+#endif /* !__unzpriv_h */
diff --git a/Build/source/libs/unzip/version.h b/Build/source/libs/unzip/version.h
new file mode 100644
index 00000000000..763cc13078c
--- /dev/null
+++ b/Build/source/libs/unzip/version.h
@@ -0,0 +1,44 @@
+/*
+ version.h (for UnZip) by Info-ZIP.
+
+ This header file is not copyrighted and may be distributed without
+ restriction. (That's a little geek humor, heh heh.)
+ */
+
+#ifndef __version_h /* don't include more than once */
+#define __version_h
+
+#ifdef BETA
+# undef BETA /* define BETA for internal beta releases */
+#endif
+
+#ifdef BETA
+# define BETALEVEL "d BETA"
+# define VERSION_DATE "27 November 98" /* internal beta version */
+#else
+# define BETALEVEL ""
+# define VERSION_DATE "28 November 1998" /* official release version */
+# define RELEASE
+#endif
+
+#define UZ_MAJORVER 5 /* UnZip */
+#define UZ_MINORVER 4
+
+#define ZI_MAJORVER 2 /* ZipInfo */
+#define ZI_MINORVER 3
+
+#define PATCHLEVEL 0
+
+
+/* these are obsolete but remain for backward compatibility: */
+#define D2_MAJORVER UZ_MAJORVER /* DLL for OS/2 */
+#define D2_MINORVER UZ_MINORVER
+#define D2_PATCHLEVEL PATCHLEVEL
+
+#define DW_MAJORVER UZ_MAJORVER /* DLL for MS Windows */
+#define DW_MINORVER UZ_MINORVER
+#define DW_PATCHLEVEL PATCHLEVEL
+
+#define WIN_VERSION_DATE VERSION_DATE
+
+#endif /* !__version_h */
diff --git a/Build/source/libs/unzip/win32.mak b/Build/source/libs/unzip/win32.mak
new file mode 100644
index 00000000000..d41b5ee3c22
--- /dev/null
+++ b/Build/source/libs/unzip/win32.mak
@@ -0,0 +1,83 @@
+################################################################################
+#
+# Makefile : Unzip
+# Author : Fabrice Popineau <Fabrice.Popineau@supelec.fr>
+# Platform : Win32, Microsoft VC++ 6.0, depends upon fpTeX 0.5 sources
+# Time-stamp: <02/09/23 17:41:22 popineau>
+#
+################################################################################
+root_srcdir=..\..
+INCLUDE=$(INCLUDE);$(root_srcdir)\texk
+
+USE_GNUW32 = 1
+USE_UNZIP = 1
+MAKE_UNZIP = 1
+USE_ADVAPI = 1
+
+!include <msvc/common.mak>
+
+{win32}.c{$(objdir)}.obj:
+ $(compile) $<
+{windll}.c{$(objdir)}.obj:
+ $(compile) $<
+{windll}.rc{$(objdir)}.res:
+ $(RC) $(rcvars) $(rcflags) /fo$@ $<
+
+DEFS= $(DEFS) -DHAVE_CONFIG_H -DWINDLL -DUSE_EF_UT_TIME -DDLL -DUNZIPLIB
+
+programs = $(unzipdll)
+libfiles = $(unziplib)
+includefiles = unzip.h
+objects = \
+ $(objdir)\api.obj \
+ $(objdir)\crc32.obj \
+ $(objdir)\crctab.obj \
+ $(objdir)\crypt.obj \
+ $(objdir)\explode.obj \
+ $(objdir)\extract.obj \
+ $(objdir)\fileio.obj \
+ $(objdir)\globals.obj \
+ $(objdir)\inflate.obj \
+ $(objdir)\list.obj \
+ $(objdir)\match.obj \
+ $(objdir)\nt.obj \
+ $(objdir)\process.obj \
+ $(objdir)\ttyio.obj \
+ $(objdir)\unreduce.obj \
+ $(objdir)\unshrink.obj \
+ $(objdir)\win32.obj \
+ $(objdir)\windll.obj \
+ $(objdir)\zipinfo.obj
+
+default: all
+
+all: $(objdir) $(unzip)
+
+lib: $(objdir) $(unziplib)
+
+!ifdef UNZIP_DLL
+DEFS = $(DEFS) -DMAKE_UNZIP_DLL
+
+$(unziplib): $(objdir) $(objects)
+ $(archive) /DEF $(objects)
+
+$(unzipdll): $(objects) $(objdir)\windll.res
+ $(link_dll) $(**) $(unziplib:.lib=.exp) $(conlibs)
+!else
+$(unziplib): $(objdir) $(objects)
+ $(archive) $(objects)
+!endif
+
+!include <msvc/config.mak>
+!include <msvc/install.mak>
+
+install:: install-exec install-include install-lib
+
+!include <msvc/clean.mak>
+!include <msvc/rdepend.mak>
+!include "./depend.mak"
+
+#
+# Local Variables:
+# mode: makefile
+# End: \ No newline at end of file
diff --git a/Build/source/libs/unzip/win32/nt.c b/Build/source/libs/unzip/win32/nt.c
new file mode 100644
index 00000000000..5f5572381f1
--- /dev/null
+++ b/Build/source/libs/unzip/win32/nt.c
@@ -0,0 +1,659 @@
+/*
+
+ Copyright (c) 1996 Scott Field
+
+ Module Name:
+
+ nt.c
+
+ Abstract:
+
+ This module implements WinNT security descriptor operations for the
+ Win32 Info-ZIP project. Operation such as setting file security,
+ using/querying local and remote privileges, and queuing of operations
+ is performed here. The contents of this module are only relevant
+ when the code is running on Windows NT, and the target volume supports
+ persistent Acl storage.
+
+ User privileges that allow accessing certain privileged aspects of the
+ security descriptor (such as the Sacl) are only used if the user specified
+ to do so.
+
+ Author:
+
+ Scott Field (sfield@microsoft.com)
+
+ Last revised: 18 Jan 97
+
+ */
+
+#define WIN32_LEAN_AND_MEAN
+#define UNZIP_INTERNAL
+#include "unzip.h"
+#include <windows.h>
+#ifdef __RSXNT__
+# include "win32/rsxntwin.h"
+#endif
+#include "win32/nt.h"
+
+
+#ifdef NTSD_EAS /* This file is only needed for NTSD handling */
+
+/* Borland C++ does not define FILE_SHARE_DELETE. Others also? */
+#ifndef FILE_SHARE_DELETE
+# define FILE_SHARE_DELETE 0x00000004
+#endif
+
+
+/* private prototypes */
+
+static BOOL Initialize(VOID);
+#if 0 /* currently unused */
+static BOOL Shutdown(VOID);
+#endif
+static BOOL DeferSet(char *resource, PVOLUMECAPS VolumeCaps, uch *buffer);
+static VOID GetRemotePrivilegesSet(CHAR *FileName, PDWORD dwRemotePrivileges);
+static VOID InitLocalPrivileges(VOID);
+
+
+BOOL bInitialized = FALSE; /* module level stuff initialized? */
+HANDLE hInitMutex = NULL; /* prevent multiple initialization */
+
+BOOL g_bRestorePrivilege = FALSE; /* for local set file security override */
+BOOL g_bSaclPrivilege = FALSE; /* for local set sacl operations, only when
+ restore privilege not present */
+
+/* our single cached volume capabilities structure that describes the last
+ volume root we encountered. A single entry like this works well in the
+ zip/unzip scenario for a number of reasons:
+ 1. typically one extraction path during unzip.
+ 2. typically process one volume at a time during zip, and then move
+ on to the next.
+ 3. no cleanup code required and no memory leaks.
+ 4. simple code.
+
+ This approach should be reworked to a linked list approach if we expect to
+ be called by many threads which are processing a variety of input/output
+ volumes, since lock contention and stale data may become a bottleneck. */
+
+VOLUMECAPS g_VolumeCaps;
+CRITICAL_SECTION VolumeCapsLock;
+
+
+/* our deferred set structure linked list element, used for making a copy
+ of input data which is used at a later time to process the original input
+ at a time when it makes more sense. eg, applying security to newly created
+ directories, after all files have been placed in such directories. */
+
+CRITICAL_SECTION SetDeferLock;
+
+typedef struct _DEFERRED_SET {
+ struct _DEFERRED_SET *Next;
+ uch *buffer; /* must point to DWORD aligned block */
+ PVOLUMECAPS VolumeCaps;
+ char *resource;
+} DEFERRED_SET, *PDEFERRED_SET, *LPDEFERRED_SET;
+
+PDEFERRED_SET pSetHead = NULL;
+PDEFERRED_SET pSetTail;
+
+static BOOL Initialize(VOID)
+{
+ HANDLE hMutex;
+ HANDLE hOldMutex;
+
+ if(bInitialized) return TRUE;
+
+ hMutex = CreateMutex(NULL, TRUE, NULL);
+ if(hMutex == NULL) return FALSE;
+
+ hOldMutex = (HANDLE)InterlockedExchange((LPLONG)&hInitMutex, (LONG)hMutex);
+
+ if(hOldMutex != NULL) {
+ /* somebody setup the mutex already */
+ InterlockedExchange((LPLONG)&hInitMutex, (LONG)hOldMutex);
+
+ CloseHandle(hMutex); /* close new, un-needed mutex */
+
+ /* wait for initialization to complete and return status */
+ WaitForSingleObject(hOldMutex, INFINITE);
+ ReleaseMutex(hOldMutex);
+
+ return bInitialized;
+ }
+
+ /* initialize module level resources */
+
+ InitializeCriticalSection( &SetDeferLock );
+
+ InitializeCriticalSection( &VolumeCapsLock );
+ memset(&g_VolumeCaps, 0, sizeof(VOLUMECAPS));
+
+ InitLocalPrivileges();
+
+ bInitialized = TRUE;
+
+ ReleaseMutex(hMutex); /* release correct mutex */
+
+ return TRUE;
+}
+
+#if 0 /* currently not used ! */
+static BOOL Shutdown(VOID)
+{
+ /* really need to free critical sections, disable enabled privilges, etc,
+ but doing so brings up possibility of race conditions if those resources
+ are about to be used. The easiest way to handle this is let these
+ resources be freed when the process terminates... */
+
+ return TRUE;
+}
+#endif /* never */
+
+
+static BOOL DeferSet(char *resource, PVOLUMECAPS VolumeCaps, uch *buffer)
+{
+ PDEFERRED_SET psd;
+ DWORD cbDeferSet;
+ DWORD cbResource;
+ DWORD cbBuffer;
+
+ if(!bInitialized) if(!Initialize()) return FALSE;
+
+ cbResource = lstrlenA(resource) + 1;
+ cbBuffer = GetSecurityDescriptorLength((PSECURITY_DESCRIPTOR)buffer);
+ cbDeferSet = sizeof(DEFERRED_SET) + cbBuffer + sizeof(VOLUMECAPS) +
+ cbResource;
+
+ psd = (PDEFERRED_SET)HeapAlloc(GetProcessHeap(), 0, cbDeferSet);
+ if(psd == NULL) return FALSE;
+
+ psd->Next = NULL;
+ psd->buffer = (uch *)(psd+1);
+ psd->VolumeCaps = (PVOLUMECAPS)((char *)psd->buffer + cbBuffer);
+ psd->resource = (char *)((char *)psd->VolumeCaps + sizeof(VOLUMECAPS));
+
+ memcpy(psd->buffer, buffer, cbBuffer);
+ memcpy(psd->VolumeCaps, VolumeCaps, sizeof(VOLUMECAPS));
+ psd->VolumeCaps->bProcessDefer = TRUE;
+ memcpy(psd->resource, resource, cbResource);
+
+ /* take defer lock */
+ EnterCriticalSection( &SetDeferLock );
+
+ /* add element at tail of list */
+
+ if(pSetHead == NULL) {
+ pSetHead = psd;
+ } else {
+ pSetTail->Next = psd;
+ }
+
+ pSetTail = psd;
+
+ /* release defer lock */
+ LeaveCriticalSection( &SetDeferLock );
+
+ return TRUE;
+}
+
+BOOL ProcessDefer(PDWORD dwDirectoryCount, PDWORD dwBytesProcessed,
+ PDWORD dwDirectoryFail, PDWORD dwBytesFail)
+{
+ PDEFERRED_SET This;
+ PDEFERRED_SET Next;
+
+ *dwDirectoryCount = 0;
+ *dwBytesProcessed = 0;
+
+ *dwDirectoryFail = 0;
+ *dwBytesFail = 0;
+
+ if(!bInitialized) return TRUE; /* nothing to do */
+
+ EnterCriticalSection( &SetDeferLock );
+
+ This = pSetHead;
+
+ while(This) {
+
+ if(SecuritySet(This->resource, This->VolumeCaps, This->buffer)) {
+ (*dwDirectoryCount)++;
+ *dwBytesProcessed +=
+ GetSecurityDescriptorLength((PSECURITY_DESCRIPTOR)This->buffer);
+ } else {
+ (*dwDirectoryFail)++;
+ *dwBytesFail +=
+ GetSecurityDescriptorLength((PSECURITY_DESCRIPTOR)This->buffer);
+ }
+
+ Next = This->Next;
+ HeapFree(GetProcessHeap(), 0, This);
+ This = Next;
+ }
+
+ pSetHead = NULL;
+
+ LeaveCriticalSection( &SetDeferLock );
+
+ return TRUE;
+}
+
+BOOL ValidateSecurity(uch *securitydata)
+{
+ PSECURITY_DESCRIPTOR sd = (PSECURITY_DESCRIPTOR)securitydata;
+ PACL pAcl;
+ PSID pSid;
+ BOOL bAclPresent;
+ BOOL bDefaulted;
+
+ if(!IsWinNT()) return TRUE; /* don't do anything if not on WinNT */
+
+ if(!IsValidSecurityDescriptor(sd)) return FALSE;
+
+ /* verify Dacl integrity */
+
+ if(!GetSecurityDescriptorDacl(sd, &bAclPresent, &pAcl, &bDefaulted))
+ return FALSE;
+
+ if(bAclPresent) {
+ if(!IsValidAcl(pAcl)) return FALSE;
+ }
+
+ /* verify Sacl integrity */
+
+ if(!GetSecurityDescriptorSacl(sd, &bAclPresent, &pAcl, &bDefaulted))
+ return FALSE;
+
+ if(bAclPresent) {
+ if(!IsValidAcl(pAcl)) return FALSE;
+ }
+
+ /* verify owner integrity */
+
+ if(!GetSecurityDescriptorOwner(sd, &pSid, &bDefaulted))
+ return FALSE;
+
+ if(pSid != NULL) {
+ if(!IsValidSid(pSid)) return FALSE;
+ }
+
+ /* verify group integrity */
+
+ if(!GetSecurityDescriptorGroup(sd, &pSid, &bDefaulted))
+ return FALSE;
+
+ if(pSid != NULL) {
+ if(!IsValidSid(pSid)) return FALSE;
+ }
+
+ return TRUE;
+}
+
+static VOID GetRemotePrivilegesSet(char *FileName, PDWORD dwRemotePrivileges)
+{
+ HANDLE hFile;
+
+ *dwRemotePrivileges = 0;
+
+ /* see if we have the SeRestorePrivilege */
+
+ hFile = CreateFileA(
+ FileName,
+ ACCESS_SYSTEM_SECURITY | WRITE_DAC | WRITE_OWNER | READ_CONTROL,
+ FILE_SHARE_READ | FILE_SHARE_DELETE, /* no sd updating allowed here */
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS,
+ NULL
+ );
+
+ if(hFile != INVALID_HANDLE_VALUE) {
+ /* no remote way to determine SeRestorePrivilege -- just try a
+ read/write to simulate it */
+ SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION |
+ SACL_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION |
+ GROUP_SECURITY_INFORMATION;
+ PSECURITY_DESCRIPTOR sd;
+ DWORD cbBuf = 0;
+
+ GetKernelObjectSecurity(hFile, si, NULL, cbBuf, &cbBuf);
+
+ if(ERROR_INSUFFICIENT_BUFFER == GetLastError()) {
+ if((sd = HeapAlloc(GetProcessHeap(), 0, cbBuf)) != NULL) {
+ if(GetKernelObjectSecurity(hFile, si, sd, cbBuf, &cbBuf)) {
+ if(SetKernelObjectSecurity(hFile, si, sd))
+ *dwRemotePrivileges |= OVERRIDE_RESTORE;
+ }
+ HeapFree(GetProcessHeap(), 0, sd);
+ }
+ }
+
+ CloseHandle(hFile);
+ } else {
+
+ /* see if we have the SeSecurityPrivilege */
+ /* note we don't need this if we have SeRestorePrivilege */
+
+ hFile = CreateFileA(
+ FileName,
+ ACCESS_SYSTEM_SECURITY,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, /* max */
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL
+ );
+
+ if(hFile != INVALID_HANDLE_VALUE) {
+ CloseHandle(hFile);
+ *dwRemotePrivileges |= OVERRIDE_SACL;
+ }
+ }
+}
+
+
+BOOL GetVolumeCaps(
+ char *rootpath, /* filepath, or NULL */
+ char *name, /* filename associated with rootpath */
+ PVOLUMECAPS VolumeCaps /* result structure describing capabilities */
+ )
+{
+ char TempRootPath[MAX_PATH + 1];
+ DWORD cchTempRootPath = 0;
+ BOOL bSuccess = TRUE; /* assume success until told otherwise */
+
+ if(!bInitialized) if(!Initialize()) return FALSE;
+
+ /* process the input path to produce a consistent path suitable for
+ compare operations and also suitable for certain picky Win32 API
+ that don't like forward slashes */
+
+ if(rootpath != NULL && rootpath[0] != '\0') {
+ DWORD i;
+
+ cchTempRootPath = lstrlen(rootpath);
+ if(cchTempRootPath > MAX_PATH) return FALSE;
+
+ /* copy input, converting forward slashes to back slashes as we go */
+
+ for(i = 0 ; i <= cchTempRootPath ; i++) {
+ if(rootpath[i] == '/') TempRootPath[i] = '\\';
+ else TempRootPath[i] = rootpath[i];
+ }
+
+ /* check for UNC and Null terminate or append trailing \ as
+ appropriate */
+
+ /* possible valid UNCs we are passed follow:
+ \\machine\foo\bar (path is \\machine\foo\)
+ \\machine\foo (path is \\machine\foo\)
+ \\machine\foo\
+ \\.\c$\ (FIXFIX: Win32API doesn't like this - GetComputerName())
+ LATERLATER: handling mounted DFS drives in the future will require
+ slightly different logic which isn't available today.
+ This is required because directories can point at
+ different servers which have differing capabilities.
+ */
+
+ if(TempRootPath[0] == '\\' && TempRootPath[1] == '\\') {
+ DWORD slash = 0;
+
+ for(i = 2 ; i < cchTempRootPath ; i++) {
+ if(TempRootPath[i] == '\\') {
+ slash++;
+
+ if(slash == 2) {
+ i++;
+ TempRootPath[i] = '\0';
+ cchTempRootPath = i;
+ break;
+ }
+ }
+ }
+
+ /* if there was only one slash found, just tack another onto the
+ end */
+
+ if(slash == 1 && TempRootPath[cchTempRootPath] != '\\') {
+ TempRootPath[cchTempRootPath] = TempRootPath[0]; /* '\' */
+ TempRootPath[cchTempRootPath+1] = '\0';
+ cchTempRootPath++;
+ }
+
+ } else {
+
+ if(TempRootPath[1] == ':') {
+
+ /* drive letter specified, truncate to root */
+ TempRootPath[2] = '\\';
+ TempRootPath[3] = '\0';
+ cchTempRootPath = 3;
+ } else {
+
+ /* must be file on current drive */
+ TempRootPath[0] = '\0';
+ cchTempRootPath = 0;
+ }
+
+ }
+
+ } /* if path != NULL */
+
+ /* grab lock protecting cached entry */
+ EnterCriticalSection( &VolumeCapsLock );
+
+ if(!g_VolumeCaps.bValid ||
+ lstrcmpi(g_VolumeCaps.RootPath, TempRootPath) != 0)
+ {
+
+ /* no match found, build up new entry */
+
+ DWORD dwFileSystemFlags;
+ DWORD dwRemotePrivileges = 0;
+ BOOL bRemote = FALSE;
+
+ /* release lock during expensive operations */
+ LeaveCriticalSection( &VolumeCapsLock );
+
+ bSuccess = GetVolumeInformation(
+ (TempRootPath[0] == '\0') ? NULL : TempRootPath,
+ NULL, 0,
+ NULL, NULL,
+ &dwFileSystemFlags,
+ NULL, 0);
+
+
+ /* only if target volume supports Acls, and we were told to use
+ privileges do we need to go out and test for the remote case */
+
+ if(bSuccess && (dwFileSystemFlags & FS_PERSISTENT_ACLS) &&
+ VolumeCaps->bUsePrivileges)
+ {
+ if(GetDriveType( (TempRootPath[0] == '\0') ? NULL : TempRootPath )
+ == DRIVE_REMOTE)
+ {
+ bRemote = TRUE;
+
+ /* make a determination about our remote capabilities */
+
+ GetRemotePrivilegesSet(name, &dwRemotePrivileges);
+ }
+ }
+
+ /* always take the lock again, since we release it below */
+ EnterCriticalSection( &VolumeCapsLock );
+
+ /* replace the existing data if successful */
+ if(bSuccess) {
+
+ lstrcpynA(g_VolumeCaps.RootPath, TempRootPath, cchTempRootPath+1);
+ g_VolumeCaps.bProcessDefer = FALSE;
+ g_VolumeCaps.dwFileSystemFlags = dwFileSystemFlags;
+ g_VolumeCaps.bRemote = bRemote;
+ g_VolumeCaps.dwRemotePrivileges = dwRemotePrivileges;
+ g_VolumeCaps.bValid = TRUE;
+ }
+ }
+
+ if(bSuccess) {
+ /* copy input elements */
+ g_VolumeCaps.bUsePrivileges = VolumeCaps->bUsePrivileges;
+ g_VolumeCaps.dwFileAttributes = VolumeCaps->dwFileAttributes;
+
+ /* give caller results */
+ memcpy(VolumeCaps, &g_VolumeCaps, sizeof(VOLUMECAPS));
+ } else {
+ g_VolumeCaps.bValid = FALSE;
+ }
+
+ LeaveCriticalSection( &VolumeCapsLock ); /* release lock */
+
+ return bSuccess;
+}
+
+
+BOOL SecuritySet(char *resource, PVOLUMECAPS VolumeCaps, uch *securitydata)
+{
+ HANDLE hFile;
+ DWORD dwDesiredAccess = 0;
+ DWORD dwFlags = 0;
+ PSECURITY_DESCRIPTOR sd = (PSECURITY_DESCRIPTOR)securitydata;
+ SECURITY_DESCRIPTOR_CONTROL sdc;
+ SECURITY_INFORMATION RequestedInfo = 0;
+ DWORD dwRev;
+ BOOL bRestorePrivilege = FALSE;
+ BOOL bSaclPrivilege = FALSE;
+ BOOL bSuccess;
+
+ if(!bInitialized) if(!Initialize()) return FALSE;
+
+ /* defer directory processing */
+
+ if(VolumeCaps->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+ if(!VolumeCaps->bProcessDefer) {
+ return DeferSet(resource, VolumeCaps, securitydata);
+ } else {
+ /* opening a directory requires FILE_FLAG_BACKUP_SEMANTICS */
+ dwFlags |= FILE_FLAG_BACKUP_SEMANTICS;
+ }
+ }
+
+ /* evaluate the input security desriptor and act accordingly */
+
+ if(!IsValidSecurityDescriptor(sd))
+ return FALSE;
+
+ if(!GetSecurityDescriptorControl(sd, &sdc, &dwRev))
+ return FALSE;
+
+ /* setup privilege usage based on if told we can use privileges, and if so,
+ what privileges we have */
+
+ if(VolumeCaps->bUsePrivileges) {
+ if(VolumeCaps->bRemote) {
+ /* use remotely determined privileges */
+ if(VolumeCaps->dwRemotePrivileges & OVERRIDE_RESTORE)
+ bRestorePrivilege = TRUE;
+
+ if(VolumeCaps->dwRemotePrivileges & OVERRIDE_SACL)
+ bSaclPrivilege = TRUE;
+
+ } else {
+ /* use local privileges */
+ bRestorePrivilege = g_bRestorePrivilege;
+ bSaclPrivilege = g_bSaclPrivilege;
+ }
+ }
+
+
+ /* if a Dacl is present write Dacl out */
+ /* if we have SeRestorePrivilege, write owner and group info out */
+
+ if(sdc & SE_DACL_PRESENT) {
+ dwDesiredAccess |= WRITE_DAC;
+ RequestedInfo |= DACL_SECURITY_INFORMATION;
+
+ if(bRestorePrivilege) {
+ dwDesiredAccess |= WRITE_OWNER;
+ RequestedInfo |= (OWNER_SECURITY_INFORMATION |
+ GROUP_SECURITY_INFORMATION);
+ }
+ }
+
+ /* if a Sacl is present and we have either SeRestorePrivilege or
+ SeSystemSecurityPrivilege try to write Sacl out */
+
+ if((sdc & SE_SACL_PRESENT) && (bRestorePrivilege || bSaclPrivilege)) {
+ dwDesiredAccess |= ACCESS_SYSTEM_SECURITY;
+ RequestedInfo |= SACL_SECURITY_INFORMATION;
+ }
+
+ if(RequestedInfo == 0) /* nothing to do */
+ return FALSE;
+
+ if(bRestorePrivilege)
+ dwFlags |= FILE_FLAG_BACKUP_SEMANTICS;
+
+ hFile = CreateFileA(
+ resource,
+ dwDesiredAccess,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,/* max sharing */
+ NULL,
+ OPEN_EXISTING,
+ dwFlags,
+ NULL
+ );
+
+ if(hFile == INVALID_HANDLE_VALUE)
+ return FALSE;
+
+ bSuccess = SetKernelObjectSecurity(hFile, RequestedInfo, sd);
+
+ CloseHandle(hFile);
+
+ return bSuccess;
+}
+
+static VOID InitLocalPrivileges(VOID)
+{
+ HANDLE hToken;
+ TOKEN_PRIVILEGES tp;
+
+ /* try to enable some interesting privileges that give us the ability
+ to get some security information that we normally cannot.
+
+ note that enabling privileges is only relevant on the local machine;
+ when accessing files that are on a remote machine, any privileges
+ that are present on the remote machine get enabled by default. */
+
+ if(!OpenProcessToken(GetCurrentProcess(),
+ TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken))
+ return;
+
+ tp.PrivilegeCount = 1;
+ tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+ if(LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &tp.Privileges[0].Luid)) {
+
+ /* try to enable SeRestorePrivilege; if this succeeds, we can write
+ all aspects of the security descriptor */
+
+ if(AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL) &&
+ GetLastError() == ERROR_SUCCESS) g_bRestorePrivilege = TRUE;
+
+ }
+
+ /* try to enable SeSystemSecurityPrivilege, if SeRestorePrivilege not
+ present; if this succeeds, we can write the Sacl */
+
+ if(!g_bRestorePrivilege &&
+ LookupPrivilegeValue(NULL, SE_SECURITY_NAME, &tp.Privileges[0].Luid)) {
+
+ if(AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL) &&
+ GetLastError() == ERROR_SUCCESS) g_bSaclPrivilege = TRUE;
+ }
+
+ CloseHandle(hToken);
+}
+#endif /* NTSD_EAS */
diff --git a/Build/source/libs/unzip/win32/nt.h b/Build/source/libs/unzip/win32/nt.h
new file mode 100644
index 00000000000..0109c2b678a
--- /dev/null
+++ b/Build/source/libs/unzip/win32/nt.h
@@ -0,0 +1,28 @@
+/* nt.h: central header for EF_NTSD "SD" extra field */
+
+#ifndef _NT_H
+#define _NT_H
+
+#define NTSD_BUFFERSIZE (1024) /* threshold to cause malloc() */
+#define OVERRIDE_BACKUP 1 /* we have SeBackupPrivilege on remote */
+#define OVERRIDE_RESTORE 2 /* we have SeRestorePrivilege on remote */
+#define OVERRIDE_SACL 4 /* we have SeSystemSecurityPrivilege on remote */
+
+typedef struct {
+ BOOL bValid; /* are our contents valid? */
+ BOOL bProcessDefer; /* process deferred entry yet? */
+ BOOL bUsePrivileges; /* use privilege overrides? */
+ DWORD dwFileSystemFlags; /* describes target file system */
+ BOOL bRemote; /* is volume remote? */
+ DWORD dwRemotePrivileges; /* relevant only on remote volumes */
+ DWORD dwFileAttributes;
+ char RootPath[MAX_PATH+1]; /* path to network / filesystem */
+} VOLUMECAPS, *PVOLUMECAPS, *LPVOLUMECAPS;
+
+BOOL SecuritySet(char *resource, PVOLUMECAPS VolumeCaps, uch *securitydata);
+BOOL GetVolumeCaps(char *rootpath, char *name, PVOLUMECAPS VolumeCaps);
+BOOL ValidateSecurity(uch *securitydata);
+BOOL ProcessDefer(PDWORD dwDirectoryCount, PDWORD dwBytesProcessed,
+ PDWORD dwDirectoryFail, PDWORD dwBytesFail);
+
+#endif /* _NT_H */
diff --git a/Build/source/libs/unzip/win32/w32cfg.h b/Build/source/libs/unzip/win32/w32cfg.h
new file mode 100644
index 00000000000..18a8e3f85c3
--- /dev/null
+++ b/Build/source/libs/unzip/win32/w32cfg.h
@@ -0,0 +1,222 @@
+/*---------------------------------------------------------------------------
+ Win32 specific configuration section:
+ ---------------------------------------------------------------------------*/
+
+#ifndef __w32cfg_h
+#define __w32cfg_h
+
+#if (defined(__CYGWIN__) && !defined(__CYGWIN32__))
+# define __CYGWIN32__ /* new versions of CygWin may not define this */
+#endif
+
+#include <sys/types.h> /* off_t, time_t, dev_t, ... */
+#include <sys/stat.h>
+#include <io.h> /* read(), open(), etc. */
+#include <time.h>
+#if (defined(__RSXNT__) || defined(__EMX__)) && !defined(tzset)
+# define tzset _tzset
+#endif
+#ifdef __MINGW32__
+ extern void _tzset(void); /* this is missing in <time.h> */
+# ifndef tzset
+# define tzset _tzset
+# endif
+#endif
+#include <memory.h>
+#if (!defined(__RSXNT__) && !defined(__CYGWIN32__))
+# include <direct.h> /* mkdir() */
+#endif
+#include <fcntl.h>
+#ifdef __CYGWIN32__
+# include <unistd.h>
+ extern int setmode(int, int); /* this is missing in <fcntl.h> */
+#endif
+#if (defined(MSC) || defined(__WATCOMC__) || defined(__MINGW32__))
+# include <sys/utime.h>
+#else
+# include <utime.h>
+#endif
+
+#if defined(FILEIO_C)
+# ifndef __CYGWIN32__
+# include <conio.h>
+# endif
+# include <windows.h>
+# ifdef __RSXNT__
+# include "win32/rsxntwin.h"
+# endif
+#endif
+#if (defined(ENVARGS_C) || defined(EXTRACT_C) || defined(UNZIP_C) || \
+ defined(ZCRYPT_INTERNAL))
+# include <windows.h>
+# ifdef __RSXNT__
+# include "win32/rsxntwin.h"
+# endif
+#endif
+#if (defined(__CYGWIN32__) || defined(__MINGW32__))
+ /* the following definitions are missing in their <windows.h> */
+# ifndef AnsiToOem
+# define AnsiToOem CharToOemA
+# endif
+# ifndef OemToAnsi
+# define OemToAnsi OemToCharA
+# endif
+#endif
+
+#define DIR_END '\\' /* OS uses '\\' as directory separator */
+#define DIR_END2 '/' /* also check for '/' (RTL may convert) */
+#ifndef DATE_FORMAT
+# define DATE_FORMAT DF_MDY
+#endif
+#define lenEOL 2
+#define PutNativeEOL {*q++ = native(CR); *q++ = native(LF);}
+
+#if (defined(__RSXNT__) && !defined(HAVE_MKTIME))
+# define HAVE_MKTIME /* use mktime() in time conversion routines */
+#endif
+#if (defined(__CYGWIN32__) && defined(HAVE_MKTIME))
+# undef HAVE_MKTIME /* Cygnus' mktime() implementation is buggy */
+#endif
+#if (!defined(NT_TZBUG_WORKAROUND) && !defined(NO_NT_TZBUG_WORKAROUND))
+# define NT_TZBUG_WORKAROUND
+#endif
+#if (!defined(NO_EF_UT_TIME) && !defined(USE_EF_UT_TIME))
+# define USE_EF_UT_TIME
+#endif
+#if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP))
+# define TIMESTAMP
+#endif
+#if (!defined(NO_NTSD_EAS) && !defined(NTSD_EAS))
+# define NTSD_EAS /* enable NTSD support unless explicitly suppressed */
+#endif
+
+/* handlers for OEM <--> ANSI string conversions */
+#ifdef __RSXNT__
+ /* RSXNT uses OEM coded strings in functions supplied by C RTL */
+# ifdef CRTL_CP_IS_ISO
+# undef CRTL_CP_IS_ISO
+# endif
+# ifndef CRTL_CP_IS_OEM
+# define CRTL_CP_IS_OEM
+# endif
+#else
+ /* "real" native WIN32 compilers use ANSI coded strings in C RTL calls */
+# ifndef CRTL_CP_IS_ISO
+# define CRTL_CP_IS_ISO
+# endif
+# ifdef CRTL_CP_IS_OEM
+# undef CRTL_CP_IS_OEM
+# endif
+#endif
+
+#ifdef CRTL_CP_IS_ISO
+ /* C RTL's file system support assumes ANSI coded strings */
+# define ISO_TO_INTERN(src, dst) {if ((src) != (dst)) strcpy((dst), (src));}
+# define OEM_TO_INTERN(src, dst) OemToAnsi(src, dst)
+# define INTERN_TO_ISO(src, dst) {if ((src) != (dst)) strcpy((dst), (src));}
+# define INTERN_TO_OEM(src, dst) AnsiToOem(src, dst)
+#endif /* CRTL_CP_IS_ISO */
+#ifdef CRTL_CP_IS_OEM
+ /* C RTL's file system support assumes OEM coded strings */
+# define ISO_TO_INTERN(src, dst) AnsiToOem(src, dst)
+# define OEM_TO_INTERN(src, dst) {if ((src) != (dst)) strcpy((dst), (src));}
+# define INTERN_TO_ISO(src, dst) OemToAnsi(src, dst)
+# define INTERN_TO_OEM(src, dst) {if ((src) != (dst)) strcpy((dst), (src));}
+#endif /* CRTL_CP_IS_OEM */
+#define _OEM_INTERN(str1) OEM_TO_INTERN(str1, str1)
+#define _ISO_INTERN(str1) ISO_TO_INTERN(str1, str1)
+#ifndef WINDLL
+ /* Despite best intentions, for the command-line version UzpPassword()
+ * could return either character set, depending on whether running under
+ * Win95 (DOS-session) or WinNT (native WinNT command interpreter)! */
+# define STR_TO_CP2(dst, src) (AnsiToOem(src, dst), dst)
+# define STR_TO_CP3(dst, src) (OemToAnsi(src, dst), dst)
+#else
+ /* The WINDLL front end is known to supply ISO/ANSI-coded passwords! */
+# define STR_TO_CP2(dst, src) (AnsiToOem(src, dst), dst)
+#endif
+/* dummy defines to disable these functions, they are not needed */
+#define STR_TO_OEM
+#define STR_TO_ISO
+
+/* Static variables that we have to add to Uz_Globs: */
+#define SYSTEM_SPECIFIC_GLOBALS \
+ int created_dir, renamed_fullpath, fnlen;\
+ unsigned nLabelDrive;\
+ char lastRootPath[4];\
+ int lastVolOldFAT, lastVolLocTim;\
+ char *rootpath, *buildpathHPFS, *buildpathFAT, *endHPFS, *endFAT;\
+ char *dirname, *wildname, matchname[FILNAMSIZ];\
+ int rootlen, have_dirname, dirnamelen, notfirstcall;\
+ zvoid *wild_dir;
+
+/* created_dir, renamed_fullpath, fnlen, and nLabelDrive are used by */
+/* both mapname() and checkdir(). */
+/* lastRootPath and lastVolOldFAT are used by IsVolumeOldFAT(). */
+/* rootlen, rootpath, buildpathHPFS, buildpathFAT, endHPFS, and endFAT */
+/* are used by checkdir(). */
+/* wild_dir, dirname, wildname, matchname[], dirnamelen, have_dirname, */
+/* and notfirstcall are used by do_wild(). */
+
+#if (defined(_MSC_VER) && !defined(MSC))
+# define MSC
+#endif
+
+/* This replacement for C-RTL-supplied getch() (or similar) functionality
+ * avoids leaving unabsorbed LFs in the keyboard buffer under Windows95,
+ * and supports the <ALT>+[0]<digit><digit><digit> feature.
+ */
+int getch_win32 OF((void));
+
+/* This patch of stat() is useful for at least two compilers. It is */
+/* difficult to take a stat() of a root directory under Windows95, so */
+/* zstat_win32() detects that case and fills in suitable values. */
+#ifndef __RSXNT__
+# ifndef W32_STATROOT_FIX
+# define W32_STATROOT_FIX
+# endif
+#endif /* !__RSXNT__ */
+
+#if (defined(NT_TZBUG_WORKAROUND) || defined(W32_STATROOT_FIX))
+# define W32_STAT_BANDAID
+# if (defined(NT_TZBUG_WORKAROUND) && defined(REENTRANT))
+# define __W32STAT_GLOBALS__ Uz_Globs *pG,
+# define __W32STAT_G__ pG,
+# else
+# define __W32STAT_GLOBALS__
+# define __W32STAT_G__
+# endif
+# undef SSTAT
+# ifdef WILD_STAT_BUG
+# define SSTAT(path, pbuf) (iswild(path) || zstat_win32(__W32STAT_G__ path, pbuf))
+# else
+# define SSTAT(path, pbuf) zstat_win32(__W32STAT_G__ path, pbuf)
+# endif
+#endif
+
+#ifdef __WATCOMC__
+# ifdef __386__
+# ifndef WATCOMC_386
+# define WATCOMC_386
+# endif
+# define __32BIT__
+# undef far
+# define far
+# undef near
+# define near
+
+/* Get asm routines to link properly without using "__cdecl": */
+# ifndef USE_ZLIB
+# pragma aux crc32 "_*" parm caller [] value [eax] modify [eax]
+# pragma aux get_crc_table "_*" parm caller [] value [eax] \
+ modify [eax ecx edx]
+# endif /* !USE_ZLIB */
+# endif /* __386__ */
+
+# ifndef EPIPE
+# define EPIPE -1
+# endif
+# define PIPE_ERROR (errno == EPIPE)
+#endif /* __WATCOMC__ */
+
+#endif /* !__w32cfg_h */
diff --git a/Build/source/libs/unzip/win32/win32.c b/Build/source/libs/unzip/win32/win32.c
new file mode 100644
index 00000000000..c1d9a68f0b9
--- /dev/null
+++ b/Build/source/libs/unzip/win32/win32.c
@@ -0,0 +1,2390 @@
+/*---------------------------------------------------------------------------
+
+ win32.c
+
+ 32-bit Windows-specific (NT/95) routines for use with Info-ZIP's UnZip 5.3
+ and later.
+
+ Contains: GetLoadPath()
+ Opendir()
+ Readdir()
+ Closedir()
+ process_defer_NT() process any deferred items
+ SetSD() set security descriptor on file
+ EvalExtraFields() evaluate and process and extra field NOW
+ IsWinNT() indicate type of WIN32 platform
+ test_NTSD() test integrity of NT security data
+ utime2FileTime()
+ FStampIsLocTime()
+ FileTime2utime()
+ VFatFileTime2utime()
+ UTCtime2Localtime()
+ NTtzbugWorkaround()
+ getNTfiletime()
+ close_outfile()
+ stamp_file()
+ isfloppy()
+ NTQueryVolInfo()
+ IsVolumeOldFAT()
+ do_wild()
+ mapattr()
+ mapname()
+ map2fat()
+ checkdir()
+ version()
+ zstat_win32()
+ getch_win32()
+
+ ---------------------------------------------------------------------------*/
+
+
+#define UNZIP_INTERNAL
+#include "unzip.h"
+#include <windows.h> /* must be AFTER unzip.h to avoid struct G problems */
+#ifdef __RSXNT__
+# include "win32/rsxntwin.h"
+#endif
+#include "win32/nt.h"
+
+#ifndef FUNZIP /* most of this file is not used with fUnZip */
+
+#if (defined(__GO32__) || defined(__EMX__) || defined(__CYGWIN32__))
+# define MKDIR(path,mode) mkdir(path,mode)
+#else
+# define MKDIR(path,mode) mkdir(path)
+#endif
+
+#ifdef HAVE_WORKING_DIRENT_H
+# undef HAVE_WORKING_DIRENT_H
+#endif
+/* The emxrtl dirent support of (__GO32__ || __EMX__) converts to lowercase! */
+#if defined(__CYGWIN32__)
+# define HAVE_WORKING_DIRENT_H
+#endif
+
+#ifndef SFX
+# ifdef HAVE_WORKING_DIRENT_H
+# include <dirent.h> /* use readdir() */
+# define zdirent dirent
+# define zDIR DIR
+# define Opendir opendir
+# define Readdir readdir
+# define Closedir closedir
+# else /* !HAVE_WORKING_DIRENT_H */
+ typedef struct zdirent {
+ char reserved [21];
+ char ff_attrib;
+ short ff_ftime;
+ short ff_fdate;
+ long size;
+ char d_name[MAX_PATH];
+ int d_first;
+ HANDLE d_hFindFile;
+ } zDIR;
+
+ static zDIR *Opendir (const char *n);
+ static struct zdirent *Readdir (zDIR *d);
+ static void Closedir (zDIR *d);
+# endif /* ?HAVE_WORKING_DIRENT_H */
+#endif /* !SFX */
+
+
+/* Function prototypes */
+#ifdef NTSD_EAS
+ static int SetSD(__GPRO__ char *path, PVOLUMECAPS VolumeCaps,
+ uch *eb_ptr, unsigned eb_len);
+ static int EvalExtraFields(__GPRO__ char *path, uch *ef_ptr,
+ unsigned ef_len);
+#endif
+
+#if (defined(USE_EF_UT_TIME) || defined(NT_TZBUG_WORKAROUND) || \
+ defined(TIMESTAMP))
+ static void utime2FileTime(time_t ut, FILETIME *pft);
+ static int FStampIsLocTime(__GPRO__ const char *path);
+#endif /* USE_EF_UT_TIME || NT_TZBUG_WORKAROUND || TIMESTAMP */
+#ifdef NT_TZBUG_WORKAROUND
+ static int FileTime2utime(const FILETIME *pft, time_t *ut);
+#ifdef W32_STAT_BANDAID
+ static int VFatFileTime2utime(const FILETIME *pft, time_t *ut);
+#endif
+ static time_t UTCtime2Localtime(time_t utctime);
+ static void NTtzbugWorkaround(time_t ut, FILETIME *pft);
+#endif /* NT_TZBUG_WORKAROUND */
+
+static int getNTfiletime (__GPRO__ FILETIME *pModFT, FILETIME *pAccFT,
+ FILETIME *pCreFT);
+static int isfloppy (int nDrive);
+static int NTQueryVolInfo (__GPRO__ const char *name);
+static int IsVolumeOldFAT (__GPRO__ const char *name);
+static void map2fat (char *pathcomp, char **pEndFAT);
+
+
+#ifdef __MINGW32__
+ int _CRT_glob = 0; /* suppress command line globbing by C RTL */
+#endif
+
+/* static int created_dir; */ /* used by mapname(), checkdir() */
+/* static int renamed_fullpath; */ /* ditto */
+/* static int fnlen; */ /* ditto */
+/* static unsigned nLabelDrive; */ /* ditto */
+
+extern char Far TruncNTSD[]; /* in extract.c */
+
+
+
+#ifdef SFX
+
+/**************************/
+/* Function GetLoadPath() */
+/**************************/
+
+char *GetLoadPath(__GPRO)
+{
+#ifdef MSC
+ extern char *_pgmptr;
+ return _pgmptr;
+
+#else /* use generic API call */
+
+ GetModuleFileName(NULL, G.filename, FILNAMSIZ-1);
+ _ISO_INTERN(G.filename); /* translate to codepage of C rtl's stdio */
+ return G.filename;
+#endif
+
+} /* end function GetLoadPath() */
+
+
+
+
+
+#else /* !SFX */
+
+#ifndef HAVE_WORKING_DIRENT_H
+
+/**********************/ /* Borrowed from ZIP 2.0 sources */
+/* Function Opendir() */ /* Difference: no special handling for */
+/**********************/ /* hidden or system files. */
+
+static zDIR *Opendir(n)
+ const char *n; /* directory to open */
+{
+ zDIR *d; /* malloc'd return value */
+ char *p; /* malloc'd temporary string */
+ WIN32_FIND_DATA fd;
+ extent len = strlen(n);
+
+ /* Start searching for files in directory n */
+
+ if ((d = (zDIR *)malloc(sizeof(zDIR))) == NULL ||
+ (p = malloc(strlen(n) + 5)) == NULL)
+ {
+ if (d != (zDIR *)NULL)
+ free((void *)d);
+ return (zDIR *)NULL;
+ }
+ INTERN_TO_ISO(n, p);
+ if (len > 0) {
+ if (p[len-1] == ':')
+ p[len++] = '.'; /* x: => x:. */
+ else if (p[len-1] == '/' || p[len-1] == '\\')
+ --len; /* foo/ => foo */
+ }
+ strcpy(p+len, "/*");
+
+ if (INVALID_HANDLE_VALUE == (d->d_hFindFile = FindFirstFile(p, &fd))) {
+ free((zvoid *)d);
+ free((zvoid *)p);
+ return NULL;
+ }
+ strcpy(d->d_name, fd.cFileName);
+
+ free((zvoid *)p);
+ d->d_first = 1;
+ return d;
+
+} /* end of function Opendir() */
+
+
+
+
+/**********************/ /* Borrowed from ZIP 2.0 sources */
+/* Function Readdir() */ /* Difference: no special handling for */
+/**********************/ /* hidden or system files. */
+
+static struct zdirent *Readdir(d)
+ zDIR *d; /* directory stream from which to read */
+{
+ /* Return pointer to first or next directory entry, or NULL if end. */
+
+ if ( d->d_first )
+ d->d_first = 0;
+ else
+ {
+ WIN32_FIND_DATA fd;
+
+ if ( !FindNextFile(d->d_hFindFile, &fd) )
+ return NULL;
+
+ ISO_TO_INTERN(fd.cFileName, d->d_name);
+ }
+ return (struct zdirent *)d;
+
+} /* end of function Readdir() */
+
+
+
+
+/***********************/
+/* Function Closedir() */ /* Borrowed from ZIP 2.0 sources */
+/***********************/
+
+static void Closedir(d)
+ zDIR *d; /* directory stream to close */
+{
+ FindClose(d->d_hFindFile);
+ free(d);
+}
+
+#endif /* !HAVE_WORKING_DIRENT_H */
+#endif /* ?SFX */
+
+
+
+
+#ifdef NTSD_EAS
+
+/*********************************/
+/* Function process_defer_NT() */
+/*********************************/
+
+void process_defer_NT(__G)
+ __GDEF
+{
+ /* process deferred items */
+
+ DWORD dir, bytes;
+ DWORD dirfail, bytesfail;
+
+ ProcessDefer(&dir, &bytes, &dirfail, &bytesfail);
+
+ if (!uO.tflag && (uO.qflag < 2)) {
+ if (dir)
+ Info(slide, 0, ((char *)slide,
+ " updated: %lu directory entries with %lu bytes security",
+ (ulg)dir, (ulg)bytes));
+ if (dirfail)
+ Info(slide, 0, ((char *)slide,
+ " failed: %lu directory entries with %lu bytes security",
+ (ulg)dirfail, (ulg)bytesfail));
+ }
+}
+
+
+
+/**********************/
+/* Function SetSD() */ /* return almost-PK errors */
+/**********************/
+
+static int SetSD(__G__ path, VolumeCaps, eb_ptr, eb_len)
+ __GDEF
+ char *path;
+ PVOLUMECAPS VolumeCaps;
+ uch *eb_ptr;
+ unsigned eb_len;
+{
+ ulg ntsd_ucSize;
+ uch *security_data;
+ int error;
+
+ if (eb_ptr == NULL || eb_len < EB_NTSD_L_LEN)
+ return PK_OK; /* not a valid NTSD extra field: assume OK */
+
+ /* check if we know how to handle this version */
+ if (*(eb_ptr + (EB_HEADSIZE+EB_NTSD_VERSION)) > (uch)EB_NTSD_MAX_VER)
+ return PK_OK;
+
+ ntsd_ucSize = makelong(eb_ptr + (EB_HEADSIZE+EB_UCSIZE_P));
+ if (ntsd_ucSize > 0L && eb_len <= (EB_NTSD_L_LEN + EB_CMPRHEADLEN))
+ return IZ_EF_TRUNC; /* no compressed data! */
+
+ /* allocate storage for uncompressed data */
+ security_data = (uch *)malloc((extent)ntsd_ucSize);
+ if (security_data == (uch *)NULL)
+ return PK_MEM4;
+
+ error = memextract(__G__ security_data, ntsd_ucSize,
+ (eb_ptr + (EB_HEADSIZE+EB_NTSD_L_LEN)), (ulg)(eb_len - EB_NTSD_L_LEN));
+
+ if (error == PK_OK) {
+ if (SecuritySet(path, VolumeCaps, security_data)) {
+ error = PK_COOL;
+ if (!uO.tflag && (uO.qflag < 2) &&
+ (!(VolumeCaps->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)))
+ Info(slide, 0, ((char *)slide, " (%ld bytes security)",
+ ntsd_ucSize));
+ }
+ }
+
+ free(security_data);
+ return error;
+}
+
+
+
+
+/********************************/ /* scan extra fields for something */
+/* Function EvalExtraFields() */ /* we happen to know */
+/********************************/
+
+static int EvalExtraFields(__G__ path, ef_ptr, ef_len)
+ __GDEF
+ char *path;
+ uch *ef_ptr;
+ unsigned ef_len;
+{
+ int rc = PK_OK;
+
+ if (!uO.X_flag)
+ return PK_OK; /* user said don't process ACLs; for now, no other
+ extra block types are handled here */
+
+ while (ef_len >= EB_HEADSIZE)
+ {
+ unsigned eb_id = makeword(EB_ID + ef_ptr);
+ unsigned eb_len = makeword(EB_LEN + ef_ptr);
+
+ if (eb_len > (ef_len - EB_HEADSIZE)) {
+ /* discovered some extra field inconsistency! */
+ Trace((stderr,
+ "EvalExtraFields: block length %u > rest ef_size %u\n", eb_len,
+ ef_len - EB_HEADSIZE));
+ break;
+ }
+
+ switch (eb_id)
+ {
+ /* process security descriptor extra data if:
+ Caller is WinNT AND
+ Target local/remote drive supports acls AND
+ Target file is not a directory (else we defer processing
+ until later)
+ */
+ case EF_NTSD:
+ if (IsWinNT()) {
+ VOLUMECAPS VolumeCaps;
+
+ /* provide useful input */
+ VolumeCaps.dwFileAttributes = G.pInfo->file_attr;
+ VolumeCaps.bUsePrivileges = (uO.X_flag > 1);
+
+ /* check target volume capabilities - just fall through
+ * and try if fail */
+ if (GetVolumeCaps(G.rootpath, path, &VolumeCaps) &&
+ !(VolumeCaps.dwFileSystemFlags & FS_PERSISTENT_ACLS))
+ {
+ rc = PK_OK;
+ break;
+ }
+ rc = SetSD(__G__ path, &VolumeCaps, ef_ptr, eb_len);
+ } else
+ rc = PK_OK;
+ break;
+
+#if 0
+ /* perhaps later we can add support for unzipping OS/2 EAs to NT */
+ case EF_OS2:
+ rc = SetEAs(__G__ path, ef_ptr);
+ break;
+
+ case EF_PKUNIX:
+ case EF_IZUNIX:
+ case EF_IZUNIX2:
+ case EF_TIME:
+ break; /* handled elsewhere */
+#else /* ! 0 */
+#ifdef DEBUG
+ case EF_AV:
+ case EF_OS2:
+ case EF_PKVMS:
+ case EF_PKW32:
+ case EF_PKUNIX:
+ case EF_IZVMS:
+ case EF_IZUNIX:
+ case EF_IZUNIX2:
+ case EF_TIME:
+ case EF_MAC3:
+ case EF_JLMAC:
+ case EF_ZIPIT:
+ case EF_VMCMS:
+ case EF_MVS:
+ case EF_ACL:
+ case EF_BEOS:
+ case EF_QDOS:
+ case EF_AOSVS:
+ case EF_SPARK:
+ case EF_MD5:
+ case EF_ASIUNIX:
+ break; /* shut up for other known e.f. blocks */
+#endif /* DEBUG */
+#endif /* ? 0 */
+
+ default:
+ Trace((stderr,
+ "EvalExtraFields: unknown extra field block, ID=%u\n",
+ eb_id));
+ break;
+ }
+
+ ef_ptr += (eb_len + EB_HEADSIZE);
+ ef_len -= (eb_len + EB_HEADSIZE);
+
+ if (rc != PK_OK)
+ break;
+ }
+
+ return rc;
+}
+
+
+
+
+#ifndef SFX
+
+/**************************/
+/* Function test_NTSD() */ /* returns PK_WARN when NTSD data is invalid */
+/**************************/
+
+#ifdef __BORLANDC__
+/* Turn off warning about not using all parameters for this function only */
+#pragma argsused
+#endif
+int test_NTSD(__G__ eb, eb_size, eb_ucptr, eb_ucsize)
+ __GDEF
+ uch *eb;
+ unsigned eb_size;
+ uch *eb_ucptr;
+ ulg eb_ucsize;
+{
+ int r = PK_OK;
+
+ if (!ValidateSecurity(eb_ucptr))
+ r = PK_WARN;
+ return r;
+
+} /* end function test_NTSD() */
+
+#endif /* !SFX */
+#endif /* NTSD_EAS */
+
+
+
+
+/**********************/
+/* Function IsWinNT() */
+/**********************/
+
+int IsWinNT(void) /* returns TRUE if real NT, FALSE if Win95 or Win32s */
+{
+ static DWORD g_PlatformId = 0xFFFFFFFF; /* saved platform indicator */
+
+ if (g_PlatformId == 0xFFFFFFFF) {
+ /* note: GetVersionEx() doesn't exist on WinNT 3.1 */
+ if (GetVersion() < 0x80000000)
+ g_PlatformId = TRUE;
+ else
+ g_PlatformId = FALSE;
+ }
+ return (int)g_PlatformId;
+}
+
+
+/* DEBUG_TIME insertion: */
+#ifdef DEBUG_TIME
+static int show_NTFileTime(FILE *hdo, char *TTmsg, int isloc, FILETIME *pft);
+
+static int show_NTFileTime(FILE *hdo, char *TTmsg, int isloc, FILETIME *pft)
+{
+ SYSTEMTIME w32tm;
+ int rval;
+
+ rval = FileTimeToSystemTime(pft, &w32tm);
+ if (!rval) {
+ fprintf(hdo, "%s\n %08lX,%08lX (%s) -> Conversion failed !!!\n",
+ TTmsg, (ulg)(pft->dwHighDateTime), (ulg)(pft->dwLowDateTime),
+ (isloc ? "local" : "UTC"));
+ } else {
+ fprintf(hdo, "%s\n %08lx,%08lx -> %04u-%02u-%02u, %02u:%02u:%02u %s\n",
+ TTmsg, (ulg)(pft->dwHighDateTime), (ulg)(pft->dwLowDateTime),
+ w32tm.wYear, w32tm.wMonth, w32tm.wDay, w32tm.wHour,
+ w32tm.wMinute, w32tm.wSecond, (isloc ? "local" : "UTC"));
+ }
+ return rval;
+}
+#define FTTrace(x) show_NTFileTime x
+#else
+#define FTTrace(x)
+#endif /* DEBUG_TIME */
+/* end of TIME_DEBUG insertion */
+
+#if (defined(USE_EF_UT_TIME) || defined(NT_TZBUG_WORKAROUND) || \
+ defined(TIMESTAMP))
+
+#if ((defined(__GNUC__) || defined(ULONG_LONG_MAX)) && !defined(HAVE_INT64))
+ typedef long long LLONG64;
+ typedef unsigned long long ULLNG64;
+# define HAVE_INT64
+#endif
+#if (defined(__WATCOMC__) && (__WATCOMC__ >= 1100) && !defined(HAVE_INT64))
+ typedef __int64 LLONG64;
+ typedef unsigned __int64 ULLNG64;
+# define HAVE_INT64
+#endif
+#if (defined(_MSC_VER) && (_MSC_VER >= 1100) && !defined(HAVE_INT64))
+ typedef __int64 LLONG64;
+ typedef unsigned __int64 ULLNG64;
+# define HAVE_INT64
+#endif
+
+/*****************************/
+/* Function utime2FileTime() */ /* convert Unix time_t format into the */
+/*****************************/ /* form used by SetFileTime() in NT/95 */
+
+#define UNIX_TIME_ZERO_HI 0x019DB1DEUL
+#define UNIX_TIME_ZERO_LO 0xD53E8000UL
+#define NT_QUANTA_PER_UNIX 10000000L
+
+static void utime2FileTime(time_t ut, FILETIME *pft)
+{
+#ifdef HAVE_INT64
+ ULLNG64 NTtime;
+
+ /* NT_QUANTA_PER_UNIX is small enough so that "ut * NT_QUANTA_PER_UNIX"
+ * cannot overflow in 64-bit signed calculation, regardless wether "ut"
+ * is signed or unsigned. */
+ NTtime = ((LLONG64)ut * NT_QUANTA_PER_UNIX) +
+ ((ULLNG64)UNIX_TIME_ZERO_LO + ((ULLNG64)UNIX_TIME_ZERO_HI << 32));
+ pft->dwLowDateTime = (DWORD)NTtime;
+ pft->dwHighDateTime = (DWORD)(NTtime >> 32);
+
+#else /* !HAVE_INT64 (64-bit integer arithmetics may not be supported) */
+ unsigned int b1, b2, carry = 0;
+ unsigned long r0, r1, r2, r3;
+ long r4; /* signed, to catch environments with signed time_t */
+
+ b1 = ut & 0xFFFF;
+ b2 = (ut >> 16) & 0xFFFF; /* if ut is over 32 bits, too bad */
+ r1 = b1 * (NT_QUANTA_PER_UNIX & 0xFFFF);
+ r2 = b1 * (NT_QUANTA_PER_UNIX >> 16);
+ r3 = b2 * (NT_QUANTA_PER_UNIX & 0xFFFF);
+ r4 = b2 * (NT_QUANTA_PER_UNIX >> 16);
+ r0 = (r1 + (r2 << 16)) & 0xFFFFFFFFL;
+ if (r0 < r1)
+ carry++;
+ r1 = r0;
+ r0 = (r0 + (r3 << 16)) & 0xFFFFFFFFL;
+ if (r0 < r1)
+ carry++;
+ pft->dwLowDateTime = r0 + UNIX_TIME_ZERO_LO;
+ if (pft->dwLowDateTime < r0)
+ carry++;
+ pft->dwHighDateTime = r4 + (r2 >> 16) + (r3 >> 16)
+ + UNIX_TIME_ZERO_HI + carry;
+#endif /* ?HAVE_INT64 */
+
+} /* end function utime2FileTime() */
+
+
+
+/******************************/
+/* Function FStampIsLocTime() */
+/******************************/
+
+static int FStampIsLocTime(__GPRO__ const char *path)
+{
+ return (NTQueryVolInfo(__G__ path) ? G.lastVolLocTim : FALSE);
+}
+
+#endif /* USE_EF_UT_TIME || NT_TZBUG_WORKAROUND || TIMESTAMP */
+
+
+
+#ifndef NT_TZBUG_WORKAROUND
+# define UTIME_BOUNDCHECK_1(utimval) \
+ if (fs_uses_loctime) { \
+ utime_dosmin = dos_to_unix_time(DOSTIME_MINIMUM); \
+ if ((ulg)utimval < (ulg)utime_dosmin) \
+ utimval = utime_dosmin; \
+ }
+# define UTIME_BOUNDCHECK_N(utimval) \
+ if (fs_uses_loctime && ((ulg)utimval < (ulg)utime_dosmin)) \
+ utimval = utime_dosmin;
+# define NT_TZBUG_PRECOMPENSATE(ut, pft)
+
+#else /* NT_TZBUG_WORKAROUND */
+# define UNIX_TIME_UMAX_HI 0x0236485EUL
+# define UNIX_TIME_UMAX_LO 0xD4A5E980UL
+# define UNIX_TIME_SMIN_HI 0x0151669EUL
+# define UNIX_TIME_SMIN_LO 0xD53E8000UL
+# define UNIX_TIME_SMAX_HI 0x01E9FD1EUL
+# define UNIX_TIME_SMAX_LO 0xD4A5E980UL
+# define UTIME_1980_JAN_01_00_00 315532800L
+# define UTIME_BOUNDCHECK_1(utimval)
+# define UTIME_BOUNDCHECK_N(utimval)
+# define NT_TZBUG_PRECOMPENSATE(ut, pft) \
+ if (fs_uses_loctime) NTtzbugWorkaround(ut, pft);
+
+ /* nonzero if `y' is a leap year, else zero */
+# define leap(y) (((y)%4 == 0 && (y)%100 != 0) || (y)%400 == 0)
+ /* number of leap years from 1970 to `y' (not including `y' itself) */
+# define nleap(y) (((y)-1969)/4 - ((y)-1901)/100 + ((y)-1601)/400)
+
+extern ZCONST ush ydays[]; /* defined in fileio.c */
+
+/*****************************/
+/* Function FileTime2utime() */
+/*****************************/
+
+static int FileTime2utime(const FILETIME *pft, time_t *ut)
+{
+#ifdef HAVE_INT64
+ ULLNG64 NTtime;
+
+ NTtime = ((ULLNG64)pft->dwLowDateTime +
+ ((ULLNG64)pft->dwHighDateTime << 32));
+
+ /* underflow and overflow handling */
+#ifdef CHECK_UTIME_SIGNED_UNSIGNED
+ if ((time_t)0x80000000L < (time_t)0L)
+ {
+ if (NTtime < ((ULLNG64)UNIX_TIME_SMIN_LO +
+ ((ULLNG64)UNIX_TIME_SMIN_HI << 32))) {
+ *ut = (time_t)LONG_MIN;
+ return FALSE;
+ }
+ if (NTtime > ((ULLNG64)UNIX_TIME_SMAX_LO +
+ ((ULLNG64)UNIX_TIME_SMAX_HI << 32))) {
+ *ut = (time_t)LONG_MAX;
+ return FALSE;
+ }
+ }
+ else
+#endif /* CHECK_UTIME_SIGNED_UNSIGNED */
+ {
+ if (NTtime < ((ULLNG64)UNIX_TIME_ZERO_LO +
+ ((ULLNG64)UNIX_TIME_ZERO_HI << 32))) {
+ *ut = (time_t)0;
+ return FALSE;
+ }
+ if (NTtime > ((ULLNG64)UNIX_TIME_UMAX_LO +
+ ((ULLNG64)UNIX_TIME_UMAX_HI << 32))) {
+ *ut = (time_t)ULONG_MAX;
+ return FALSE;
+ }
+ }
+
+ NTtime -= ((ULLNG64)UNIX_TIME_ZERO_LO +
+ ((ULLNG64)UNIX_TIME_ZERO_HI << 32));
+ *ut = (time_t)(NTtime / (unsigned long)NT_QUANTA_PER_UNIX);
+ return TRUE;
+#else /* !HAVE_INT64 (64-bit integer arithmetics may not be supported) */
+ time_t days;
+ SYSTEMTIME w32tm;
+
+ /* underflow and overflow handling */
+#ifdef CHECK_UTIME_SIGNED_UNSIGNED
+ if ((time_t)0x80000000L < (time_t)0L)
+ {
+ if ((pft->dwHighDateTime < UNIX_TIME_SMIN_HI) ||
+ ((pft->dwHighDateTime == UNIX_TIME_SMIN_HI) &&
+ (pft->dwLowDateTime < UNIX_TIME_SMIN_LO))) {
+ *ut = (time_t)LONG_MIN;
+ return FALSE;
+ if ((pft->dwHighDateTime > UNIX_TIME_SMAX_HI) ||
+ ((pft->dwHighDateTime == UNIX_TIME_SMAX_HI) &&
+ (pft->dwLowDateTime > UNIX_TIME_SMAX_LO))) {
+ *ut = (time_t)LONG_MAX;
+ return FALSE;
+ }
+ }
+ else
+#endif /* CHECK_UTIME_SIGNED_UNSIGNED */
+ {
+ if ((pft->dwHighDateTime < UNIX_TIME_ZERO_HI) ||
+ ((pft->dwHighDateTime == UNIX_TIME_ZERO_HI) &&
+ (pft->dwLowDateTime < UNIX_TIME_ZERO_LO))) {
+ *ut = (time_t)0;
+ return FALSE;
+ }
+ if ((pft->dwHighDateTime > UNIX_TIME_UMAX_HI) ||
+ ((pft->dwHighDateTime == UNIX_TIME_UMAX_HI) &&
+ (pft->dwLowDateTime > UNIX_TIME_UMAX_LO))) {
+ *ut = (time_t)ULONG_MAX;
+ return FALSE;
+ }
+ }
+
+ FileTimeToSystemTime(pft, &w32tm);
+
+ /* set `days' to the number of days into the year */
+ days = w32tm.wDay - 1 + ydays[w32tm.wMonth-1] +
+ (w32tm.wMonth > 2 && leap (w32tm.wYear));
+
+ /* now set `days' to the number of days since 1 Jan 1970 */
+ days += 365 * (time_t)(w32tm.wYear - 1970) +
+ (time_t)(nleap(w32tm.wYear));
+
+ *ut = (time_t)(86400L * days + 3600L * (time_t)w32tm.wHour +
+ (time_t)(60 * w32tm.wMinute + w32tm.wSecond));
+ return TRUE;
+#endif /* ?HAVE_INT64 */
+} /* end function FileTime2utime() */
+
+
+
+#ifdef W32_STAT_BANDAID
+/*********************************/
+/* Function VFatFileTime2utime() */
+/*********************************/
+
+static int VFatFileTime2utime(const FILETIME *pft, time_t *ut)
+{
+ FILETIME lft;
+#ifndef HAVE_MKTIME
+ WORD wDOSDate, wDOSTime;
+#else
+ SYSTEMTIME w32tm;
+ struct tm ltm;
+#endif
+
+ FileTimeToLocalFileTime(pft, &lft);
+ FTTrace((stdout, "VFatFT2utime, feed for mktime()", 1, &lft));
+#ifndef HAVE_MKTIME
+ /* This version of the FILETIME-to-UNIXTIME conversion function
+ * uses DOS-DATE-TIME format as intermediate stage. For modification
+ * and access times, this is no problem. But, the extra fine resolution
+ * of the VFAT-stored creation time gets lost.
+ */
+ FileTimeToDosDateTime(&lft, &wDOSDate, &wDOSTime);
+ TTrace((stdout,"DosDateTime is %04u-%02u-%02u %02u:%02u:%02u\n",
+ (unsigned)((wDOSDate>>9)&0x7f)+1980,(unsigned)((wDOSDate>>5)&0x0f),
+ (unsigned)(wDOSDate&0x1f),(unsigned)((wDOSTime>>11)&0x1f),
+ (unsigned)((wDOSTime>>5)&0x3f),(unsigned)((wDOSTime<<1)&0x3e)));
+ *ut = dos_to_unix_time(((ulg)wDOSDate << 16) | (ulg)wDOSTime);
+
+ /* a cheap error check: dos_to_unix_time() only returns an odd time
+ * when clipping at maximum time_t value. DOS_DATE_TIME values have
+ * a resolution of 2 seconds and are therefore even numbers.
+ */
+ return (((*ut)&1) == (time_t)0);
+#else /* HAVE_MKTIME */
+ FileTimeToSystemTime(&lft, &w32tm);
+ /* underflow and overflow handling */
+ /* TODO: The range checks are not accurate, the actual limits may
+ * be off by one daylight-saving-time shift (typically 1 hour),
+ * depending on the current state of "is_dst".
+ */
+#ifdef CHECK_UTIME_SIGNED_UNSIGNED
+ if ((time_t)0x80000000L < (time_t)0L)
+ {
+ if ((pft->dwHighDateTime < UNIX_TIME_SMIN_HI) ||
+ ((pft->dwHighDateTime == UNIX_TIME_SMIN_HI) &&
+ (pft->dwLowDateTime < UNIX_TIME_SMIN_LO))) {
+ *ut = (time_t)LONG_MIN;
+ return FALSE;
+ if ((pft->dwHighDateTime > UNIX_TIME_SMAX_HI) ||
+ ((pft->dwHighDateTime == UNIX_TIME_SMAX_HI) &&
+ (pft->dwLowDateTime > UNIX_TIME_SMAX_LO))) {
+ *ut = (time_t)LONG_MAX;
+ return FALSE;
+ }
+ }
+ else
+#endif /* CHECK_UTIME_SIGNED_UNSIGNED */
+ {
+ if ((pft->dwHighDateTime < UNIX_TIME_ZERO_HI) ||
+ ((pft->dwHighDateTime == UNIX_TIME_ZERO_HI) &&
+ (pft->dwLowDateTime < UNIX_TIME_ZERO_LO))) {
+ *ut = (time_t)0;
+ return FALSE;
+ }
+ if ((pft->dwHighDateTime > UNIX_TIME_UMAX_HI) ||
+ ((pft->dwHighDateTime == UNIX_TIME_UMAX_HI) &&
+ (pft->dwLowDateTime > UNIX_TIME_UMAX_LO))) {
+ *ut = (time_t)ULONG_MAX;
+ return FALSE;
+ }
+ }
+ ltm.tm_year = w32tm.wYear - 1900;
+ ltm.tm_mon = w32tm.wMonth - 1;
+ ltm.tm_mday = w32tm.wDay;
+ ltm.tm_hour = w32tm.wHour;
+ ltm.tm_min = w32tm.wMinute;
+ ltm.tm_sec = w32tm.wSecond;
+ ltm.tm_isdst = -1; /* let mktime determine if DST is in effect */
+ *ut = mktime(&ltm);
+
+ /* a cheap error check: mktime returns "(time_t)-1L" on conversion errors.
+ * Normally, we would have to apply a consistency check because "-1"
+ * could also be a valid time. But, it is quite unlikely to read back odd
+ * time numbers from file systems that store time stamps in DOS format.
+ * (The only known exception is creation time on VFAT partitions.)
+ */
+ return (*ut != (time_t)-1L);
+#endif /* ?HAVE_MKTIME */
+
+} /* end function VFatFileTime2utime() */
+#endif /* W32_STAT_BANDAID */
+
+
+
+/********************************/
+/* Function UTCtime2Localtime() */ /* borrowed from Zip's mkgmtime() */
+/********************************/
+
+static time_t UTCtime2Localtime(time_t utctime)
+{
+ time_t utc = utctime;
+ struct tm *tm;
+ unsigned years, months, days, hours, minutes, seconds;
+
+
+#ifdef __BORLANDC__ /* Borland C++ 5.x crashes when trying to reference tm */
+ if (utc < UTIME_1980_JAN_01_00_00)
+ utc = UTIME_1980_JAN_01_00_00;
+#endif
+ tm = localtime(&utc);
+ if (tm == (struct tm *)NULL)
+ /* localtime() did not accept given utc time value; as an emergency
+ exit, the unconverted utctime value is returned */
+ return utctime;
+
+ years = tm->tm_year + 1900; /* year - 1900 -> year */
+ months = tm->tm_mon; /* 0..11 */
+ days = tm->tm_mday - 1; /* 1..31 -> 0..30 */
+ hours = tm->tm_hour; /* 0..23 */
+ minutes = tm->tm_min; /* 0..59 */
+ seconds = tm->tm_sec; /* 0..61 in ANSI C */
+
+ /* set `days' to the number of days into the year */
+ days += ydays[months] + (months > 1 && leap(years));
+
+ /* now set `days' to the number of days since 1 Jan 1970 */
+ days += 365 * (years - 1970) + nleap(years);
+
+ return (time_t)(86400L * (ulg)days + 3600L * (ulg)hours +
+ (ulg)(60 * minutes + seconds));
+
+} /* end function UTCtime2Localtime() */
+
+
+
+/********************************/
+/* Function NTtzbugWorkaround() */
+/********************************/
+
+static void NTtzbugWorkaround(time_t ut, FILETIME *pft)
+{
+ FILETIME C_RTL_locft, NTAPI_locft;
+ time_t ux_loctime = UTCtime2Localtime(ut);
+
+ /* This routine is only used when the target file system stores time-
+ * stamps as local time in MSDOS format. Thus we make sure that the
+ * resulting timestamp is within the range of MSDOS date-time values. */
+ if (ux_loctime < UTIME_1980_JAN_01_00_00)
+ ux_loctime = UTIME_1980_JAN_01_00_00;
+
+ utime2FileTime(ux_loctime, &C_RTL_locft);
+ if (!FileTimeToLocalFileTime(pft, &NTAPI_locft))
+ return;
+ else {
+ long time_shift_l, time_shift_h;
+ int carry = 0;
+
+ time_shift_l = C_RTL_locft.dwLowDateTime - NTAPI_locft.dwLowDateTime;
+ if (C_RTL_locft.dwLowDateTime < NTAPI_locft.dwLowDateTime)
+ carry--;
+ time_shift_h = C_RTL_locft.dwHighDateTime - NTAPI_locft.dwHighDateTime;
+ pft->dwLowDateTime += time_shift_l;
+ if (pft->dwLowDateTime < (ulg)time_shift_l)
+ carry++;
+ pft->dwHighDateTime += time_shift_h + carry;
+ TTrace((stdout, "FileTime shift: %08lx:%08lx\n",
+ time_shift_h+carry,time_shift_l));
+ }
+} /* end function NTtzbugWorkaround() */
+
+#endif /* ?NT_TZBUG_WORKAROUND */
+
+
+
+/****************************/ /* Get the file time in a format that */
+/* Function getNTfiletime() */ /* can be used by SetFileTime() in NT */
+/****************************/
+
+static int getNTfiletime(__G__ pModFT, pAccFT, pCreFT)
+ __GDEF
+ FILETIME *pModFT;
+ FILETIME *pAccFT;
+ FILETIME *pCreFT;
+{
+#ifdef NT_TZBUG_WORKAROUND
+ time_t ux_modtime;
+#else /* !NT_TZBUG_WORKAROUND */
+ FILETIME locft; /* 64-bit value made up of two 32-bit [low & high] */
+ WORD wDOSDate; /* for converting from DOS date to Windows NT */
+ WORD wDOSTime;
+#endif /* ?NT_TZBUG_WORKAROUND */
+#ifdef USE_EF_UT_TIME
+ unsigned eb_izux_flg;
+ iztimes z_utime; /* struct for Unix-style actime & modtime, + creatime */
+#endif
+#if (defined(USE_EF_UT_TIME) && !defined(NT_TZBUG_WORKAROUND))
+ time_t utime_dosmin;
+# endif
+#if (defined(USE_EF_UT_TIME) || defined(NT_TZBUG_WORKAROUND))
+ int fs_uses_loctime = FStampIsLocTime(__G__ G.filename);
+#endif
+
+ /* Copy and/or convert time and date variables, if necessary;
+ * return a flag indicating which time stamps are available. */
+#ifdef USE_EF_UT_TIME
+ if (G.extra_field &&
+#ifdef IZ_CHECK_TZ
+ G.tz_is_valid &&
+#endif
+ ((eb_izux_flg = ef_scan_for_izux(G.extra_field,
+ G.lrec.extra_field_length, 0, G.lrec.last_mod_dos_datetime,
+ &z_utime, NULL)) & EB_UT_FL_MTIME))
+ {
+ TTrace((stderr, "getNTfiletime: Unix e.f. modif. time = %lu\n",
+ z_utime.mtime));
+ UTIME_BOUNDCHECK_1(z_utime.mtime)
+ utime2FileTime(z_utime.mtime, pModFT);
+ NT_TZBUG_PRECOMPENSATE(z_utime.mtime, pModFT)
+ if (eb_izux_flg & EB_UT_FL_ATIME) {
+ UTIME_BOUNDCHECK_N(z_utime.atime)
+ utime2FileTime(z_utime.atime, pAccFT);
+ NT_TZBUG_PRECOMPENSATE(z_utime.atime, pAccFT)
+ }
+ if (eb_izux_flg & EB_UT_FL_CTIME) {
+ UTIME_BOUNDCHECK_N(z_utime.ctime)
+ utime2FileTime(z_utime.ctime, pCreFT);
+ NT_TZBUG_PRECOMPENSATE(z_utime.ctime, pCreFT)
+ }
+ return (int)eb_izux_flg;
+ }
+#endif /* USE_EF_UT_TIME */
+#ifdef NT_TZBUG_WORKAROUND
+ ux_modtime = dos_to_unix_time(G.lrec.last_mod_dos_datetime);
+ utime2FileTime(ux_modtime, pModFT);
+ NT_TZBUG_PRECOMPENSATE(ux_modtime, pModFT)
+#else /* !NT_TZBUG_WORKAROUND */
+
+ wDOSTime = (WORD)(G.lrec.last_mod_dos_datetime);
+ wDOSDate = (WORD)(G.lrec.last_mod_dos_datetime >> 16);
+
+ /* The DosDateTimeToFileTime() function converts a DOS date/time
+ * into a 64-bit Windows NT file time */
+ if (!DosDateTimeToFileTime(wDOSDate, wDOSTime, &locft))
+ {
+ Info(slide, 0, ((char *)slide, "DosDateTime failed: %d\n",
+ (int)GetLastError()));
+ return 0;
+ }
+ if (!LocalFileTimeToFileTime(&locft, pModFT))
+ {
+ Info(slide, 0, ((char *)slide, "LocalFileTime failed: %d\n",
+ (int)GetLastError()));
+ *pModFT = locft;
+ }
+#endif /* ?NT_TZBUG_WORKAROUND */
+ *pAccFT = *pModFT;
+ return (EB_UT_FL_MTIME | EB_UT_FL_ATIME);
+
+} /* end function getNTfiletime() */
+
+
+
+
+/****************************/
+/* Function close_outfile() */
+/****************************/
+
+void close_outfile(__G)
+ __GDEF
+{
+ FILETIME Modft; /* File time type defined in NT, `last modified' time */
+ FILETIME Accft; /* NT file time type, `last access' time */
+ FILETIME Creft; /* NT file time type, `file creation' time */
+ HANDLE hFile; /* File handle defined in NT */
+ int gotTime;
+#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */
+ char *ansi_name = (char *)alloca(strlen(G.filename) + 1);
+
+ INTERN_TO_ISO(G.filename, ansi_name);
+# define Ansi_Fname ansi_name
+#else
+# define Ansi_Fname G.filename
+#endif
+
+ /* Close the file and then re-open it using the Win32
+ * CreateFile call, so that the file can be created
+ * with GENERIC_WRITE access, otherwise the SetFileTime
+ * call will fail. */
+ fclose(G.outfile);
+
+ /* don't set the time stamp and attributes on standard output */
+ if (uO.cflag)
+ return;
+
+ gotTime = getNTfiletime(__G__ &Modft, &Accft, &Creft);
+
+ /* open a handle to the file before processing extra fields;
+ we do this in case new security on file prevents us from updating
+ time stamps */
+ hFile = CreateFile(Ansi_Fname, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+
+ /* sfield@microsoft.com: set attributes before time in case we decide to
+ support other filetime members later. This also allows us to apply
+ attributes before the security is changed, which may prevent this
+ from succeeding otherwise. Also, since most files don't have
+ any interesting attributes, only change them if something other than
+ FILE_ATTRIBUTE_ARCHIVE appears in the attributes. This works well
+ as an optimization because FILE_ATTRIBUTE_ARCHIVE gets applied to the
+ file anyway, when it's created new. */
+ if((G.pInfo->file_attr & 0x7F) & ~FILE_ATTRIBUTE_ARCHIVE) {
+ if (!SetFileAttributes(Ansi_Fname, G.pInfo->file_attr & 0x7F))
+ Info(slide, 1, ((char *)slide,
+ "\nwarning (%d): could not set file attributes\n",
+ (int)GetLastError()));
+ }
+
+#ifdef NTSD_EAS
+ /* set extra fields, both stored-in-zipfile and .LONGNAME flavors */
+ if (G.extra_field) { /* zipfile extra field may have extended attribs */
+ int err = EvalExtraFields(__G__ G.filename, G.extra_field,
+ G.lrec.extra_field_length);
+
+ if (err == IZ_EF_TRUNC) {
+ if (uO.qflag)
+ Info(slide, 1, ((char *)slide, "%-22s ",
+ FnFilter1(G.filename)));
+ Info(slide, 1, ((char *)slide, LoadFarString(TruncNTSD),
+ makeword(G.extra_field+2)-10, uO.qflag? "\n":""));
+ }
+ }
+#endif /* NTSD_EAS */
+
+ if ( hFile == INVALID_HANDLE_VALUE )
+ Info(slide, 1, ((char *)slide,
+ "\nCreateFile error %d when trying set file time\n",
+ (int)GetLastError()));
+ else {
+ if (gotTime) {
+ FILETIME *pModft = (gotTime & EB_UT_FL_MTIME) ? &Modft : NULL;
+ FILETIME *pAccft = (gotTime & EB_UT_FL_ATIME) ? &Accft : NULL;
+ FILETIME *pCreft = (gotTime & EB_UT_FL_CTIME) ? &Creft : NULL;
+
+ if (!SetFileTime(hFile, pCreft, pAccft, pModft))
+ Info(slide, 0, ((char *)slide, "\nSetFileTime failed: %d\n",
+ (int)GetLastError()));
+ }
+ CloseHandle(hFile);
+ }
+
+ return;
+
+#undef Ansi_Fname
+
+} /* end function close_outfile() */
+
+
+
+
+#ifdef TIMESTAMP
+
+/*************************/
+/* Function stamp_file() */
+/*************************/
+
+int stamp_file(__GPRO__ ZCONST char *fname, time_t modtime)
+{
+ FILETIME Modft; /* File time type defined in NT, `last modified' time */
+ HANDLE hFile; /* File handle defined in NT */
+ int errstat = 0; /* return status: 0 == "OK", -1 == "Failure" */
+#ifndef NT_TZBUG_WORKAROUND
+ time_t utime_dosmin; /* internal variable for UTIME_BOUNDCHECK_1 */
+#endif
+ int fs_uses_loctime = FStampIsLocTime(__G__ fname);
+#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */
+ char *ansi_name = (char *)alloca(strlen(fname) + 1);
+
+ INTERN_TO_ISO(fname, ansi_name);
+# define Ansi_Fname ansi_name
+#else
+# define Ansi_Fname fname
+#endif
+
+ /* open a handle to the file to prepare setting the mod-time stamp */
+ hFile = CreateFile(Ansi_Fname, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if ( hFile == INVALID_HANDLE_VALUE ) {
+ errstat = -1;
+ } else {
+ /* convert time_t modtime into WIN32 native 64bit format */
+ UTIME_BOUNDCHECK_1(modtime)
+ utime2FileTime(modtime, &Modft);
+ NT_TZBUG_PRECOMPENSATE(modtime, &Modft)
+ /* set Access and Modification times of the file to modtime */
+ if (!SetFileTime(hFile, NULL, &Modft, &Modft)) {
+ errstat = -1;
+ }
+ CloseHandle(hFile);
+ }
+
+ return errstat;
+
+#undef Ansi_Fname
+} /* end function stamp_file() */
+
+#endif /* TIMESTAMP */
+
+
+
+
+/***********************/
+/* Function isfloppy() */ /* more precisely, is it removable? */
+/***********************/
+
+static int isfloppy(int nDrive) /* 1 == A:, 2 == B:, etc. */
+{
+ char rootPathName[4];
+
+ rootPathName[0] = (char)('A' + nDrive - 1); /* build the root path */
+ rootPathName[1] = ':'; /* name, e.g. "A:/" */
+ rootPathName[2] = '/';
+ rootPathName[3] = '\0';
+
+ return (GetDriveType(rootPathName) == DRIVE_REMOVABLE);
+
+} /* end function isfloppy() */
+
+
+
+
+/*****************************/
+/* Function NTQueryVolInfo() */
+/*****************************/
+
+/*
+ * Note: 8.3 limits on filenames apply only to old-style FAT filesystems.
+ * More recent versions of Windows (Windows NT 3.5 / Windows 4.0)
+ * can support long filenames (LFN) on FAT filesystems. Check the
+ * filesystem maximum component length field to detect LFN support.
+ */
+
+static int NTQueryVolInfo(__GPRO__ const char *name)
+{
+ /* static char lastRootPath[4] = ""; */
+ /* static int lastVolOldFAT; */
+ /* static int lastVolLocTim; */
+ char *tmp0;
+ char tmp1[MAX_PATH], tmp2[MAX_PATH];
+ unsigned volSerNo, maxCompLen, fileSysFlags;
+#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */
+ char *ansi_name = (char *)alloca(strlen(name) + 1);
+
+ INTERN_TO_ISO(name, ansi_name);
+ name = ansi_name;
+#endif
+
+ if ((!strncmp(name, "//", 2) || !strncmp(name,"\\\\", 2)) &&
+ (name[2] != '\0' && name[2] != '/' && name[2] != '\\')) {
+ /* GetFullPathname() and GetVolumeInformation() do not work
+ * on UNC names. For now, we return "error".
+ * **FIXME**: check if UNC name is mapped to a drive letter
+ * and use mapped drive for volume info query.
+ */
+ return FALSE;
+ }
+ if (isalpha((uch)name[0]) && (name[1] == ':'))
+ tmp0 = (char *)name;
+ else
+ {
+ if (!GetFullPathName(name, MAX_PATH, tmp1, &tmp0))
+ return FALSE;
+ tmp0 = &tmp1[0];
+ }
+ if (strncmp(G.lastRootPath, tmp0, 2) != 0) {
+ /* For speed, we skip repeated queries for the same device */
+ strncpy(G.lastRootPath, tmp0, 2); /* Build the root path name, */
+ G.lastRootPath[2] = '/'; /* e.g. "A:/" */
+ G.lastRootPath[3] = '\0';
+
+ if (!GetVolumeInformation((LPCTSTR)G.lastRootPath,
+ (LPTSTR)tmp1, (DWORD)MAX_PATH,
+ (LPDWORD)&volSerNo, (LPDWORD)&maxCompLen,
+ (LPDWORD)&fileSysFlags, (LPTSTR)tmp2, (DWORD)MAX_PATH)) {
+ G.lastRootPath[0] = '\0';
+ return FALSE;
+ }
+
+ /* LFNs are available if the component length is > 12 */
+ G.lastVolOldFAT = (maxCompLen <= 12);
+/* G.lastVolOldFAT = !strncmp(strupr(tmp2), "FAT", 3); old version */
+
+ /* Volumes in (V)FAT and (OS/2) HPFS format store file timestamps in
+ * local time!
+ */
+ G.lastVolLocTim = !strncmp(strupr(tmp2), "VFAT", 4) ||
+ !strncmp(tmp2, "HPFS", 4) ||
+ !strncmp(tmp2, "FAT", 3);
+ }
+
+ return TRUE;
+
+} /* end function NTQueryVolInfo() */
+
+
+
+
+/*****************************/
+/* Function IsVolumeOldFAT() */
+/*****************************/
+
+static int IsVolumeOldFAT(__GPRO__ const char *name)
+{
+ return (NTQueryVolInfo(__G__ name) ? G.lastVolOldFAT : FALSE);
+}
+
+
+
+
+#ifndef SFX
+
+/************************/
+/* Function do_wild() */ /* identical to OS/2 version */
+/************************/
+
+char *do_wild(__G__ wildspec)
+ __GDEF
+ char *wildspec; /* only used first time on a given dir */
+{
+ /* static zDIR *wild_dir = NULL; */
+ /* static char *dirname, *wildname, matchname[FILNAMSIZ]; */
+ /* static int firstcall=TRUE, have_dirname, dirnamelen; */
+ char *fnamestart;
+ struct zdirent *file;
+
+ /* Even when we're just returning wildspec, we *always* do so in
+ * matchname[]--calling routine is allowed to append four characters
+ * to the returned string, and wildspec may be a pointer to argv[].
+ */
+ if (!G.notfirstcall) { /* first call: must initialize everything */
+ G.notfirstcall = TRUE;
+
+ if (!iswild(wildspec)) {
+ strcpy(G.matchname, wildspec);
+ G.have_dirname = FALSE;
+ G.wild_dir = NULL;
+ return G.matchname;
+ }
+
+ /* break the wildspec into a directory part and a wildcard filename */
+ if ((G.wildname = strrchr(wildspec, '/')) == NULL &&
+ (G.wildname = strrchr(wildspec, ':')) == NULL) {
+ G.dirname = ".";
+ G.dirnamelen = 1;
+ G.have_dirname = FALSE;
+ G.wildname = wildspec;
+ } else {
+ ++G.wildname; /* point at character after '/' or ':' */
+ G.dirnamelen = G.wildname - wildspec;
+ if ((G.dirname = (char *)malloc(G.dirnamelen+1)) == NULL) {
+ Info(slide, 1, ((char *)slide,
+ "warning: cannot allocate wildcard buffers\n"));
+ strcpy(G.matchname, wildspec);
+ return G.matchname; /* but maybe filespec was not a wildcard */
+ }
+ strncpy(G.dirname, wildspec, G.dirnamelen);
+ G.dirname[G.dirnamelen] = '\0'; /* terminate for strcpy below */
+ G.have_dirname = TRUE;
+ }
+ Trace((stderr, "do_wild: dirname = [%s]\n", G.dirname));
+
+ if ((G.wild_dir = (zvoid *)Opendir(G.dirname)) != NULL) {
+ if (G.have_dirname) {
+ strcpy(G.matchname, G.dirname);
+ fnamestart = G.matchname + G.dirnamelen;
+ } else
+ fnamestart = G.matchname;
+ while ((file = Readdir((zDIR *)G.wild_dir)) != NULL) {
+ Trace((stderr, "do_wild: Readdir returns %s\n", file->d_name));
+ strcpy(fnamestart, file->d_name);
+ if (strrchr(fnamestart, '.') == (char *)NULL)
+ strcat(fnamestart, ".");
+ if (match(fnamestart, G.wildname, 1) && /* 1 == ignore case */
+ /* skip "." and ".." directory entries */
+ strcmp(fnamestart, ".") && strcmp(fnamestart, "..")) {
+ Trace((stderr, "do_wild: match() succeeds\n"));
+ /* remove trailing dot */
+ fnamestart += strlen(fnamestart) - 1;
+ if (*fnamestart == '.')
+ *fnamestart = '\0';
+ return G.matchname;
+ }
+ }
+ /* if we get to here directory is exhausted, so close it */
+ Closedir((zDIR *)G.wild_dir);
+ G.wild_dir = NULL;
+ }
+ Trace((stderr, "do_wild: Opendir(%s) returns NULL\n", G.dirname));
+
+ /* return the raw wildspec in case that works (e.g., directory not
+ * searchable, but filespec was not wild and file is readable) */
+ strcpy(G.matchname, wildspec);
+ return G.matchname;
+ }
+
+ /* last time through, might have failed opendir but returned raw wildspec */
+ if (G.wild_dir == NULL) {
+ G.notfirstcall = FALSE; /* reset for new wildspec */
+ if (G.have_dirname)
+ free(G.dirname);
+ return (char *)NULL;
+ }
+
+ /* If we've gotten this far, we've read and matched at least one entry
+ * successfully (in a previous call), so dirname has been copied into
+ * matchname already.
+ */
+ if (G.have_dirname) {
+ /* strcpy(G.matchname, G.dirname); */
+ fnamestart = G.matchname + G.dirnamelen;
+ } else
+ fnamestart = G.matchname;
+ while ((file = Readdir((zDIR *)G.wild_dir)) != NULL) {
+ Trace((stderr, "do_wild: readdir returns %s\n", file->d_name));
+ strcpy(fnamestart, file->d_name);
+ if (strrchr(fnamestart, '.') == (char *)NULL)
+ strcat(fnamestart, ".");
+ if (match(fnamestart, G.wildname, 1)) { /* 1 == ignore case */
+ Trace((stderr, "do_wild: match() succeeds\n"));
+ /* remove trailing dot */
+ fnamestart += strlen(fnamestart) - 1;
+ if (*fnamestart == '.')
+ *fnamestart = '\0';
+ return G.matchname;
+ }
+ }
+
+ Closedir((zDIR *)G.wild_dir); /* at least one entry read; nothing left */
+ G.wild_dir = NULL;
+ G.notfirstcall = FALSE; /* reset for new wildspec */
+ if (G.have_dirname)
+ free(G.dirname);
+ return (char *)NULL;
+
+} /* end function do_wild() */
+
+#endif /* !SFX */
+
+
+
+/**********************/
+/* Function mapattr() */
+/**********************/
+
+/* Identical to MS-DOS, OS/2 versions. However, NT has a lot of extra
+ * permission stuff, so this function should probably be extended in the
+ * future. */
+
+int mapattr(__G)
+ __GDEF
+{
+ /* set archive bit for file entries (file is not backed up): */
+ G.pInfo->file_attr = ((unsigned)G.crec.external_file_attributes |
+ (G.crec.external_file_attributes & FILE_ATTRIBUTE_DIRECTORY ?
+ 0 : FILE_ATTRIBUTE_ARCHIVE)) & 0xff;
+ return 0;
+
+} /* end function mapattr() */
+
+
+
+
+/************************/
+/* Function mapname() */
+/************************/
+ /* return 0 if no error, 1 if caution (filename */
+int mapname(__G__ renamed) /* truncated), 2 if warning (skip file because */
+ __GDEF /* dir doesn't exist), 3 if error (skip file), */
+ int renamed; /* or 10 if out of memory (skip file) */
+{ /* [also IZ_VOL_LABEL, IZ_CREATED_DIR] */
+ char pathcomp[FILNAMSIZ]; /* path-component buffer */
+ char *pp, *cp=NULL; /* character pointers */
+ char *lastsemi = NULL; /* pointer to last semi-colon in pathcomp */
+ int error;
+ register unsigned workch; /* hold the character being tested */
+
+
+/*---------------------------------------------------------------------------
+ Initialize various pointers and counters and stuff.
+ ---------------------------------------------------------------------------*/
+
+ /* can create path as long as not just freshening, or if user told us */
+ G.create_dirs = (!uO.fflag || renamed);
+
+ G.created_dir = FALSE; /* not yet */
+ G.renamed_fullpath = FALSE;
+ G.fnlen = strlen(G.filename);
+
+ if (renamed) {
+ cp = G.filename - 1; /* point to beginning of renamed name... */
+ while (*++cp)
+ if (*cp == '\\') /* convert backslashes to forward */
+ *cp = '/';
+ cp = G.filename;
+ /* use temporary rootpath if user gave full pathname */
+ if (G.filename[0] == '/') {
+ G.renamed_fullpath = TRUE;
+ pathcomp[0] = '/'; /* copy the '/' and terminate */
+ pathcomp[1] = '\0';
+ ++cp;
+ } else if (isalpha((uch)G.filename[0]) && G.filename[1] == ':') {
+ G.renamed_fullpath = TRUE;
+ pp = pathcomp;
+ *pp++ = *cp++; /* copy the "d:" (+ '/', possibly) */
+ *pp++ = *cp++;
+ if (*cp == '/')
+ *pp++ = *cp++; /* otherwise add "./"? */
+ *pp = '\0';
+ }
+ }
+
+ /* pathcomp is ignored unless renamed_fullpath is TRUE: */
+ if ((error = checkdir(__G__ pathcomp, INIT)) != 0) /* init path buffer */
+ return error; /* ...unless no mem or vol label on hard disk */
+
+ *pathcomp = '\0'; /* initialize translation buffer */
+ pp = pathcomp; /* point to translation buffer */
+ if (!renamed) { /* cp already set if renamed */
+ if (uO.jflag) /* junking directories */
+ cp = (char *)strrchr(G.filename, '/');
+ if (cp == NULL) /* no '/' or not junking dirs */
+ cp = G.filename; /* point to internal zipfile-member pathname */
+ else
+ ++cp; /* point to start of last component of path */
+ }
+
+/*---------------------------------------------------------------------------
+ Begin main loop through characters in filename.
+ ---------------------------------------------------------------------------*/
+
+ while ((workch = (uch)*cp++) != 0) {
+
+ switch (workch) {
+ case '/': /* can assume -j flag not given */
+ *pp = '\0';
+ if ((error = checkdir(__G__ pathcomp, APPEND_DIR)) > 1)
+ return error;
+ pp = pathcomp; /* reset conversion buffer for next piece */
+ lastsemi = NULL; /* leave directory semi-colons alone */
+ break;
+
+ case ':': /* drive names not stored in zipfile, */
+ case '<': /* so no colons allowed */
+ case '>': /* no redirection symbols allowed either */
+ case '|': /* no pipe signs allowed */
+ case '"': /* no double quotes allowed */
+ case '?': /* no wildcards allowed */
+ case '*':
+ *pp++ = '_'; /* these rules apply equally to FAT and NTFS */
+ break;
+ case ';': /* start of VMS version? */
+ lastsemi = pp; /* remove VMS version later... */
+ *pp++ = ';'; /* but keep semicolon for now */
+ break;
+
+ case ' ': /* keep spaces unless specifically */
+ /* NT cannot create filenames with spaces on FAT volumes */
+ if (uO.sflag || IsVolumeOldFAT(__G__ G.filename))
+ *pp++ = '_';
+ else
+ *pp++ = ' ';
+ break;
+
+ default:
+ /* allow European characters in filenames: */
+ if (isprint(workch) || workch >= 127)
+ *pp++ = (char)workch;
+ } /* end switch */
+ } /* end while loop */
+
+ *pp = '\0'; /* done with pathcomp: terminate it */
+
+ /* if not saving them, remove VMS version numbers (appended "###") */
+ if (!uO.V_flag && lastsemi) {
+ pp = lastsemi + 1; /* semi-colon was kept: expect #'s after */
+ while (isdigit((uch)(*pp)))
+ ++pp;
+ if (*pp == '\0') /* only digits between ';' and end: nuke */
+ *lastsemi = '\0';
+ }
+
+/*---------------------------------------------------------------------------
+ Report if directory was created (and no file to create: filename ended
+ in '/'), check name to be sure it exists, and combine path and name be-
+ fore exiting.
+ ---------------------------------------------------------------------------*/
+
+ if (G.filename[G.fnlen-1] == '/') {
+ checkdir(__G__ G.filename, GETPATH);
+ if (G.created_dir) {
+#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */
+ char *ansi_name = (char *)alloca(strlen(G.filename) + 1);
+
+ INTERN_TO_ISO(G.filename, ansi_name);
+# define Ansi_Fname ansi_name
+#else
+# define Ansi_Fname G.filename
+#endif
+ if (QCOND2) {
+ Info(slide, 0, ((char *)slide, " creating: %-22s\n",
+ FnFilter1(G.filename)));
+ }
+
+ /* set file attributes:
+ The default for newly created directories is "DIR attribute
+ flags set", so there is no need to change attributes unless
+ one of the DOS style attribute flags is set. The readonly
+ attribute need not be masked, since it does not prevent
+ modifications in the new directory. */
+ if(G.pInfo->file_attr & (0x7F & ~FILE_ATTRIBUTE_DIRECTORY)) {
+ if (!SetFileAttributes(Ansi_Fname, G.pInfo->file_attr & 0x7F))
+ Info(slide, 1, ((char *)slide,
+ "\nwarning (%d): could not set file attributes for %s\n",
+ (int)GetLastError(), G.filename));
+ }
+
+#ifdef NTSD_EAS
+ /* set extra fields, both stored-in-zipfile and .LONGNAME flavors */
+ if (G.extra_field) { /* zipfile e.f. may have extended attribs */
+ int err = EvalExtraFields(__G__ G.filename, G.extra_field,
+ G.lrec.extra_field_length);
+
+ if (err == IZ_EF_TRUNC) {
+ if (uO.qflag)
+ Info(slide, 1, ((char *)slide, "%-22s ",
+ FnFilter1(G.filename)));
+ Info(slide, 1, ((char *)slide, LoadFarString(TruncNTSD),
+ makeword(G.extra_field+2)-10, uO.qflag? "\n":""));
+ }
+ }
+#endif /* NTSD_EAS */
+ return IZ_CREATED_DIR; /* set dir time (note trailing '/') */
+ }
+ return 2; /* dir existed already; don't look for data to extract */
+ }
+
+ if (*pathcomp == '\0') {
+ Info(slide, 1, ((char *)slide, "mapname: conversion of %s failed\n",
+ FnFilter1(G.filename)));
+ return 3;
+ }
+
+ checkdir(__G__ pathcomp, APPEND_NAME); /* returns 1 if truncated: care? */
+ checkdir(__G__ G.filename, GETPATH);
+ Trace((stderr, "mapname returns with filename = [%s] (error = %d)\n\n",
+ FnFilter1(G.filename), error));
+
+ if (G.pInfo->vollabel) { /* set the volume label now */
+ char drive[4];
+#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */
+ char *ansi_name = (char *)alloca(strlen(G.filename) + 1);
+ INTERN_TO_ISO(G.filename, ansi_name);
+# define Ansi_Fname ansi_name
+#else
+# define Ansi_Fname G.filename
+#endif
+
+ /* Build a drive string, e.g. "b:" */
+ drive[0] = (char)('a' + G.nLabelDrive - 1);
+ strcpy(drive + 1, ":\\");
+ if (QCOND2)
+ Info(slide, 0, ((char *)slide, "labelling %s %-22s\n", drive,
+ FnFilter1(G.filename)));
+ if (!SetVolumeLabel(drive, Ansi_Fname)) {
+ Info(slide, 1, ((char *)slide,
+ "mapname: error setting volume label\n"));
+ return 3;
+ }
+ return 2; /* success: skip the "extraction" quietly */
+#undef Ansi_Fname
+ }
+
+ return error;
+
+} /* end function mapname() */
+
+
+
+
+/**********************/
+/* Function map2fat() */ /* Not quite identical to OS/2 version */
+/**********************/
+
+static void map2fat(pathcomp, pEndFAT)
+ char *pathcomp, **pEndFAT;
+{
+ char *ppc = pathcomp; /* variable pointer to pathcomp */
+ char *pEnd = *pEndFAT; /* variable pointer to buildpathFAT */
+ char *pBegin = *pEndFAT; /* constant pointer to start of this comp. */
+ char *last_dot = NULL; /* last dot not converted to underscore */
+ int dotname = FALSE; /* flag: path component begins with dot */
+ /* ("." and ".." don't count) */
+ register unsigned workch; /* hold the character being tested */
+
+
+ /* Only need check those characters which are legal in NTFS but not
+ * in FAT: to get here, must already have passed through mapname.
+ * Also must truncate path component to ensure 8.3 compliance.
+ */
+ while ((workch = (uch)*ppc++) != 0) {
+ switch (workch) {
+ case '[':
+ case ']':
+ case '+':
+ case ',':
+ case ';':
+ case '=':
+ *pEnd++ = '_'; /* convert brackets to underscores */
+ break;
+
+ case '.':
+ if (pEnd == *pEndFAT) { /* nothing appended yet... */
+ if (*ppc == '\0') /* don't bother appending a */
+ break; /* "./" component to the path */
+ else if (*ppc == '.' && ppc[1] == '\0') { /* "../" */
+ *pEnd++ = '.'; /* add first dot, unchanged... */
+ ++ppc; /* skip second dot, since it will */
+ } else { /* be "added" at end of if-block */
+ *pEnd++ = '_'; /* FAT doesn't allow null filename */
+ dotname = TRUE; /* bodies, so map .exrc -> _.exrc */
+ } /* (extra '_' now, "dot" below) */
+ } else if (dotname) { /* found a second dot, but still */
+ dotname = FALSE; /* have extra leading underscore: */
+ *pEnd = '\0'; /* remove it by shifting chars */
+ pEnd = *pEndFAT + 1; /* left one space (e.g., .p1.p2: */
+ while (pEnd[1]) { /* __p1 -> _p1_p2 -> _p1.p2 when */
+ *pEnd = pEnd[1]; /* finished) [opt.: since first */
+ ++pEnd; /* two chars are same, can start */
+ } /* shifting at second position] */
+ }
+ last_dot = pEnd; /* point at last dot so far... */
+ *pEnd++ = '_'; /* convert dot to underscore for now */
+ break;
+
+ default:
+ *pEnd++ = (char)workch;
+
+ } /* end switch */
+ } /* end while loop */
+
+ *pEnd = '\0'; /* terminate buildpathFAT */
+
+ /* NOTE: keep in mind that pEnd points to the end of the path
+ * component, and *pEndFAT still points to the *beginning* of it...
+ * Also note that the algorithm does not try to get too fancy:
+ * if there are no dots already, the name either gets truncated
+ * at 8 characters or the last underscore is converted to a dot
+ * (only if more characters are saved that way). In no case is
+ * a dot inserted between existing characters.
+ */
+ if (last_dot == NULL) { /* no dots: check for underscores... */
+ char *plu = strrchr(pBegin, '_'); /* pointer to last underscore */
+
+ if (plu == NULL) { /* no dots, no underscores: truncate at 8 chars */
+ *pEndFAT += 8; /* (or could insert '.' and keep 11...?) */
+ if (*pEndFAT > pEnd)
+ *pEndFAT = pEnd; /* oops...didn't have 8 chars to truncate */
+ else
+ **pEndFAT = '\0';
+ } else if (MIN(plu - pBegin, 8) + MIN(pEnd - plu - 1, 3) > 8) {
+ last_dot = plu; /* be lazy: drop through to next if-blk */
+ } else if ((pEnd - *pEndFAT) > 8) {
+ *pEndFAT += 8; /* more fits into just basename than if */
+ **pEndFAT = '\0'; /* convert last underscore to dot */
+ } else
+ *pEndFAT = pEnd; /* whole thing fits into 8 chars or less */
+ }
+
+ if (last_dot != NULL) { /* one dot (or two, in the case of */
+ *last_dot = '.'; /* "..") is OK: put it back in */
+
+ if ((last_dot - pBegin) > 8) {
+ char *p, *q;
+ int i;
+
+ p = last_dot;
+ q = last_dot = pBegin + 8;
+ for (i = 0; (i < 4) && *p; ++i) /* too many chars in basename: */
+ *q++ = *p++; /* shift .ext left and trun- */
+ *q = '\0'; /* cate/terminate it */
+ *pEndFAT = q;
+ } else if ((pEnd - last_dot) > 4) { /* too many chars in extension */
+ *pEndFAT = last_dot + 4;
+ **pEndFAT = '\0';
+ } else
+ *pEndFAT = pEnd; /* filename is fine; point at terminating zero */
+
+ if ((last_dot - pBegin) > 0 && last_dot[-1] == ' ')
+ last_dot[-1] = '_'; /* NO blank in front of '.'! */
+ }
+} /* end function map2fat() */
+
+
+
+
+/***********************/ /* Borrowed from os2.c for UnZip 5.1. */
+/* Function checkdir() */ /* Difference: no EA stuff */
+/***********************/ /* HPFS stuff works on NTFS too */
+
+int checkdir(__G__ pathcomp, flag)
+ __GDEF
+ char *pathcomp;
+ int flag;
+/*
+ * returns: 1 - (on APPEND_NAME) truncated filename
+ * 2 - path doesn't exist, not allowed to create
+ * 3 - path doesn't exist, tried to create and failed; or
+ * path exists and is not a directory, but is supposed to be
+ * 4 - path is too long
+ * 10 - can't allocate memory for filename buffers
+ */
+{
+ /* static int rootlen = 0; */ /* length of rootpath */
+ /* static char *rootpath; */ /* user's "extract-to" directory */
+ /* static char *buildpathHPFS; */ /* full path (so far) to extracted file, */
+ /* static char *buildpathFAT; */ /* both HPFS/EA (main) and FAT versions */
+ /* static char *endHPFS; */ /* corresponding pointers to end of */
+ /* static char *endFAT; */ /* buildpath ('\0') */
+
+# define FN_MASK 7
+# define FUNCTION (flag & FN_MASK)
+
+
+
+/*---------------------------------------------------------------------------
+ APPEND_DIR: append the path component to the path being built and check
+ for its existence. If doesn't exist and we are creating directories, do
+ so for this one; else signal success or error as appropriate.
+ ---------------------------------------------------------------------------*/
+
+ if (FUNCTION == APPEND_DIR) {
+ char *p = pathcomp;
+ int too_long=FALSE;
+
+ Trace((stderr, "appending dir segment [%s]\n", pathcomp));
+ while ((*G.endHPFS = *p++) != '\0') /* copy to HPFS filename */
+ ++G.endHPFS;
+ if (!IsVolumeOldFAT(__G__ G.buildpathHPFS)) {
+ p = pathcomp;
+ while ((*G.endFAT = *p++) != '\0') /* copy to FAT filename, too */
+ ++G.endFAT;
+ } else
+ map2fat(pathcomp, &G.endFAT); /* map into FAT fn, update endFAT */
+
+ /* GRR: could do better check, see if overrunning buffer as we go:
+ * check endHPFS-buildpathHPFS after each append, set warning variable
+ * if within 20 of FILNAMSIZ; then if var set, do careful check when
+ * appending. Clear variable when begin new path. */
+
+ /* next check: need to append '/', at least one-char name, '\0' */
+ if ((G.endHPFS-G.buildpathHPFS) > FILNAMSIZ-3)
+ too_long = TRUE; /* check if extracting dir? */
+#ifdef FIX_STAT_BUG
+ /* Borland C++ 5.0 does not handle a call to stat() well if the
+ * directory does not exist (it tends to crash in strange places.)
+ * This is apparently a problem only when compiling for GUI rather
+ * than console. The code below attempts to work around this problem.
+ */
+ if (access(G.buildpathFAT, 0) != 0) {
+ if (!G.create_dirs) { /* told not to create (freshening) */
+ free(G.buildpathHPFS);
+ free(G.buildpathFAT);
+ return 2; /* path doesn't exist: nothing to do */
+ }
+ if (too_long) { /* GRR: should allow FAT extraction w/o EAs */
+ Info(slide, 1, ((char *)slide,
+ "checkdir error: path too long: %s\n",
+ FnFilter1(G.buildpathHPFS)));
+ free(G.buildpathHPFS);
+ free(G.buildpathFAT);
+ return 4; /* no room for filenames: fatal */
+ }
+ if (MKDIR(G.buildpathFAT, 0777) == -1) { /* create the directory */
+ Info(slide, 1, ((char *)slide,
+ "checkdir error: cannot create %s\n\
+ unable to process %s.\n",
+ FnFilter2(G.buildpathFAT), FnFilter1(G.filename)));
+ free(G.buildpathHPFS);
+ free(G.buildpathFAT);
+ return 3; /* path didn't exist, tried to create, failed */
+ }
+ G.created_dir = TRUE;
+ }
+#endif /* FIX_STAT_BUG */
+ if (SSTAT(G.buildpathFAT, &G.statbuf)) /* path doesn't exist */
+ {
+ if (!G.create_dirs) { /* told not to create (freshening) */
+ free(G.buildpathHPFS);
+ free(G.buildpathFAT);
+ return 2; /* path doesn't exist: nothing to do */
+ }
+ if (too_long) { /* GRR: should allow FAT extraction w/o EAs */
+ Info(slide, 1, ((char *)slide,
+ "checkdir error: path too long: %s\n",
+ FnFilter1(G.buildpathHPFS)));
+ free(G.buildpathHPFS);
+ free(G.buildpathFAT);
+ return 4; /* no room for filenames: fatal */
+ }
+ if (MKDIR(G.buildpathFAT, 0777) == -1) { /* create the directory */
+ Info(slide, 1, ((char *)slide,
+ "checkdir error: cannot create %s\n\
+ unable to process %s.\n",
+ FnFilter2(G.buildpathFAT), FnFilter1(G.filename)));
+ free(G.buildpathHPFS);
+ free(G.buildpathFAT);
+ return 3; /* path didn't exist, tried to create, failed */
+ }
+ G.created_dir = TRUE;
+ } else if (!S_ISDIR(G.statbuf.st_mode)) {
+ Info(slide, 1, ((char *)slide,
+ "checkdir error: %s exists but is not directory\n \
+ unable to process %s.\n",
+ FnFilter2(G.buildpathFAT), FnFilter1(G.filename)));
+ free(G.buildpathHPFS);
+ free(G.buildpathFAT);
+ return 3; /* path existed but wasn't dir */
+ }
+ if (too_long) {
+ Info(slide, 1, ((char *)slide,
+ "checkdir error: path too long: %s\n",
+ FnFilter1(G.buildpathHPFS)));
+ free(G.buildpathHPFS);
+ free(G.buildpathFAT);
+ return 4; /* no room for filenames: fatal */
+ }
+ *G.endHPFS++ = '/';
+ *G.endFAT++ = '/';
+ *G.endHPFS = *G.endFAT = '\0';
+ Trace((stderr, "buildpathHPFS now = [%s]\nbuildpathFAT now = [%s]\n",
+ FnFilter1(G.buildpathHPFS), FnFilter2(G.buildpathFAT)));
+ return 0;
+
+ } /* end if (FUNCTION == APPEND_DIR) */
+
+/*---------------------------------------------------------------------------
+ GETPATH: copy full FAT path to the string pointed at by pathcomp (want
+ filename to reflect name used on disk, not EAs; if full path is HPFS,
+ buildpathFAT and buildpathHPFS will be identical). Also free both paths.
+ ---------------------------------------------------------------------------*/
+
+ if (FUNCTION == GETPATH) {
+ Trace((stderr, "getting and freeing FAT path [%s]\n",
+ FnFilter1(G.buildpathFAT)));
+ Trace((stderr, "freeing HPFS path [%s]\n",
+ FnFilter1(G.buildpathHPFS)));
+ strcpy(pathcomp, G.buildpathFAT);
+ free(G.buildpathFAT);
+ free(G.buildpathHPFS);
+ G.buildpathHPFS = G.buildpathFAT = G.endHPFS = G.endFAT = NULL;
+ return 0;
+ }
+
+/*---------------------------------------------------------------------------
+ APPEND_NAME: assume the path component is the filename; append it and
+ return without checking for existence.
+ ---------------------------------------------------------------------------*/
+
+ if (FUNCTION == APPEND_NAME) {
+ char *p = pathcomp;
+ int error = 0;
+
+ Trace((stderr, "appending filename [%s]\n", FnFilter1(pathcomp)));
+ while ((*G.endHPFS = *p++) != '\0') { /* copy to HPFS filename */
+ ++G.endHPFS;
+ if ((G.endHPFS-G.buildpathHPFS) >= FILNAMSIZ) {
+ *--G.endHPFS = '\0';
+ Info(slide, 1, ((char *)slide,
+ "checkdir warning: path too long; truncating\n \
+ %s\n -> %s\n",
+ FnFilter1(G.filename), FnFilter2(G.buildpathHPFS)));
+ error = 1; /* filename truncated */
+ }
+ }
+
+ if ( G.pInfo->vollabel || !IsVolumeOldFAT(__G__ G.buildpathHPFS)) {
+ p = pathcomp;
+ while ((*G.endFAT = *p++) != '\0') /* copy to FAT filename, too */
+ ++G.endFAT;
+ } else
+ map2fat(pathcomp, &G.endFAT); /* map into FAT fn, update endFAT */
+ Trace((stderr, "buildpathHPFS: %s\nbuildpathFAT: %s\n",
+ FnFilter1(G.buildpathHPFS), FnFilter2(G.buildpathFAT)));
+
+ return error; /* could check for existence, prompt for new name... */
+
+ } /* end if (FUNCTION == APPEND_NAME) */
+
+/*---------------------------------------------------------------------------
+ INIT: allocate and initialize buffer space for the file currently being
+ extracted. If file was renamed with an absolute path, don't prepend the
+ extract-to path.
+ ---------------------------------------------------------------------------*/
+
+ if (FUNCTION == INIT) {
+ Trace((stderr, "initializing buildpathHPFS and buildpathFAT to "));
+ if ((G.buildpathHPFS = (char *)malloc(G.fnlen+G.rootlen+1)) == NULL)
+ return 10;
+ if ((G.buildpathFAT = (char *)malloc(G.fnlen+G.rootlen+1)) == NULL) {
+ free(G.buildpathHPFS);
+ return 10;
+ }
+ if (G.pInfo->vollabel) { /* use root or renamed path, but don't store */
+/* GRR: for network drives, do strchr() and return IZ_VOL_LABEL if not [1] */
+ if (G.renamed_fullpath && pathcomp[1] == ':')
+ *G.buildpathHPFS = (char)ToLower(*pathcomp);
+ else if (!G.renamed_fullpath && G.rootlen > 1 &&
+ G.rootpath[1] == ':')
+ *G.buildpathHPFS = (char)ToLower(*G.rootpath);
+ else {
+ char tmpN[MAX_PATH], *tmpP;
+ if (GetFullPathName(".", MAX_PATH, tmpN, &tmpP) > MAX_PATH)
+ { /* by definition of MAX_PATH we should never get here */
+ Info(slide, 1, ((char *)slide,
+ "checkdir warning: current dir path too long\n"));
+ return 1; /* can't get drive letter */
+ }
+ G.nLabelDrive = *tmpN - 'a' + 1;
+ *G.buildpathHPFS = (char)(G.nLabelDrive - 1 + 'a');
+ }
+ G.nLabelDrive = *G.buildpathHPFS - 'a' + 1; /* save for mapname() */
+ if (uO.volflag == 0 || *G.buildpathHPFS < 'a' /* no labels/bogus? */
+ || (uO.volflag == 1 && !isfloppy(G.nLabelDrive))) { /* !fixed */
+ free(G.buildpathHPFS);
+ free(G.buildpathFAT);
+ return IZ_VOL_LABEL; /* skipping with message */
+ }
+ *G.buildpathHPFS = '\0';
+ } else if (G.renamed_fullpath) /* pathcomp = valid data */
+ strcpy(G.buildpathHPFS, pathcomp);
+ else if (G.rootlen > 0)
+ strcpy(G.buildpathHPFS, G.rootpath);
+ else
+ *G.buildpathHPFS = '\0';
+ G.endHPFS = G.buildpathHPFS;
+ G.endFAT = G.buildpathFAT;
+ while ((*G.endFAT = *G.endHPFS) != '\0') {
+ ++G.endFAT;
+ ++G.endHPFS;
+ }
+ Trace((stderr, "[%s]\n", FnFilter1(G.buildpathHPFS)));
+ return 0;
+ }
+
+/*---------------------------------------------------------------------------
+ ROOT: if appropriate, store the path in rootpath and create it if neces-
+ sary; else assume it's a zipfile member and return. This path segment
+ gets used in extracting all members from every zipfile specified on the
+ command line. Note that under OS/2 and MS-DOS, if a candidate extract-to
+ directory specification includes a drive letter (leading "x:"), it is
+ treated just as if it had a trailing '/'--that is, one directory level
+ will be created if the path doesn't exist, unless this is otherwise pro-
+ hibited (e.g., freshening).
+ ---------------------------------------------------------------------------*/
+
+#if (!defined(SFX) || defined(SFX_EXDIR))
+ if (FUNCTION == ROOT) {
+ Trace((stderr, "initializing root path to [%s]\n",
+ FnFilter1(pathcomp)));
+ if (pathcomp == NULL) {
+ G.rootlen = 0;
+ return 0;
+ }
+ if ((G.rootlen = strlen(pathcomp)) > 0) {
+ int had_trailing_pathsep=FALSE, has_drive=FALSE, xtra=2;
+
+ if (isalpha((uch)pathcomp[0]) && pathcomp[1] == ':')
+ has_drive = TRUE; /* drive designator */
+ if (pathcomp[G.rootlen-1] == '/' || pathcomp[G.rootlen-1] == '\\') {
+ pathcomp[--G.rootlen] = '\0';
+ had_trailing_pathsep = TRUE;
+ }
+ if (has_drive && (G.rootlen == 2)) {
+ if (!had_trailing_pathsep) /* i.e., original wasn't "x:/" */
+ xtra = 3; /* room for '.' + '/' + 0 at end of "x:" */
+ } else if (G.rootlen > 0) { /* need not check "x:." and "x:/" */
+ if (SSTAT(pathcomp, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode))
+ {
+ /* path does not exist */
+ if (!G.create_dirs /* || iswild(pathcomp) */ ) {
+ G.rootlen = 0;
+ return 2; /* treat as stored file */
+ }
+ /* create directory (could add loop here to scan pathcomp
+ * and create more than one level, but really necessary?) */
+ if (MKDIR(pathcomp, 0777) == -1) {
+ Info(slide, 1, ((char *)slide,
+ "checkdir: cannot create extraction directory: %s\n",
+ FnFilter1(pathcomp)));
+ G.rootlen = 0; /* path didn't exist, tried to create, */
+ return 3; /* failed: file exists, or need 2+ levels */
+ }
+ }
+ }
+ if ((G.rootpath = (char *)malloc(G.rootlen+xtra)) == NULL) {
+ G.rootlen = 0;
+ return 10;
+ }
+ strcpy(G.rootpath, pathcomp);
+ if (xtra == 3) /* had just "x:", make "x:." */
+ G.rootpath[G.rootlen++] = '.';
+ G.rootpath[G.rootlen++] = '/';
+ G.rootpath[G.rootlen] = '\0';
+ Trace((stderr, "rootpath now = [%s]\n", FnFilter1(G.rootpath)));
+ }
+ return 0;
+ }
+#endif /* !SFX || SFX_EXDIR */
+
+/*---------------------------------------------------------------------------
+ END: free rootpath, immediately prior to program exit.
+ ---------------------------------------------------------------------------*/
+
+ if (FUNCTION == END) {
+ Trace((stderr, "freeing rootpath\n"));
+ if (G.rootlen > 0) {
+ free(G.rootpath);
+ G.rootlen = 0;
+ }
+ return 0;
+ }
+
+ return 99; /* should never reach */
+
+} /* end function checkdir() */
+
+
+
+
+
+#ifndef SFX
+#ifndef WINDLL
+
+/************************/
+/* Function version() */
+/************************/
+
+void version(__G)
+ __GDEF
+{
+ int len;
+#if (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__DJGPP__))
+ char buf[80];
+#if (defined(_MSC_VER) && (_MSC_VER > 900))
+ char buf2[80];
+#endif
+#endif
+
+ len = sprintf((char *)slide, CompiledWith,
+
+#if defined(_MSC_VER) /* MSC == VC++, but what about SDK compiler? */
+ (sprintf(buf, "Microsoft C %d.%02d ", _MSC_VER/100, _MSC_VER%100), buf),
+# if (_MSC_VER == 800)
+ "(Visual C++ v1.1)",
+# elif (_MSC_VER == 850)
+ "(Windows NT v3.5 SDK)",
+# elif (_MSC_VER == 900)
+ "(Visual C++ v2.x)",
+# elif (_MSC_VER > 900)
+ (sprintf(buf2, "(Visual C++ %d.%d)", _MSC_VER/100 - 6, _MSC_VER%100/10),
+ buf2),
+# else
+ "(bad version)",
+# endif
+#elif defined(__WATCOMC__)
+# if (__WATCOMC__ % 10 > 0)
+ (sprintf(buf, "Watcom C/C++ %d.%02d", __WATCOMC__ / 100,
+ __WATCOMC__ % 100), buf), "",
+# else
+ (sprintf(buf, "Watcom C/C++ %d.%d", __WATCOMC__ / 100,
+ (__WATCOMC__ % 100) / 10), buf), "",
+# endif
+#elif defined(__BORLANDC__)
+ "Borland C++",
+# if (__BORLANDC__ < 0x0200)
+ " 1.0",
+# elif (__BORLANDC__ == 0x0200)
+ " 2.0",
+# elif (__BORLANDC__ == 0x0400)
+ " 3.0",
+# elif (__BORLANDC__ == 0x0410) /* __BCPLUSPLUS__ = 0x0310 */
+ " 3.1",
+# elif (__BORLANDC__ == 0x0452) /* __BCPLUSPLUS__ = 0x0320 */
+ " 4.0 or 4.02",
+# elif (__BORLANDC__ == 0x0460) /* __BCPLUSPLUS__ = 0x0340 */
+ " 4.5",
+# elif (__BORLANDC__ == 0x0500) /* __BCPLUSPLUS__ = 0x0340 */
+ " 5.0",
+# elif (__BORLANDC__ == 0x0520) /* __BCPLUSPLUS__ = 0x0520 */
+ " 5.2 (C++ Builder)", /* GRR: assume this will stay sync'd? */
+# else
+ " later than 5.2",
+# endif
+#elif defined(__LCC__)
+ "LCC-Win32", "",
+#elif defined(__GNUC__)
+# if defined(__RSXNT__)
+# if (defined(__DJGPP__) && !defined(__EMX__))
+ (sprintf(buf, "rsxnt(djgpp v%d.%02d) / gcc ",
+ __DJGPP__, __DJGPP_MINOR__), buf),
+# elif defined(__DJGPP__)
+ (sprintf(buf, "rsxnt(emx+djgpp v%d.%02d) / gcc ",
+ __DJGPP__, __DJGPP_MINOR__), buf),
+# elif (defined(__GO32__) && !defined(__EMX__))
+ "rsxnt(djgpp v1.x) / gcc ",
+# elif defined(__GO32__)
+ "rsxnt(emx + djgpp v1.x) / gcc ",
+# elif defined(__EMX__)
+ "rsxnt(emx)+gcc ",
+# else
+ "rsxnt(unknown) / gcc ",
+# endif
+# elif defined(__CYGWIN32__)
+ "cygnus win32 / gcc ",
+# elif defined(__MINGW32__)
+ "mingw32 / gcc ",
+# else
+ "gcc ",
+# endif
+ __VERSION__,
+#else /* !_MSC_VER, !__WATCOMC__, !__BORLANDC__, !__LCC__, !__GNUC__ */
+ "unknown compiler (SDK?)", "",
+#endif /* ?compilers */
+
+ "Windows 95 / Windows NT", "\n(32-bit)",
+
+#ifdef __DATE__
+ " on ", __DATE__
+#else
+ "", ""
+#endif
+ );
+
+ (*G.message)((zvoid *)&G, slide, (ulg)len, 0);
+
+ return;
+
+} /* end function version() */
+
+#endif /* !WINDLL */
+#endif /* !SFX */
+
+
+
+#ifdef W32_STAT_BANDAID
+
+/* All currently known variants of WIN32 operating systems (Windows 95/98,
+ * WinNT 3.x, 4.0, 5.0) have a nasty bug in the OS kernel concerning
+ * conversions between UTC and local time: In the time conversion functions
+ * of the Win32 API, the timezone offset (including seasonal daylight saving
+ * shift) between UTC and local time evaluation is erratically based on the
+ * current system time. The correct evaluation must determine the offset
+ * value as it {was/is/will be} for the actual time to be converted.
+ *
+ * Some versions of MS C runtime lib's stat() returns utc time-stamps so
+ * that localtime(timestamp) corresponds to the (potentially false) local
+ * time shown by the OS' system programs (Explorer, command shell dir, etc.)
+ * The RSXNT port follows the same strategy, but fails to recognize the
+ * access-time attribute.
+ *
+ * For the NTFS file system (and other filesystems that store time-stamps
+ * as UTC values), this results in st_mtime (, st_{c|a}time) fields which
+ * are not stable but vary according to the seasonal change of "daylight
+ * saving time in effect / not in effect".
+ *
+ * Other C runtime libs (CygWin, or the CRT DLLs supplied with Win95/NT
+ * return the unix-time equivalent of the UTC FILETIME values as got back
+ * from the Win32 API call. This time, return values from NTFS are correct
+ * whereas utimes from files on (V)FAT volumes vary according to the DST
+ * switches.
+ *
+ * To achieve timestamp consistency of UTC (UT extra field) values in
+ * Zip archives, the Info-ZIP programs require work-around code for
+ * proper time handling in stat() (and other time handling routines).
+ */
+/* stat() functions under Windows95 tend to fail for root directories. *
+ * Watcom and Borland, at least, are affected by this bug. Watcom made *
+ * a partial fix for 11.0 but still missed some cases. This substitute *
+ * detects the case and fills in reasonable values. Otherwise we get *
+ * effects like failure to extract to a root dir because it's not found. */
+
+int zstat_win32(__W32STAT_GLOBALS__ const char *path, struct stat *buf)
+{
+ if (!stat(path, buf))
+ {
+#ifdef NT_TZBUG_WORKAROUND
+ /* stat was successful, now redo the time-stamp fetches */
+ int fs_uses_loctime = FStampIsLocTime(__G__ path);
+ HANDLE h;
+ FILETIME Modft, Accft, Creft;
+#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */
+ char *ansi_path = (char *)alloca(strlen(path) + 1);
+
+ INTERN_TO_ISO(path, ansi_path);
+# define Ansi_Path ansi_path
+#else
+# define Ansi_Path path
+#endif
+
+ TTrace((stdout, "stat(%s) finds modtime %08lx\n", path, buf->st_mtime));
+ h = CreateFile(Ansi_Path, GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (h != INVALID_HANDLE_VALUE) {
+ BOOL ftOK = GetFileTime(h, &Creft, &Accft, &Modft);
+ CloseHandle(h);
+
+ if (ftOK) {
+ FTTrace((stdout, "GetFileTime returned Modft", 0, &Modft));
+ FTTrace((stdout, "GetFileTime returned Creft", 0, &Creft));
+ if (!fs_uses_loctime) {
+ /* On a filesystem that stores UTC timestamps, we refill
+ * the time fields of the struct stat buffer by directly
+ * using the UTC values as returned by the Win32
+ * GetFileTime() API call.
+ */
+ FileTime2utime(&Modft, &(buf->st_mtime));
+ if (Accft.dwLowDateTime != 0 || Accft.dwHighDateTime != 0)
+ FileTime2utime(&Accft, &(buf->st_atime));
+ else
+ buf->st_atime = buf->st_mtime;
+ if (Creft.dwLowDateTime != 0 || Creft.dwHighDateTime != 0)
+ FileTime2utime(&Creft, &(buf->st_ctime));
+ else
+ buf->st_ctime = buf->st_mtime;
+ TTrace((stdout,"NTFS, recalculated modtime %08lx\n",
+ buf->st_mtime));
+ } else {
+ /* On VFAT and FAT-like filesystems, the FILETIME values
+ * are converted back to the stable local time before
+ * converting them to UTC unix time-stamps.
+ */
+ VFatFileTime2utime(&Modft, &(buf->st_mtime));
+ if (Accft.dwLowDateTime != 0 || Accft.dwHighDateTime != 0)
+ VFatFileTime2utime(&Accft, &(buf->st_atime));
+ else
+ buf->st_atime = buf->st_mtime;
+ if (Creft.dwLowDateTime != 0 || Creft.dwHighDateTime != 0)
+ VFatFileTime2utime(&Creft, &(buf->st_ctime));
+ else
+ buf->st_ctime = buf->st_mtime;
+ TTrace((stdout, "VFAT, recalculated modtime %08lx\n",
+ buf->st_mtime));
+ }
+ }
+ }
+# undef Ansi_Path
+#endif /* NT_TZBUG_WORKAROUND */
+ return 0;
+ }
+#ifdef W32_STATROOT_FIX
+ else
+ {
+ DWORD flags;
+#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */
+ char *ansi_path = (char *)alloca(strlen(path) + 1);
+
+ INTERN_TO_ISO(path, ansi_path);
+# define Ansi_Path ansi_path
+#else
+# define Ansi_Path path
+#endif
+
+ flags = GetFileAttributes(Ansi_Path);
+ if (flags != 0xFFFFFFFF && flags & FILE_ATTRIBUTE_DIRECTORY) {
+ Trace((stderr, "\nstat(\"%s\",...) failed on existing directory\n",
+ path));
+ memset(buf, 0, sizeof(struct stat));
+ buf->st_atime = buf->st_ctime = buf->st_mtime =
+ dos_to_unix_time(DOSTIME_MINIMUM); /* 1-1-80 */
+ buf->st_mode = S_IFDIR | S_IREAD |
+ ((flags & FILE_ATTRIBUTE_READONLY) ? 0 : S_IWRITE);
+ return 0;
+ } /* assumes: stat() won't fail on non-dirs without good reason */
+# undef Ansi_Path
+ }
+#endif /* W32_STATROOT_FIX */
+ return -1;
+}
+
+#endif /* W32_STAT_BANDAID */
+
+#endif /* !FUNZIP */
+
+
+
+#ifndef WINDLL
+/* This replacement getch() function was originally created for Watcom C
+ * and then additionally used with CYGWIN. Since UnZip 5.4, all other Win32
+ * ports apply this replacement rather that their supplied getch() (or
+ * alike) function. There are problems with unabsorbed LF characters left
+ * over in the keyboard buffer under Win95 (and 98) when ENTER was pressed.
+ * (Under Win95, ENTER returns two(!!) characters: CR-LF.) This problem
+ * does not appear when run on a WinNT console prompt!
+ */
+
+/* Watcom 10.6's getch() does not handle Alt+<digit><digit><digit>. */
+/* Note that if PASSWD_FROM_STDIN is defined, the file containing */
+/* the password must have a carriage return after the word, not a */
+/* Unix-style newline (linefeed only). This discards linefeeds. */
+
+int getch_win32(void)
+{
+ HANDLE stin;
+ DWORD rc;
+ unsigned char buf[2];
+ int ret = -1;
+ DWORD odemode = ~(DWORD)0;
+
+# ifdef PASSWD_FROM_STDIN
+ stin = GetStdHandle(STD_INPUT_HANDLE);
+# else
+ stin = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
+ if (stin == INVALID_HANDLE_VALUE)
+ return -1;
+# endif
+ if (GetConsoleMode(stin, &odemode))
+ SetConsoleMode(stin, ENABLE_PROCESSED_INPUT); /* raw except ^C noticed */
+ if (ReadFile(stin, &buf, 1, &rc, NULL) && rc == 1)
+ ret = buf[0];
+ /* when the user hits return we get CR LF. We discard the LF, not the CR,
+ * because when we call this for the first time after a previous input
+ * such as the one for "replace foo? [y]es, ..." the LF may still be in
+ * the input stream before whatever the user types at our prompt. */
+ if (ret == '\n')
+ if (ReadFile(stin, &buf, 1, &rc, NULL) && rc == 1)
+ ret = buf[0];
+ if (odemode != ~(DWORD)0)
+ SetConsoleMode(stin, odemode);
+# ifndef PASSWD_FROM_STDIN
+ CloseHandle(stin);
+# endif
+ return ret;
+}
+#endif /* !WINDLL */
diff --git a/Build/source/libs/unzip/windll/decs.h b/Build/source/libs/unzip/windll/decs.h
new file mode 100644
index 00000000000..fc11410771f
--- /dev/null
+++ b/Build/source/libs/unzip/windll/decs.h
@@ -0,0 +1,29 @@
+#ifndef __decs_h /* prevent multiple inclusions */
+#define __decs_h
+
+#include <windows.h>
+#ifndef __unzip_h
+# include "unzip.h"
+#endif
+#ifndef __structs_h
+# include "structs.h"
+#endif
+
+#define WizMatch match
+
+void WINAPI Wiz_NoPrinting(int f);
+int WINAPI Wiz_Validate(LPSTR archive, int AllCodes);
+BOOL WINAPI Wiz_Init(zvoid *, LPUSERFUNCTIONS);
+BOOL WINAPI Wiz_SetOpts(zvoid *, LPDCL);
+int WINAPI Wiz_Unzip(zvoid *, int, char **, int, char **);
+int WINAPI Wiz_SingleEntryUnzip(int, char **, int, char **,
+ LPDCL, LPUSERFUNCTIONS);
+
+int WINAPI Wiz_UnzipToMemory(LPSTR zip, LPSTR file,
+ LPUSERFUNCTIONS lpUserFunctions,
+ UzpBuffer *retstr);
+int WINAPI Wiz_Grep(LPSTR archive, LPSTR file, LPSTR pattern,
+ int cmd, int SkipBin,
+ LPUSERFUNCTIONS lpUserFunctions);
+
+#endif /* __decs_h */
diff --git a/Build/source/libs/unzip/windll/structs.h b/Build/source/libs/unzip/windll/structs.h
new file mode 100644
index 00000000000..39a908d3e16
--- /dev/null
+++ b/Build/source/libs/unzip/windll/structs.h
@@ -0,0 +1,72 @@
+#ifndef __structs_h
+#define __structs_h
+
+#ifndef Far
+# define Far far
+#endif
+
+/* Porting definitions between Win 3.1x and Win32 */
+#ifdef WIN32
+# define far
+# define _far
+# define __far
+# define near
+# define _near
+# define __near
+# ifndef FAR
+# define FAR
+# endif
+#endif
+
+#ifndef PATH_MAX
+# define PATH_MAX 260 /* max total file or directory name path */
+#endif
+
+#ifndef DEFINED_ONCE
+#define DEFINED_ONCE
+
+typedef int (WINAPI DLLPRNT) (LPSTR, unsigned long);
+typedef int (WINAPI DLLPASSWORD) (LPSTR, int, LPCSTR, LPCSTR);
+typedef int (WINAPI DLLSERVICE) (LPCSTR, unsigned long);
+#endif
+typedef void (WINAPI DLLSND) (void);
+typedef int (WINAPI DLLREPLACE)(LPSTR);
+typedef void (WINAPI DLLMESSAGE)(unsigned long, unsigned long, unsigned,
+ unsigned, unsigned, unsigned, unsigned, unsigned,
+ char, LPSTR, LPSTR, unsigned long, char);
+
+typedef struct {
+DLLPRNT *print;
+DLLSND *sound;
+DLLREPLACE *replace;
+DLLPASSWORD *password;
+DLLMESSAGE *SendApplicationMessage;
+DLLSERVICE *ServCallBk;
+unsigned long TotalSizeComp;
+unsigned long TotalSize;
+int CompFactor;
+unsigned int NumMembers;
+WORD cchComment;
+} USERFUNCTIONS, far * LPUSERFUNCTIONS;
+
+typedef struct {
+int ExtractOnlyNewer;
+int SpaceToUnderscore;
+int PromptToOverwrite;
+int fQuiet;
+int ncflag;
+int ntflag;
+int nvflag;
+int nUflag;
+int nzflag;
+int ndflag;
+int noflag;
+int naflag;
+int nZIflag;
+int C_flag;
+int fPrivilege;
+LPSTR lpszZipFN;
+LPSTR lpszExtractDir;
+} DCL, far * LPDCL;
+
+#endif /* __structs_h */
diff --git a/Build/source/libs/unzip/windll/unzver.h b/Build/source/libs/unzip/windll/unzver.h
new file mode 100644
index 00000000000..d216ec225fa
--- /dev/null
+++ b/Build/source/libs/unzip/windll/unzver.h
@@ -0,0 +1,15 @@
+/*
+ Copyright (c) 1990-2000 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 2000-Apr-09 or later
+ (the contents of which are also included in unzip.h) for terms of use.
+ If, for some reason, these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+#ifndef __unzver_h /* prevent multiple inclusions */
+#define __unzver_h
+
+#define UNZ_DLL_VERSION "5.41\0"
+#define COMPANY_NAME "Info-ZIP\0"
+
+#endif /* __unzver_h */
diff --git a/Build/source/libs/unzip/windll/windll.c b/Build/source/libs/unzip/windll/windll.c
new file mode 100644
index 00000000000..ced6d5d6b4b
--- /dev/null
+++ b/Build/source/libs/unzip/windll/windll.c
@@ -0,0 +1,744 @@
+/*
+ Copyright (C) 1996 Mike White
+ Permission is granted to any individual or institution to use, copy, or
+ redistribute this software so long as all of the original files are included,
+ that it is not sold for profit, and that this copyright notice is retained.
+
+*/
+/* Windows Info-ZIP Unzip DLL module
+ *
+ * Author: Mike White
+ *
+ * Original: 1996
+ *
+ * This module has the entry points for "unzipping" a zip file.
+ */
+
+/*---------------------------------------------------------------------------
+
+ This file is the WINDLL replacement for the generic ``main program source
+ file'' unzip.c.
+
+ See the general comments in the header part of unzip.c.
+
+ Copyrights: see accompanying file "COPYING" in UnZip source distribution.
+ (This software is free but NOT IN THE PUBLIC DOMAIN. There
+ are some restrictions on commercial use.)
+
+ ---------------------------------------------------------------------------*/
+
+#include <windows.h>
+#ifdef __RSXNT__
+# include "win32/rsxntwin.h"
+#endif
+#ifdef __BORLANDC__
+#include <dir.h>
+#endif
+#define UNZIP_INTERNAL
+#include "unzip.h"
+#include "crypt.h"
+#include "version.h"
+#include "windll.h"
+#include "structs.h"
+#include "consts.h"
+
+/* Added type casts to prevent potential "type mismatch" error messages. */
+#ifdef REENTRANT
+# undef __G
+# undef __G__
+# define __G (Uz_Globs *)pG
+# define __G__ (Uz_Globs *)pG,
+#endif
+
+HANDLE hwildZipFN;
+HANDLE hInst; /* current instance */
+HANDLE hDCL;
+int fNoPrinting = 0;
+extern jmp_buf dll_error_return;
+
+/* For displaying status messages and error messages */
+static int UZ_EXP DllMessagePrint(zvoid *pG, uch *buf, ulg size, int flag);
+
+#if 0 /* currently unused */
+/* For displaying files extracted to the display window */
+int DllDisplayPrint(zvoid *pG, uch *buf, ulg size, int flag);
+#endif /* never */
+
+/* Callback function for status report and/or user interception */
+static int UZ_EXP Wiz_StatReportCB(zvoid *pG, int fnflag, ZCONST char *zfn,
+ ZCONST char *efn, ZCONST zvoid *details);
+
+/* Dummy sound function for those applications that don't use sound */
+static void WINAPI DummySound(void);
+
+#ifndef UNZIPLIB
+/* DLL Entry Point */
+
+#ifdef __BORLANDC__
+#pragma argsused
+/* Borland seems to want DllEntryPoint instead of DllMain like MSVC */
+#define DllMain DllEntryPoint
+#endif
+#ifdef WIN32
+BOOL WINAPI DllMain( HINSTANCE hInstance,
+ DWORD dwReason,
+ LPVOID plvReserved)
+#else
+int FAR PASCAL LibMain( HINSTANCE hInstance,
+ WORD wDataSegment,
+ WORD wHeapSize,
+ LPSTR lpszCmdLine )
+#endif
+{
+#ifndef WIN32
+/* The startup code for the DLL initializes the local heap(if there is one)
+ * with a call to LocalInit which locks the data segment.
+ */
+
+if ( wHeapSize != 0 )
+ {
+ UnlockData( 0 );
+ }
+hInst = hInstance;
+return 1; /* Indicate that the DLL was initialized successfully. */
+#else
+BOOL rc = TRUE;
+switch( dwReason )
+ {
+ case DLL_PROCESS_ATTACH:
+ // DLL is loaded. Do your initialization here.
+ // If cannot init, set rc to FALSE.
+ hInst = hInstance;
+ break;
+
+ case DLL_PROCESS_DETACH:
+ // DLL is unloaded. Do your cleanup here.
+ break;
+ default:
+ break;
+ }
+return rc;
+#endif
+}
+
+#ifdef __BORLANDC__
+#pragma argsused
+#endif
+int FAR PASCAL WEP ( int bSystemExit )
+{
+return 1;
+}
+#endif /* !UNZIPLIB */
+
+/* DLL calls */
+
+/*
+ ExtractOnlyNewer = true if you are to extract only newer
+ SpaceToUnderscore = true if convert space to underscore
+ PromptToOverwrite = true if prompt to overwrite is wanted
+ fQuiet = quiet flag. 1 = few messages, 2 = no messages, 0 = all messages
+ ncflag = write to stdout if true
+ ntflag = test zip file
+ nvflag = verbose listing
+ nUflag = "update" (extract only newer/new files)
+ nzflag = display zip file comment
+ ndflag = all args are files/dir to be extracted
+ noflag = overwrite all files
+ naflag = do end-of-line translation
+ nZIflag = get Zip Info if TRUE
+ C_flag = be case insensitive if TRUE
+ fPrivilege = restore ACL's if 1, use privileges if 2
+ lpszZipFN = zip file name
+ lpszExtractDir = directory to extract to; NULL means: current directory
+*/
+
+BOOL WINAPI Wiz_SetOpts(pG, C)
+zvoid *pG;
+LPDCL C;
+{
+ uO.qflag = C->fQuiet; /* Quiet flag */
+ G.pfnames = (char **)&fnames[0]; /* assign default file name vector */
+ G.pxnames = (char **)&fnames[1];
+
+ uO.jflag = !C->ndflag;
+ uO.cflag = C->ncflag;
+ uO.overwrite_all = C->noflag;
+ uO.tflag = C->ntflag ;
+ uO.vflag = C->nvflag;
+ uO.zflag = C->nzflag;
+ uO.uflag = C->nUflag;
+ uO.aflag = C->naflag;
+ uO.C_flag = C->C_flag;
+ uO.uflag = C->ExtractOnlyNewer;
+ G.prompt_always = C->PromptToOverwrite;
+#ifdef WIN32
+ uO.X_flag = C->fPrivilege;
+#endif
+ uO.overwrite_none = !uO.overwrite_all;
+ uO.sflag = C->SpaceToUnderscore; /* Translate spaces to underscores? */
+ if (C->nZIflag)
+ {
+ uO.zipinfo_mode = TRUE;
+ uO.hflag = TRUE;
+ uO.lflag = 10;
+ uO.qflag = 2;
+ }
+ else
+ {
+ uO.zipinfo_mode = FALSE;
+ }
+
+ G.extract_flag = (!uO.zipinfo_mode &&
+ !uO.cflag && !uO.tflag && !uO.vflag && !uO.zflag
+#ifdef TIMESTAMP
+ && !uO.T_flag
+#endif
+ );
+
+ if (C->lpszExtractDir != NULL && G.extract_flag)
+ {
+#ifndef CRTL_CP_IS_ISO
+ char *pExDirRoot = (char *)malloc(strlen(C->lpszExtractDir)+1);
+
+ if (pExDirRoot == NULL)
+ return FALSE;
+ ISO_TO_INTERN(C->lpszExtractDir, pExDirRoot);
+#else
+# define pExDirRoot C->lpszExtractDir
+#endif
+ uO.exdir = pExDirRoot;
+ }
+ else
+ {
+ uO.exdir = (char *)NULL;
+ }
+
+/* G.wildzipfn needs to be initialized so that do_wild does not wind
+ up clearing out the zip file name when it returns in process.c
+*/
+ hwildZipFN = GlobalAlloc(GPTR, FILNAMSIZ);
+ if (hwildZipFN == (HGLOBAL) NULL)
+ return FALSE;
+
+ G.wildzipfn = GlobalLock(hwildZipFN);
+ lstrcpy(G.wildzipfn, C->lpszZipFN);
+ _ISO_INTERN(G.wildzipfn);
+
+ return TRUE; /* set up was OK */
+}
+
+void FreeDllMem(__GPRO)
+{
+ if (G.wildzipfn) {
+ GlobalUnlock(hwildZipFN);
+ G.wildzipfn = NULL;
+ }
+ if (hwildZipFN)
+ hwildZipFN = GlobalFree(hwildZipFN);
+
+ uO.zipinfo_mode = FALSE;
+}
+
+int WINAPI Wiz_SingleEntryUnzip(int ifnc, char **ifnv, int xfnc, char **xfnv,
+ LPDCL C, LPUSERFUNCTIONS lpUserFunc)
+{
+int retcode;
+CONSTRUCTGLOBALS();
+
+if (!Wiz_Init((zvoid *)&G, lpUserFunc))
+ {
+ DESTROYGLOBALS();
+ return PK_BADERR;
+ }
+
+if (C->lpszZipFN == NULL) /* Something has screwed up, we don't have a filename */
+ {
+ DESTROYGLOBALS();
+ return PK_NOZIP;
+ }
+
+Wiz_SetOpts((zvoid *)&G, C);
+
+#ifdef SFX
+G.zipfn = C->lpszZipFN;
+G.argv0 = C->lpszZipFN;
+#endif
+
+/* Here is the actual call to "unzip" the files (or whatever else you
+ * are doing.)
+ */
+retcode = Wiz_Unzip((zvoid *)&G, ifnc, ifnv, xfnc, xfnv);
+
+DESTROYGLOBALS();
+return retcode;
+}
+
+
+BOOL WINAPI Wiz_Init(pG, lpUserFunc)
+zvoid *pG;
+LPUSERFUNCTIONS lpUserFunc;
+{
+G.message = DllMessagePrint;
+G.statreportcb = Wiz_StatReportCB;
+if (lpUserFunc->sound == NULL)
+ lpUserFunc->sound = DummySound;
+G.lpUserFunctions = lpUserFunc;
+
+if (!G.lpUserFunctions->print ||
+ !G.lpUserFunctions->sound ||
+ !G.lpUserFunctions->replace)
+ return FALSE;
+
+return TRUE;
+}
+
+int WINAPI Wiz_Unzip(pG, ifnc, ifnv, xfnc, xfnv)
+zvoid *pG;
+int ifnc;
+char **ifnv;
+int xfnc;
+char **xfnv;
+{
+int retcode, f_cnt;
+#ifndef CRTL_CP_IS_ISO
+char **intern_ifv = NULL, **intern_xfv = NULL;
+#endif
+
+if (ifnv == (char **)NULL && ifnc != 0)
+ ifnc = 0;
+else
+ for (f_cnt = 0; f_cnt < ifnc; f_cnt++)
+ if (ifnv[f_cnt] == (char *)NULL) {
+ ifnc = f_cnt;
+ break;
+ }
+if (xfnv == (char **)NULL && xfnc != 0)
+ xfnc = 0;
+else
+ for (f_cnt = 0; f_cnt < xfnc; f_cnt++)
+ if (xfnv[f_cnt] == (char *)NULL) {
+ xfnc = f_cnt;
+ break;
+ }
+
+G.process_all_files = (ifnc == 0 && xfnc == 0); /* for speed */
+G.filespecs = ifnc;
+G.xfilespecs = xfnc;
+
+if (ifnc > 0) {
+#ifdef CRTL_CP_IS_ISO
+ G.pfnames = ifnv;
+#else /* !CRTL_CP_IS_ISO */
+ unsigned bufsize = 0;
+
+ intern_ifv = (char **)malloc((ifnc+1)*sizeof(char **));
+ if (intern_ifv == (char **)NULL)
+ {
+ FreeDllMem(__G);
+ return PK_BADERR;
+ }
+
+ for (f_cnt = ifnc; --f_cnt >= 0;)
+ bufsize += strlen(ifnv[f_cnt]) + 1;
+ intern_ifv[0] = (char *)malloc(bufsize);
+ if (intern_ifv[0] == (char *)NULL)
+ {
+ free(intern_ifv);
+ FreeDllMem(__G);
+ return PK_BADERR;
+ }
+
+ for (f_cnt = 0; ; f_cnt++)
+ {
+ ISO_TO_INTERN(ifnv[f_cnt], intern_ifv[f_cnt]);
+ if ((f_cnt+1) >= ifnc)
+ break;
+ intern_ifv[f_cnt+1] = intern_ifv[f_cnt] +
+ (strlen(intern_ifv[f_cnt]) + 1);
+ }
+ intern_ifv[ifnc] = (char *)NULL;
+ G.pfnames = intern_ifv;
+#endif /* ?CRTL_CP_IS_ISO */
+ }
+
+if (xfnc > 0) {
+#ifdef CRTL_CP_IS_ISO
+ G.pxnames = xfnv;
+#else /* !CRTL_CP_IS_ISO */
+ unsigned bufsize = 0;
+
+ intern_xfv = (char **)malloc((xfnc+1)*sizeof(char **));
+ if (intern_xfv == (char **)NULL)
+ {
+ if (ifnc > 0)
+ {
+ free(intern_ifv[0]);
+ free(intern_ifv);
+ }
+ FreeDllMem(__G);
+ return PK_BADERR;
+ }
+
+ for (f_cnt = xfnc; --f_cnt >= 0;)
+ bufsize += strlen(xfnv[f_cnt]) + 1;
+ intern_xfv[0] = (char *)malloc(bufsize);
+ if (intern_xfv[0] == (char *)NULL)
+ {
+ free(intern_xfv);
+ if (ifnc > 0)
+ {
+ free(intern_ifv[0]);
+ free(intern_ifv);
+ }
+ FreeDllMem(__G);
+ return PK_BADERR;
+ }
+
+ for (f_cnt = 0; ; f_cnt++)
+ {
+ ISO_TO_INTERN(xfnv[f_cnt], intern_xfv[f_cnt]);
+ if ((f_cnt+1) >= xfnc)
+ break;
+ intern_xfv[f_cnt+1] = intern_xfv[f_cnt] +
+ (strlen(intern_xfv[f_cnt]) + 1);
+ }
+ intern_xfv[xfnc] = (char *)NULL;
+ G.pxnames = intern_xfv;
+#endif /* ?CRTL_CP_IS_ISO */
+ }
+
+/*---------------------------------------------------------------------------
+ Okey dokey, we have everything we need to get started. Let's roll.
+ ---------------------------------------------------------------------------*/
+
+retcode = setjmp(dll_error_return);
+if (retcode)
+ {
+#ifndef CRTL_CP_IS_ISO
+ if (xfnc > 0)
+ {
+ free(intern_xfv[0]);
+ free(intern_xfv);
+ }
+ if (ifnc > 0)
+ {
+ free(intern_ifv[0]);
+ free(intern_ifv);
+ }
+#endif
+ FreeDllMem(__G);
+ return PK_BADERR;
+ }
+
+retcode = process_zipfiles(__G);
+#ifndef CRTL_CP_IS_ISO
+if (xfnc > 0)
+ {
+ free(intern_xfv[0]);
+ free(intern_xfv);
+ }
+if (ifnc > 0)
+ {
+ free(intern_ifv[0]);
+ free(intern_ifv);
+ }
+#endif
+FreeDllMem(__G);
+return retcode;
+}
+
+
+int win_fprintf(zvoid *pG, FILE *file, unsigned int size, char far *buffer)
+{
+if ((file != stderr) && (file != stdout))
+ {
+ return write(fileno(file),(char far *)(buffer),size);
+ }
+if (!fNoPrinting)
+ return G.lpUserFunctions->print((LPSTR)buffer, size);
+return (int)size;
+}
+
+/**********************************
+ * Function DllMessagePrint() *
+ * *
+ * Send messages to status window *
+ **********************************/
+#ifdef __BORLANDC__
+#pragma argsused
+#endif
+static int UZ_EXP DllMessagePrint(pG, buf, size, flag)
+ zvoid *pG; /* globals struct: always passed */
+ uch *buf; /* preformatted string to be printed */
+ ulg size; /* length of string (may include nulls) */
+ int flag; /* flag bits */
+{
+if (!fNoPrinting)
+ return G.lpUserFunctions->print((LPSTR)buf, size);
+else
+ return (int)size;
+}
+
+#if 0 /* currently unused */
+/********************************
+ * Function DllDisplayPrint() *
+ * *
+ * Send files to display window *
+ ********************************/
+#ifdef __BORLANDC__
+#pragma argsused
+#endif
+int DllDisplayPrint(pG, buf, size, flag)
+ zvoid *pG; /* globals struct: always passed */
+ uch *buf; /* preformatted string to be printed */
+ ulg size; /* length of string (may include nulls) */
+ int flag; /* flag bits */
+{
+return (!fNoPrinting ? G.lpUserFunctions->print((LPSTR)buf, size) : (int)size);
+}
+#endif /* never */
+
+
+/**********************************
+ * Function UzpPassword() *
+ * *
+ * Prompt for decryption password *
+ **********************************/
+#ifdef __BORLANDC__
+#pragma argsused
+#endif
+int UZ_EXP UzpPassword(pG, rcnt, pwbuf, size, zfn, efn)
+ zvoid *pG; /* globals struct: always passed */
+ int *rcnt; /* retry counter */
+ char *pwbuf; /* buffer for password */
+ int size; /* size of password buffer */
+ ZCONST char *zfn; /* name of zip archiv */
+ ZCONST char *efn; /* name of archiv entry being processed */
+{
+#if CRYPT
+ LPSTR m;
+
+ if (*rcnt == 0) {
+ *rcnt = 2;
+ m = "Enter password for: ";
+ } else {
+ (*rcnt)--;
+ m = "Password incorrect--reenter: ";
+ }
+
+ return (*G.lpUserFunctions->password)((LPSTR)pwbuf, size, m, (LPSTR)efn);
+#else /* !CRYPT */
+ return IZ_PW_ERROR; /* internal error, function should never get called */
+#endif /* ?CRYPT */
+} /* end function UzpPassword() */
+
+/* Turn off all messages to the calling application */
+void WINAPI Wiz_NoPrinting(int f)
+{
+fNoPrinting = f;
+}
+
+/* Dummy sound function for those applications that don't use sound */
+static void WINAPI DummySound(void)
+{
+}
+
+/* Interface between WINDLL specific service callback functions and the
+ generic DLL's "status report & user interception" callback */
+#ifdef __BORLANDC__
+#pragma argsused
+#endif
+static int WINAPI Wiz_StatReportCB(zvoid *pG, int fnflag, ZCONST char *zfn,
+ ZCONST char *efn, ZCONST zvoid *details)
+{
+ int rval = UZ_ST_CONTINUE;
+
+ switch (fnflag) {
+ case UZ_ST_START_EXTRACT:
+ if (G.lpUserFunctions->sound != NULL)
+ (*G.lpUserFunctions->sound)();
+ break;
+ case UZ_ST_FINISH_MEMBER:
+ if ((G.lpUserFunctions->ServCallBk != NULL) &&
+ (*G.lpUserFunctions->ServCallBk)(efn, *((unsigned long *)details)))
+ rval = UZ_ST_BREAK;
+ break;
+ case UZ_ST_IN_PROGRESS:
+ break;
+ default:
+ break;
+ }
+ return rval;
+}
+
+
+#ifndef SFX
+#ifndef __16BIT__
+
+int WINAPI Wiz_UnzipToMemory(LPSTR zip, LPSTR file,
+ LPUSERFUNCTIONS lpUserFunctions, UzpBuffer *retstr)
+{
+ int r;
+#ifndef CRTL_CP_IS_ISO
+ char *intern_zip, *intern_file;
+#endif
+
+ CONSTRUCTGLOBALS();
+#ifndef CRTL_CP_IS_ISO
+ intern_zip = (char *)malloc(strlen(zip)+1);
+ if (intern_zip == NULL) {
+ DESTROYGLOBALS()
+ return PK_MEM;
+ }
+ intern_file = (char *)malloc(strlen(file)+1);
+ if (intern_file == NULL) {
+ DESTROYGLOBALS()
+ free(intern_zip);
+ return PK_MEM;
+ }
+ ISO_TO_INTERN(zip, intern_zip);
+ ISO_TO_INTERN(file, intern_file);
+# define zip intern_zip
+# define file intern_file
+#endif
+ if (!Wiz_Init((zvoid *)&G, lpUserFunctions)) {
+ DESTROYGLOBALS();
+ return PK_BADERR;
+ }
+ G.redirect_data = 1;
+
+ r = (unzipToMemory(__G__ zip, file, retstr) == PK_COOL);
+
+ DESTROYGLOBALS()
+#ifndef CRTL_CP_IS_ISO
+# undef file
+# undef zip
+ free(intern_file);
+ free(intern_zip);
+#endif
+ if (!r && retstr->strlength) {
+ free(retstr->strptr);
+ retstr->strptr = NULL;
+ }
+ return r;
+}
+
+
+
+
+/* Purpose: Determine if file in archive contains the string szSearch
+
+ Parameters: archive = archive name
+ file = file contained in the archive. This cannot be
+ a wild card to be meaningful
+ pattern = string to search for
+ cmd = 0 - case-insensitive search
+ 1 - case-sensitve search
+ 2 - case-insensitive, whole words only
+ 3 - case-sensitive, whole words only
+ SkipBin = if true, skip any files that have control
+ characters other than CR, LF, or tab in the first
+ 100 characters.
+
+ Returns: TRUE if a match is found
+ FALSE if no match is found
+ -1 on error
+
+ Comments: This does not pretend to be as useful as the standard
+ Unix grep, which returns the strings associated with a
+ particular pattern, nor does it search past the first
+ matching occurrence of the pattern.
+ */
+
+int WINAPI Wiz_Grep(LPSTR archive, LPSTR file, LPSTR pattern, int cmd,
+ int SkipBin, LPUSERFUNCTIONS lpUserFunctions)
+{
+ int retcode = FALSE, compare;
+ ulg i, j, patternLen, buflen;
+ char * sz, *p;
+ UzpBuffer retstr;
+
+ /* Turn off any windows printing functions, as they may not have been
+ * identified yet. There is no requirement that we initialize the
+ * dll with printing stuff for this. */
+ Wiz_NoPrinting(TRUE);
+
+ if (!Wiz_UnzipToMemory(archive, file, lpUserFunctions, &retstr)) {
+ Wiz_NoPrinting(FALSE);
+ return -1; /* not enough memory, file not found, or other error */
+ }
+
+ if (SkipBin) {
+ if (retstr.strlength < 100)
+ buflen = retstr.strlength;
+ else
+ buflen = 100;
+ for (i = 0; i < buflen; i++) {
+ if (iscntrl(retstr.strptr[i])) {
+ if ((retstr.strptr[i] != 0x0A) &&
+ (retstr.strptr[i] != 0x0D) &&
+ (retstr.strptr[i] != 0x09))
+ {
+ /* OK, we now think we have a binary file of some sort */
+ free(retstr.strptr);
+ Wiz_NoPrinting(FALSE);
+ return FALSE;
+ }
+ }
+ }
+ }
+
+ patternLen = strlen(pattern);
+
+ if (retstr.strlength < patternLen) {
+ free(retstr.strptr);
+ Wiz_NoPrinting(FALSE);
+ return FALSE;
+ }
+
+ sz = malloc(patternLen + 3); /* add two in case doing whole words only */
+ if (cmd > 1) {
+ strcpy(sz, " ");
+ strcat(sz, pattern);
+ strcat(sz, " ");
+ } else
+ strcpy(sz, pattern);
+
+ if ((cmd == 0) || (cmd == 2)) {
+ for (i = 0; i < strlen(sz); i++)
+ sz[i] = toupper(sz[i]);
+ for (i = 0; i < retstr.strlength; i++)
+ retstr.strptr[i] = toupper(retstr.strptr[i]);
+ }
+
+ for (i = 0; i < (retstr.strlength - patternLen); i++) {
+ p = &retstr.strptr[i];
+ compare = TRUE;
+ for (j = 0; j < patternLen; j++) {
+ /* We cannot do strncmp here, as we may be dealing with a
+ * "binary" file, such as a word processing file, or perhaps
+ * even a true executable of some sort. */
+ if (p[j] != sz[j]) {
+ compare = FALSE;
+ break;
+ }
+ }
+ if (compare == TRUE) {
+ retcode = TRUE;
+ break;
+ }
+ }
+
+ free(sz);
+ free(retstr.strptr);
+ Wiz_NoPrinting(FALSE); /* Turn printing back on */
+ return retcode;
+}
+#endif /* !__16BIT__ */
+
+int WINAPI Wiz_Validate(LPSTR archive, int AllCodes)
+{
+ return UzpValidate((char *)archive, AllCodes);
+}
+
+#endif /* !SFX */
diff --git a/Build/source/libs/unzip/windll/windll.h b/Build/source/libs/unzip/windll/windll.h
new file mode 100644
index 00000000000..a32623b5960
--- /dev/null
+++ b/Build/source/libs/unzip/windll/windll.h
@@ -0,0 +1,46 @@
+#ifndef __windll_h /* prevent multiple inclusions */
+#define __windll_h
+
+#include <windows.h>
+#include <assert.h> /* required for all Windows applications */
+#include <setjmp.h>
+#include <commdlg.h>
+#if (!defined(__RSXNT__) && !defined(__MINGW32__))
+# include <dlgs.h>
+#endif
+#define UNZIP_INTERNAL
+#include "unzip.h"
+#include "structs.h"
+#include "decs.h"
+
+#ifndef MSWIN
+# define MSWIN
+#endif
+
+/* Allow compilation under Borland C++ also */
+#ifndef __based
+# define __based(A)
+#endif
+
+#ifndef PATH_MAX
+# define PATH_MAX 260 /* max total file or directory name path */
+#endif
+
+#define IDM_REPLACE_NO 100
+#define IDM_REPLACE_TEXT 101
+#define IDM_REPLACE_YES 102
+#define IDM_REPLACE_ALL 103
+#define IDM_REPLACE_NONE 104
+#define IDM_REPLACE_RENAME 105
+#define IDM_REPLACE_HELP 106
+
+extern jmp_buf dll_error_return;
+
+extern HANDLE hInst; /* current instance */
+
+#ifdef UNZIP_INTERNAL
+void FreeDllMem(__GPRO);
+int win_fprintf(zvoid *pG, FILE *file, unsigned int, char far *);
+#endif
+
+#endif /* __windll_h */
diff --git a/Build/source/libs/unzip/windll/windll.rc b/Build/source/libs/unzip/windll/windll.rc
new file mode 100644
index 00000000000..4e9218ff022
--- /dev/null
+++ b/Build/source/libs/unzip/windll/windll.rc
@@ -0,0 +1,40 @@
+#include <windows.h>
+#if (defined(WIN32) && !defined(__EMX__) && !defined(__MINGW32__))
+#include <winver.h>
+#endif
+#include "../windll/unzver.h"
+
+VS_VERSION_INFO VERSIONINFO
+FILEVERSION 1,1,0,0
+PRODUCTVERSION 3,0,0,0
+FILEFLAGSMASK 0x3L
+FILEOS VOS__WINDOWS32
+FILETYPE VFT_DLL
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+#ifdef _UNICODE
+ BLOCK "040904B0"
+#else
+ BLOCK "040904E4"
+#endif
+ BEGIN
+ VALUE "CompanyName", COMPANY_NAME
+ VALUE "FileDescription", "Info-ZIP's UnZip DLL for Win32\0"
+ VALUE "FileVersion", UNZ_DLL_VERSION
+ VALUE "InternalName", "UnZip32\0"
+ VALUE "LegalCopyright", "Info-ZIP 1996-2000\0"
+ VALUE "OriginalFilename", "UNZIP32.DLL\0"
+ VALUE "ProductName", "Info-ZIP's UnZip Windows DLL\0"
+ VALUE "ProductVersion", UNZ_DLL_VERSION
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+#ifdef _UNICODE
+ VALUE "Translation", 0x409, 1200
+#else
+ VALUE "Translation", 0x409, 1252
+#endif
+ END
+END
diff --git a/Build/source/libs/unzip/zip.h b/Build/source/libs/unzip/zip.h
new file mode 100644
index 00000000000..5c079467f7a
--- /dev/null
+++ b/Build/source/libs/unzip/zip.h
@@ -0,0 +1,15 @@
+/* This is a dummy zip.h to allow the source files shared with Zip (crypt.c,
+ crc32.c, crctab.c, ttyio.c) to compile for UnZip. */
+
+#ifndef __zip_h /* don't include more than once */
+#define __zip_h
+
+#define UNZIP_INTERNAL
+#include "unzip.h"
+
+#define local static
+
+#define ZE_MEM PK_MEM
+#define ziperr(c, h) return
+
+#endif /* !__zip_h */
diff --git a/Build/source/libs/unzip/zipinfo.c b/Build/source/libs/unzip/zipinfo.c
new file mode 100644
index 00000000000..c244c1e92f5
--- /dev/null
+++ b/Build/source/libs/unzip/zipinfo.c
@@ -0,0 +1,1912 @@
+/*---------------------------------------------------------------------------
+
+ zipinfo.c Greg Roelofs et al.
+
+ This file contains all of the ZipInfo-specific listing routines for UnZip.
+
+ Contains: zi_opts()
+ zi_end_central()
+ zipinfo()
+ zi_long()
+ zi_short()
+ zi_time()
+
+ ---------------------------------------------------------------------------*/
+
+
+#define UNZIP_INTERNAL
+#include "unzip.h"
+
+
+#ifndef NO_ZIPINFO /* strings use up too much space in small-memory systems */
+
+/* Define OS-specific attributes for use on ALL platforms--the S_xxxx
+ * versions of these are defined differently (or not defined) by different
+ * compilers and operating systems. */
+
+#define UNX_IFMT 0170000 /* Unix file type mask */
+#define UNX_IFDIR 0040000 /* Unix directory */
+#define UNX_IFREG 0100000 /* Unix regular file */
+#define UNX_IFSOCK 0140000 /* Unix socket (BSD, not SysV or Amiga) */
+#define UNX_IFLNK 0120000 /* Unix symbolic link (not SysV, Amiga) */
+#define UNX_IFBLK 0060000 /* Unix block special (not Amiga) */
+#define UNX_IFCHR 0020000 /* Unix character special (not Amiga) */
+#define UNX_IFIFO 0010000 /* Unix fifo (BCC, not MSC or Amiga) */
+#define UNX_ISUID 04000 /* Unix set user id on execution */
+#define UNX_ISGID 02000 /* Unix set group id on execution */
+#define UNX_ISVTX 01000 /* Unix directory permissions control */
+#define UNX_ENFMT UNX_ISGID /* Unix record locking enforcement flag */
+#define UNX_IRWXU 00700 /* Unix read, write, execute: owner */
+#define UNX_IRUSR 00400 /* Unix read permission: owner */
+#define UNX_IWUSR 00200 /* Unix write permission: owner */
+#define UNX_IXUSR 00100 /* Unix execute permission: owner */
+#define UNX_IRWXG 00070 /* Unix read, write, execute: group */
+#define UNX_IRGRP 00040 /* Unix read permission: group */
+#define UNX_IWGRP 00020 /* Unix write permission: group */
+#define UNX_IXGRP 00010 /* Unix execute permission: group */
+#define UNX_IRWXO 00007 /* Unix read, write, execute: other */
+#define UNX_IROTH 00004 /* Unix read permission: other */
+#define UNX_IWOTH 00002 /* Unix write permission: other */
+#define UNX_IXOTH 00001 /* Unix execute permission: other */
+
+#define VMS_IRUSR UNX_IRUSR /* VMS read/owner */
+#define VMS_IWUSR UNX_IWUSR /* VMS write/owner */
+#define VMS_IXUSR UNX_IXUSR /* VMS execute/owner */
+#define VMS_IRGRP UNX_IRGRP /* VMS read/group */
+#define VMS_IWGRP UNX_IWGRP /* VMS write/group */
+#define VMS_IXGRP UNX_IXGRP /* VMS execute/group */
+#define VMS_IROTH UNX_IROTH /* VMS read/other */
+#define VMS_IWOTH UNX_IWOTH /* VMS write/other */
+#define VMS_IXOTH UNX_IXOTH /* VMS execute/other */
+
+#define AMI_IFMT 06000 /* Amiga file type mask */
+#define AMI_IFDIR 04000 /* Amiga directory */
+#define AMI_IFREG 02000 /* Amiga regular file */
+#define AMI_IHIDDEN 00200 /* to be supported in AmigaDOS 3.x */
+#define AMI_ISCRIPT 00100 /* executable script (text command file) */
+#define AMI_IPURE 00040 /* allow loading into resident memory */
+#define AMI_IARCHIVE 00020 /* not modified since bit was last set */
+#define AMI_IREAD 00010 /* can be opened for reading */
+#define AMI_IWRITE 00004 /* can be opened for writing */
+#define AMI_IEXECUTE 00002 /* executable image, a loadable runfile */
+#define AMI_IDELETE 00001 /* can be deleted */
+
+#define LFLAG 3 /* short "ls -l" type listing */
+
+static int zi_long OF((__GPRO__ ulg *pEndprev));
+static int zi_short OF((__GPRO));
+static void zi_showMacTypeCreator
+ OF((__GPRO__ uch *ebfield));
+static char *zi_time OF((__GPRO__ ZCONST ulg *datetimez,
+ ZCONST time_t *modtimez, char *d_t_str));
+
+
+/**********************************************/
+/* Strings used in zipinfo.c (ZipInfo half) */
+/**********************************************/
+
+static char nullStr[] = "";
+
+static ZCONST char Far LongHeader[] = "Archive: %s %ld bytes %d file%s\n";
+static ZCONST char Far ShortHeader[] = "Archive: %s %ld %d\n";
+static ZCONST char Far EndCentDirRec[] = "\nEnd-of-central-directory record:\n";
+static ZCONST char Far LineSeparators[] = "-------------------------------\n\n";
+static ZCONST char Far ActOffsetCentDir[] = "\
+ Actual offset of end-of-central-dir record: %9ld (%.8lXh)\n\
+ Expected offset of end-of-central-dir record: %9ld (%.8lXh)\n\
+ (based on the length of the central directory and its expected offset)\n\n";
+static ZCONST char Far SinglePartArchive1[] = "\
+ This zipfile constitutes the sole disk of a single-part archive; its\n\
+ central directory contains %u %s. The central directory is %lu\n\
+ (%.8lXh) bytes long, and its (expected) offset in bytes from the\n";
+static ZCONST char Far SinglePartArchive2[] = "\
+ beginning of the zipfile is %lu (%.8lXh).\n\n";
+static ZCONST char Far MultiPartArchive1[] = "\
+ This zipfile constitutes disk %u of a multi-part archive. The central\n\
+ directory starts on disk %u; %u of its entries %s contained within\n";
+static ZCONST char Far MultiPartArchive2[] = "\
+ this zipfile, out of a total of %u %s. The entire central\n\
+ directory is %lu (%.8lXh) bytes long, and its offset in bytes from\n";
+static ZCONST char Far MultiPartArchive3[] = "\
+ the beginning of the zipfile in which it begins is %lu (%.8lXh).\n\n";
+static ZCONST char Far NoZipfileComment[] = " There is no zipfile comment.\n";
+static ZCONST char Far ZipfileCommentDesc[] =
+ " The zipfile comment is %u bytes long and contains the following text:\n\n";
+static ZCONST char Far ZipfileCommBegin[] =
+ "======================== zipfile comment begins ==========================\n";
+static ZCONST char Far ZipfileCommEnd[] =
+ "========================= zipfile comment ends ===========================\n";
+static ZCONST char Far ZipfileCommTrunc2[] = "\n The zipfile comment is truncated.\n";
+static ZCONST char Far ZipfileCommTruncMsg[] =
+ "\ncaution: zipfile comment truncated\n";
+
+static ZCONST char Far CentralDirEntry[] =
+ "\nCentral directory entry #%d:\n---------------------------\n\n";
+static ZCONST char Far ZipfileStats[] =
+ "%d file%s, %lu bytes uncompressed, %lu bytes compressed: %s%d.%d%%\n";
+
+/* zi_long() strings */
+static ZCONST char Far OS_FAT[] = "MS-DOS, OS/2 or NT FAT";
+static ZCONST char Far OS_Amiga[] = "Amiga";
+static ZCONST char Far OS_VMS[] = "VMS";
+static ZCONST char Far OS_Unix[] = "Unix";
+static ZCONST char Far OS_VMCMS[] = "VM/CMS";
+static ZCONST char Far OS_AtariST[] = "Atari ST";
+static ZCONST char Far OS_HPFS[] = "OS/2 or NT HPFS";
+static ZCONST char Far OS_Macintosh[] = "Macintosh HFS";
+static ZCONST char Far OS_ZSystem[] = "Z-System";
+static ZCONST char Far OS_CPM[] = "CP/M";
+static ZCONST char Far OS_TOPS20[] = "TOPS-20";
+static ZCONST char Far OS_NTFS[] = "NTFS";
+static ZCONST char Far OS_QDOS[] = "SMS/QDOS";
+static ZCONST char Far OS_Acorn[] = "Acorn RISC OS";
+static ZCONST char Far OS_MVS[] = "MVS";
+static ZCONST char Far OS_VFAT[] = "Win32 VFAT";
+static ZCONST char Far OS_BeOS[] = "BeOS";
+static ZCONST char Far OS_Tandem[] = "Tandem NSK";
+
+static ZCONST char Far MthdNone[] = "none (stored)";
+static ZCONST char Far MthdShrunk[] = "shrunk";
+static ZCONST char Far MthdRedF1[] = "reduced (factor 1)";
+static ZCONST char Far MthdRedF2[] = "reduced (factor 2)";
+static ZCONST char Far MthdRedF3[] = "reduced (factor 3)";
+static ZCONST char Far MthdRedF4[] = "reduced (factor 4)";
+static ZCONST char Far MthdImplode[] = "imploded";
+static ZCONST char Far MthdToken[] = "tokenized";
+static ZCONST char Far MthdDeflate[] = "deflated";
+static ZCONST char Far MthdEnDeflate[] = "deflated (enhanced)";
+static ZCONST char Far MthdDCLImplode[] = "imploded (PK DCL)";
+
+static ZCONST char Far DeflNorm[] = "normal";
+static ZCONST char Far DeflMax[] = "maximum";
+static ZCONST char Far DeflFast[] = "fast";
+static ZCONST char Far DeflSFast[] = "superfast";
+
+static ZCONST char Far ExtraBytesPreceding[] =
+ " There are an extra %ld bytes preceding this file.\n\n";
+
+static ZCONST char Far UnknownNo[] = "unknown (%d)";
+
+static ZCONST char Far LocalHeaderOffset[] =
+ "\n offset of local header from start of archive: %lu (%.8lXh) bytes\n";
+static ZCONST char Far HostOS[] =
+ " file system or operating system of origin: %s\n";
+static ZCONST char Far EncodeSWVer[] =
+ " version of encoding software: %d.%d\n";
+static ZCONST char Far MinOSCompReq[] =
+ " minimum file system compatibility required: %s\n";
+static ZCONST char Far MinSWVerReq[] =
+ " minimum software version required to extract: %d.%d\n";
+static ZCONST char Far CompressMethod[] =
+ " compression method: %s\n";
+static ZCONST char Far SlideWindowSizeImplode[] =
+ " size of sliding dictionary (implosion): %cK\n";
+static ZCONST char Far ShannonFanoTrees[] =
+ " number of Shannon-Fano trees (implosion): %c\n";
+static ZCONST char Far CompressSubtype[] =
+ " compression sub-type (deflation): %s\n";
+static ZCONST char Far FileSecurity[] =
+ " file security status: %sencrypted\n";
+static ZCONST char Far ExtendedLocalHdr[] =
+ " extended local header: %s\n";
+static ZCONST char Far FileModDate[] =
+ " file last modified on (DOS date/time): %s\n";
+#ifdef USE_EF_UT_TIME
+ static ZCONST char Far UT_FileModDate[] =
+ " file last modified on (UT extra field modtime): %s %s\n";
+ static ZCONST char Far LocalTime[] = "local";
+#ifndef NO_GMTIME
+ static ZCONST char Far GMTime[] = "UTC";
+#endif
+#endif /* USE_EF_UT_TIME */
+static ZCONST char Far CRC32Value[] =
+ " 32-bit CRC value (hex): %.8lx\n";
+static ZCONST char Far CompressedFileSize[] =
+ " compressed size: %lu bytes\n";
+static ZCONST char Far UncompressedFileSize[] =
+ " uncompressed size: %lu bytes\n";
+static ZCONST char Far FilenameLength[] =
+ " length of filename: %u characters\n";
+static ZCONST char Far ExtraFieldLength[] =
+ " length of extra field: %u bytes\n";
+static ZCONST char Far FileCommentLength[] =
+ " length of file comment: %u characters\n";
+static ZCONST char Far FileDiskNum[] =
+ " disk number on which file begins: disk %u\n";
+static ZCONST char Far ApparentFileType[] =
+ " apparent file type: %s\n";
+static ZCONST char Far VMSFileAttributes[] =
+ " VMS file attributes (%06o octal): %s\n";
+static ZCONST char Far AmigaFileAttributes[] =
+ " Amiga file attributes (%06o octal): %s\n";
+static ZCONST char Far UnixFileAttributes[] =
+ " Unix file attributes (%06o octal): %s\n";
+static ZCONST char Far NonMSDOSFileAttributes[] =
+ " non-MSDOS external file attributes: %06lX hex\n";
+static ZCONST char Far MSDOSFileAttributes[] =
+ " MS-DOS file attributes (%02X hex): none\n";
+static ZCONST char Far MSDOSFileAttributesRO[] =
+ " MS-DOS file attributes (%02X hex): read-only\n";
+static ZCONST char Far MSDOSFileAttributesAlpha[] =
+ " MS-DOS file attributes (%02X hex): %s%s%s%s%s%s\n";
+
+
+static ZCONST char Far ExtraFieldTrunc[] = "\n\
+ error: EF data block (type 0x%04x) size %u exceeds remaining extra field\n\
+ space %u; block length has been truncated.\n";
+static ZCONST char Far ExtraFields[] = "\n\
+ The central-directory extra field contains:";
+static ZCONST char Far ExtraFieldType[] = "\n\
+ - A subfield with ID 0x%04x (%s) and %u data bytes";
+static ZCONST char Far efAV[] = "PKWARE AV";
+static ZCONST char Far efOS2[] = "OS/2";
+static ZCONST char Far efPKVMS[] = "PKWARE VMS";
+static ZCONST char Far efPKWin32[] = "PKWARE Win32";
+static ZCONST char Far efPKUnix[] = "PKWARE Unix";
+static ZCONST char Far efIZVMS[] = "Info-ZIP VMS";
+static ZCONST char Far efIZUnix[] = "old Info-ZIP Unix/OS2/NT";
+static ZCONST char Far efIZUnix2[] = "Unix UID/GID";
+static ZCONST char Far efTime[] = "universal time";
+static ZCONST char Far efJLMac[] = "old Info-ZIP Macintosh";
+static ZCONST char Far efMac3[] = "new Info-ZIP Macintosh";
+static ZCONST char Far efZipIt[] = "ZipIt Macintosh";
+static ZCONST char Far efZipIt2[] = "ZipIt Macintosh (short)";
+static ZCONST char Far efVMCMS[] = "VM/CMS";
+static ZCONST char Far efMVS[] = "MVS";
+static ZCONST char Far efACL[] = "OS/2 ACL";
+static ZCONST char Far efNTSD[] = "Security Descriptor";
+static ZCONST char Far efBeOS[] = "BeOS";
+static ZCONST char Far efQDOS[] = "SMS/QDOS";
+static ZCONST char Far efAOSVS[] = "AOS/VS";
+static ZCONST char Far efSpark[] = "Acorn SparkFS";
+static ZCONST char Far efMD5[] = "Fred Kantor MD5";
+static ZCONST char Far efASiUnix[] = "ASi Unix";
+static ZCONST char Far efUnknown[] = "unknown";
+
+static ZCONST char Far OS2EAs[] = ".\n\
+ The local extra field has %lu bytes of OS/2 extended attributes.\n\
+ (May not match OS/2 \"dir\" amount due to storage method)";
+static ZCONST char Far izVMSdata[] = ". The extra\n\
+ field is %s and has %lu bytes of VMS %s information%s";
+static ZCONST char Far izVMSstored[] = "stored";
+static ZCONST char Far izVMSrleenc[] = "run-length encoded";
+static ZCONST char Far izVMSdeflat[] = "deflated";
+static ZCONST char Far izVMScunknw[] = "compressed(?)";
+static ZCONST char Far *izVMScomp[4] =
+ {izVMSstored, izVMSrleenc, izVMSdeflat, izVMScunknw};
+static ZCONST char Far ACLdata[] = ".\n\
+ The local extra field has %lu bytes of access control list information";
+static ZCONST char Far NTSDData[] = ".\n\
+ The local extra field has %lu bytes of NT security descriptor data";
+static ZCONST char Far UTdata[] = ".\n\
+ The local extra field has UTC/GMT %s time%s";
+static ZCONST char Far UTmodification[] = "modification";
+static ZCONST char Far UTaccess[] = "access";
+static ZCONST char Far UTcreation[] = "creation";
+static ZCONST char Far ZipItFname[] = ".\n\
+ The Mac long filename is %s.\n";
+static ZCONST char Far Mac3data[] = ".\n\
+ The local extra field has %lu bytes of %scompressed Macintosh\n\
+ finder attributes";
+ /* MacOSdata[] is used by EF_MAC3, EF_ZIPIT, EF_ZIPIT2 and EF_JLEE e. f. */
+static ZCONST char Far MacOSdata[] = ".\n\
+ The associated file has type code `%c%c%c%c' and creator code `%c%c%c%c'";
+static ZCONST char Far MacOSdata1[] = ".\n\
+ The associated file has type code `0x%lx' and creator code `0x%lx'";
+static ZCONST char Far MacOSJLEEflags[] = "\n File is marked as %s";
+static ZCONST char Far MacOS_RF[] = "Resource-fork";
+static ZCONST char Far MacOS_DF[] = "Data-fork";
+static ZCONST char Far MacOSMAC3flags[] = ".\n\
+ File is marked as %s, File Dates are in %d Bit";
+static ZCONST char Far BeOSdata[] = ".\n\
+ The local extra field has %lu bytes of %scompressed BeOS file attributes";
+ /* The associated file has type code `%c%c%c%c' and creator code `%c%c%c%c'" */
+static ZCONST char Far QDOSdata[] = ".\n\
+ The QDOS extra field subtype is `%c%c%c%c'";
+static ZCONST char Far AOSVSdata[] = ".\n\
+ The AOS/VS extra field revision is %d.%d";
+static ZCONST char Far MD5data[] = ".\n\
+ The 128-bit MD5 signature is %s";
+#ifdef CMS_MVS
+ static ZCONST char Far VmMvsExtraField[] = ".\n\
+ The stored file open mode (FLDATA TYPE) is \"%s\"";
+ static ZCONST char Far VmMvsInvalid[] = "[invalid]";
+#endif /* CMS_MVS */
+
+static ZCONST char Far First20[] = ". The first\n 20 are: ";
+static ZCONST char Far ColonIndent[] = ":\n ";
+static ZCONST char Far efFormat[] = " %02x";
+
+static ZCONST char Far lExtraFieldType[] = "\n\
+ There %s a local extra field with ID 0x%04x (%s) and\n\
+ %u data bytes (%s).\n";
+static ZCONST char Far efIZuid[] =
+ "GMT modification/access times and Unix UID/GID";
+static ZCONST char Far efIZnouid[] = "GMT modification/access times only";
+
+
+static ZCONST char Far NoFileComment[] = "\n There is no file comment.\n";
+static ZCONST char Far FileCommBegin[] = "\n\
+------------------------- file comment begins ----------------------------\n";
+static ZCONST char Far FileCommEnd[] = "\
+-------------------------- file comment ends -----------------------------\n";
+
+/* zi_time() strings */
+static ZCONST char Far BogusFmt[] = "%03d";
+static ZCONST char Far DMYHMTime[] = "%2u-%s-%02u %02u:%02u";
+static ZCONST char Far YMDHMSTime[] = "%u %s %u %02u:%02u:%02u";
+static ZCONST char Far DecimalTime[] = "%04u%02u%02u.%02u%02u%02u";
+static ZCONST char Far YMDHMSTimeError[] = "???? ??? ?? ??:??:??";
+
+
+
+
+
+#ifndef WINDLL
+
+/************************/
+/* Function zi_opts() */
+/************************/
+
+int zi_opts(__G__ pargc, pargv)
+ int *pargc;
+ char ***pargv;
+ __GDEF
+{
+ char **argv, *s;
+ int argc, c, error=FALSE, negative=0;
+ int hflag_slmv=TRUE, hflag_2=FALSE; /* diff options => diff defaults */
+ int tflag_slm=TRUE, tflag_2v=FALSE;
+ int explicit_h=FALSE, explicit_t=FALSE;
+
+
+#ifdef MACOS
+ uO.lflag = LFLAG; /* reset default on each call */
+#endif
+ G.extract_flag = FALSE; /* zipinfo does not extract to disk */
+ argc = *pargc;
+ argv = *pargv;
+
+ while (--argc > 0 && (*++argv)[0] == '-') {
+ s = argv[0] + 1;
+ while ((c = *s++) != 0) { /* "!= 0": prevent Turbo C warning */
+ switch (c) {
+ case '-':
+ ++negative;
+ break;
+ case '1': /* shortest listing: JUST filenames */
+ if (negative)
+ uO.lflag = -2, negative = 0;
+ else
+ uO.lflag = 1;
+ break;
+ case '2': /* just filenames, plus headers if specified */
+ if (negative)
+ uO.lflag = -2, negative = 0;
+ else
+ uO.lflag = 2;
+ break;
+#ifndef CMS_MVS
+ case ('C'): /* -C: match filenames case-insensitively */
+ if (negative)
+ uO.C_flag = FALSE, negative = 0;
+ else
+ uO.C_flag = TRUE;
+ break;
+#endif /* !CMS_MVS */
+ case 'h': /* header line */
+ if (negative)
+ hflag_2 = hflag_slmv = FALSE, negative = 0;
+ else {
+ hflag_2 = hflag_slmv = explicit_h = TRUE;
+ if (uO.lflag == -1)
+ uO.lflag = 0;
+ }
+ break;
+ case 'l': /* longer form of "ls -l" type listing */
+ if (negative)
+ uO.lflag = -2, negative = 0;
+ else
+ uO.lflag = 5;
+ break;
+ case 'm': /* medium form of "ls -l" type listing */
+ if (negative)
+ uO.lflag = -2, negative = 0;
+ else
+ uO.lflag = 4;
+ break;
+#ifdef MORE
+ case 'M': /* send output through built-in "more" */
+ if (negative)
+ G.M_flag = FALSE, negative = 0;
+ else
+ G.M_flag = TRUE;
+ break;
+#endif
+ case 's': /* default: shorter "ls -l" type listing */
+ if (negative)
+ uO.lflag = -2, negative = 0;
+ else
+ uO.lflag = 3;
+ break;
+ case 't': /* totals line */
+ if (negative)
+ tflag_2v = tflag_slm = FALSE, negative = 0;
+ else {
+ tflag_2v = tflag_slm = explicit_t = TRUE;
+ if (uO.lflag == -1)
+ uO.lflag = 0;
+ }
+ break;
+ case ('T'): /* use (sortable) decimal time format */
+ if (negative)
+ uO.T_flag = FALSE, negative = 0;
+ else
+ uO.T_flag = TRUE;
+ break;
+ case 'v': /* turbo-verbose listing */
+ if (negative)
+ uO.lflag = -2, negative = 0;
+ else
+ uO.lflag = 10;
+ break;
+ case 'z': /* print zipfile comment */
+ if (negative)
+ uO.zflag = negative = 0;
+ else
+ uO.zflag = 1;
+ break;
+ case 'Z': /* ZipInfo mode: ignore */
+ break;
+ default:
+ error = TRUE;
+ break;
+ }
+ }
+ }
+ if ((argc-- == 0) || error) {
+ *pargc = argc;
+ *pargv = argv;
+ return USAGE(error);
+ }
+
+#ifdef MORE
+ if (G.M_flag && !isatty(1)) /* stdout redirected: "more" func useless */
+ G.M_flag = 0;
+#endif
+
+ /* if no listing options given (or all negated), or if only -h/-t given
+ * with individual files specified, use default listing format */
+ if ((uO.lflag < 0) || ((argc > 0) && (uO.lflag == 0)))
+ uO.lflag = LFLAG;
+
+ /* set header and totals flags to default or specified values */
+ switch (uO.lflag) {
+ case 0: /* 0: can only occur if either -t or -h explicitly given; */
+ case 2: /* therefore set both flags equal to normally false value */
+ uO.hflag = hflag_2;
+ uO.tflag = tflag_2v;
+ break;
+ case 1: /* only filenames, *always* */
+ uO.hflag = FALSE;
+ uO.tflag = FALSE;
+ uO.zflag = FALSE;
+ break;
+ case 3:
+ case 4:
+ case 5:
+ uO.hflag = ((argc > 0) && !explicit_h)? FALSE : hflag_slmv;
+ uO.tflag = ((argc > 0) && !explicit_t)? FALSE : tflag_slm;
+ break;
+ case 10:
+ uO.hflag = hflag_slmv;
+ uO.tflag = tflag_2v;
+ break;
+ }
+
+ *pargc = argc;
+ *pargv = argv;
+ return 0;
+
+} /* end function zi_opts() */
+
+#endif /* !WINDLL */
+
+
+
+
+
+/*******************************/
+/* Function zi_end_central() */
+/*******************************/
+
+int zi_end_central(__G) /* return PK-type error code */
+ __GDEF
+{
+ int error = PK_COOL;
+
+
+/*---------------------------------------------------------------------------
+ Print out various interesting things about the zipfile.
+ ---------------------------------------------------------------------------*/
+
+ /* header fits on one line, for anything up to 10GB and 10000 files: */
+ if (uO.hflag)
+ Info(slide, 0, ((char *)slide, ((int)strlen(G.zipfn) < 39)?
+ LoadFarString(LongHeader) : LoadFarString(ShortHeader), G.zipfn,
+ (long)G.ziplen, G.ecrec.total_entries_central_dir,
+ (G.ecrec.total_entries_central_dir==1)?
+ nullStr : "s"));
+
+ /* verbose format */
+ if (uO.lflag > 9) {
+ Info(slide, 0, ((char *)slide, LoadFarString(EndCentDirRec)));
+ Info(slide, 0, ((char *)slide, LoadFarString(LineSeparators)));
+
+ Info(slide, 0, ((char *)slide, LoadFarString(ActOffsetCentDir),
+ (long)G.real_ecrec_offset, (long)G.real_ecrec_offset,
+ (long)G.expect_ecrec_offset, (long)G.expect_ecrec_offset));
+
+ if (G.ecrec.number_this_disk == 0) {
+ Info(slide, 0, ((char *)slide, LoadFarString(SinglePartArchive1),
+ G.ecrec.total_entries_central_dir,
+ (G.ecrec.total_entries_central_dir == 1)? "entry" : "entries",
+ G.ecrec.size_central_directory,
+ G.ecrec.size_central_directory));
+ Info(slide, 0, ((char *)slide, LoadFarString(SinglePartArchive2),
+ G.ecrec.offset_start_central_directory,
+ G.ecrec.offset_start_central_directory));
+ } else {
+ Info(slide, 0, ((char *)slide, LoadFarString(MultiPartArchive1),
+ G.ecrec.number_this_disk + 1,
+ G.ecrec.num_disk_start_cdir + 1,
+ G.ecrec.num_entries_centrl_dir_ths_disk,
+ (G.ecrec.num_entries_centrl_dir_ths_disk == 1)? "is" : "are"));
+ Info(slide, 0, ((char *)slide, LoadFarString(MultiPartArchive2),
+ G.ecrec.total_entries_central_dir,
+ (G.ecrec.total_entries_central_dir == 1) ? "entry" : "entries",
+ G.ecrec.size_central_directory,
+ G.ecrec.size_central_directory));
+ Info(slide, 0, ((char *)slide, LoadFarString(MultiPartArchive3),
+ G.ecrec.offset_start_central_directory,
+ G.ecrec.offset_start_central_directory));
+ }
+
+ /*-----------------------------------------------------------------------
+ Get the zipfile comment, if any, and print it out. (Comment may be
+ up to 64KB long. May the fleas of a thousand camels infest the arm-
+ pits of anyone who actually takes advantage of this fact.)
+ -----------------------------------------------------------------------*/
+
+ if (!G.ecrec.zipfile_comment_length)
+ Info(slide, 0, ((char *)slide, LoadFarString(NoZipfileComment)));
+ else {
+ Info(slide, 0, ((char *)slide, LoadFarString(ZipfileCommentDesc),
+ G.ecrec.zipfile_comment_length));
+ Info(slide, 0, ((char *)slide, LoadFarString(ZipfileCommBegin)));
+ if (do_string(__G__ G.ecrec.zipfile_comment_length, DISPLAY))
+ error = PK_WARN;
+ Info(slide, 0, ((char *)slide, LoadFarString(ZipfileCommEnd)));
+ if (error)
+ Info(slide, 0, ((char *)slide,
+ LoadFarString(ZipfileCommTrunc2)));
+ } /* endif (comment exists) */
+
+ /* non-verbose mode: print zipfile comment only if requested */
+ } else if (uO.zflag && G.ecrec.zipfile_comment_length) {
+ if (do_string(__G__ G.ecrec.zipfile_comment_length, DISPLAY)) {
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(ZipfileCommTruncMsg)));
+ error = PK_WARN;
+ }
+ } /* endif (verbose) */
+
+ return error;
+
+} /* end function zi_end_central() */
+
+
+
+
+
+/************************/
+/* Function zipinfo() */
+/************************/
+
+int zipinfo(__G) /* return PK-type error code */
+ __GDEF
+{
+ int do_this_file=FALSE, error, error_in_archive=PK_COOL;
+ int *fn_matched=NULL, *xn_matched=NULL;
+ unsigned j, members=0;
+ ulg tot_csize=0L, tot_ucsize=0L;
+ ulg endprev; /* buffers end of previous entry for zi_long()'s check
+ * of extra bytes */
+
+
+/*---------------------------------------------------------------------------
+ Malloc space for check on unmatched filespecs (no big deal if one or both
+ are NULL).
+ ---------------------------------------------------------------------------*/
+
+ if (G.filespecs > 0 &&
+ (fn_matched=(int *)malloc(G.filespecs*sizeof(int))) != NULL)
+ for (j = 0; j < G.filespecs; ++j)
+ fn_matched[j] = FALSE;
+
+ if (G.xfilespecs > 0 &&
+ (xn_matched=(int *)malloc(G.xfilespecs*sizeof(int))) != NULL)
+ for (j = 0; j < G.xfilespecs; ++j)
+ xn_matched[j] = FALSE;
+
+/*---------------------------------------------------------------------------
+ Set file pointer to start of central directory, then loop through cen-
+ tral directory entries. Check that directory-entry signature bytes are
+ actually there (just a precaution), then process the entry. We know
+ the entire central directory is on this disk: we wouldn't have any of
+ this information unless the end-of-central-directory record was on this
+ disk, and we wouldn't have gotten to this routine unless this is also
+ the disk on which the central directory starts. In practice, this had
+ better be the *only* disk in the archive, but maybe someday we'll add
+ multi-disk support.
+ ---------------------------------------------------------------------------*/
+
+ uO.L_flag = FALSE; /* zipinfo mode: never convert name to lowercase */
+ G.pInfo = G.info; /* (re-)initialize, (just to make sure) */
+ G.pInfo->textmode = 0; /* so one can read on screen (is this ever used?) */
+
+ /* reset endprev for new zipfile; account for multi-part archives (?) */
+ endprev = (G.crec.relative_offset_local_header == 4L)? 4L : 0L;
+
+
+ for (j = 0; j++ < (unsigned)G.ecrec.total_entries_central_dir;) {
+ if (readbuf(__G__ G.sig, 4) == 0)
+ return PK_EOF;
+ if (strncmp(G.sig, central_hdr_sig, 4)) { /* just to make sure */
+ Info(slide, 0x401, ((char *)slide, LoadFarString(CentSigMsg), j));
+ return PK_BADERR; /* sig not found */
+ }
+ /* process_cdir_file_hdr() sets pInfo->hostnum, pInfo->lcflag, ...: */
+ if ((error = process_cdir_file_hdr(__G)) != PK_COOL)
+ return error; /* only PK_EOF defined */
+
+ if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) !=
+ PK_COOL)
+ {
+ error_in_archive = error; /* might be warning */
+ if (error > PK_WARN) /* fatal */
+ return error;
+ }
+
+ if (!G.process_all_files) { /* check if specified on command line */
+ unsigned i;
+
+ do_this_file = FALSE;
+ for (i = 0; i < G.filespecs; i++)
+ if (match(G.filename, G.pfnames[i], uO.C_flag)) {
+ do_this_file = TRUE;
+ if (fn_matched)
+ fn_matched[i] = TRUE;
+ break; /* found match, so stop looping */
+ }
+ if (do_this_file) { /* check if this is an excluded file */
+ for (i = 0; i < G.xfilespecs; i++)
+ if (match(G.filename, G.pxnames[i], uO.C_flag)) {
+ do_this_file = FALSE; /* ^-- ignore case in match */
+ if (xn_matched)
+ xn_matched[i] = TRUE;
+ break;
+ }
+ }
+ }
+
+ /*-----------------------------------------------------------------------
+ If current file was specified on command line, or if no names were
+ specified, do the listing for this file. Otherwise, get rid of the
+ file comment and go back for the next file.
+ -----------------------------------------------------------------------*/
+
+ if (G.process_all_files || do_this_file) {
+
+ switch (uO.lflag) {
+ case 1:
+ case 2:
+ fnprint(__G);
+ SKIP_(G.crec.extra_field_length)
+ SKIP_(G.crec.file_comment_length)
+ break;
+
+ case 3:
+ case 4:
+ case 5:
+ if ((error = zi_short(__G)) != PK_COOL) {
+ error_in_archive = error; /* might be warning */
+ if (error > PK_WARN) /* fatal */
+ return error;
+ }
+ break;
+
+ case 10:
+ Info(slide, 0, ((char *)slide,
+ LoadFarString(CentralDirEntry), j));
+ if ((error = zi_long(__G__ &endprev)) != PK_COOL) {
+ error_in_archive = error; /* might be warning */
+ if (error > PK_WARN) /* fatal */
+ return error;
+ }
+ break;
+
+ default:
+ SKIP_(G.crec.extra_field_length)
+ SKIP_(G.crec.file_comment_length)
+ break;
+
+ } /* end switch (lflag) */
+
+ tot_csize += G.crec.csize;
+ tot_ucsize += G.crec.ucsize;
+ if (G.crec.general_purpose_bit_flag & 1)
+ tot_csize -= 12; /* don't count encryption header */
+ ++members;
+
+#ifdef DLL
+ if ((G.statreportcb != NULL) &&
+ (*G.statreportcb)(__G__ UZ_ST_FINISH_MEMBER, G.zipfn,
+ G.filename, NULL)) {
+ if (fn_matched)
+ free((zvoid *)fn_matched);
+ if (xn_matched)
+ free((zvoid *)xn_matched);
+ return IZ_CTRLC; /* cancel operation by user request */
+ }
+#endif
+#ifdef MACOS /* MacOS is no preemptive OS, thus call event-handling by hand */
+ UserStop();
+#endif
+
+ } else { /* not listing this file */
+ SKIP_(G.crec.extra_field_length)
+ SKIP_(G.crec.file_comment_length)
+
+ } /* end if (list member?) */
+
+ } /* end for-loop (j: member files) */
+
+/*---------------------------------------------------------------------------
+ Check that we actually found requested files; if so, print totals.
+ ---------------------------------------------------------------------------*/
+
+ if (uO.tflag) {
+ char *sgn = "";
+ int cfactor = ratio(tot_ucsize, tot_csize);
+
+ if (cfactor < 0) {
+ sgn = "-";
+ cfactor = -cfactor;
+ }
+ Info(slide, 0, ((char *)slide, LoadFarString(ZipfileStats),
+ members, (members==1)? nullStr:"s", tot_ucsize,
+ tot_csize, sgn, cfactor/10, cfactor%10));
+ }
+
+/*---------------------------------------------------------------------------
+ Check for unmatched filespecs on command line and print warning if any
+ found.
+ ---------------------------------------------------------------------------*/
+
+ if (fn_matched) {
+ for (j = 0; j < G.filespecs; ++j)
+ if (!fn_matched[j])
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(FilenameNotMatched), G.pfnames[j]));
+ free((zvoid *)fn_matched);
+ }
+ if (xn_matched) {
+ for (j = 0; j < G.xfilespecs; ++j)
+ if (!xn_matched[j])
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(ExclFilenameNotMatched), G.pxnames[j]));
+ free((zvoid *)xn_matched);
+ }
+
+/*---------------------------------------------------------------------------
+ Double check that we're back at the end-of-central-directory record.
+ ---------------------------------------------------------------------------*/
+
+ if (readbuf(__G__ G.sig, 4) == 0) /* disk error? */
+ return PK_EOF;
+ if (strncmp(G.sig, end_central_sig, 4)) { /* just to make sure again */
+ Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg)));
+ error_in_archive = PK_WARN; /* didn't find sig */
+ }
+ if (members == 0 && error_in_archive <= PK_WARN)
+ error_in_archive = PK_FIND;
+
+ if (uO.lflag >= 10)
+ (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0);
+
+ return error_in_archive;
+
+} /* end function zipinfo() */
+
+
+
+
+
+/************************/
+/* Function zi_long() */
+/************************/
+
+static int zi_long(__G__ pEndprev) /* return PK-type error code */
+ __GDEF
+ ulg *pEndprev; /* for zi_long() check of extra bytes */
+{
+#ifdef USE_EF_UT_TIME
+ iztimes z_utime;
+#endif
+ int error, error_in_archive=PK_COOL;
+ ush hostnum, hostver, extnum, extver, methnum, xattr;
+ char workspace[12], attribs[22];
+ ZCONST char *varmsg_str;
+ char unkn[16];
+ static ZCONST char Far *os[NUM_HOSTS] = {
+ OS_FAT, OS_Amiga, OS_VMS, OS_Unix, OS_VMCMS, OS_AtariST, OS_HPFS,
+ OS_Macintosh, OS_ZSystem, OS_CPM, OS_TOPS20, OS_NTFS, OS_QDOS,
+ OS_Acorn, OS_VFAT, OS_MVS, OS_BeOS, OS_Tandem
+ };
+ static ZCONST char Far *method[NUM_METHODS] = {
+ MthdNone, MthdShrunk, MthdRedF1, MthdRedF2, MthdRedF3, MthdRedF4,
+ MthdImplode, MthdToken, MthdDeflate, MthdEnDeflate, MthdDCLImplode
+ };
+ static ZCONST char Far *dtypelng[4] = {
+ DeflNorm, DeflMax, DeflFast, DeflSFast
+ };
+
+
+/*---------------------------------------------------------------------------
+ Check whether there's any extra space inside the zipfile. If *pEndprev is
+ zero, it's probably a signal that OS/2 extra fields are involved (with
+ unknown compressed size). We won't worry about prepended junk here...
+ ---------------------------------------------------------------------------*/
+
+ if (G.crec.relative_offset_local_header != *pEndprev && *pEndprev > 0L) {
+ /* GRR DEBUG
+ Info(slide, 0, ((char *)slide,
+ " [crec.relative_offset_local_header = %lu, endprev = %lu]\n",
+ G.crec.relative_offset_local_header, *pEndprev));
+ */
+ Info(slide, 0, ((char *)slide, LoadFarString(ExtraBytesPreceding),
+ (long)G.crec.relative_offset_local_header - (long)(*pEndprev)));
+ }
+
+ /* calculate endprev for next time around (problem: extra fields may
+ * differ in length between local and central-directory records) */
+ *pEndprev = G.crec.relative_offset_local_header + 4L + LREC_SIZE +
+ G.crec.filename_length + G.crec.extra_field_length +
+ G.crec.file_comment_length + G.crec.csize;
+
+/*---------------------------------------------------------------------------
+ Read the extra field, if any. It may be used to get UNIX style modtime.
+ ---------------------------------------------------------------------------*/
+
+ if ((error = do_string(__G__ G.crec.extra_field_length, EXTRA_FIELD)) != 0)
+ {
+ if (G.extra_field != NULL) {
+ free(G.extra_field);
+ G.extra_field = NULL;
+ }
+ error_in_archive = error;
+ /* The premature return in case of a "fatal" error (PK_EOF) is
+ * delayed until we analyze the extra field contents.
+ * This allows us to display all the other info that has been
+ * successfully read in.
+ */
+ }
+
+/*---------------------------------------------------------------------------
+ Print out various interesting things about the compressed file.
+ ---------------------------------------------------------------------------*/
+
+ hostnum = (ush)(G.pInfo->hostnum);
+ hostver = G.crec.version_made_by[0];
+ extnum = (ush)MIN(G.crec.version_needed_to_extract[1], NUM_HOSTS);
+ extver = G.crec.version_needed_to_extract[0];
+ methnum = (ush)MIN(G.crec.compression_method, NUM_METHODS);
+
+ (*G.message)((zvoid *)&G, (uch *)" ", 2L, 0); fnprint(__G);
+
+ Info(slide, 0, ((char *)slide, LoadFarString(LocalHeaderOffset),
+ G.crec.relative_offset_local_header,
+ G.crec.relative_offset_local_header));
+
+ if (hostnum >= NUM_HOSTS) {
+ sprintf(unkn, LoadFarString(UnknownNo),
+ (int)G.crec.version_made_by[1]);
+ varmsg_str = unkn;
+ } else {
+ varmsg_str = LoadFarStringSmall(os[hostnum]);
+ }
+ Info(slide, 0, ((char *)slide, LoadFarString(HostOS), varmsg_str));
+ Info(slide, 0, ((char *)slide, LoadFarString(EncodeSWVer), hostver/10,
+ hostver%10));
+
+ if (extnum >= NUM_HOSTS) {
+ sprintf(unkn, LoadFarString(UnknownNo),
+ (int)G.crec.version_needed_to_extract[1]);
+ varmsg_str = unkn;
+ } else {
+ varmsg_str = LoadFarStringSmall(os[extnum]);
+ }
+ Info(slide, 0, ((char *)slide, LoadFarString(MinOSCompReq), varmsg_str));
+ Info(slide, 0, ((char *)slide, LoadFarString(MinSWVerReq), extver/10,
+ extver%10));
+
+ if (methnum >= NUM_METHODS) {
+ sprintf(unkn, LoadFarString(UnknownNo), G.crec.compression_method);
+ varmsg_str = unkn;
+ } else {
+ varmsg_str = LoadFarStringSmall(method[methnum]);
+ }
+ Info(slide, 0, ((char *)slide, LoadFarString(CompressMethod), varmsg_str));
+ if (methnum == IMPLODED) {
+ Info(slide, 0, ((char *)slide, LoadFarString(SlideWindowSizeImplode),
+ (G.crec.general_purpose_bit_flag & 2)? '8' : '4'));
+ Info(slide, 0, ((char *)slide, LoadFarString(ShannonFanoTrees),
+ (G.crec.general_purpose_bit_flag & 4)? '3' : '2'));
+ } else if (methnum == DEFLATED) {
+ ush dnum=(ush)((G.crec.general_purpose_bit_flag>>1) & 3);
+
+ Info(slide, 0, ((char *)slide, LoadFarString(CompressSubtype),
+ LoadFarStringSmall(dtypelng[dnum])));
+ }
+
+ Info(slide, 0, ((char *)slide, LoadFarString(FileSecurity),
+ (G.crec.general_purpose_bit_flag & 1) ? nullStr : "not "));
+ Info(slide, 0, ((char *)slide, LoadFarString(ExtendedLocalHdr),
+ (G.crec.general_purpose_bit_flag & 8) ? "yes" : "no"));
+ /* print upper 3 bits for amusement? */
+
+ /* For printing of date & time, a "char d_t_buf[21]" is required.
+ * To save stack space, we reuse the "char attribs[22]" buffer which
+ * is not used yet.
+ */
+# define d_t_buf attribs
+
+ zi_time(__G__ &G.crec.last_mod_dos_datetime, NULL, d_t_buf);
+ Info(slide, 0, ((char *)slide, LoadFarString(FileModDate), d_t_buf));
+#ifdef USE_EF_UT_TIME
+ if (G.extra_field &&
+#ifdef IZ_CHECK_TZ
+ G.tz_is_valid &&
+#endif
+ (ef_scan_for_izux(G.extra_field, G.crec.extra_field_length, 1,
+ G.crec.last_mod_dos_datetime, &z_utime, NULL)
+ & EB_UT_FL_MTIME))
+ {
+ TIMET_TO_NATIVE(z_utime.mtime) /* NOP unless MSC 7.0 or Macintosh */
+ d_t_buf[0] = (char)0; /* signal "show local time" */
+ zi_time(__G__ &G.crec.last_mod_dos_datetime, &(z_utime.mtime), d_t_buf);
+ Info(slide, 0, ((char *)slide, LoadFarString(UT_FileModDate),
+ d_t_buf, LoadFarStringSmall(LocalTime)));
+#ifndef NO_GMTIME
+ d_t_buf[0] = (char)1; /* signal "show UTC (GMT) time" */
+ zi_time(__G__ &G.crec.last_mod_dos_datetime, &(z_utime.mtime), d_t_buf);
+ Info(slide, 0, ((char *)slide, LoadFarString(UT_FileModDate),
+ d_t_buf, LoadFarStringSmall(GMTime)));
+#endif /* !NO_GMTIME */
+ }
+#endif /* USE_EF_UT_TIME */
+
+ Info(slide, 0, ((char *)slide, LoadFarString(CRC32Value), G.crec.crc32));
+ Info(slide, 0, ((char *)slide, LoadFarString(CompressedFileSize),
+ G.crec.csize));
+ Info(slide, 0, ((char *)slide, LoadFarString(UncompressedFileSize),
+ G.crec.ucsize));
+ Info(slide, 0, ((char *)slide, LoadFarString(FilenameLength),
+ G.crec.filename_length));
+ Info(slide, 0, ((char *)slide, LoadFarString(ExtraFieldLength),
+ G.crec.extra_field_length));
+ Info(slide, 0, ((char *)slide, LoadFarString(FileCommentLength),
+ G.crec.file_comment_length));
+ Info(slide, 0, ((char *)slide, LoadFarString(FileDiskNum),
+ G.crec.disk_number_start + 1));
+ Info(slide, 0, ((char *)slide, LoadFarString(ApparentFileType),
+ (G.crec.internal_file_attributes & 1)? "text"
+ : (G.crec.internal_file_attributes & 2)? "ebcdic"
+ : "binary")); /* changed to accept EBCDIC */
+#ifdef ATARI
+ printf(" external file attributes (hex): %.8lx\n",
+ G.crec.external_file_attributes);
+#endif
+ xattr = (ush)((G.crec.external_file_attributes >> 16) & 0xFFFF);
+ if (hostnum == VMS_) {
+ char *p=attribs, *q=attribs+1;
+ int i, j, k;
+
+ for (k = 0; k < 12; ++k)
+ workspace[k] = 0;
+ if (xattr & VMS_IRUSR)
+ workspace[0] = 'R';
+ if (xattr & VMS_IWUSR) {
+ workspace[1] = 'W';
+ workspace[3] = 'D';
+ }
+ if (xattr & VMS_IXUSR)
+ workspace[2] = 'E';
+ if (xattr & VMS_IRGRP)
+ workspace[4] = 'R';
+ if (xattr & VMS_IWGRP) {
+ workspace[5] = 'W';
+ workspace[7] = 'D';
+ }
+ if (xattr & VMS_IXGRP)
+ workspace[6] = 'E';
+ if (xattr & VMS_IROTH)
+ workspace[8] = 'R';
+ if (xattr & VMS_IWOTH) {
+ workspace[9] = 'W';
+ workspace[11] = 'D';
+ }
+ if (xattr & VMS_IXOTH)
+ workspace[10] = 'E';
+
+ *p++ = '(';
+ for (k = j = 0; j < 3; ++j) { /* loop over groups of permissions */
+ for (i = 0; i < 4; ++i, ++k) /* loop over perms within a group */
+ if (workspace[k])
+ *p++ = workspace[k];
+ *p++ = ','; /* group separator */
+ if (j == 0)
+ while ((*p++ = *q++) != ',')
+ ; /* system, owner perms are same */
+ }
+ *p-- = 0;
+ *p = ')'; /* overwrite last comma */
+ Info(slide, 0, ((char *)slide, LoadFarString(VMSFileAttributes), xattr,
+ attribs));
+
+ } else if (hostnum == AMIGA_) {
+ switch (xattr & AMI_IFMT) {
+ case AMI_IFDIR: attribs[0] = 'd'; break;
+ case AMI_IFREG: attribs[0] = '-'; break;
+ default: attribs[0] = '?'; break;
+ }
+ attribs[1] = (xattr & AMI_IHIDDEN)? 'h' : '-';
+ attribs[2] = (xattr & AMI_ISCRIPT)? 's' : '-';
+ attribs[3] = (xattr & AMI_IPURE)? 'p' : '-';
+ attribs[4] = (xattr & AMI_IARCHIVE)? 'a' : '-';
+ attribs[5] = (xattr & AMI_IREAD)? 'r' : '-';
+ attribs[6] = (xattr & AMI_IWRITE)? 'w' : '-';
+ attribs[7] = (xattr & AMI_IEXECUTE)? 'e' : '-';
+ attribs[8] = (xattr & AMI_IDELETE)? 'd' : '-';
+ attribs[9] = 0; /* better dlm the string */
+ Info(slide, 0, ((char *)slide, LoadFarString(AmigaFileAttributes),
+ xattr, attribs));
+
+ } else if ((hostnum != FS_FAT_) && (hostnum != FS_HPFS_) &&
+ (hostnum != FS_NTFS_) && (hostnum != FS_VFAT_) &&
+ (hostnum != ACORN_) &&
+ (hostnum != VM_CMS_) && (hostnum != MVS_))
+ { /* assume Unix-like */
+ switch ((unsigned)(xattr & UNX_IFMT)) {
+ case (unsigned)UNX_IFDIR: attribs[0] = 'd'; break;
+ case (unsigned)UNX_IFREG: attribs[0] = '-'; break;
+ case (unsigned)UNX_IFLNK: attribs[0] = 'l'; break;
+ case (unsigned)UNX_IFBLK: attribs[0] = 'b'; break;
+ case (unsigned)UNX_IFCHR: attribs[0] = 'c'; break;
+ case (unsigned)UNX_IFIFO: attribs[0] = 'p'; break;
+ case (unsigned)UNX_IFSOCK: attribs[0] = 's'; break;
+ default: attribs[0] = '?'; break;
+ }
+ attribs[1] = (xattr & UNX_IRUSR)? 'r' : '-';
+ attribs[4] = (xattr & UNX_IRGRP)? 'r' : '-';
+ attribs[7] = (xattr & UNX_IROTH)? 'r' : '-';
+
+ attribs[2] = (xattr & UNX_IWUSR)? 'w' : '-';
+ attribs[5] = (xattr & UNX_IWGRP)? 'w' : '-';
+ attribs[8] = (xattr & UNX_IWOTH)? 'w' : '-';
+
+ if (xattr & UNX_IXUSR)
+ attribs[3] = (xattr & UNX_ISUID)? 's' : 'x';
+ else
+ attribs[3] = (xattr & UNX_ISUID)? 'S' : '-'; /* S = undefined */
+ if (xattr & UNX_IXGRP)
+ attribs[6] = (xattr & UNX_ISGID)? 's' : 'x'; /* == UNX_ENFMT */
+ else
+ attribs[6] = (xattr & UNX_ISGID)? 'l' : '-';
+ if (xattr & UNX_IXOTH)
+ attribs[9] = (xattr & UNX_ISVTX)? 't' : 'x'; /* "sticky bit" */
+ else
+ attribs[9] = (xattr & UNX_ISVTX)? 'T' : '-'; /* T = undefined */
+ attribs[10] = 0;
+
+ Info(slide, 0, ((char *)slide, LoadFarString(UnixFileAttributes), xattr,
+ attribs));
+
+ } else {
+ Info(slide, 0, ((char *)slide, LoadFarString(NonMSDOSFileAttributes),
+ G.crec.external_file_attributes >> 8));
+
+ } /* endif (hostnum: external attributes format) */
+
+ if ((xattr=(ush)(G.crec.external_file_attributes & 0xFF)) == 0)
+ Info(slide, 0, ((char *)slide, LoadFarString(MSDOSFileAttributes),
+ xattr));
+ else if (xattr == 1)
+ Info(slide, 0, ((char *)slide, LoadFarString(MSDOSFileAttributesRO),
+ xattr));
+ else
+ Info(slide, 0, ((char *)slide, LoadFarString(MSDOSFileAttributesAlpha),
+ xattr, (xattr&1)? "rdo " : nullStr,
+ (xattr&2)? "hid " : nullStr,
+ (xattr&4)? "sys " : nullStr,
+ (xattr&8)? "lab " : nullStr,
+ (xattr&16)? "dir " : nullStr,
+ (xattr&32)? "arc" : nullStr));
+
+/*---------------------------------------------------------------------------
+ Analyze the extra field, if any, and print the file comment, if any (the
+ filename has already been printed, above). That finishes up this file
+ entry...
+ ---------------------------------------------------------------------------*/
+
+ if (G.crec.extra_field_length > 0) {
+ uch *ef_ptr = G.extra_field;
+ ush ef_len = G.crec.extra_field_length;
+ ush eb_id, eb_datalen;
+ ZCONST char Far *ef_fieldname;
+
+ if (error_in_archive > PK_WARN) /* fatal: can't continue */
+ /* delayed "fatal error" return from extra field reading */
+ return error;
+ if (G.extra_field == (uch *)NULL)
+ return PK_ERR; /* not consistent with crec length */
+
+ Info(slide, 0, ((char *)slide, LoadFarString(ExtraFields)));
+
+ while (ef_len >= EB_HEADSIZE) {
+ eb_id = makeword(&ef_ptr[EB_ID]);
+ eb_datalen = makeword(&ef_ptr[EB_LEN]);
+ ef_ptr += EB_HEADSIZE;
+ ef_len -= EB_HEADSIZE;
+
+ if (eb_datalen > (ush)ef_len) {
+ Info(slide, 0x421, ((char *)slide,
+ LoadFarString(ExtraFieldTrunc), eb_id, eb_datalen, ef_len));
+ eb_datalen = ef_len;
+ }
+
+ switch (eb_id) {
+ case EF_AV:
+ ef_fieldname = efAV;
+ break;
+ case EF_OS2:
+ ef_fieldname = efOS2;
+ break;
+ case EF_ACL:
+ ef_fieldname = efACL;
+ break;
+ case EF_NTSD:
+ ef_fieldname = efNTSD;
+ break;
+ case EF_PKVMS:
+ ef_fieldname = efPKVMS;
+ break;
+ case EF_IZVMS:
+ ef_fieldname = efIZVMS;
+ break;
+ case EF_PKW32:
+ ef_fieldname = efPKWin32;
+ break;
+ case EF_PKUNIX:
+ ef_fieldname = efPKUnix;
+ break;
+ case EF_IZUNIX:
+ ef_fieldname = efIZUnix;
+ if (G.crec.version_made_by[1] == UNIX_ && *pEndprev > 0L)
+ *pEndprev += 4L; /* also have UID/GID in local copy */
+ break;
+ case EF_IZUNIX2:
+ ef_fieldname = efIZUnix2;
+ if (*pEndprev > 0L)
+ *pEndprev += 4L; /* 4 byte UID/GID in local copy */
+ break;
+ case EF_TIME:
+ ef_fieldname = efTime;
+ break;
+ case EF_MAC3:
+ ef_fieldname = efMac3;
+ break;
+ case EF_JLMAC:
+ ef_fieldname = efJLMac;
+ break;
+ case EF_ZIPIT:
+ ef_fieldname = efZipIt;
+ break;
+ case EF_ZIPIT2:
+ ef_fieldname = efZipIt2;
+ break;
+ case EF_VMCMS:
+ ef_fieldname = efVMCMS;
+ break;
+ case EF_MVS:
+ ef_fieldname = efMVS;
+ break;
+ case EF_BEOS:
+ ef_fieldname = efBeOS;
+ break;
+ case EF_QDOS:
+ ef_fieldname = efQDOS;
+ break;
+ case EF_AOSVS:
+ ef_fieldname = efAOSVS;
+ break;
+ case EF_SPARK: /* from RISC OS */
+ ef_fieldname = efSpark;
+ break;
+ case EF_MD5:
+ ef_fieldname = efMD5;
+ break;
+ case EF_ASIUNIX:
+ ef_fieldname = efASiUnix;
+ break;
+ default:
+ ef_fieldname = efUnknown;
+ break;
+ }
+ Info(slide, 0, ((char *)slide, LoadFarString(ExtraFieldType),
+ eb_id, LoadFarStringSmall(ef_fieldname), eb_datalen));
+
+ /* additional, field-specific information: */
+ switch (eb_id) {
+ case EF_OS2:
+ case EF_ACL:
+ if (eb_datalen >= EB_OS2_HLEN) {
+ if (eb_id == EF_OS2)
+ ef_fieldname = OS2EAs;
+ else
+ ef_fieldname = ACLdata;
+ Info(slide, 0, ((char *)slide,
+ LoadFarString(ef_fieldname), makelong(ef_ptr)));
+ *pEndprev = 0L; /* no clue about csize of local */
+ }
+ break;
+ case EF_NTSD:
+ if (eb_datalen >= EB_NTSD_C_LEN) {
+ Info(slide, 0, ((char *)slide, LoadFarString(NTSDData),
+ makelong(ef_ptr)));
+ *pEndprev = 0L; /* no clue about csize of local */
+ }
+ break;
+ case EF_IZVMS:
+ if (eb_datalen >= 8) {
+ char *p, q[8];
+ int compr = makeword(ef_ptr+4) & 7;
+
+ *q = '\0';
+ if (compr > 3)
+ compr = 3;
+ if (strncmp((char *)ef_ptr, "VFAB", 4) == 0)
+ p = "FAB";
+ else if (strncmp((char *)ef_ptr, "VALL", 4) == 0)
+ p = "XABALL";
+ else if (strncmp((char *)ef_ptr, "VFHC", 4) == 0)
+ p = "XABFHC";
+ else if (strncmp((char *)ef_ptr, "VDAT", 4) == 0)
+ p = "XABDAT";
+ else if (strncmp((char *)ef_ptr, "VRDT", 4) == 0)
+ p = "XABRDT";
+ else if (strncmp((char *)ef_ptr, "VPRO", 4) == 0)
+ p = "XABPRO";
+ else if (strncmp((char *)ef_ptr, "VKEY", 4) == 0)
+ p = "XABKEY";
+ else if (strncmp((char *)ef_ptr, "VMSV", 4) == 0) {
+ p = "version";
+ if (eb_datalen >= 16) {
+ q[0] = ' ';
+ q[1] = '(';
+ strncpy(q+2, (char *)ef_ptr+12, 4);
+ q[6] = ')';
+ q[7] = '\0';
+ }
+ } else
+ p = "version";
+ Info(slide, 0, ((char *)slide, LoadFarString(izVMSdata),
+ LoadFarStringSmall(izVMScomp[compr]),
+ makeword(ef_ptr+6), p, q));
+ }
+ break;
+ case EF_TIME:
+ if (eb_datalen >= 1) {
+ char types[80];
+ int num = 0, len;
+
+ *types = '\0';
+ if (*ef_ptr & 1) {
+ strcpy(types, LoadFarString(UTmodification));
+ ++num;
+ }
+ if (*ef_ptr & 2) {
+ len = strlen(types);
+ if (num)
+ types[len++] = '/';
+ strcpy(types+len, LoadFarString(UTaccess));
+ ++num;
+ if (*pEndprev > 0L)
+ *pEndprev += 4L;
+ }
+ if (*ef_ptr & 4) {
+ len = strlen(types);
+ if (num)
+ types[len++] = '/';
+ strcpy(types+len, LoadFarString(UTcreation));
+ ++num;
+ if (*pEndprev > 0L)
+ *pEndprev += 4L;
+ }
+ if (num > 0)
+ Info(slide, 0, ((char *)slide,
+ LoadFarString(UTdata), types,
+ num == 1? nullStr : "s"));
+ }
+ break;
+ case EF_MAC3:
+ if (eb_datalen >= EB_MAC3_HLEN) {
+ ulg eb_uc = makelong(ef_ptr);
+ unsigned mac3_flgs = makeword(ef_ptr+EB_FLGS_OFFS);
+ unsigned eb_is_uc = mac3_flgs & EB_M3_FL_UNCMPR;
+
+ Info(slide, 0, ((char *)slide, LoadFarString(Mac3data),
+ eb_uc, eb_is_uc ? "un" : nullStr));
+ if (eb_is_uc) {
+ if (*pEndprev > 0L)
+ *pEndprev += makelong(ef_ptr);
+ } else {
+ *pEndprev = 0L; /* no clue about csize of local */
+ }
+
+ Info(slide, 0, ((char *)slide,
+ LoadFarString(MacOSMAC3flags),
+ LoadFarStringSmall(mac3_flgs & EB_M3_FL_DATFRK ?
+ MacOS_DF : MacOS_RF),
+ (mac3_flgs & EB_M3_FL_TIME64 ? 64 : 32)));
+ zi_showMacTypeCreator(__G__ &ef_ptr[6]);
+ }
+ break;
+ case EF_ZIPIT2:
+ if (eb_datalen >= 5 &&
+ strncmp((char *)ef_ptr, "ZPIT", 4) == 0) {
+
+ if (eb_datalen >= 12) {
+ zi_showMacTypeCreator(__G__ &ef_ptr[4]);
+ }
+ }
+
+ case EF_ZIPIT:
+ if (eb_datalen >= 5 &&
+ strncmp((char *)ef_ptr, "ZPIT", 4) == 0) {
+ unsigned fnlen = ef_ptr[4];
+
+ if (eb_datalen >= fnlen + (5 + 8)) {
+ uch nullchar = ef_ptr[fnlen+5];
+
+ ef_ptr[fnlen+5] = '\0'; /* terminate filename */
+ Info(slide, 0, ((char *)slide,
+ LoadFarString(ZipItFname), (char *)ef_ptr+5));
+ ef_ptr[fnlen+5] = nullchar;
+ zi_showMacTypeCreator(__G__ &ef_ptr[fnlen+5]);
+ }
+ }
+ break;
+ case EF_JLMAC:
+ if (eb_datalen >= 40 &&
+ strncmp((char *)ef_ptr, "JLEE", 4) == 0)
+ {
+ zi_showMacTypeCreator(__G__ &ef_ptr[4]);
+
+ Info(slide, 0, ((char *)slide,
+ LoadFarString(MacOSJLEEflags),
+ LoadFarStringSmall(ef_ptr[31] & 1 ?
+ MacOS_DF : MacOS_RF)));
+ }
+ break;
+#ifdef CMS_MVS
+ case EF_VMCMS:
+ case EF_MVS:
+ {
+ char type[100];
+
+ Info(slide, 0, ((char *)slide,
+ LoadFarString(VmMvsExtraField),
+ (getVMMVSexfield(type, ef_ptr-EB_HEADSIZE,
+ (unsigned)eb_datalen) > 0)?
+ type : LoadFarStringSmall(VmMvsInvalid)));
+ }
+ break;
+#endif /* CMS_MVS */
+ case EF_BEOS:
+ if (eb_datalen >= EB_BEOS_HLEN) {
+ ulg eb_uc = makelong(ef_ptr);
+ unsigned eb_is_uc =
+ *(ef_ptr+EB_FLGS_OFFS) & EB_BE_FL_UNCMPR;
+
+ Info(slide, 0, ((char *)slide, LoadFarString(BeOSdata),
+ eb_uc, eb_is_uc ? "un" : nullStr));
+ if (eb_is_uc) {
+ if (*pEndprev > 0L)
+ *pEndprev += makelong(ef_ptr);
+ } else {
+ *pEndprev = 0L; /* no clue about csize of local */
+ }
+ }
+ break;
+ case EF_QDOS:
+ if (eb_datalen >= 4) {
+ Info(slide, 0, ((char *)slide, LoadFarString(QDOSdata),
+ ef_ptr[0], ef_ptr[1], ef_ptr[2], ef_ptr[3]));
+ }
+ break;
+ case EF_AOSVS:
+ if (eb_datalen >= 5) {
+ Info(slide, 0, ((char *)slide, LoadFarString(AOSVSdata),
+ ((int)(uch)ef_ptr[4])/10, ((int)(uch)ef_ptr[4])%10));
+ }
+ break;
+ case EF_MD5:
+ if (eb_datalen >= 19) {
+ char md5[33];
+ int i;
+
+ for (i = 0; i < 16; ++i)
+ sprintf(&md5[i<<1], "%02x", ef_ptr[15-i]);
+ md5[32] = '\0';
+ Info(slide, 0, ((char *)slide, LoadFarString(MD5data),
+ md5));
+ break;
+ } /* else: fall through !! */
+ default:
+ if (eb_datalen > 0) {
+ ush i, n;
+
+ if (eb_datalen <= 24) {
+ Info(slide, 0, ((char *)slide,
+ LoadFarString(ColonIndent)));
+ n = eb_datalen;
+ } else {
+ Info(slide, 0, ((char *)slide,
+ LoadFarString(First20)));
+ n = 20;
+ }
+ for (i = 0; i < n; ++i)
+ Info(slide, 0, ((char *)slide,
+ LoadFarString(efFormat), ef_ptr[i]));
+ }
+ break;
+ }
+ (*G.message)((zvoid *)&G, (uch *)".", 1L, 0);
+
+ ef_ptr += eb_datalen;
+ ef_len -= eb_datalen;
+ }
+ (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0);
+ }
+
+ /* high bit == Unix/OS2/NT GMT times (mtime, atime); next bit == UID/GID */
+ if ((xattr = (ush)((G.crec.external_file_attributes & 0xC000) >> 12)) & 8)
+ {
+ if (hostnum == UNIX_ || hostnum == FS_HPFS_ || hostnum == FS_NTFS_)
+ {
+ Info(slide, 0, ((char *)slide, LoadFarString(lExtraFieldType),
+ "is", EF_IZUNIX, LoadFarStringSmall(efIZUnix),
+ (unsigned)(xattr&12), (xattr&4)? efIZuid : efIZnouid));
+ if (*pEndprev > 0L)
+ *pEndprev += (ulg)(xattr&12);
+ }
+ else if (hostnum == FS_FAT_ && !(xattr&4))
+ Info(slide, 0, ((char *)slide, LoadFarString(lExtraFieldType),
+ "may be", EF_IZUNIX, LoadFarStringSmall(efIZUnix), 8,
+ efIZnouid));
+ }
+
+ if (!G.crec.file_comment_length)
+ Info(slide, 0, ((char *)slide, LoadFarString(NoFileComment)));
+ else {
+ Info(slide, 0, ((char *)slide, LoadFarString(FileCommBegin)));
+ if ((error = do_string(__G__ G.crec.file_comment_length, DISPL_8)) !=
+ PK_COOL)
+ {
+ error_in_archive = error; /* might be warning */
+ if (error > PK_WARN) /* fatal */
+ return error;
+ }
+ Info(slide, 0, ((char *)slide, LoadFarString(FileCommEnd)));
+ }
+
+ return error_in_archive;
+
+} /* end function zi_long() */
+
+
+
+
+
+/*************************/
+/* Function zi_short() */
+/*************************/
+
+static int zi_short(__G) /* return PK-type error code */
+ __GDEF
+{
+#ifdef USE_EF_UT_TIME
+ iztimes z_utime;
+ time_t *z_modtim;
+#endif
+ int k, error, error_in_archive=PK_COOL;
+ ush methnum, hostnum, hostver, xattr;
+ char *p, workspace[12], attribs[16];
+ char methbuf[5];
+ static ZCONST char dtype[5]="NXFS"; /* normal, maximum, fast, superfast */
+ static ZCONST char Far os[NUM_HOSTS+1][4] = {
+ "fat", "ami", "vms", "unx", "cms", "atr", "hpf", "mac", "zzz",
+ "cpm", "t20", "ntf", "qds", "aco", "vft", "mvs", "be ", "nsk",
+ "???"
+ };
+ static ZCONST char Far method[NUM_METHODS+1][5] = {
+ "stor", "shrk", "re:1", "re:2", "re:3", "re:4", "i#:#", "tokn",
+ "def#", "edef", "dcli", "u###"
+ };
+
+
+/*---------------------------------------------------------------------------
+ Print out various interesting things about the compressed file.
+ ---------------------------------------------------------------------------*/
+
+ methnum = (ush)MIN(G.crec.compression_method, NUM_METHODS);
+ hostnum = (ush)(G.pInfo->hostnum);
+ hostver = G.crec.version_made_by[0];
+/*
+ extnum = MIN(G.crec.version_needed_to_extract[1], NUM_HOSTS);
+ extver = G.crec.version_needed_to_extract[0];
+ */
+
+ zfstrcpy(methbuf, method[methnum]);
+ if (methnum == IMPLODED) {
+ methbuf[1] = (char)((G.crec.general_purpose_bit_flag & 2)? '8' : '4');
+ methbuf[3] = (char)((G.crec.general_purpose_bit_flag & 4)? '3' : '2');
+ } else if (methnum == DEFLATED) {
+ ush dnum=(ush)((G.crec.general_purpose_bit_flag>>1) & 3);
+ methbuf[3] = dtype[dnum];
+ } else if (methnum >= NUM_METHODS) { /* unknown */
+ sprintf(&methbuf[1], "%03u", G.crec.compression_method);
+ }
+
+ for (k = 0; k < 15; ++k)
+ attribs[k] = ' ';
+ attribs[15] = 0;
+
+ xattr = (ush)((G.crec.external_file_attributes >> 16) & 0xFFFF);
+ switch (hostnum) {
+ case VMS_:
+ { int i, j;
+
+ for (k = 0; k < 12; ++k)
+ workspace[k] = 0;
+ if (xattr & VMS_IRUSR)
+ workspace[0] = 'R';
+ if (xattr & VMS_IWUSR) {
+ workspace[1] = 'W';
+ workspace[3] = 'D';
+ }
+ if (xattr & VMS_IXUSR)
+ workspace[2] = 'E';
+ if (xattr & VMS_IRGRP)
+ workspace[4] = 'R';
+ if (xattr & VMS_IWGRP) {
+ workspace[5] = 'W';
+ workspace[7] = 'D';
+ }
+ if (xattr & VMS_IXGRP)
+ workspace[6] = 'E';
+ if (xattr & VMS_IROTH)
+ workspace[8] = 'R';
+ if (xattr & VMS_IWOTH) {
+ workspace[9] = 'W';
+ workspace[11] = 'D';
+ }
+ if (xattr & VMS_IXOTH)
+ workspace[10] = 'E';
+
+ p = attribs;
+ for (k = j = 0; j < 3; ++j) { /* groups of permissions */
+ for (i = 0; i < 4; ++i, ++k) /* perms within a group */
+ if (workspace[k])
+ *p++ = workspace[k];
+ *p++ = ','; /* group separator */
+ }
+ *--p = ' '; /* overwrite last comma */
+ if ((p - attribs) < 12)
+ sprintf(&attribs[12], "%d.%d", hostver/10, hostver%10);
+ }
+ break;
+
+ case FS_FAT_:
+ case FS_HPFS_:
+ case FS_NTFS_:
+ case VM_CMS_:
+ case FS_VFAT_:
+ case MVS_:
+ case ACORN_:
+ xattr = (ush)(G.crec.external_file_attributes & 0xFF);
+ sprintf(attribs, ".r.-... %d.%d", hostver/10, hostver%10);
+ attribs[2] = (xattr & 0x01)? '-' : 'w';
+ attribs[5] = (xattr & 0x02)? 'h' : '-';
+ attribs[6] = (xattr & 0x04)? 's' : '-';
+ attribs[4] = (xattr & 0x20)? 'a' : '-';
+ if (xattr & 0x10) {
+ attribs[0] = 'd';
+ attribs[3] = 'x';
+ } else
+ attribs[0] = '-';
+ if (IS_VOLID(xattr))
+ attribs[0] = 'V';
+ else if ((p = strrchr(G.filename, '.')) != (char *)NULL) {
+ ++p;
+ if (STRNICMP(p, "com", 3) == 0 || STRNICMP(p, "exe", 3) == 0 ||
+ STRNICMP(p, "btm", 3) == 0 || STRNICMP(p, "cmd", 3) == 0 ||
+ STRNICMP(p, "bat", 3) == 0)
+ attribs[3] = 'x';
+ }
+ break;
+
+ case AMIGA_:
+ switch (xattr & AMI_IFMT) {
+ case AMI_IFDIR: attribs[0] = 'd'; break;
+ case AMI_IFREG: attribs[0] = '-'; break;
+ default: attribs[0] = '?'; break;
+ }
+ attribs[1] = (xattr & AMI_IHIDDEN)? 'h' : '-';
+ attribs[2] = (xattr & AMI_ISCRIPT)? 's' : '-';
+ attribs[3] = (xattr & AMI_IPURE)? 'p' : '-';
+ attribs[4] = (xattr & AMI_IARCHIVE)? 'a' : '-';
+ attribs[5] = (xattr & AMI_IREAD)? 'r' : '-';
+ attribs[6] = (xattr & AMI_IWRITE)? 'w' : '-';
+ attribs[7] = (xattr & AMI_IEXECUTE)? 'e' : '-';
+ attribs[8] = (xattr & AMI_IDELETE)? 'd' : '-';
+ sprintf(&attribs[12], "%d.%d", hostver/10, hostver%10);
+ break;
+
+ default: /* assume Unix-like */
+ switch ((unsigned)(xattr & UNX_IFMT)) {
+ case (unsigned)UNX_IFDIR: attribs[0] = 'd'; break;
+ case (unsigned)UNX_IFREG: attribs[0] = '-'; break;
+ case (unsigned)UNX_IFLNK: attribs[0] = 'l'; break;
+ case (unsigned)UNX_IFBLK: attribs[0] = 'b'; break;
+ case (unsigned)UNX_IFCHR: attribs[0] = 'c'; break;
+ case (unsigned)UNX_IFIFO: attribs[0] = 'p'; break;
+ case (unsigned)UNX_IFSOCK: attribs[0] = 's'; break;
+ default: attribs[0] = '?'; break;
+ }
+ attribs[1] = (xattr & UNX_IRUSR)? 'r' : '-';
+ attribs[4] = (xattr & UNX_IRGRP)? 'r' : '-';
+ attribs[7] = (xattr & UNX_IROTH)? 'r' : '-';
+ attribs[2] = (xattr & UNX_IWUSR)? 'w' : '-';
+ attribs[5] = (xattr & UNX_IWGRP)? 'w' : '-';
+ attribs[8] = (xattr & UNX_IWOTH)? 'w' : '-';
+
+ if (xattr & UNX_IXUSR)
+ attribs[3] = (xattr & UNX_ISUID)? 's' : 'x';
+ else
+ attribs[3] = (xattr & UNX_ISUID)? 'S' : '-'; /* S==undefined */
+ if (xattr & UNX_IXGRP)
+ attribs[6] = (xattr & UNX_ISGID)? 's' : 'x'; /* == UNX_ENFMT */
+ else
+ /* attribs[6] = (xattr & UNX_ISGID)? 'l' : '-'; real 4.3BSD */
+ attribs[6] = (xattr & UNX_ISGID)? 'S' : '-'; /* SunOS 4.1.x */
+ if (xattr & UNX_IXOTH)
+ attribs[9] = (xattr & UNX_ISVTX)? 't' : 'x'; /* "sticky bit" */
+ else
+ attribs[9] = (xattr & UNX_ISVTX)? 'T' : '-'; /* T==undefined */
+
+ sprintf(&attribs[12], "%d.%d", hostver/10, hostver%10);
+ break;
+
+ } /* end switch (hostnum: external attributes format) */
+
+ Info(slide, 0, ((char *)slide, "%s %s %8lu ", attribs,
+ LoadFarStringSmall(os[hostnum]), G.crec.ucsize));
+ Info(slide, 0, ((char *)slide, "%c",
+ (G.crec.general_purpose_bit_flag & 1)?
+ ((G.crec.internal_file_attributes & 1)? 'T' : 'B') : /* encrypted */
+ ((G.crec.internal_file_attributes & 1)? 't' : 'b'))); /* plaintext */
+ k = (G.crec.extra_field_length ||
+ /* a local-only "UX" (old Unix/OS2/NT GMT times "IZUNIX") e.f.? */
+ ((G.crec.external_file_attributes & 0x8000) &&
+ (hostnum == UNIX_ || hostnum == FS_HPFS_ || hostnum == FS_NTFS_)));
+ Info(slide, 0, ((char *)slide, "%c", k?
+ ((G.crec.general_purpose_bit_flag & 8)? 'X' : 'x') : /* extra field */
+ ((G.crec.general_purpose_bit_flag & 8)? 'l' : '-'))); /* no extra field */
+ /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ extended local header or not */
+
+ if (uO.lflag == 4) {
+ ulg csiz = G.crec.csize;
+
+ if (G.crec.general_purpose_bit_flag & 1)
+ csiz -= 12; /* if encrypted, don't count encryption header */
+ Info(slide, 0, ((char *)slide, "%3d%%",
+ (ratio(G.crec.ucsize,csiz)+5)/10));
+ } else if (uO.lflag == 5)
+ Info(slide, 0, ((char *)slide, " %8lu", G.crec.csize));
+
+ /* Read the extra field, if any. The extra field info may be used
+ * in the file modification time section, below.
+ */
+ if ((error = do_string(__G__ G.crec.extra_field_length, EXTRA_FIELD)) != 0)
+ {
+ if (G.extra_field != NULL) {
+ free(G.extra_field);
+ G.extra_field = NULL;
+ }
+ error_in_archive = error;
+ /* We do not return prematurely in case of a "fatal" error (PK_EOF).
+ * This does not hurt here, because we do not need to read from the
+ * zipfile again before the end of this function.
+ */
+ }
+
+ /* For printing of date & time, a "char d_t_buf[16]" is required.
+ * To save stack space, we reuse the "char attribs[16]" buffer whose
+ * content is no longer needed.
+ */
+# define d_t_buf attribs
+#ifdef USE_EF_UT_TIME
+ z_modtim = G.extra_field &&
+#ifdef IZ_CHECK_TZ
+ G.tz_is_valid &&
+#endif
+ (ef_scan_for_izux(G.extra_field, G.crec.extra_field_length, 1,
+ G.crec.last_mod_dos_datetime, &z_utime, NULL)
+ & EB_UT_FL_MTIME)
+ ? &z_utime.mtime : NULL;
+ TIMET_TO_NATIVE(z_utime.mtime) /* NOP unless MSC 7.0 or Macintosh */
+ d_t_buf[0] = (char)0; /* signal "show local time" */
+#else
+# define z_modtim NULL
+#endif
+ Info(slide, 0, ((char *)slide, " %s %s ", methbuf,
+ zi_time(__G__ &G.crec.last_mod_dos_datetime, z_modtim, d_t_buf)));
+ fnprint(__G);
+
+/*---------------------------------------------------------------------------
+ Skip the file comment, if any (the filename has already been printed,
+ above). That finishes up this file entry...
+ ---------------------------------------------------------------------------*/
+
+ SKIP_(G.crec.file_comment_length)
+
+ return error_in_archive;
+
+} /* end function zi_short() */
+
+
+
+
+
+/**************************************/
+/* Function zi_showMacTypeCreator() */
+/**************************************/
+
+static void zi_showMacTypeCreator(__G__ ebfield)
+ __GDEF
+ uch *ebfield;
+{
+ /* not every Type / Creator character is printable */
+ if (isprint(ebfield[0]) && isprint(ebfield[1]) &&
+ isprint(ebfield[2]) && isprint(ebfield[3]) &&
+ isprint(ebfield[4]) && isprint(ebfield[5]) &&
+ isprint(ebfield[6]) && isprint(ebfield[7])) {
+ Info(slide, 0, ((char *)slide, LoadFarString(MacOSdata),
+ ebfield[0], ebfield[1], ebfield[2], ebfield[3],
+ ebfield[4], ebfield[5], ebfield[6], ebfield[7]));
+ } else {
+ Info(slide, 0, ((char *)slide, LoadFarString(MacOSdata1),
+ (((ulg)ebfield[0]) << 24) +
+ (((ulg)ebfield[1]) << 16) +
+ (((ulg)ebfield[2]) << 8) +
+ ((ulg)ebfield[3]),
+ (((ulg)ebfield[4]) << 24) +
+ (((ulg)ebfield[5]) << 16) +
+ (((ulg)ebfield[6]) << 8) +
+ ((ulg)ebfield[7])));
+ }
+} /* end function zi_showMacTypeCreator() */
+
+
+
+
+
+/************************/
+/* Function zi_time() */
+/************************/
+
+static char *zi_time(__G__ datetimez, modtimez, d_t_str)
+ __GDEF
+ ZCONST ulg *datetimez;
+ ZCONST time_t *modtimez;
+ char *d_t_str;
+{
+ unsigned yr, mo, dy, hh, mm, ss;
+ char monthbuf[4];
+ ZCONST char *monthstr;
+ static ZCONST char Far month[12][4] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+ };
+#ifdef USE_EF_UT_TIME
+ struct tm *t;
+#endif
+
+
+
+/*---------------------------------------------------------------------------
+ Convert the file-modification date and time info to a string of the form
+ "1991 Feb 23 17:15:00", "23-Feb-91 17:15" or "19910223.171500", depending
+ on values of lflag and T_flag. If using Unix-time extra fields, convert
+ to local time or not, depending on value of first character in d_t_str[].
+ ---------------------------------------------------------------------------*/
+
+#ifdef USE_EF_UT_TIME
+ if (modtimez != NULL) {
+#ifndef NO_GMTIME
+ /* check for our secret message from above... */
+ t = (d_t_str[0] == (char)1)? gmtime(modtimez) : localtime(modtimez);
+#else
+ t = localtime(modtimez);
+#endif
+ if (uO.lflag > 9 && t == (struct tm *)NULL)
+ /* time conversion error in verbose listing format,
+ * return string with '?' instead of data
+ */
+ return (strcpy(d_t_str, LoadFarString(YMDHMSTimeError)));
+ } else
+ t = (struct tm *)NULL;
+ if (t != (struct tm *)NULL) {
+ mo = (unsigned)(t->tm_mon + 1);
+ dy = (unsigned)(t->tm_mday);
+ yr = (unsigned)(t->tm_year);
+
+ hh = (unsigned)(t->tm_hour);
+ mm = (unsigned)(t->tm_min);
+ ss = (unsigned)(t->tm_sec);
+ } else
+#endif /* USE_EF_UT_TIME */
+ {
+ yr = ((unsigned)(*datetimez >> 25) & 0x7f) + 80;
+ mo = ((unsigned)(*datetimez >> 21) & 0x0f);
+ dy = ((unsigned)(*datetimez >> 16) & 0x1f);
+
+ hh = (((unsigned)*datetimez >> 11) & 0x1f);
+ mm = (((unsigned)*datetimez >> 5) & 0x3f);
+ ss = (((unsigned)*datetimez << 1) & 0x3e);
+ }
+
+ if (mo == 0 || mo > 12) {
+ sprintf(monthbuf, LoadFarString(BogusFmt), mo);
+ monthstr = monthbuf;
+ } else
+ monthstr = LoadFarStringSmall(month[mo-1]);
+
+ if (uO.lflag > 9) /* verbose listing format */
+ sprintf(d_t_str, LoadFarString(YMDHMSTime), yr+1900, monthstr, dy, hh,
+ mm, ss);
+ else if (uO.T_flag)
+ sprintf(d_t_str, LoadFarString(DecimalTime), yr+1900, mo, dy, hh, mm,
+ ss);
+ else /* was: if ((uO.lflag >= 3) && (uO.lflag <= 5)) */
+ sprintf(d_t_str, LoadFarString(DMYHMTime), dy, monthstr, yr%100, hh,
+ mm);
+
+ return d_t_str;
+
+} /* end function zi_time() */
+
+#endif /* !NO_ZIPINFO */