--- extract.c	2005-02-26 05:47:30.000000000 +0100
+++ extract.c	2007-12-03 13:49:01.000000000 +0100
@@ -308,7 +308,7 @@ int extract_or_test_files(__G)    /* ret
     int reached_end, no_endsig_found;
     int error, error_in_archive=PK_COOL;
     int *fn_matched=NULL, *xn_matched=NULL;
-    unsigned members_processed;
+    Z_OFF_T members_processed;
     ulg num_skipped=0L, num_bad_pwd=0L;
     Z_OFF_T old_extra_bytes = 0L;
 #ifdef SET_DIR_ATTRIB
@@ -541,7 +541,7 @@ int extract_or_test_files(__G)    /* ret
         G.cur_zipfile_bufstart = ftell((FILE *)G.zipfd);
 #else /* !USE_STRM_INPUT */
         G.cur_zipfile_bufstart =
-          lseek(G.zipfd, cd_bufstart, SEEK_SET);
+          lseek64(G.zipfd,(Z_OFF_T)cd_bufstart, SEEK_SET);
 #endif /* ?USE_STRM_INPUT */
         read(G.zipfd, (char *)G.inbuf, INBUFSIZ);  /* been here before... */
         G.inptr = cd_inptr;
@@ -942,7 +942,8 @@ static int extract_or_test_entrylist(__G
         Trace((stderr,
           "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n",
           (long)bufstart, (long)G.cur_zipfile_bufstart));
-        if (request < 0) {
+        if ((request < 0) || (request > MAX_ZIP_SIZE)) { /* >2^32-8193 */  
+	    printf("retry - request = 0x%lu\n", (ulg)request);
             Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(SeekMsg),
               G.zipfn, LoadFarString(ReportMsg)));
             error_in_archive = PK_ERR;
@@ -982,7 +983,7 @@ static int extract_or_test_entrylist(__G
             G.cur_zipfile_bufstart = ftell((FILE *)G.zipfd);
 #else /* !USE_STRM_INPUT */
             G.cur_zipfile_bufstart =
-              lseek(G.zipfd, bufstart, SEEK_SET);
+              lseek64(G.zipfd, bufstart, SEEK_SET);
 #endif /* ?USE_STRM_INPUT */
             if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) <= 0)
             {
--- fileio.c	2005-02-27 03:10:12.000000000 +0100
+++ fileio.c	2007-12-03 13:49:01.000000000 +0100
@@ -113,6 +113,9 @@ static int disk_error OF((__GPRO));
 /* Strings used in fileio.c */
 /****************************/
 
+static ZCONST char Far ZipFileTooBig[] =
+  "error:  Zip file too big (greater than %lu bytes)\n";
+
 static ZCONST char Far CannotOpenZipfile[] =
   "error:  cannot open zipfile [ %s ]\n        %s\n";
 
@@ -183,6 +186,7 @@ static ZCONST char Far ExtraFieldTooLong
 int open_input_file(__G)    /* return 1 if open failed */
     __GDEF
 {
+    struct stat64 sb;
     /*
      *  open the zipfile for reading and in BINARY mode to prevent cr/lf
      *  translation, which would corrupt the bitstreams
@@ -201,9 +205,9 @@ int open_input_file(__G)    /* return 1 
     G.zipfd = fopen(G.zipfn, FOPR);
 #else /* !USE_STRM_INPUT */
 # ifdef O_BINARY
-    G.zipfd = open(G.zipfn, O_RDONLY | O_BINARY);
+    G.zipfd = open(G.zipfn, O_RDONLY | O_BINARY | O_LARGEFILE);
 # else
-    G.zipfd = open(G.zipfn, O_RDONLY);
+    G.zipfd = open(G.zipfn, O_RDONLY | O_LARGEFILE);
 # endif
 #endif /* ?USE_STRM_INPUT */
 #endif /* ?CMS_MVS */
@@ -221,6 +225,12 @@ int open_input_file(__G)    /* return 1 
           G.zipfn, strerror(errno)));
         return 1;
     }
+    fstat64(G.zipfd, &sb);
+    if (sb.st_size > MAX_ZIP_SIZE) {
+        Info(slide, 0x401, ((char *)slide,
+                           LoadFarString(ZipFileTooBig),
+                           ((ulg)MAX_ZIP_SIZE)));
+    }
     return 0;
 
 } /* end function open_input_file() */
@@ -238,6 +248,7 @@ int open_input_file(__G)    /* return 1 
 int open_outfile(__G)         /* return 1 if fail */
     __GDEF
 {
+    int fd;
 #ifdef DLL
     if (G.redirect_data)
         return (redirect_outfile(__G) == FALSE);
@@ -259,7 +270,7 @@ int open_outfile(__G)         /* return 
     }
 #endif /* BORLAND_STAT_BUG */
 #ifdef SYMLINKS
-    if (SSTAT(G.filename, &G.statbuf) == 0 || lstat(G.filename,&G.statbuf) == 0)
+    if (SSTAT(G.filename, &G.statbuf) == 0 || lstat64(G.filename,&G.statbuf) == 0)
 #else
     if (SSTAT(G.filename, &G.statbuf) == 0)
 #endif /* ?SYMLINKS */
@@ -413,7 +424,9 @@ int open_outfile(__G)         /* return 
 #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) {
+    
+    fd = open(G.filename, O_WRONLY | O_LARGEFILE | O_CREAT);
+    if ((G.outfile = fdopen(fd, FOPW)) == (FILE *)NULL) {
         Info(slide, 0x401, ((char *)slide, LoadFarString(CannotCreateFile),
           FnFilter1(G.filename)));
         return 1;
@@ -682,7 +695,7 @@ int seek_zipf(__G__ abs_offset)
     Z_OFF_T inbuf_offset = request % INBUFSIZ;
     Z_OFF_T bufstart = request - inbuf_offset;
 
-    if (request < 0) {
+    if (request < 0) { 
         Info(slide, 1, ((char *)slide, LoadFarStringSmall(SeekMsg),
              G.zipfn, LoadFarString(ReportMsg)));
         return(PK_BADERR);
@@ -694,7 +707,7 @@ int seek_zipf(__G__ abs_offset)
         fseek(G.zipfd, bufstart, SEEK_SET);
         G.cur_zipfile_bufstart = ftell(G.zipfd);
 #else /* !USE_STRM_INPUT */
-        G.cur_zipfile_bufstart = lseek(G.zipfd, bufstart, SEEK_SET);
+        G.cur_zipfile_bufstart = lseek64(G.zipfd, bufstart, SEEK_SET);
 #endif /* ?USE_STRM_INPUT */
         Trace((stderr,
           "       request = %ld, (abs+extra) = %ld, inbuf_offset = %ld\n",
@@ -1850,7 +1863,7 @@ int check_for_newer(__G__ filename)  /* 
         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) {
+        if (lstat64(filename, &G.statbuf) == 0) {
             Trace((stderr,
               "check_for_newer:  lstat(%s) returns 0:  symlink does exist\n",
               FnFilter1(filename)));
@@ -1867,7 +1880,7 @@ int check_for_newer(__G__ 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)) {
+    if (lstat64(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 && !IS_OVERWRT_ALL)
--- globals.h	2004-11-22 01:42:00.000000000 +0100
+++ globals.h	2007-12-03 13:49:01.000000000 +0100
@@ -256,7 +256,12 @@ typedef struct Globals {
     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 */
+#ifdef _LARGEFILE64_SOURCE
+    struct stat64   statbuf;       /* used by main, mapname, check_for_newer */
+#else
+    struct stat   statbuf;       /* used by main, mapname, check_for_newer */
+#endif
+    
 
     int      mem_mode;
     uch      *outbufptr;           /* extract.c static */
--- list.c	2005-01-27 02:02:02.000000000 +0100
+++ list.c	2007-12-03 13:55:10.000000000 +0100
@@ -62,12 +62,12 @@
      "%8lu  %-7s%8lu %4s  %02u%c%02u%c%02u %02u:%02u  %08lx %c";
    static ZCONST char Far LongFileTrailer[] =
      "--------          -------  ---                       \
-     -------\n%8lu         %8lu %4s                            %lu file%s\n";
+     -------\n%8ju         %8ju %4s                            %lu file%s\n";
 #ifdef OS2_EAS
    static ZCONST char Far ShortHdrStats[] =
      "%9lu %6lu %6lu  %02u%c%02u%c%02u %02u:%02u  %c";
    static ZCONST char Far ShortFileTrailer[] = " --------  -----  -----       \
-            -------\n%9lu %6lu %6lu                   %lu file%s\n";
+            -------\n%9ju %6lu %6lu                   %lu file%s\n";
    static ZCONST char Far OS2ExtAttrTrailer[] =
      "%lu file%s %lu bytes of OS/2 extended attributes attached.\n";
    static ZCONST char Far OS2ACLTrailer[] =
@@ -76,7 +76,7 @@
    static ZCONST char Far ShortHdrStats[] =
      "%9lu  %02u%c%02u%c%02u %02u:%02u  %c";
    static ZCONST char Far ShortFileTrailer[] = " --------       \
-            -------\n%9lu                   %lu file%s\n";
+            -------\n%9ju                   %lu file%s\n";
 #endif /* ?OS2_EAS */
 #endif /* !WINDLL */
 
@@ -105,7 +105,8 @@ int list_files(__G)    /* return PK-type
     struct tm *t;
 #endif
     unsigned yr, mo, dy, hh, mm;
-    ulg csiz, tot_csize=0L, tot_ucsize=0L;
+    ulg csiz;
+    unsigned long long tot_csize=0, tot_ucsize=0;
 #ifdef OS2_EAS
     ulg ea_size, tot_easize=0L, tot_eafiles=0L;
     ulg acl_size, tot_aclsize=0L, tot_aclfiles=0L;
--- process.c	2007-12-03 13:44:30.000000000 +0100
+++ process.c	2007-12-03 13:49:01.000000000 +0100
@@ -934,8 +934,8 @@ static int find_ecrec(__G__ searchlen)  
     Treat case of short zipfile separately.
   ---------------------------------------------------------------------------*/
 
-    if (G.ziplen <= INBUFSIZ) {
-        lseek(G.zipfd, 0L, SEEK_SET);
+    if ((unsigned long)G.ziplen <= (unsigned long)INBUFSIZ) {
+        lseek64(G.zipfd, 0L, SEEK_SET);
         if ((G.incnt = read(G.zipfd,(char *)G.inbuf,(unsigned int)G.ziplen))
             == (int)G.ziplen)
 
@@ -962,7 +962,7 @@ static int find_ecrec(__G__ searchlen)  
             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,
+            G.cur_zipfile_bufstart = lseek64(G.zipfd, G.ziplen-tail_len,
               SEEK_SET);
 #endif /* ?USE_STRM_INPUT */
             if ((G.incnt = read(G.zipfd, (char *)G.inbuf,
@@ -996,7 +996,7 @@ static int find_ecrec(__G__ searchlen)  
 
         for (i = 1;  !found && (i <= numblks);  ++i) {
             G.cur_zipfile_bufstart -= INBUFSIZ;
-            lseek(G.zipfd, G.cur_zipfile_bufstart, SEEK_SET);
+            lseek64(G.zipfd, G.cur_zipfile_bufstart, SEEK_SET);
             if ((G.incnt = read(G.zipfd,(char *)G.inbuf,INBUFSIZ))
                 != INBUFSIZ)
                 break;          /* fall through and fail */
--- process.c.orig	1970-01-01 01:00:00.000000000 +0100
+++ process.c.orig	2007-12-03 13:44:30.000000000 +0100
@@ -0,0 +1,1690 @@
+/*
+  Copyright (c) 1990-2004 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, all these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*---------------------------------------------------------------------------
+
+  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()
+             getRISCOSexfield()
+
+  ---------------------------------------------------------------------------*/
+
+
+#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";
+# ifdef CHEAP_SFX_AUTORUN
+   static ZCONST char Far AutorunPrompt[] =
+     "\nAuto-run command: %s\nExecute this command? [y/n] ";
+   static ZCONST char Far NotAutoRunning[] =
+     "Not executing auto-run command.";
+# endif
+
+#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 or open %s, %s.zip or %s.\n";
+# 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";
+# 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";
+
+static ZCONST char Far FileNameTooLong[] =
+  "%s: error: %s (truncated): %s\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] */ =       /* ASCII 'P', */
+      central_hdr_sig[0] = end_central_sig[0] = 0x50;   /* not EBCDIC */
+
+    local_hdr_sig[1]  /* = extd_local_sig[1] */ =       /* 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(WIN32) && defined(USE_EF_UT_TIME))
+    /* For the Win32 environment, we may have to "prepare" the environment
+       prior to the tzset() call, to work around tzset() implementation bugs.
+     */
+    iz_w32_prepareTZenv();
+#endif
+
+#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
+
+/*---------------------------------------------------------------------------
+    Initialize the internal flag holding the mode of processing "overwrite
+    existing file" cases.  We do not use the calling interface flags directly
+    because the overwrite mode may be changed by user interaction while
+    processing archive files.  Such a change should not affect the option
+    settings as passed through the DLL calling interface.
+    In case of conflicting options, the 'safer' flag uO.overwrite_none takes
+    precedence.
+  ---------------------------------------------------------------------------*/
+    G.overwrite_mode = (uO.overwrite_none ? OVERWRT_NEVER :
+                        (uO.overwrite_all ? OVERWRT_ALWAYS : OVERWRT_QUERY));
+
+/*---------------------------------------------------------------------------
+    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));
+    }
+#ifdef CHEAP_SFX_AUTORUN
+    if (G.autorun_command[0] && !uO.qflag) { /* NO autorun without prompt! */
+        Info(slide, 0x81, ((char *)slide, LoadFarString(AutorunPrompt),
+                      FnFilter1(G.autorun_command)));
+        if (fgets(G.answerbuf, 9, stdin) != (char *)NULL
+            && toupper(*G.answerbuf) == 'Y')
+            system(G.autorun_command);
+        else
+            Info(slide, 1, ((char *)slide, LoadFarString(NotAutoRunning)));
+    }
+#endif /* CHEAP_SFX_AUTORUN */
+
+#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;
+
+        if (strlen(G.wildzipfn) > strlen(G.zipfn))
+        {
+            Info(slide, 1, ((char *)slide,
+                            LoadFarString(FileNameTooLong),
+                            uO.zipinfo_mode? LoadFarStringSmall(Zipnfo) : LoadFarStringSmall(Unzip),
+                            G.zipfn, strerror(ENAMETOOLONG)));
+
+            free_G_buffers(__G);
+            return PK_NOZIP;
+        }
+
+        /* 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;
+
+        Trace((stderr, "do_seekable(0) returns %d\n", error));
+        if (error != IZ_DIR && error > error_in_archive)
+            error_in_archive = 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)
+    {
+#if (!defined(UNIX) && !defined(AMIGA)) /* filenames with wildcard characters */
+        if (iswild(G.wildzipfn)) {
+            if (iswild(lastzipfn)) {
+                NumMissDirs = NumMissFiles = 0;
+                error_in_archive = PK_COOL;
+                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);
+
+            NumMissDirs = NumMissFiles = 0;
+            error_in_archive = PK_COOL;
+
+#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
+            Trace((stderr, "do_seekable(1) returns %d\n", error));
+            switch (error) {
+              case PK_WARN:
+                ++NumWarnFiles;
+                break;
+              case IZ_DIR:
+                ++NumMissDirs;
+                error = PK_NOZIP;
+                break;
+              case PK_NOZIP:
+                /* increment again => bug:
+                   "1 file had no zipfile directory." */
+                /* ++NumMissFiles */ ;
+                break;
+              default:
+                if (error)
+                    ++NumLoseFiles;
+                else
+                    ++NumWinFiles;
+                break;
+            }
+
+            if (error > error_in_archive)
+                error_in_archive = 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
+{
+#ifndef SFX
+    unsigned i;
+#endif
+
+#ifdef SYSTEM_SPECIFIC_DTOR
+    SYSTEM_SPECIFIC_DTOR(__G);
+#endif
+
+    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 (G.extra_field != (uch *)NULL) {
+        free(G.extra_field);
+        G.extra_field = (uch *)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;
+
+#ifndef SFX
+    for (i = 0; i < DIR_BLKSIZ; i++) {
+        if (G.info[i].cfilname != (char Far *)NULL) {
+            zffree(G.info[i].cfilname);
+            G.info[i].cfilname = (char Far *)NULL;
+        }
+    }
+#endif
+
+#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;
+    ulg nmember = 0L;
+#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) ||
+#ifdef THEOS
+        (error = S_ISLIB(G.statbuf.st_mode)) != 0 ||
+#endif
+        (error = S_ISDIR(G.statbuf.st_mode)) != 0)
+    {
+#ifndef SFX
+        if (lastchance && (uO.qflag < 3)) {
+#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 || QDOS) */
+            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 || QDOS) */
+        }
+#endif /* !SFX */
+        return error? IZ_DIR : PK_NOZIP;
+    }
+    G.ziplen = G.statbuf.st_size;
+
+#ifndef SFX
+#if defined(UNIX) || defined(DOS_OS2_W32) || defined(THEOS)
+    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) {
+            CLOSE_INFILE();
+            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)) > MPN_INF_SKIP) {
+            /* out of memory, or file in way */
+            CLOSE_INFILE();
+            return (error == MPN_NOMEM ? PK_MEM : PK_ERR);
+        }
+    }
+#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) <
+            (Z_OFF_T)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).
+      -----------------------------------------------------------------------*/
+
+        error = seek_zipf(__G__ G.ecrec.offset_start_central_directory);
+        if (error == PK_BADERR) {
+            CLOSE_INFILE();
+            return PK_BADERR;
+        }
+#ifdef OLD_SEEK_TEST
+        if (error != PK_OK || readbuf(__G__ 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 ((error != PK_OK) || (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;
+            error = seek_zipf(__G__ G.ecrec.offset_start_central_directory);
+            if ((error != PK_OK) || (readbuf(__G__ G.sig, 4) == 0) ||
+                strncmp(G.sig, central_hdr_sig, 4))
+            {
+                if (error != PK_BADERR)
+                  Info(slide, 0x401, ((char *)slide,
+                    LoadFarString(CentDirStartNotFound), G.zipfn,
+                    LoadFarStringSmall(ReportMsg)));
+                CLOSE_INFILE();
+                return (error != PK_OK ? error : 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.
+      -----------------------------------------------------------------------*/
+
+        error = seek_zipf(__G__ G.ecrec.offset_start_central_directory);
+        if (error != PK_OK) {
+            CLOSE_INFILE();
+            return error;
+        }
+
+        Trace((stderr, "about to extract/list files (error = %d)\n",
+          error_in_archive));
+
+#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 > 0L)) {
+# ifdef WIN32
+        if (stamp_file(__G__ G.zipfn, uxstamp)) {       /* TIME-STAMP 'EM */
+# else
+        if (stamp_file(G.zipfn, uxstamp)) {             /* TIME-STAMP 'EM */
+# endif
+            if (uO.qflag < 3)
+                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;
+    Z_OFF_T 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 (ECREC_SIZE+4) bytes from end of zipfile */
+            for (G.inptr = G.inbuf+(int)G.ziplen-(ECREC_SIZE+4);
+                 G.inptr >= G.inbuf;
+                 --G.inptr) {
+                if ( (*G.inptr == (uch)0x50) &&         /* ASCII '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 (ECREC_SIZE+4) bytes from end of zipfile */
+            for (G.inptr = G.inbuf+(int)tail_len-(ECREC_SIZE+4);
+                 G.inptr >= G.inbuf;
+                 --G.inptr) {
+                if ( (*G.inptr == (uch)0x50) &&         /* ASCII 'P' */
+                     !strncmp((char *)G.inptr, end_central_sig, 4)) {
+                    G.incnt -= (int)(G.inptr - G.inbuf);
+                    found = TRUE;
+                    break;
+                }
+            }
+            /* sig may span block boundary: */
+            memcpy((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: */
+            memcpy((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 (defined(SFX) && defined(CHEAP_SFX_AUTORUN))
+        if (do_string(__G__ G.ecrec.zipfile_comment_length, CHECK_AUTORUN)) {
+#else
+        if (do_string(__G__ G.ecrec.zipfile_comment_length, DISPLAY)) {
+#endif
+            Info(slide, 0x401, ((char *)slide,
+              LoadFarString(ZipfileCommTrunc1)));
+            error = PK_WARN;
+        }
+    }
+#if (defined(SFX) && defined(CHEAP_SFX_AUTORUN))
+    else if (G.ecrec.zipfile_comment_length) {
+        if (do_string(__G__ G.ecrec.zipfile_comment_length, CHECK_AUTORUN_Q)) {
+            Info(slide, 0x401, ((char *)slide,
+              LoadFarString(ZipfileCommTrunc1)));
+            error = PK_WARN;
+        }
+    }
+#endif
+    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->hostver = G.crec.version_made_by[0];
+    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 == 1)       /* name conversion for monocase systems */
+        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_, ATHEOS_, BEOS_ (Z_SYSTEM_), THEOS_: */
+                         /*  no conversion */
+        }
+    else if (uO.L_flag > 1)   /* let -LL force lower case for all names */
+        G.pInfo->lcflag = 1;
+
+    /* 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;
+
+    /* this flag is needed to detect archives made by "PKZIP for Unix" when
+       deciding which kind of codepage conversion has to be applied to
+       strings (see do_string() function in fileio.c) */
+    G.pInfo->HasUxAtt = (G.crec.external_file_attributes & 0xffff0000L) != 0L;
+
+    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]);
+
+    if ((G.lrec.general_purpose_bit_flag & 8) != 0) {
+        /* can't trust local header, use central directory: */
+        G.lrec.crc32 = G.pInfo->crc;
+        G.lrec.csize = G.pInfo->compr_size;
+        G.lrec.ucsize = G.pInfo->uncompr_size;
+    }
+
+    G.csize = (long)G.lrec.csize;
+
+    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)
+    ZCONST 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;
+    long i_time;        /* buffer for Unix style 32-bit integer time value */
+#ifdef TIME_T_TYPE_DOUBLE
+    int ut_in_archive_sgn = 0;
+#else
+    int ut_zip_unzip_compatible = FALSE;
+#endif
+
+/*---------------------------------------------------------------------------
+    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) {
+                        i_time = (long)makelong((EB_HEADSIZE+eb_idx) + ef_buf);
+                        eb_idx += 4;
+                        TTrace((stderr,"  UT e.f. modification time = %ld\n",
+                                i_time));
+
+#ifdef TIME_T_TYPE_DOUBLE
+                        if ((ulg)(i_time) & (ulg)(0x80000000L)) {
+                            if (dos_mdatetime == DOSTIME_MINIMUM) {
+                              ut_in_archive_sgn = -1;
+                              z_utim->mtime =
+                                (time_t)((long)i_time | (~(long)0x7fffffffL));
+                            } else if (dos_mdatetime >= DOSTIME_2038_01_18) {
+                              ut_in_archive_sgn = 1;
+                              z_utim->mtime =
+                                (time_t)((ulg)i_time & (ulg)0xffffffffL);
+                            } else {
+                              ut_in_archive_sgn = 0;
+                              /* cannot determine sign of mtime;
+                                 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_in_archive_sgn = 0;
+                            z_utim->mtime = (time_t)i_time;
+                        }
+#else /* !TIME_T_TYPE_DOUBLE */
+                        if ((ulg)(i_time) & (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 interprets 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;
+                        }
+                        z_utim->mtime = (time_t)i_time;
+#endif /* ?TIME_T_TYPE_DOUBLE */
+                    } 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) {
+                        i_time = (long)makelong((EB_HEADSIZE+eb_idx) + ef_buf);
+                        eb_idx += 4;
+                        TTrace((stderr,"  UT e.f. access time = %ld\n",
+                                i_time));
+#ifdef TIME_T_TYPE_DOUBLE
+                        if ((ulg)(i_time) & (ulg)(0x80000000L)) {
+                            if (ut_in_archive_sgn == -1)
+                              z_utim->atime =
+                                (time_t)((long)i_time | (~(long)0x7fffffffL));
+                            } else if (ut_in_archive_sgn == 1) {
+                              z_utim->atime =
+                                (time_t)((ulg)i_time & (ulg)0xffffffffL);
+                            } else {
+                              /* sign of 32-bit time is unknown -> ignore it */
+                              flags &= ~EB_UT_FL_ATIME;
+                              TTrace((stderr,
+                                "  UT access time range error: skip time!\n"));
+                            }
+                        } else {
+                            z_utim->atime = (time_t)i_time;
+                        }
+#else /* !TIME_T_TYPE_DOUBLE */
+                        if (((ulg)(i_time) & (ulg)(0x80000000L)) &&
+                            !ut_zip_unzip_compatible) {
+                            flags &= ~EB_UT_FL_ATIME;
+                            TTrace((stderr,
+                              "  UT access time range error: skip time!\n"));
+                        } else {
+                            z_utim->atime = (time_t)i_time;
+                        }
+#endif /* ?TIME_T_TYPE_DOUBLE */
+                    } else {
+                        flags &= ~EB_UT_FL_ATIME;
+                    }
+                }
+                if (flags & EB_UT_FL_CTIME) {
+                    if ((eb_idx+4) <= eb_len) {
+                        i_time = (long)makelong((EB_HEADSIZE+eb_idx) + ef_buf);
+                        TTrace((stderr,"  UT e.f. creation time = %ld\n",
+                                i_time));
+#ifdef TIME_T_TYPE_DOUBLE
+                        if ((ulg)(i_time) & (ulg)(0x80000000L)) {
+                            if (ut_in_archive_sgn == -1)
+                              z_utim->ctime =
+                                (time_t)((long)i_time | (~(long)0x7fffffffL));
+                            } else if (ut_in_archive_sgn == 1) {
+                              z_utim->ctime =
+                                (time_t)((ulg)i_time & (ulg)0xffffffffL);
+                            } else {
+                              /* sign of 32-bit time is unknown -> ignore it */
+                              flags &= ~EB_UT_FL_CTIME;
+                              TTrace((stderr,
+                              "  UT creation time range error: skip time!\n"));
+                            }
+                        } else {
+                            z_utim->ctime = (time_t)i_time;
+                        }
+#else /* !TIME_T_TYPE_DOUBLE */
+                        if (((ulg)(i_time) & (ulg)(0x80000000L)) &&
+                            !ut_zip_unzip_compatible) {
+                            flags &= ~EB_UT_FL_CTIME;
+                            TTrace((stderr,
+                              "  UT creation time range error: skip time!\n"));
+                        } else {
+                            z_utim->ctime = (time_t)i_time;
+                        }
+#endif /* ?TIME_T_TYPE_DOUBLE */
+                    } 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) {
+                    flags |= (EB_UT_FL_MTIME | EB_UT_FL_ATIME);
+                    i_time = (long)makelong((EB_HEADSIZE+EB_UX_MTIME)+ef_buf);
+                    TTrace((stderr,"  Unix EF modtime = %ld\n", i_time));
+#ifdef TIME_T_TYPE_DOUBLE
+                    if ((ulg)(i_time) & (ulg)(0x80000000L)) {
+                        if (dos_mdatetime == DOSTIME_MINIMUM) {
+                            ut_in_archive_sgn = -1;
+                            z_utim->mtime =
+                              (time_t)((long)i_time | (~(long)0x7fffffffL));
+                        } else if (dos_mdatetime >= DOSTIME_2038_01_18) {
+                            ut_in_archive_sgn = 1;
+                            z_utim->mtime =
+                              (time_t)((ulg)i_time & (ulg)0xffffffffL);
+                        } else {
+                            ut_in_archive_sgn = 0;
+                            /* cannot determine sign of mtime;
+                               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_in_archive_sgn = 0;
+                        z_utim->mtime = (time_t)i_time;
+                    }
+#else /* !TIME_T_TYPE_DOUBLE */
+                    if ((ulg)(i_time) & (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;
+                    }
+                    z_utim->mtime = (time_t)i_time;
+#endif /* ?TIME_T_TYPE_DOUBLE */
+                    i_time = (long)makelong((EB_HEADSIZE+EB_UX_ATIME)+ef_buf);
+                    TTrace((stderr,"  Unix EF actime = %ld\n", i_time));
+#ifdef TIME_T_TYPE_DOUBLE
+                    if ((ulg)(i_time) & (ulg)(0x80000000L)) {
+                        if (ut_in_archive_sgn == -1)
+                            z_utim->atime =
+                              (time_t)((long)i_time | (~(long)0x7fffffffL));
+                        } else if (ut_in_archive_sgn == 1) {
+                            z_utim->atime =
+                              (time_t)((ulg)i_time & (ulg)0xffffffffL);
+                        } else if (flags & 0x0ff) {
+                            /* sign of 32-bit time is unknown -> ignore it */
+                            flags &= ~EB_UT_FL_ATIME;
+                            TTrace((stderr,
+                                "  UX access time range error: skip time!\n"));
+                        }
+                    } else {
+                        z_utim->atime = (time_t)i_time;
+                    }
+#else /* !TIME_T_TYPE_DOUBLE */
+                    if (((ulg)(i_time) & (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"));
+                    } else {
+                        z_utim->atime = (time_t)i_time;
+                    }
+#endif /* ?TIME_T_TYPE_DOUBLE */
+                }
+                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 */
+
+
+#if (defined(RISCOS) || defined(ACORN_FTYPE_NFS))
+
+#define SPARKID_2 0x30435241    /* = "ARC0" */
+
+/*******************************/
+/* Function getRISCOSexfield() */
+/*******************************/
+
+zvoid *getRISCOSexfield(ef_buf, ef_len)
+    ZCONST uch *ef_buf; /* buffer containing extra field */
+    unsigned ef_len;    /* total length of extra field */
+{
+    unsigned eb_id;
+    unsigned eb_len;
+
+/*---------------------------------------------------------------------------
+    This function scans the extra field for a Acorn SPARK filetype ef-block.
+    If a valid block is found, the function returns a pointer to the start
+    of the SPARK_EF block in the extra field buffer.  Otherwise, a NULL
+    pointer is returned.
+  ---------------------------------------------------------------------------*/
+
+    if (ef_len == 0 || ef_buf == NULL)
+        return NULL;
+
+    TTrace((stderr,"\ngetRISCOSexfield: 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,
+              "getRISCOSexfield: block length %u > rest ef_size %u\n", eb_len,
+              ef_len - EB_HEADSIZE));
+            break;
+        }
+
+        if (eb_id == EF_SPARK && (eb_len == 24 || eb_len == 20)) {
+            if (makelong(EB_HEADSIZE + ef_buf) == SPARKID_2) {
+                /* Return a pointer to the valid SPARK filetype ef block */
+                return (zvoid *)ef_buf;
+            }
+        }
+
+        /* Skip this extra field block */
+        ef_buf += (eb_len + EB_HEADSIZE);
+        ef_len -= (eb_len + EB_HEADSIZE);
+    }
+
+    return NULL;
+}
+
+#endif /* (RISCOS || ACORN_FTYPE_NFS) */
--- unix/Makefile	2007-12-03 13:44:30.000000000 +0100
+++ unix/Makefile	2007-12-03 13:54:38.000000000 +0100
@@ -783,7 +783,7 @@ linux_asm:	linux
 # Linux (Posix, approximately SysV):  virtually any version since before 0.96,
 # for any platform.  Change "-O" to "-O3" or whatever, as desired...
 linux_noasm:	unix_make
-	$(MAKE) unzips CC=gcc LD=gcc CF="$(RPM_OPT_FLAGS) -I. $(LOC)"
+	$(MAKE) unzips CC=gcc LD=gcc CF="$(RPM_OPT_FLAGS) -D_LARGEFILE64_SOURCE -I. $(LOC)"
 
 # Linux with lcc compiler:  __inline__ (stat.h) not recognized, and must edit
 # /usr/include/gnu/types.h to get rid of "long long" if __LCC__ defined.  -O3
--- unzip.h	2007-12-03 13:44:30.000000000 +0100
+++ unzip.h	2007-12-03 13:49:01.000000000 +0100
@@ -606,6 +606,8 @@ typedef struct central_directory_file_he
 #define UZ_ST_CONTINUE          0
 #define UZ_ST_BREAK             1
 
+#define MAX_ZIP_SIZE           0xffffdffe
+
 
 /*---------------------------------------------------------------------------
     Prototypes for public UnZip API (DLL) functions.
--- unzip.h.orig	1970-01-01 01:00:00.000000000 +0100
+++ unzip.h.orig	2007-12-03 13:44:30.000000000 +0100
@@ -0,0 +1,660 @@
+/*---------------------------------------------------------------------------
+
+  unzip.h (new)
+
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  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).
+
+  ---------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------
+This is version 2005-Feb-10 of the Info-ZIP copyright and license.
+The definitive version of this document should be available at
+ftp://ftp.info-zip.org/pub/infozip/license.html indefinitely.
+
+
+Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+For the purposes of this copyright and license, "Info-ZIP" is defined as
+the following set of individuals:
+
+   Mark Adler, John Bush, Karl Davis, Harald Denker, Jean-Michel Dubois,
+   Jean-loup Gailly, Hunter Goatley, Ed Gordon, Ian Gorman, Chris Herborth,
+   Dirk Haase, Greg Hartwig, Robert Heath, Jonathan Hudson, Paul Kienitz,
+   David Kirschbaum, Johnny Lee, Onno van der Linden, Igor Mandrichenko,
+   Steve P. Miller, Sergio Monesi, Keith Owens, George Petrov, Greg Roelofs,
+   Kai Uwe Rommel, Steve Salisbury, Dave Smith, Steven M. Schweda,
+   Christian Spieler, Cosmin Truta, Antoine Verheijen, Paul von Behren,
+   Rich Wales, Mike White
+
+This software is provided "as is," without warranty of any kind, express
+or implied.  In no event shall Info-ZIP or its contributors be held liable
+for any direct, indirect, incidental, special or consequential damages
+arising out of the use of or inability to use this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+    1. Redistributions of source code must retain the above copyright notice,
+       definition, disclaimer, and this list of conditions.
+
+    2. Redistributions in binary form (compiled executables) must reproduce
+       the above copyright notice, definition, disclaimer, and this list of
+       conditions in documentation and/or other materials provided with the
+       distribution.  The sole exception to this condition is redistribution
+       of a standard UnZipSFX binary (including SFXWiz) as part of a
+       self-extracting archive; that is permitted without inclusion of this
+       license, as long as the normal SFX banner has not been removed from
+       the binary or disabled.
+
+    3. Altered versions--including, but not limited to, ports to new operating
+       systems, existing ports with new graphical interfaces, and dynamic,
+       shared, or static library versions--must be plainly marked as such
+       and must not be misrepresented as being the original source.  Such
+       altered versions also must not be misrepresented as being Info-ZIP
+       releases--including, but not limited to, labeling of the altered
+       versions with the names "Info-ZIP" (or any variation thereof, including,
+       but not limited to, different capitalizations), "Pocket UnZip," "WiZ"
+       or "MacZip" without the explicit permission of Info-ZIP.  Such altered
+       versions are further prohibited from misrepresentative use of the
+       Zip-Bugs or Info-ZIP e-mail addresses or of the Info-ZIP URL(s).
+
+    4. Info-ZIP retains the right to use the names "Info-ZIP," "Zip," "UnZip,"
+       "UnZipSFX," "WiZ," "Pocket UnZip," "Pocket Zip," and "MacZip" for its
+       own source and binary releases.
+  ---------------------------------------------------------------------------*/
+
+#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
+#  ifdef __unix__
+#    undef __unix__
+#  endif
+#endif
+
+#if ((defined(__convex__) || defined(__convexc__)) && !defined(CONVEX))
+#  define CONVEX
+#endif
+
+#if (defined(unix) || defined(_unix) || defined(__unix) || defined(__unix__))
+#  ifndef UNIX
+#    define UNIX
+#  endif
+#endif /* unix || _unix || __unix || __unix__ */
+#if (defined(M_XENIX) || defined(COHERENT) || defined(__hpux))
+#  ifndef UNIX
+#    define UNIX
+#  endif
+#endif /* M_XENIX || COHERENT || __hpux */
+#if (defined(__NetBSD__) || defined(__FreeBSD__))
+#  ifndef UNIX
+#    define UNIX
+#  endif
+#endif /* __NetBSD__ || __FreeBSD__ */
+#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
+
+#if defined(_WIN32_WCE)
+#  ifndef WIN32         /* WinCE is treated as a variant of the Win32 API */
+#    define WIN32
+#  endif
+#  ifndef UNICODE       /* WinCE requires UNICODE wide character support */
+#    define UNICODE
+#  endif
+#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 MS-DOS, or OS/2, or Win32,
+ * or IBM C Set/2, or Borland C, or Watcom C, or GNU gcc (emx or Cygwin),
+ * or Macintosh, or Sequent, or Atari, or IBM RS/6000, or Silicon Graphics,
+ * or Convex?, or AtheOS, or BeOS.
+ */
+#if (defined(__STDC__) || defined(MSDOS) || defined(OS2) || defined(WIN32))
+#  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(__EMX__) || defined(__CYGWIN__))
+#  ifndef PROTO
+#    define PROTO
+#  endif
+#  ifndef MODERN
+#    define MODERN
+#  endif
+#endif
+#if (defined(MACOS) || defined(ATARI_ST) || defined(RISCOS) || defined(THEOS))
+#  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(__ATHEOS__) || 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
+   /* for UnZip, the "basic" part of the win32 api is sufficient */
+#  ifndef WIN32_LEAN_AND_MEAN
+#    define WIN32_LEAN_AND_MEAN
+#    define IZ_HASDEFINED_WIN32LEAN
+#  endif
+#  include <windows.h>
+#  include "windll/structs.h"
+#  ifdef IZ_HASDEFINED_WIN32LEAN
+#    undef WIN32_LEAN_AND_MEAN
+#    undef IZ_HASDEFINED_WIN32LEAN
+#  endif
+#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
+
+#ifdef __cplusplus
+extern "C" {
+#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 TANDEM
+    int bflag;          /* -b: create text files in 'C' format (180)*/
+#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(__ATHEOS__) || defined(__BEOS__) || defined(MACOS))
+    int J_flag;         /* -J: ignore AtheOS/BeOS/MacOS e. f. info (unzip) */
+#endif
+#if (defined(__ATHEOS__) || defined(__BEOS__) || defined(UNIX))
+    int K_flag;         /* -K: keep setuid/setgid/tacky permissions */
+#endif
+    int lflag;          /* -12slmv: listing format (zipinfo) */
+    int iso8859_2;      /* -O: ISO8859-2 is used instead ISO8859-1 */
+    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 */
+#ifdef TANDEM
+    int rflag;          /* -r: remove file extensions */
+#endif
+#ifndef FUNZIP
+#if (defined(MSDOS) || defined(FLEXOS) || defined(OS2) || defined(WIN32))
+    int sflag;          /* -s: convert spaces in filenames to underscores */
+#endif
+    int no_conv_enc;    /* -S: suppress encoding conversion */
+#if (defined(NLM))
+    int sflag;          /* -s: convert spaces in filenames to underscores */
+#endif
+#if (defined(MSDOS) || defined(__human68k__) || 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 */
+    int W_flag;         /* -W: wildcard '*' won't match '/' dir separator */
+#if (defined (__ATHEOS__) || defined(__BEOS__) || defined(UNIX))
+    int X_flag;         /* -X: restore owner/protection or UID/GID or ACLs */
+#else
+#if (defined(TANDEM) || defined(THEOS))
+    int X_flag;         /* -X: restore owner/protection or UID/GID or ACLs */
+#else
+#if (defined(OS2) || defined(VMS) || defined(WIN32))
+    int X_flag;         /* -X: restore owner/protection or UID/GID or ACLs */
+#endif
+#endif
+#endif
+    int zflag;          /* -z: display the zipfile comment (only, for unzip) */
+#if (!defined(RISCOS) && !defined(CMS_MVS) && !defined(TANDEM))
+    int ddotflag;       /* -:: don't skip over "../" path elements */
+#endif
+#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_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 */
+
+/* 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       /* no details */
+#define UZ_ST_IN_PROGRESS       2       /* no details */
+#define UZ_ST_FINISH_MEMBER     3       /* 'details': extracted size */
+
+/* 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));
+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));
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/*---------------------------------------------------------------------------
+    Remaining private stuff for UnZip compilation.
+  ---------------------------------------------------------------------------*/
+
+#ifdef UNZIP_INTERNAL
+#  include "unzpriv.h"
+#endif
+
+
+#endif /* !__unzip_h */
--- unzpriv.h	2007-12-03 13:44:30.000000000 +0100
+++ unzpriv.h	2007-12-03 13:49:01.000000000 +0100
@@ -785,9 +785,9 @@
 #endif
 #ifndef SSTAT
 #  ifdef WILD_STAT_BUG
-#    define SSTAT(path,pbuf) (iswild(path) || stat(path,pbuf))
+#    define SSTAT(path,pbuf) (iswild(path) || stat64(path,pbuf))
 #  else
-#    define SSTAT stat
+#    define SSTAT stat64
 #  endif
 #endif
 #ifndef STRNICMP
