git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@7748 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
		
			
				
	
	
		
			1384 lines
		
	
	
		
			51 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1384 lines
		
	
	
		
			51 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*---------------------------------------------------------------------------
 | 
						|
 | 
						|
  process.c
 | 
						|
 | 
						|
  This file contains the top-level routines for processing multiple zipfiles.
 | 
						|
 | 
						|
  Contains:  process_zipfiles()
 | 
						|
             free_G_buffers()
 | 
						|
             do_seekable()
 | 
						|
             find_ecrec()
 | 
						|
             uz_end_central()
 | 
						|
             process_cdir_file_hdr()
 | 
						|
             get_cdir_ent()
 | 
						|
             process_local_file_hdr()
 | 
						|
             ef_scan_for_izux()
 | 
						|
 | 
						|
  ---------------------------------------------------------------------------*/
 | 
						|
 | 
						|
 | 
						|
#define UNZIP_INTERNAL
 | 
						|
#include "unzip.h"
 | 
						|
#ifdef WINDLL
 | 
						|
#  ifdef POCKET_UNZIP
 | 
						|
#    include "wince/intrface.h"
 | 
						|
#  else
 | 
						|
#    include "windll/windll.h"
 | 
						|
#  endif
 | 
						|
#endif
 | 
						|
 | 
						|
static int    do_seekable        OF((__GPRO__ int lastchance));
 | 
						|
static int    find_ecrec         OF((__GPRO__ long searchlen));
 | 
						|
 | 
						|
int files = 0;
 | 
						|
 | 
						|
static ZCONST char Far CannotAllocateBuffers[] =
 | 
						|
  "error:  cannot allocate unzip buffers\n";
 | 
						|
 | 
						|
#ifdef SFX
 | 
						|
   static ZCONST char Far CannotFindMyself[] =
 | 
						|
     "unzipsfx:  cannot find myself! [%s]\n";
 | 
						|
 | 
						|
#else /* !SFX */
 | 
						|
   /* process_zipfiles() strings */
 | 
						|
# if (defined(IZ_CHECK_TZ) && defined(USE_EF_UT_TIME))
 | 
						|
     static ZCONST char Far WarnInvalidTZ[] =
 | 
						|
       "Warning: TZ environment variable not found, cannot use UTC times!!\n";
 | 
						|
# endif
 | 
						|
   static ZCONST char Far FilesProcessOK[] =
 | 
						|
     "%d archive%s successfully processed.\n";
 | 
						|
   static ZCONST char Far ArchiveWarning[] =
 | 
						|
     "%d archive%s had warnings but no fatal errors.\n";
 | 
						|
   static ZCONST char Far ArchiveFatalError[] =
 | 
						|
     "%d archive%s had fatal errors.\n";
 | 
						|
   static ZCONST char Far FileHadNoZipfileDir[] =
 | 
						|
     "%d file%s had no zipfile directory.\n";
 | 
						|
   static ZCONST char Far ZipfileWasDir[] = "1 \"zipfile\" was a directory.\n";
 | 
						|
   static ZCONST char Far ManyZipfilesWereDir[] =
 | 
						|
     "%d \"zipfiles\" were directories.\n";
 | 
						|
   static ZCONST char Far NoZipfileFound[] = "No zipfiles found.\n";
 | 
						|
 | 
						|
   /* do_seekable() strings */
 | 
						|
# ifdef UNIX
 | 
						|
   static ZCONST char Far CannotFindZipfileDirMsg[] =
 | 
						|
     "%s:  cannot find zipfile directory in one of %s or\n\
 | 
						|
        %s%s.zip, and cannot find %s, period.\n";
 | 
						|
   static ZCONST char Far CannotFindEitherZipfile[] =
 | 
						|
     "%s:  cannot find %s, %s.zip or %s.\n";   /* ", so there" removed 970918 */
 | 
						|
# else /* !UNIX */
 | 
						|
# ifndef AMIGA
 | 
						|
   static ZCONST char Far CannotFindWildcardMatch[] =
 | 
						|
     "%s:  cannot find any matches for wildcard specification \"%s\".\n";
 | 
						|
# endif /* !AMIGA */
 | 
						|
   static ZCONST char Far CannotFindZipfileDirMsg[] =
 | 
						|
     "%s:  cannot find zipfile directory in %s,\n\
 | 
						|
        %sand cannot find %s, period.\n";
 | 
						|
   static ZCONST char Far CannotFindEitherZipfile[] =
 | 
						|
     "%s:  cannot find either %s or %s.\n";    /* ", so there" removed 970918 */
 | 
						|
# endif /* ?UNIX */
 | 
						|
   extern ZCONST char Far Zipnfo[];       /* in unzip.c */
 | 
						|
#ifndef WINDLL
 | 
						|
   static ZCONST char Far Unzip[] = "unzip";
 | 
						|
#else
 | 
						|
   static ZCONST char Far Unzip[] = "UnZip DLL";
 | 
						|
#endif
 | 
						|
   static ZCONST char Far MaybeExe[] =
 | 
						|
     "note:  %s may be a plain executable, not an archive\n";
 | 
						|
   static ZCONST char Far CentDirNotInZipMsg[] = "\n\
 | 
						|
   [%s]:\n\
 | 
						|
     Zipfile is disk %u of a multi-disk archive, and this is not the disk on\n\
 | 
						|
     which the central zipfile directory begins (disk %u).\n";
 | 
						|
   static ZCONST char Far EndCentDirBogus[] =
 | 
						|
     "\nwarning [%s]:  end-of-central-directory record claims this\n\
 | 
						|
  is disk %u but that the central directory starts on disk %u; this is a\n\
 | 
						|
  contradiction.  Attempting to process anyway.\n";
 | 
						|
# ifdef NO_MULTIPART
 | 
						|
   static ZCONST char Far NoMultiDiskArcSupport[] =
 | 
						|
     "\nerror [%s]:  zipfile is part of multi-disk archive\n\
 | 
						|
  (sorry, not yet supported).\n";
 | 
						|
   static ZCONST char Far MaybePakBug[] = "warning [%s]:\
 | 
						|
  zipfile claims to be 2nd disk of a 2-part archive;\n\
 | 
						|
  attempting to process anyway.  If no further errors occur, this archive\n\
 | 
						|
  was probably created by PAK v2.51 or earlier.  This bug was reported to\n\
 | 
						|
  NoGate in March 1991 and was supposed to have been fixed by mid-1991; as\n\
 | 
						|
  of mid-1992 it still hadn't been.  (If further errors do occur, archive\n\
 | 
						|
  was probably created by PKZIP 2.04c or later; UnZip does not yet support\n\
 | 
						|
  multi-part archives.)\n";
 | 
						|
# else
 | 
						|
   static ZCONST char Far MaybePakBug[] = "warning [%s]:\
 | 
						|
  zipfile claims to be last disk of a multi-part archive;\n\
 | 
						|
  attempting to process anyway, assuming all parts have been concatenated\n\
 | 
						|
  together in order.  Expect \"errors\" and warnings...true multi-part support\
 | 
						|
\n  doesn't exist yet (coming soon).\n";
 | 
						|
# endif
 | 
						|
   static ZCONST char Far ExtraBytesAtStart[] =
 | 
						|
     "warning [%s]:  %ld extra byte%s at beginning or within zipfile\n\
 | 
						|
  (attempting to process anyway)\n";
 | 
						|
#endif /* ?SFX */
 | 
						|
 | 
						|
static ZCONST char Far MissingBytes[] =
 | 
						|
  "error [%s]:  missing %ld bytes in zipfile\n\
 | 
						|
  (attempting to process anyway)\n";
 | 
						|
static ZCONST char Far NullCentDirOffset[] =
 | 
						|
  "error [%s]:  NULL central directory offset\n\
 | 
						|
  (attempting to process anyway)\n";
 | 
						|
static ZCONST char Far ZipfileEmpty[] = "warning [%s]:  zipfile is empty\n";
 | 
						|
static ZCONST char Far CentDirStartNotFound[] =
 | 
						|
  "error [%s]:  start of central directory not found;\n\
 | 
						|
  zipfile corrupt.\n%s";
 | 
						|
#ifndef SFX
 | 
						|
   static ZCONST char Far CentDirTooLong[] =
 | 
						|
     "error [%s]:  reported length of central directory is\n\
 | 
						|
  %ld bytes too long (Atari STZip zipfile?  J.H.Holm ZIPSPLIT 1.1\n\
 | 
						|
  zipfile?).  Compensating...\n";
 | 
						|
   static ZCONST char Far CentDirEndSigNotFound[] = "\
 | 
						|
  End-of-central-directory signature not found.  Either this file is not\n\
 | 
						|
  a zipfile, or it constitutes one disk of a multi-part archive.  In the\n\
 | 
						|
  latter case the central directory and zipfile comment will be found on\n\
 | 
						|
  the last disk(s) of this archive.\n";
 | 
						|
#else /* SFX */
 | 
						|
   static ZCONST char Far CentDirEndSigNotFound[] =
 | 
						|
     "  End-of-central-directory signature not found.\n";
 | 
						|
#endif /* ?SFX */
 | 
						|
static ZCONST char Far ZipfileCommTrunc1[] =
 | 
						|
  "\ncaution:  zipfile comment truncated\n";
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/*******************************/
 | 
						|
/* Function process_zipfiles() */
 | 
						|
/*******************************/
 | 
						|
 | 
						|
int process_zipfiles(__G)    /* return PK-type error code */
 | 
						|
    __GDEF
 | 
						|
{
 | 
						|
#ifndef SFX
 | 
						|
    char *lastzipfn = (char *)NULL;
 | 
						|
    int NumWinFiles, NumLoseFiles, NumWarnFiles;
 | 
						|
    int NumMissDirs, NumMissFiles;
 | 
						|
#endif
 | 
						|
    int error=0, error_in_archive=0;
 | 
						|
 | 
						|
 | 
						|
/*---------------------------------------------------------------------------
 | 
						|
    Start by allocating buffers and (re)constructing the various PK signature
 | 
						|
    strings.
 | 
						|
  ---------------------------------------------------------------------------*/
 | 
						|
 | 
						|
    G.inbuf = (uch *)malloc(INBUFSIZ + 4);    /* 4 extra for hold[] (below) */
 | 
						|
    G.outbuf = (uch *)malloc(OUTBUFSIZ + 1);  /* 1 extra for string term. */
 | 
						|
 | 
						|
    if ((G.inbuf == (uch *)NULL) || (G.outbuf == (uch *)NULL)) {
 | 
						|
        Info(slide, 0x401, ((char *)slide,
 | 
						|
          LoadFarString(CannotAllocateBuffers)));
 | 
						|
        return(PK_MEM);
 | 
						|
    }
 | 
						|
    G.hold = G.inbuf + INBUFSIZ;     /* to check for boundary-spanning sigs */
 | 
						|
#ifndef VMS     /* VMS uses its own buffer scheme for textmode flush(). */
 | 
						|
#ifdef SMALL_MEM
 | 
						|
    G.outbuf2 = G.outbuf+RAWBUFSIZ;  /* never changes */
 | 
						|
#endif
 | 
						|
#endif /* !VMS */
 | 
						|
 | 
						|
#if 0 /* CRC_32_TAB has been NULLified by CONSTRUCTGLOBALS !!!! */
 | 
						|
    /* allocate the CRC table only later when we know we have a zipfile */
 | 
						|
    CRC_32_TAB = NULL;
 | 
						|
#endif /* 0 */
 | 
						|
 | 
						|
    /* finish up initialization of magic signature strings */
 | 
						|
    local_hdr_sig[0]  /* = extd_local_sig[0] */  = 0x50;   /* ASCII 'P', */
 | 
						|
    central_hdr_sig[0] = end_central_sig[0] = 0x50;     /* not EBCDIC */
 | 
						|
 | 
						|
    local_hdr_sig[1]  /* = extd_local_sig[1] */  = 0x4B;   /* ASCII 'K', */
 | 
						|
    central_hdr_sig[1] = end_central_sig[1] = 0x4B;     /* not EBCDIC */
 | 
						|
 | 
						|
/*---------------------------------------------------------------------------
 | 
						|
    Make sure timezone info is set correctly; localtime() returns GMT on
 | 
						|
    some OSes (e.g., Solaris 2.x) if this isn't done first.  The ifdefs were
 | 
						|
    initially copied from dos_to_unix_time() in fileio.c. probably, they are
 | 
						|
    still too strict; any listed OS that supplies tzset(), regardless of
 | 
						|
    whether the function does anything, should be removed from the ifdefs.
 | 
						|
  ---------------------------------------------------------------------------*/
 | 
						|
 | 
						|
#if (defined(IZ_CHECK_TZ) && defined(USE_EF_UT_TIME))
 | 
						|
#  ifndef VALID_TIMEZONE
 | 
						|
#     define VALID_TIMEZONE(tmp) \
 | 
						|
             (((tmp = getenv("TZ")) != NULL) && (*tmp != '\0'))
 | 
						|
#  endif
 | 
						|
    {
 | 
						|
        char *p;
 | 
						|
        G.tz_is_valid = VALID_TIMEZONE(p);
 | 
						|
#  ifndef SFX
 | 
						|
        if (!G.tz_is_valid) {
 | 
						|
            Info(slide, 0x401, ((char *)slide, LoadFarString(WarnInvalidTZ)));
 | 
						|
            error_in_archive = error = PK_WARN;
 | 
						|
        }
 | 
						|
#  endif /* !SFX */
 | 
						|
    }
 | 
						|
#endif /* IZ_CHECK_TZ && USE_EF_UT_TIME */
 | 
						|
 | 
						|
/* For systems that do not have tzset() but supply this function using another
 | 
						|
   name (_tzset() or something similar), an appropiate "#define tzset ..."
 | 
						|
   should be added to the system specifc configuration section.  */
 | 
						|
#if (!defined(T20_VMS) && !defined(MACOS) && !defined(RISCOS) && !defined(QDOS))
 | 
						|
#if (!defined(BSD) && !defined(MTS) && !defined(CMS_MVS) && !defined(TANDEM))
 | 
						|
    tzset();
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
 | 
						|
/*---------------------------------------------------------------------------
 | 
						|
    Match (possible) wildcard zipfile specification with existing files and
 | 
						|
    attempt to process each.  If no hits, try again after appending ".zip"
 | 
						|
    suffix.  If still no luck, give up.
 | 
						|
  ---------------------------------------------------------------------------*/
 | 
						|
 | 
						|
#ifdef SFX
 | 
						|
    if ((error = do_seekable(__G__ 0)) == PK_NOZIP) {
 | 
						|
#ifdef EXE_EXTENSION
 | 
						|
        int len=strlen(G.argv0);
 | 
						|
 | 
						|
        /* append .exe if appropriate; also .sfx? */
 | 
						|
        if ( (G.zipfn = (char *)malloc(len+sizeof(EXE_EXTENSION))) !=
 | 
						|
             (char *)NULL ) {
 | 
						|
            strcpy(G.zipfn, G.argv0);
 | 
						|
            strcpy(G.zipfn+len, EXE_EXTENSION);
 | 
						|
            error = do_seekable(__G__ 0);
 | 
						|
            free(G.zipfn);
 | 
						|
            G.zipfn = G.argv0;  /* for "cannot find myself" message only */
 | 
						|
        }
 | 
						|
#endif /* EXE_EXTENSION */
 | 
						|
#ifdef WIN32
 | 
						|
        G.zipfn = G.argv0;  /* for "cannot find myself" message only */
 | 
						|
#endif
 | 
						|
    }
 | 
						|
    if (error) {
 | 
						|
        if (error == IZ_DIR)
 | 
						|
            error_in_archive = PK_NOZIP;
 | 
						|
        else
 | 
						|
            error_in_archive = error;
 | 
						|
        if (error == PK_NOZIP)
 | 
						|
            Info(slide, 1, ((char *)slide, LoadFarString(CannotFindMyself),
 | 
						|
              G.zipfn));
 | 
						|
    }
 | 
						|
 | 
						|
#else /* !SFX */
 | 
						|
    NumWinFiles = NumLoseFiles = NumWarnFiles = 0;
 | 
						|
    files = NumMissDirs = NumMissFiles = 0;
 | 
						|
 | 
						|
    while ((G.zipfn = do_wild(__G__ G.wildzipfn)) != (char *)NULL) {
 | 
						|
        Trace((stderr, "do_wild( %s ) returns %s\n", G.wildzipfn, G.zipfn));
 | 
						|
 | 
						|
        lastzipfn = G.zipfn;
 | 
						|
 | 
						|
        /* print a blank line between the output of different zipfiles */
 | 
						|
        if (!uO.qflag  &&  error != PK_NOZIP  &&  error != IZ_DIR
 | 
						|
#ifdef TIMESTAMP
 | 
						|
            && (!uO.T_flag || uO.zipinfo_mode)
 | 
						|
#endif
 | 
						|
            && (NumWinFiles+NumLoseFiles+NumWarnFiles+NumMissFiles) > 0)
 | 
						|
            (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0);
 | 
						|
 | 
						|
        if ((error = do_seekable(__G__ 0)) == PK_WARN)
 | 
						|
            ++NumWarnFiles;
 | 
						|
        else if (error == IZ_DIR)
 | 
						|
            ++NumMissDirs;
 | 
						|
        else if (error == PK_NOZIP)
 | 
						|
            ++NumMissFiles;
 | 
						|
        else if (error)
 | 
						|
            ++NumLoseFiles;
 | 
						|
        else
 | 
						|
			++NumWinFiles;
 | 
						|
 | 
						|
        if(!uO.vflag)
 | 
						|
			files = NumWinFiles;
 | 
						|
 | 
						|
        if (error != IZ_DIR && error > error_in_archive)
 | 
						|
            error_in_archive = error;
 | 
						|
        Trace((stderr, "do_seekable(0) returns %d\n", error));
 | 
						|
#ifdef WINDLL
 | 
						|
        if (error == IZ_CTRLC) {
 | 
						|
            free_G_buffers(__G);
 | 
						|
            return error;
 | 
						|
        }
 | 
						|
#endif
 | 
						|
 | 
						|
    } /* end while-loop (wildcard zipfiles) */
 | 
						|
 | 
						|
    if ((NumWinFiles + NumWarnFiles + NumLoseFiles) == 0  &&
 | 
						|
        (NumMissDirs + NumMissFiles) == 1  &&  lastzipfn != (char *)NULL)
 | 
						|
    {
 | 
						|
        NumMissDirs = NumMissFiles = 0;
 | 
						|
        if (error_in_archive == PK_NOZIP)
 | 
						|
            error_in_archive = PK_COOL;
 | 
						|
 | 
						|
#if (!defined(UNIX) && !defined(AMIGA)) /* filenames with wildcard characters */
 | 
						|
        if (iswild(G.wildzipfn))
 | 
						|
            Info(slide, 0x401, ((char *)slide,
 | 
						|
              LoadFarString(CannotFindWildcardMatch), uO.zipinfo_mode?
 | 
						|
              LoadFarStringSmall(Zipnfo) : LoadFarStringSmall(Unzip),
 | 
						|
              G.wildzipfn));
 | 
						|
        else
 | 
						|
#endif
 | 
						|
        {
 | 
						|
            char *p = lastzipfn + strlen(lastzipfn);
 | 
						|
 | 
						|
            G.zipfn = lastzipfn;
 | 
						|
            strcpy(p, ZSUFX);
 | 
						|
 | 
						|
#if defined(UNIX) || defined(QDOS)
 | 
						|
   /* only Unix has case-sensitive filesystems */
 | 
						|
   /* Well FlexOS (sometimes) also has them,  but support is per media */
 | 
						|
   /* and a pig to code for,  so treat as case insensitive for now */
 | 
						|
   /* we do this under QDOS to check for .zip as well as _zip */
 | 
						|
            if ((error = do_seekable(__G__ 0)) == PK_NOZIP || error == IZ_DIR) {
 | 
						|
                if (error == IZ_DIR)
 | 
						|
                    ++NumMissDirs;
 | 
						|
                strcpy(p, ALT_ZSUFX);
 | 
						|
                error = do_seekable(__G__ 1);
 | 
						|
            }
 | 
						|
#else
 | 
						|
            error = do_seekable(__G__ 1);
 | 
						|
#endif
 | 
						|
            if (error == PK_WARN)   /* GRR: make this a switch/case stmt ... */
 | 
						|
                ++NumWarnFiles;
 | 
						|
            else if (error == IZ_DIR)
 | 
						|
                ++NumMissDirs;
 | 
						|
            else if (error == PK_NOZIP)
 | 
						|
                /* increment again => bug: "1 file had no zipfile directory." */
 | 
						|
                /* ++NumMissFiles */ ;
 | 
						|
            else if (error)
 | 
						|
                ++NumLoseFiles;
 | 
						|
            else
 | 
						|
                ++NumWinFiles;
 | 
						|
 | 
						|
            if (error > error_in_archive)
 | 
						|
                error_in_archive = error;
 | 
						|
            Trace((stderr, "do_seekable(1) returns %d\n", error));
 | 
						|
#ifdef WINDLL
 | 
						|
            if (error == IZ_CTRLC) {
 | 
						|
                free_G_buffers(__G);
 | 
						|
                return error;
 | 
						|
            }
 | 
						|
#endif
 | 
						|
        }
 | 
						|
    }
 | 
						|
#endif /* ?SFX */
 | 
						|
 | 
						|
/*---------------------------------------------------------------------------
 | 
						|
    Print summary of all zipfiles, assuming zipfile spec was a wildcard (no
 | 
						|
    need for a summary if just one zipfile).
 | 
						|
  ---------------------------------------------------------------------------*/
 | 
						|
 | 
						|
#ifndef SFX
 | 
						|
    if (iswild(G.wildzipfn) && uO.qflag < 3
 | 
						|
#ifdef TIMESTAMP
 | 
						|
        && !(uO.T_flag && uO.qflag && !uO.zipinfo_mode)
 | 
						|
#endif
 | 
						|
                                                    )
 | 
						|
    {
 | 
						|
        if ((NumMissFiles + NumLoseFiles + NumWarnFiles > 0 || NumWinFiles != 1)
 | 
						|
#ifdef TIMESTAMP
 | 
						|
            && !(uO.T_flag && !uO.zipinfo_mode)
 | 
						|
#endif
 | 
						|
            && !(uO.tflag && uO.qflag > 1))
 | 
						|
            (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0x401);
 | 
						|
        if ((NumWinFiles > 1) || (NumWinFiles == 1 &&
 | 
						|
            NumMissDirs + NumMissFiles + NumLoseFiles + NumWarnFiles > 0))
 | 
						|
            Info(slide, 0x401, ((char *)slide, LoadFarString(FilesProcessOK),
 | 
						|
              NumWinFiles, (NumWinFiles == 1)? " was" : "s were"));
 | 
						|
        if (NumWarnFiles > 0)
 | 
						|
            Info(slide, 0x401, ((char *)slide, LoadFarString(ArchiveWarning),
 | 
						|
              NumWarnFiles, (NumWarnFiles == 1)? "" : "s"));
 | 
						|
        if (NumLoseFiles > 0)
 | 
						|
            Info(slide, 0x401, ((char *)slide, LoadFarString(ArchiveFatalError),
 | 
						|
              NumLoseFiles, (NumLoseFiles == 1)? "" : "s"));
 | 
						|
        if (NumMissFiles > 0)
 | 
						|
            Info(slide, 0x401, ((char *)slide,
 | 
						|
              LoadFarString(FileHadNoZipfileDir), NumMissFiles,
 | 
						|
              (NumMissFiles == 1)? "" : "s"));
 | 
						|
        if (NumMissDirs == 1)
 | 
						|
            Info(slide, 0x401, ((char *)slide, LoadFarString(ZipfileWasDir)));
 | 
						|
        else if (NumMissDirs > 0)
 | 
						|
            Info(slide, 0x401, ((char *)slide,
 | 
						|
              LoadFarString(ManyZipfilesWereDir), NumMissDirs));
 | 
						|
        if (NumWinFiles + NumLoseFiles + NumWarnFiles == 0)
 | 
						|
            Info(slide, 0x401, ((char *)slide, LoadFarString(NoZipfileFound)));
 | 
						|
    }
 | 
						|
#endif /* !SFX */
 | 
						|
 | 
						|
    /* free allocated memory */
 | 
						|
    free_G_buffers(__G);
 | 
						|
 | 
						|
    return error_in_archive;
 | 
						|
 | 
						|
} /* end function process_zipfiles() */
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/*****************************/
 | 
						|
/* Function free_G_buffers() */
 | 
						|
/*****************************/
 | 
						|
 | 
						|
void free_G_buffers(__G)     /* releases all memory allocated in global vars */
 | 
						|
    __GDEF
 | 
						|
{
 | 
						|
    inflate_free(__G);
 | 
						|
    checkdir(__G__ (char *)NULL, END);
 | 
						|
 | 
						|
#ifdef DYNALLOC_CRCTAB
 | 
						|
    if (CRC_32_TAB) {
 | 
						|
        free_crc_table();
 | 
						|
        CRC_32_TAB = NULL;
 | 
						|
    }
 | 
						|
#endif
 | 
						|
 | 
						|
   if (G.key != (char *)NULL) {
 | 
						|
        free(G.key);
 | 
						|
        G.key = (char *)NULL;
 | 
						|
   }
 | 
						|
 | 
						|
#if (!defined(VMS) && !defined(SMALL_MEM))
 | 
						|
    /* VMS uses its own buffer scheme for textmode flush() */
 | 
						|
    if (G.outbuf2) {
 | 
						|
        free(G.outbuf2);   /* malloc'd ONLY if unshrink and -a */
 | 
						|
        G.outbuf2 = (uch *)NULL;
 | 
						|
    }
 | 
						|
#endif
 | 
						|
 | 
						|
    if (G.outbuf)
 | 
						|
        free(G.outbuf);
 | 
						|
    if (G.inbuf)
 | 
						|
        free(G.inbuf);
 | 
						|
    G.inbuf = G.outbuf = (uch *)NULL;
 | 
						|
 | 
						|
#ifdef MALLOC_WORK
 | 
						|
    if (G.area.Slide) {
 | 
						|
        free(G.area.Slide);
 | 
						|
        G.area.Slide = (uch *)NULL;
 | 
						|
    }
 | 
						|
#endif
 | 
						|
 | 
						|
} /* end function free_G_buffers() */
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/**************************/
 | 
						|
/* Function do_seekable() */
 | 
						|
/**************************/
 | 
						|
 | 
						|
static int do_seekable(__G__ lastchance)        /* return PK-type error code */
 | 
						|
    __GDEF
 | 
						|
    int lastchance;
 | 
						|
{
 | 
						|
#ifndef SFX
 | 
						|
    /* static int no_ecrec = FALSE;  SKM: moved to globals.h */
 | 
						|
    int maybe_exe=FALSE;
 | 
						|
    int too_weird_to_continue=FALSE;
 | 
						|
#ifdef TIMESTAMP
 | 
						|
    time_t uxstamp;
 | 
						|
    unsigned nmember = 0;
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
    int error=0, error_in_archive;
 | 
						|
 | 
						|
 | 
						|
/*---------------------------------------------------------------------------
 | 
						|
    Open the zipfile for reading in BINARY mode to prevent CR/LF translation,
 | 
						|
    which would corrupt the bit streams.
 | 
						|
  ---------------------------------------------------------------------------*/
 | 
						|
 | 
						|
    if (SSTAT(G.zipfn, &G.statbuf) ||
 | 
						|
        (error = S_ISDIR(G.statbuf.st_mode)) != 0)
 | 
						|
    {
 | 
						|
#ifndef SFX
 | 
						|
        if (lastchance) {
 | 
						|
#if defined(UNIX) || defined(QDOS)
 | 
						|
            if (G.no_ecrec)
 | 
						|
                Info(slide, 1, ((char *)slide,
 | 
						|
                  LoadFarString(CannotFindZipfileDirMsg), uO.zipinfo_mode?
 | 
						|
                  LoadFarStringSmall(Zipnfo) : LoadFarStringSmall(Unzip),
 | 
						|
                  G.wildzipfn, uO.zipinfo_mode? "  " : "", G.wildzipfn,
 | 
						|
                  G.zipfn));
 | 
						|
            else
 | 
						|
                Info(slide, 1, ((char *)slide,
 | 
						|
                  LoadFarString(CannotFindEitherZipfile), uO.zipinfo_mode?
 | 
						|
                  LoadFarStringSmall(Zipnfo) : LoadFarStringSmall(Unzip),
 | 
						|
                  G.wildzipfn, G.wildzipfn, G.zipfn));
 | 
						|
#else /* !UNIX */
 | 
						|
            if (G.no_ecrec)
 | 
						|
                Info(slide, 0x401, ((char *)slide,
 | 
						|
                  LoadFarString(CannotFindZipfileDirMsg), uO.zipinfo_mode?
 | 
						|
                  LoadFarStringSmall(Zipnfo) : LoadFarStringSmall(Unzip),
 | 
						|
                  G.wildzipfn, uO.zipinfo_mode? "  " : "", G.zipfn));
 | 
						|
            else
 | 
						|
                Info(slide, 0x401, ((char *)slide,
 | 
						|
                  LoadFarString(CannotFindEitherZipfile), uO.zipinfo_mode?
 | 
						|
                  LoadFarStringSmall(Zipnfo) : LoadFarStringSmall(Unzip),
 | 
						|
                  G.wildzipfn, G.zipfn));
 | 
						|
#endif /* ?UNIX */
 | 
						|
        }
 | 
						|
#endif /* !SFX */
 | 
						|
        return error? IZ_DIR : PK_NOZIP;
 | 
						|
    }
 | 
						|
    G.ziplen = G.statbuf.st_size;
 | 
						|
 | 
						|
#ifndef SFX
 | 
						|
#if defined(UNIX) || defined(DOS_OS2_W32)
 | 
						|
    if (G.statbuf.st_mode & S_IEXEC)   /* no extension on Unix exes:  might */
 | 
						|
        maybe_exe = TRUE;               /*  find unzip, not unzip.zip; etc. */
 | 
						|
#endif
 | 
						|
#endif /* !SFX */
 | 
						|
 | 
						|
#ifdef VMS
 | 
						|
    if (check_format(__G))              /* check for variable-length format */
 | 
						|
        return PK_ERR;
 | 
						|
#endif
 | 
						|
 | 
						|
    if (open_input_file(__G))   /* this should never happen, given */
 | 
						|
        return PK_NOZIP;        /*  the stat() test above, but... */
 | 
						|
 | 
						|
/*---------------------------------------------------------------------------
 | 
						|
    Find and process the end-of-central-directory header.  UnZip need only
 | 
						|
    check last 65557 bytes of zipfile:  comment may be up to 65535, end-of-
 | 
						|
    central-directory record is 18 bytes, and signature itself is 4 bytes;
 | 
						|
    add some to allow for appended garbage.  Since ZipInfo is often used as
 | 
						|
    a debugging tool, search the whole zipfile if zipinfo_mode is true.
 | 
						|
  ---------------------------------------------------------------------------*/
 | 
						|
 | 
						|
    /* initialize the CRC table pointer (once) */
 | 
						|
    if (CRC_32_TAB == NULL) {
 | 
						|
        if ((CRC_32_TAB = get_crc_table()) == NULL)
 | 
						|
            return PK_MEM;
 | 
						|
    }
 | 
						|
 | 
						|
#if (!defined(SFX) || defined(SFX_EXDIR))
 | 
						|
    /* check out if specified extraction root directory exists */
 | 
						|
    if (uO.exdir != (char *)NULL && G.extract_flag) {
 | 
						|
        G.create_dirs = !uO.fflag;
 | 
						|
        if ((error = checkdir(__G__ uO.exdir, ROOT)) > 2)
 | 
						|
            return error;   /* out of memory, or file in way */
 | 
						|
    }
 | 
						|
#endif /* !SFX || SFX_EXDIR */
 | 
						|
 | 
						|
    G.cur_zipfile_bufstart = 0;
 | 
						|
    G.inptr = G.inbuf;
 | 
						|
 | 
						|
#if (!defined(WINDLL) && !defined(SFX))
 | 
						|
#ifdef TIMESTAMP
 | 
						|
    if (!uO.zipinfo_mode && !uO.qflag && !uO.T_flag)
 | 
						|
#else
 | 
						|
    if (!uO.zipinfo_mode && !uO.qflag)
 | 
						|
#endif
 | 
						|
#ifdef WIN32    /* Win32 console may require codepage conversion for G.zipfn */
 | 
						|
        Info(slide, 0, ((char *)slide, "Archive:  %s\n", FnFilter1(G.zipfn)));
 | 
						|
#else
 | 
						|
        Info(slide, 0, ((char *)slide, "Archive:  %s\n", G.zipfn));
 | 
						|
#endif
 | 
						|
#endif /* !WINDLL && !SFX */
 | 
						|
 | 
						|
    if ((
 | 
						|
#ifndef NO_ZIPINFO
 | 
						|
         uO.zipinfo_mode &&
 | 
						|
          ((error_in_archive = find_ecrec(__G__ G.ziplen)) != 0 ||
 | 
						|
          (error_in_archive = zi_end_central(__G)) > PK_WARN))
 | 
						|
        || (!uO.zipinfo_mode &&
 | 
						|
#endif
 | 
						|
          ((error_in_archive = find_ecrec(__G__ MIN(G.ziplen,66000L))) != 0 ||
 | 
						|
          (error_in_archive = uz_end_central(__G)) > PK_WARN)))
 | 
						|
    {
 | 
						|
        CLOSE_INFILE();
 | 
						|
 | 
						|
#ifdef SFX
 | 
						|
        ++lastchance;   /* avoid picky compiler warnings */
 | 
						|
        return error_in_archive;
 | 
						|
#else
 | 
						|
        if (maybe_exe)
 | 
						|
            Info(slide, 0x401, ((char *)slide, LoadFarString(MaybeExe),
 | 
						|
            G.zipfn));
 | 
						|
        if (lastchance)
 | 
						|
            return error_in_archive;
 | 
						|
        else {
 | 
						|
            G.no_ecrec = TRUE;    /* assume we found wrong file:  e.g., */
 | 
						|
            return PK_NOZIP;       /*  unzip instead of unzip.zip */
 | 
						|
        }
 | 
						|
#endif /* ?SFX */
 | 
						|
    }
 | 
						|
 | 
						|
    if ((uO.zflag > 0) && !uO.zipinfo_mode) { /* unzip: zflag = comment ONLY */
 | 
						|
        CLOSE_INFILE();
 | 
						|
        return error_in_archive;
 | 
						|
    }
 | 
						|
 | 
						|
/*---------------------------------------------------------------------------
 | 
						|
    Test the end-of-central-directory info for incompatibilities (multi-disk
 | 
						|
    archives) or inconsistencies (missing or extra bytes in zipfile).
 | 
						|
  ---------------------------------------------------------------------------*/
 | 
						|
 | 
						|
#ifdef NO_MULTIPART
 | 
						|
    error = !uO.zipinfo_mode && (G.ecrec.number_this_disk == 1) &&
 | 
						|
            (G.ecrec.num_disk_start_cdir == 1);
 | 
						|
#else
 | 
						|
    error = !uO.zipinfo_mode && (G.ecrec.number_this_disk != 0);
 | 
						|
#endif
 | 
						|
 | 
						|
#ifndef SFX
 | 
						|
    if (uO.zipinfo_mode &&
 | 
						|
        G.ecrec.number_this_disk != G.ecrec.num_disk_start_cdir)
 | 
						|
    {
 | 
						|
        if (G.ecrec.number_this_disk > G.ecrec.num_disk_start_cdir) {
 | 
						|
            Info(slide, 0x401, ((char *)slide,
 | 
						|
              LoadFarString(CentDirNotInZipMsg), G.zipfn,
 | 
						|
              G.ecrec.number_this_disk, G.ecrec.num_disk_start_cdir));
 | 
						|
            error_in_archive = PK_FIND;
 | 
						|
            too_weird_to_continue = TRUE;
 | 
						|
        } else {
 | 
						|
            Info(slide, 0x401, ((char *)slide,
 | 
						|
              LoadFarString(EndCentDirBogus), G.zipfn,
 | 
						|
              G.ecrec.number_this_disk, G.ecrec.num_disk_start_cdir));
 | 
						|
            error_in_archive = PK_WARN;
 | 
						|
        }
 | 
						|
#ifdef NO_MULTIPART   /* concatenation of multiple parts works in some cases */
 | 
						|
    } else if (!uO.zipinfo_mode && !error && G.ecrec.number_this_disk != 0) {
 | 
						|
        Info(slide, 0x401, ((char *)slide, LoadFarString(NoMultiDiskArcSupport),
 | 
						|
          G.zipfn));
 | 
						|
        error_in_archive = PK_FIND;
 | 
						|
        too_weird_to_continue = TRUE;
 | 
						|
#endif
 | 
						|
    }
 | 
						|
 | 
						|
    if (!too_weird_to_continue) {  /* (relatively) normal zipfile:  go for it */
 | 
						|
        if (error) {
 | 
						|
            Info(slide, 0x401, ((char *)slide, LoadFarString(MaybePakBug),
 | 
						|
              G.zipfn));
 | 
						|
            error_in_archive = PK_WARN;
 | 
						|
        }
 | 
						|
#endif /* !SFX */
 | 
						|
        if ((G.extra_bytes = G.real_ecrec_offset-G.expect_ecrec_offset) <
 | 
						|
            (LONGINT)0)
 | 
						|
        {
 | 
						|
            Info(slide, 0x401, ((char *)slide, LoadFarString(MissingBytes),
 | 
						|
              G.zipfn, (long)(-G.extra_bytes)));
 | 
						|
            error_in_archive = PK_ERR;
 | 
						|
        } else if (G.extra_bytes > 0) {
 | 
						|
            if ((G.ecrec.offset_start_central_directory == 0) &&
 | 
						|
                (G.ecrec.size_central_directory != 0))   /* zip 1.5 -go bug */
 | 
						|
            {
 | 
						|
                Info(slide, 0x401, ((char *)slide,
 | 
						|
                  LoadFarString(NullCentDirOffset), G.zipfn));
 | 
						|
                G.ecrec.offset_start_central_directory = G.extra_bytes;
 | 
						|
                G.extra_bytes = 0;
 | 
						|
                error_in_archive = PK_ERR;
 | 
						|
            }
 | 
						|
#ifndef SFX
 | 
						|
            else {
 | 
						|
                Info(slide, 0x401, ((char *)slide,
 | 
						|
                  LoadFarString(ExtraBytesAtStart), G.zipfn,
 | 
						|
                  (long)G.extra_bytes, (G.extra_bytes == 1)? "":"s"));
 | 
						|
                error_in_archive = PK_WARN;
 | 
						|
            }
 | 
						|
#endif /* !SFX */
 | 
						|
        }
 | 
						|
 | 
						|
    /*-----------------------------------------------------------------------
 | 
						|
        Check for empty zipfile and exit now if so.
 | 
						|
      -----------------------------------------------------------------------*/
 | 
						|
 | 
						|
        if (G.expect_ecrec_offset==0L && G.ecrec.size_central_directory==0) {
 | 
						|
            if (uO.zipinfo_mode)
 | 
						|
                Info(slide, 0, ((char *)slide, "%sEmpty zipfile.\n",
 | 
						|
                  uO.lflag>9? "\n  " : ""));
 | 
						|
            else
 | 
						|
                Info(slide, 0x401, ((char *)slide, LoadFarString(ZipfileEmpty),
 | 
						|
                                    G.zipfn));
 | 
						|
            CLOSE_INFILE();
 | 
						|
            return (error_in_archive > PK_WARN)? error_in_archive : PK_WARN;
 | 
						|
        }
 | 
						|
 | 
						|
    /*-----------------------------------------------------------------------
 | 
						|
        Compensate for missing or extra bytes, and seek to where the start
 | 
						|
        of central directory should be.  If header not found, uncompensate
 | 
						|
        and try again (necessary for at least some Atari archives created
 | 
						|
        with STZip, as well as archives created by J.H. Holm's ZIPSPLIT 1.1).
 | 
						|
      -----------------------------------------------------------------------*/
 | 
						|
 | 
						|
        ZLSEEK( G.ecrec.offset_start_central_directory )
 | 
						|
#ifdef OLD_SEEK_TEST
 | 
						|
        if (readbuf(G.sig, 4) == 0) {
 | 
						|
            CLOSE_INFILE();
 | 
						|
            return PK_ERR;  /* file may be locked, or possibly disk error(?) */
 | 
						|
        }
 | 
						|
        if (strncmp(G.sig, central_hdr_sig, 4))
 | 
						|
#else
 | 
						|
        if ((readbuf(__G__ G.sig, 4) == 0) ||
 | 
						|
             strncmp(G.sig, central_hdr_sig, 4))
 | 
						|
#endif
 | 
						|
        {
 | 
						|
#ifndef SFX
 | 
						|
            long tmp = G.extra_bytes;
 | 
						|
#endif
 | 
						|
 | 
						|
            G.extra_bytes = 0;
 | 
						|
            ZLSEEK( G.ecrec.offset_start_central_directory )
 | 
						|
            if ((readbuf(__G__ G.sig, 4) == 0) ||
 | 
						|
                strncmp(G.sig, central_hdr_sig, 4))
 | 
						|
            {
 | 
						|
                Info(slide, 0x401, ((char *)slide,
 | 
						|
                  LoadFarString(CentDirStartNotFound), G.zipfn,
 | 
						|
                  LoadFarStringSmall(ReportMsg)));
 | 
						|
                CLOSE_INFILE();
 | 
						|
                return PK_BADERR;
 | 
						|
            }
 | 
						|
#ifndef SFX
 | 
						|
            Info(slide, 0x401, ((char *)slide, LoadFarString(CentDirTooLong),
 | 
						|
              G.zipfn, -tmp));
 | 
						|
#endif
 | 
						|
            error_in_archive = PK_ERR;
 | 
						|
        }
 | 
						|
 | 
						|
    /*-----------------------------------------------------------------------
 | 
						|
        Seek to the start of the central directory one last time, since we
 | 
						|
        have just read the first entry's signature bytes; then list, extract
 | 
						|
        or test member files as instructed, and close the zipfile.
 | 
						|
      -----------------------------------------------------------------------*/
 | 
						|
 | 
						|
        Trace((stderr, "about to extract/list files (error = %d)\n",
 | 
						|
          error_in_archive));
 | 
						|
 | 
						|
        ZLSEEK( G.ecrec.offset_start_central_directory )
 | 
						|
 | 
						|
#ifdef DLL
 | 
						|
        /* G.fValidate is used only to look at an archive to see if
 | 
						|
           it appears to be a valid archive.  There is no interest
 | 
						|
           in what the archive contains, nor in validating that the
 | 
						|
           entries in the archive are in good condition.  This is
 | 
						|
           currently used only in the Windows DLLs for purposes of
 | 
						|
           checking archives within an archive to determine whether
 | 
						|
           or not to display the inner archives.
 | 
						|
         */
 | 
						|
        if (!G.fValidate)
 | 
						|
#endif
 | 
						|
        {
 | 
						|
#ifndef NO_ZIPINFO
 | 
						|
            if (uO.zipinfo_mode)
 | 
						|
                error = zipinfo(__G);                     /* ZIPINFO 'EM */
 | 
						|
            else
 | 
						|
#endif
 | 
						|
#ifndef SFX
 | 
						|
#ifdef TIMESTAMP
 | 
						|
            if (uO.T_flag)
 | 
						|
                error = get_time_stamp(__G__ &uxstamp, &nmember);
 | 
						|
            else
 | 
						|
#endif
 | 
						|
            if (uO.vflag && !uO.tflag && !uO.cflag)
 | 
						|
                error = list_files(__G);              /* LIST 'EM */
 | 
						|
            else
 | 
						|
#endif /* !SFX */
 | 
						|
                error = extract_or_test_files(__G);   /* EXTRACT OR TEST 'EM */
 | 
						|
 | 
						|
            Trace((stderr, "done with extract/list files (error = %d)\n",
 | 
						|
                   error));
 | 
						|
        }
 | 
						|
 | 
						|
        if (error > error_in_archive)   /* don't overwrite stronger error */
 | 
						|
            error_in_archive = error;   /*  with (for example) a warning */
 | 
						|
#ifndef SFX
 | 
						|
    } /* end if (!too_weird_to_continue) */
 | 
						|
#endif
 | 
						|
 | 
						|
    CLOSE_INFILE();
 | 
						|
 | 
						|
#ifdef TIMESTAMP
 | 
						|
    if (uO.T_flag && !uO.zipinfo_mode && (nmember > 0)) {
 | 
						|
# ifdef WIN32
 | 
						|
        if (stamp_file(__G__ G.zipfn, uxstamp)) {       /* TIME-STAMP 'EM */
 | 
						|
# else
 | 
						|
        if (stamp_file(G.zipfn, uxstamp)) {             /* TIME-STAMP 'EM */
 | 
						|
# endif
 | 
						|
            Info(slide, 0x201, ((char *)slide,
 | 
						|
              "warning:  cannot set time for %s\n", G.zipfn));
 | 
						|
            if (error_in_archive < PK_WARN)
 | 
						|
                error_in_archive = PK_WARN;
 | 
						|
        }
 | 
						|
    }
 | 
						|
#endif
 | 
						|
    return error_in_archive;
 | 
						|
 | 
						|
} /* end function do_seekable() */
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/*************************/
 | 
						|
/* Function find_ecrec() */
 | 
						|
/*************************/
 | 
						|
 | 
						|
static int find_ecrec(__G__ searchlen)          /* return PK-class error */
 | 
						|
    __GDEF
 | 
						|
    long searchlen;
 | 
						|
{
 | 
						|
    int i, numblks, found=FALSE;
 | 
						|
    LONGINT tail_len;
 | 
						|
    ec_byte_rec byterec;
 | 
						|
 | 
						|
 | 
						|
/*---------------------------------------------------------------------------
 | 
						|
    Treat case of short zipfile separately.
 | 
						|
  ---------------------------------------------------------------------------*/
 | 
						|
 | 
						|
    if (G.ziplen <= INBUFSIZ) {
 | 
						|
        lseek(G.zipfd, 0L, SEEK_SET);
 | 
						|
        if ((G.incnt = read(G.zipfd,(char *)G.inbuf,(unsigned int)G.ziplen))
 | 
						|
            == (int)G.ziplen)
 | 
						|
 | 
						|
            /* 'P' must be at least 22 bytes from end of zipfile */
 | 
						|
            for (G.inptr = G.inbuf+(int)G.ziplen-22;  G.inptr >= G.inbuf;
 | 
						|
                 --G.inptr)
 | 
						|
                if ((native(*G.inptr) == 'P')  &&
 | 
						|
                     !strncmp((char *)G.inptr, end_central_sig, 4)) {
 | 
						|
                    G.incnt -= (int)(G.inptr - G.inbuf);
 | 
						|
                    found = TRUE;
 | 
						|
                    break;
 | 
						|
                }
 | 
						|
 | 
						|
/*---------------------------------------------------------------------------
 | 
						|
    Zipfile is longer than INBUFSIZ:  may need to loop.  Start with short
 | 
						|
    block at end of zipfile (if not TOO short).
 | 
						|
  ---------------------------------------------------------------------------*/
 | 
						|
 | 
						|
    } else {
 | 
						|
        if ((tail_len = G.ziplen % INBUFSIZ) > ECREC_SIZE) {
 | 
						|
#ifdef USE_STRM_INPUT
 | 
						|
            fseek((FILE *)G.zipfd, G.ziplen-tail_len, SEEK_SET);
 | 
						|
            G.cur_zipfile_bufstart = ftell((FILE *)G.zipfd);
 | 
						|
#else /* !USE_STRM_INPUT */
 | 
						|
            G.cur_zipfile_bufstart = lseek(G.zipfd, G.ziplen-tail_len,
 | 
						|
              SEEK_SET);
 | 
						|
#endif /* ?USE_STRM_INPUT */
 | 
						|
            if ((G.incnt = read(G.zipfd, (char *)G.inbuf,
 | 
						|
                (unsigned int)tail_len)) != (int)tail_len)
 | 
						|
                goto fail;      /* it's expedient... */
 | 
						|
 | 
						|
            /* 'P' must be at least 22 bytes from end of zipfile */
 | 
						|
            for (G.inptr = G.inbuf+(int)tail_len-22;  G.inptr >= G.inbuf;
 | 
						|
                 --G.inptr)
 | 
						|
                if ((native(*G.inptr) == 'P')  &&
 | 
						|
                     !strncmp((char *)G.inptr, end_central_sig, 4)) {
 | 
						|
                    G.incnt -= (int)(G.inptr - G.inbuf);
 | 
						|
                    found = TRUE;
 | 
						|
                    break;
 | 
						|
                }
 | 
						|
            /* sig may span block boundary: */
 | 
						|
            strncpy((char *)G.hold, (char *)G.inbuf, 3);
 | 
						|
        } else
 | 
						|
            G.cur_zipfile_bufstart = G.ziplen - tail_len;
 | 
						|
 | 
						|
    /*-----------------------------------------------------------------------
 | 
						|
        Loop through blocks of zipfile data, starting at the end and going
 | 
						|
        toward the beginning.  In general, need not check whole zipfile for
 | 
						|
        signature, but may want to do so if testing.
 | 
						|
      -----------------------------------------------------------------------*/
 | 
						|
 | 
						|
        numblks = (int)((searchlen - tail_len + (INBUFSIZ-1)) / INBUFSIZ);
 | 
						|
        /*               ==amount=   ==done==   ==rounding==    =blksiz=  */
 | 
						|
 | 
						|
        for (i = 1;  !found && (i <= numblks);  ++i) {
 | 
						|
            G.cur_zipfile_bufstart -= INBUFSIZ;
 | 
						|
            lseek(G.zipfd, G.cur_zipfile_bufstart, SEEK_SET);
 | 
						|
            if ((G.incnt = read(G.zipfd,(char *)G.inbuf,INBUFSIZ))
 | 
						|
                != INBUFSIZ)
 | 
						|
                break;          /* fall through and fail */
 | 
						|
 | 
						|
            for (G.inptr = G.inbuf+INBUFSIZ-1;  G.inptr >= G.inbuf;
 | 
						|
                 --G.inptr)
 | 
						|
                if ((native(*G.inptr) == 'P')  &&
 | 
						|
                     !strncmp((char *)G.inptr, end_central_sig, 4)) {
 | 
						|
                    G.incnt -= (int)(G.inptr - G.inbuf);
 | 
						|
                    found = TRUE;
 | 
						|
                    break;
 | 
						|
                }
 | 
						|
            /* sig may span block boundary: */
 | 
						|
            strncpy((char *)G.hold, (char *)G.inbuf, 3);
 | 
						|
        }
 | 
						|
    } /* end if (ziplen > INBUFSIZ) */
 | 
						|
 | 
						|
/*---------------------------------------------------------------------------
 | 
						|
    Searched through whole region where signature should be without finding
 | 
						|
    it.  Print informational message and die a horrible death.
 | 
						|
  ---------------------------------------------------------------------------*/
 | 
						|
 | 
						|
fail:
 | 
						|
    if (!found) {
 | 
						|
        if (uO.qflag || uO.zipinfo_mode)
 | 
						|
            Info(slide, 0x401, ((char *)slide, "[%s]\n", G.zipfn));
 | 
						|
        Info(slide, 0x401, ((char *)slide,
 | 
						|
          LoadFarString(CentDirEndSigNotFound)));
 | 
						|
        return PK_ERR;   /* failed */
 | 
						|
    }
 | 
						|
 | 
						|
/*---------------------------------------------------------------------------
 | 
						|
    Found the signature, so get the end-central data before returning.  Do
 | 
						|
    any necessary machine-type conversions (byte ordering, structure padding
 | 
						|
    compensation) by reading data into character array and copying to struct.
 | 
						|
  ---------------------------------------------------------------------------*/
 | 
						|
 | 
						|
    G.real_ecrec_offset = G.cur_zipfile_bufstart + (G.inptr-G.inbuf);
 | 
						|
#ifdef TEST
 | 
						|
    pipeit("\n  found end-of-central-dir signature at offset %ld (%.8lXh)\n",
 | 
						|
      G.real_ecrec_offset, G.real_ecrec_offset);
 | 
						|
    pipeit("    from beginning of file; offset %d (%.4Xh) within block\n",
 | 
						|
      G.inptr-G.inbuf, G.inptr-G.inbuf);
 | 
						|
#endif
 | 
						|
 | 
						|
    if (readbuf(__G__ (char *)byterec, ECREC_SIZE+4) == 0)
 | 
						|
        return PK_EOF;
 | 
						|
 | 
						|
    G.ecrec.number_this_disk =
 | 
						|
      makeword(&byterec[NUMBER_THIS_DISK]);
 | 
						|
    G.ecrec.num_disk_start_cdir =
 | 
						|
      makeword(&byterec[NUM_DISK_WITH_START_CENTRAL_DIR]);
 | 
						|
    G.ecrec.num_entries_centrl_dir_ths_disk =
 | 
						|
      makeword(&byterec[NUM_ENTRIES_CENTRL_DIR_THS_DISK]);
 | 
						|
    G.ecrec.total_entries_central_dir =
 | 
						|
      makeword(&byterec[TOTAL_ENTRIES_CENTRAL_DIR]);
 | 
						|
    G.ecrec.size_central_directory =
 | 
						|
      makelong(&byterec[SIZE_CENTRAL_DIRECTORY]);
 | 
						|
    G.ecrec.offset_start_central_directory =
 | 
						|
      makelong(&byterec[OFFSET_START_CENTRAL_DIRECTORY]);
 | 
						|
    G.ecrec.zipfile_comment_length =
 | 
						|
      makeword(&byterec[ZIPFILE_COMMENT_LENGTH]);
 | 
						|
 | 
						|
    G.expect_ecrec_offset = G.ecrec.offset_start_central_directory +
 | 
						|
                          G.ecrec.size_central_directory;
 | 
						|
    return PK_COOL;
 | 
						|
 | 
						|
} /* end function find_ecrec() */
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/*****************************/
 | 
						|
/* Function uz_end_central() */
 | 
						|
/*****************************/
 | 
						|
 | 
						|
int uz_end_central(__G)    /* return PK-type error code */
 | 
						|
    __GDEF
 | 
						|
{
 | 
						|
    int error = PK_COOL;
 | 
						|
 | 
						|
 | 
						|
/*---------------------------------------------------------------------------
 | 
						|
    Get the zipfile comment (up to 64KB long), if any, and print it out.
 | 
						|
    Then position the file pointer to the beginning of the central directory
 | 
						|
    and fill buffer.
 | 
						|
  ---------------------------------------------------------------------------*/
 | 
						|
 | 
						|
#ifdef WINDLL
 | 
						|
    /* for comment button: */
 | 
						|
    if ((!G.fValidate) && (G.lpUserFunctions != NULL))
 | 
						|
       G.lpUserFunctions->cchComment = G.ecrec.zipfile_comment_length;
 | 
						|
    if (G.ecrec.zipfile_comment_length && (uO.zflag > 0))
 | 
						|
#else /* !WINDLL */
 | 
						|
    if (G.ecrec.zipfile_comment_length && (uO.zflag > 0 ||
 | 
						|
        (uO.zflag == 0 &&
 | 
						|
#ifdef TIMESTAMP
 | 
						|
                          !uO.T_flag &&
 | 
						|
#endif
 | 
						|
                                        !uO.qflag)))
 | 
						|
#endif /* ?WINDLL */
 | 
						|
    {
 | 
						|
        if (do_string(__G__ G.ecrec.zipfile_comment_length, DISPLAY)) {
 | 
						|
            Info(slide, 0x401, ((char *)slide,
 | 
						|
              LoadFarString(ZipfileCommTrunc1)));
 | 
						|
            error = PK_WARN;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return error;
 | 
						|
 | 
						|
} /* end function uz_end_central() */
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/************************************/
 | 
						|
/* Function process_cdir_file_hdr() */
 | 
						|
/************************************/
 | 
						|
 | 
						|
int process_cdir_file_hdr(__G)    /* return PK-type error code */
 | 
						|
    __GDEF
 | 
						|
{
 | 
						|
    int error;
 | 
						|
 | 
						|
 | 
						|
/*---------------------------------------------------------------------------
 | 
						|
    Get central directory info, save host and method numbers, and set flag
 | 
						|
    for lowercase conversion of filename, depending on the OS from which the
 | 
						|
    file is coming.
 | 
						|
  ---------------------------------------------------------------------------*/
 | 
						|
 | 
						|
    if ((error = get_cdir_ent(__G)) != 0)
 | 
						|
        return error;
 | 
						|
 | 
						|
    G.pInfo->hostnum = MIN(G.crec.version_made_by[1], NUM_HOSTS);
 | 
						|
/*  extnum = MIN(crec.version_needed_to_extract[1], NUM_HOSTS); */
 | 
						|
 | 
						|
    G.pInfo->lcflag = 0;
 | 
						|
    if (uO.L_flag)            /* user specified case-conversion */
 | 
						|
        switch (G.pInfo->hostnum) {
 | 
						|
            case FS_FAT_:     /* PKZIP and zip -k store in uppercase */
 | 
						|
            case CPM_:        /* like MS-DOS, right? */
 | 
						|
            case VM_CMS_:     /* all caps? */
 | 
						|
            case MVS_:        /* all caps? */
 | 
						|
            case TANDEM_:
 | 
						|
            case TOPS20_:
 | 
						|
            case VMS_:        /* our Zip uses lowercase, but ASi's doesn't */
 | 
						|
        /*  case Z_SYSTEM_:   ? */
 | 
						|
        /*  case QDOS_:       ? */
 | 
						|
                G.pInfo->lcflag = 1;   /* convert filename to lowercase */
 | 
						|
                break;
 | 
						|
 | 
						|
            default:     /* AMIGA_, FS_HPFS_, FS_NTFS_, MAC_, UNIX_, ATARI_, */
 | 
						|
                break;   /*  FS_VFAT_, BEOS_ (Z_SYSTEM_):  no conversion */
 | 
						|
        }
 | 
						|
 | 
						|
    /* do Amigas (AMIGA_) also have volume labels? */
 | 
						|
    if (IS_VOLID(G.crec.external_file_attributes) &&
 | 
						|
        (G.pInfo->hostnum == FS_FAT_ || G.pInfo->hostnum == FS_HPFS_ ||
 | 
						|
         G.pInfo->hostnum == FS_NTFS_ || G.pInfo->hostnum == ATARI_))
 | 
						|
    {
 | 
						|
        G.pInfo->vollabel = TRUE;
 | 
						|
        G.pInfo->lcflag = 0;        /* preserve case of volume labels */
 | 
						|
    } else
 | 
						|
        G.pInfo->vollabel = FALSE;
 | 
						|
 | 
						|
    return PK_COOL;
 | 
						|
 | 
						|
} /* end function process_cdir_file_hdr() */
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/***************************/
 | 
						|
/* Function get_cdir_ent() */
 | 
						|
/***************************/
 | 
						|
 | 
						|
int get_cdir_ent(__G)   /* return PK-type error code */
 | 
						|
    __GDEF
 | 
						|
{
 | 
						|
    cdir_byte_hdr byterec;
 | 
						|
 | 
						|
 | 
						|
/*---------------------------------------------------------------------------
 | 
						|
    Read the next central directory entry and do any necessary machine-type
 | 
						|
    conversions (byte ordering, structure padding compensation--do so by
 | 
						|
    copying the data from the array into which it was read (byterec) to the
 | 
						|
    usable struct (crec)).
 | 
						|
  ---------------------------------------------------------------------------*/
 | 
						|
 | 
						|
    if (readbuf(__G__ (char *)byterec, CREC_SIZE) == 0)
 | 
						|
        return PK_EOF;
 | 
						|
 | 
						|
    G.crec.version_made_by[0] = byterec[C_VERSION_MADE_BY_0];
 | 
						|
    G.crec.version_made_by[1] = byterec[C_VERSION_MADE_BY_1];
 | 
						|
    G.crec.version_needed_to_extract[0] =
 | 
						|
      byterec[C_VERSION_NEEDED_TO_EXTRACT_0];
 | 
						|
    G.crec.version_needed_to_extract[1] =
 | 
						|
      byterec[C_VERSION_NEEDED_TO_EXTRACT_1];
 | 
						|
 | 
						|
    G.crec.general_purpose_bit_flag =
 | 
						|
      makeword(&byterec[C_GENERAL_PURPOSE_BIT_FLAG]);
 | 
						|
    G.crec.compression_method =
 | 
						|
      makeword(&byterec[C_COMPRESSION_METHOD]);
 | 
						|
    G.crec.last_mod_dos_datetime =
 | 
						|
      makelong(&byterec[C_LAST_MOD_DOS_DATETIME]);
 | 
						|
    G.crec.crc32 =
 | 
						|
      makelong(&byterec[C_CRC32]);
 | 
						|
    G.crec.csize =
 | 
						|
      makelong(&byterec[C_COMPRESSED_SIZE]);
 | 
						|
    G.crec.ucsize =
 | 
						|
      makelong(&byterec[C_UNCOMPRESSED_SIZE]);
 | 
						|
    G.crec.filename_length =
 | 
						|
      makeword(&byterec[C_FILENAME_LENGTH]);
 | 
						|
    G.crec.extra_field_length =
 | 
						|
      makeword(&byterec[C_EXTRA_FIELD_LENGTH]);
 | 
						|
    G.crec.file_comment_length =
 | 
						|
      makeword(&byterec[C_FILE_COMMENT_LENGTH]);
 | 
						|
    G.crec.disk_number_start =
 | 
						|
      makeword(&byterec[C_DISK_NUMBER_START]);
 | 
						|
    G.crec.internal_file_attributes =
 | 
						|
      makeword(&byterec[C_INTERNAL_FILE_ATTRIBUTES]);
 | 
						|
    G.crec.external_file_attributes =
 | 
						|
      makelong(&byterec[C_EXTERNAL_FILE_ATTRIBUTES]);  /* LONG, not word! */
 | 
						|
    G.crec.relative_offset_local_header =
 | 
						|
      makelong(&byterec[C_RELATIVE_OFFSET_LOCAL_HEADER]);
 | 
						|
 | 
						|
    return PK_COOL;
 | 
						|
 | 
						|
} /* end function get_cdir_ent() */
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/*************************************/
 | 
						|
/* Function process_local_file_hdr() */
 | 
						|
/*************************************/
 | 
						|
 | 
						|
int process_local_file_hdr(__G)    /* return PK-type error code */
 | 
						|
    __GDEF
 | 
						|
{
 | 
						|
    local_byte_hdr byterec;
 | 
						|
 | 
						|
 | 
						|
/*---------------------------------------------------------------------------
 | 
						|
    Read the next local file header and do any necessary machine-type con-
 | 
						|
    versions (byte ordering, structure padding compensation--do so by copy-
 | 
						|
    ing the data from the array into which it was read (byterec) to the
 | 
						|
    usable struct (lrec)).
 | 
						|
  ---------------------------------------------------------------------------*/
 | 
						|
 | 
						|
    if (readbuf(__G__ (char *)byterec, LREC_SIZE) == 0)
 | 
						|
        return PK_EOF;
 | 
						|
 | 
						|
    G.lrec.version_needed_to_extract[0] =
 | 
						|
      byterec[L_VERSION_NEEDED_TO_EXTRACT_0];
 | 
						|
    G.lrec.version_needed_to_extract[1] =
 | 
						|
      byterec[L_VERSION_NEEDED_TO_EXTRACT_1];
 | 
						|
 | 
						|
    G.lrec.general_purpose_bit_flag =
 | 
						|
      makeword(&byterec[L_GENERAL_PURPOSE_BIT_FLAG]);
 | 
						|
    G.lrec.compression_method = makeword(&byterec[L_COMPRESSION_METHOD]);
 | 
						|
    G.lrec.last_mod_dos_datetime = makelong(&byterec[L_LAST_MOD_DOS_DATETIME]);
 | 
						|
    G.lrec.crc32 = makelong(&byterec[L_CRC32]);
 | 
						|
    G.lrec.csize = makelong(&byterec[L_COMPRESSED_SIZE]);
 | 
						|
    G.lrec.ucsize = makelong(&byterec[L_UNCOMPRESSED_SIZE]);
 | 
						|
    G.lrec.filename_length = makeword(&byterec[L_FILENAME_LENGTH]);
 | 
						|
    G.lrec.extra_field_length = makeword(&byterec[L_EXTRA_FIELD_LENGTH]);
 | 
						|
 | 
						|
    G.csize = (long) G.lrec.csize;
 | 
						|
    G.ucsize = (long) G.lrec.ucsize;
 | 
						|
 | 
						|
    if ((G.lrec.general_purpose_bit_flag & 8) != 0) {
 | 
						|
        /* can't trust local header, use central directory: */
 | 
						|
        G.lrec.crc32 = G.pInfo->crc;
 | 
						|
        G.csize = (long)(G.lrec.csize = G.pInfo->compr_size);
 | 
						|
        G.ucsize = (long)(G.lrec.ucsize = G.pInfo->uncompr_size);
 | 
						|
    }
 | 
						|
 | 
						|
    return PK_COOL;
 | 
						|
 | 
						|
} /* end function process_local_file_hdr() */
 | 
						|
 | 
						|
 | 
						|
#ifdef USE_EF_UT_TIME
 | 
						|
 | 
						|
/*******************************/
 | 
						|
/* Function ef_scan_for_izux() */
 | 
						|
/*******************************/
 | 
						|
 | 
						|
unsigned ef_scan_for_izux(ef_buf, ef_len, ef_is_c, dos_mdatetime,
 | 
						|
                          z_utim, z_uidgid)
 | 
						|
    uch *ef_buf;        /* buffer containing extra field */
 | 
						|
    unsigned ef_len;    /* total length of extra field */
 | 
						|
    int ef_is_c;        /* flag indicating "is central extra field" */
 | 
						|
    ulg dos_mdatetime;  /* last_mod_file_date_time in DOS format */
 | 
						|
    iztimes *z_utim;    /* return storage: atime, mtime, ctime */
 | 
						|
    ush *z_uidgid;      /* return storage: uid and gid */
 | 
						|
{
 | 
						|
    unsigned flags = 0;
 | 
						|
    unsigned eb_id;
 | 
						|
    unsigned eb_len;
 | 
						|
    int have_new_type_eb = FALSE;
 | 
						|
    int ut_zip_unzip_compatible = FALSE;
 | 
						|
 | 
						|
/*---------------------------------------------------------------------------
 | 
						|
    This function scans the extra field for EF_TIME, EF_IZUNIX2, EF_IZUNIX, or
 | 
						|
    EF_PKUNIX blocks containing Unix-style time_t (GMT) values for the entry's
 | 
						|
    access, creation, and modification time.
 | 
						|
    If a valid block is found, the time stamps are copied to the iztimes
 | 
						|
    structure (provided the z_utim pointer is not NULL).
 | 
						|
    If a IZUNIX2 block is found or the IZUNIX block contains UID/GID fields,
 | 
						|
    and the z_uidgid array pointer is valid (!= NULL), the owner info is
 | 
						|
    transfered as well.
 | 
						|
    The presence of an EF_TIME or EF_IZUNIX2 block results in ignoring all
 | 
						|
    data from probably present obsolete EF_IZUNIX blocks.
 | 
						|
    If multiple blocks of the same type are found, only the information from
 | 
						|
    the last block is used.
 | 
						|
    The return value is a combination of the EF_TIME Flags field with an
 | 
						|
    additional flag bit indicating the presence of valid UID/GID info,
 | 
						|
    or 0 in case of failure.
 | 
						|
  ---------------------------------------------------------------------------*/
 | 
						|
 | 
						|
    if (ef_len == 0 || ef_buf == NULL || (z_utim == 0 && z_uidgid == NULL))
 | 
						|
        return 0;
 | 
						|
 | 
						|
    TTrace((stderr,"\nef_scan_for_izux: scanning extra field of length %u\n",
 | 
						|
      ef_len));
 | 
						|
 | 
						|
    while (ef_len >= EB_HEADSIZE) {
 | 
						|
        eb_id = makeword(EB_ID + ef_buf);
 | 
						|
        eb_len = makeword(EB_LEN + ef_buf);
 | 
						|
 | 
						|
        if (eb_len > (ef_len - EB_HEADSIZE)) {
 | 
						|
            /* discovered some extra field inconsistency! */
 | 
						|
            TTrace((stderr,
 | 
						|
              "ef_scan_for_izux: block length %u > rest ef_size %u\n", eb_len,
 | 
						|
              ef_len - EB_HEADSIZE));
 | 
						|
            break;
 | 
						|
        }
 | 
						|
 | 
						|
        switch (eb_id) {
 | 
						|
          case EF_TIME:
 | 
						|
            flags &= ~0x0ff;    /* ignore previous IZUNIX or EF_TIME fields */
 | 
						|
            have_new_type_eb = TRUE;
 | 
						|
            if ( eb_len >= EB_UT_MINLEN && z_utim != NULL) {
 | 
						|
                unsigned eb_idx = EB_UT_TIME1;
 | 
						|
                TTrace((stderr,"ef_scan_for_izux: found TIME extra field\n"));
 | 
						|
                flags |= (ef_buf[EB_HEADSIZE+EB_UT_FLAGS] & 0x0ff);
 | 
						|
                if ((flags & EB_UT_FL_MTIME)) {
 | 
						|
                    if ((eb_idx+4) <= eb_len) {
 | 
						|
                        z_utim->mtime = makelong((EB_HEADSIZE+eb_idx) + ef_buf);
 | 
						|
                        eb_idx += 4;
 | 
						|
                        TTrace((stderr,"  UT e.f. modification time = %ld\n",
 | 
						|
                                z_utim->mtime));
 | 
						|
 | 
						|
                        if ((ulg)(z_utim->mtime) & (ulg)(0x80000000L)) {
 | 
						|
                            ut_zip_unzip_compatible =
 | 
						|
                              ((time_t)0x80000000L < (time_t)0L)
 | 
						|
                              ? (dos_mdatetime == DOSTIME_MINIMUM)
 | 
						|
                              : (dos_mdatetime >= DOSTIME_2038_01_18);
 | 
						|
                            if (!ut_zip_unzip_compatible) {
 | 
						|
                            /* UnZip interpretes mtime differently than Zip;
 | 
						|
                               without modtime: ignore complete UT field */
 | 
						|
                              flags &= ~0x0ff;  /* no time_t times available */
 | 
						|
                              TTrace((stderr,
 | 
						|
                                "  UT modtime range error; ignore e.f.!\n"));
 | 
						|
                              break;            /* stop scanning this field */
 | 
						|
                            }
 | 
						|
                        } else {
 | 
						|
                            /* cannot determine, safe assumption is FALSE */
 | 
						|
                            ut_zip_unzip_compatible = FALSE;
 | 
						|
                        }
 | 
						|
                    } else {
 | 
						|
                        flags &= ~EB_UT_FL_MTIME;
 | 
						|
                        TTrace((stderr,"  UT e.f. truncated; no modtime\n"));
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                if (ef_is_c) {
 | 
						|
                    break;      /* central version of TIME field ends here */
 | 
						|
                }
 | 
						|
 | 
						|
                if (flags & EB_UT_FL_ATIME) {
 | 
						|
                    if ((eb_idx+4) <= eb_len) {
 | 
						|
                        z_utim->atime = makelong((EB_HEADSIZE+eb_idx) + ef_buf);
 | 
						|
                        eb_idx += 4;
 | 
						|
                        TTrace((stderr,"  UT e.f. access time = %ld\n",
 | 
						|
                                z_utim->atime));
 | 
						|
                        if (((ulg)(z_utim->atime) & (ulg)(0x80000000L)) &&
 | 
						|
                            !ut_zip_unzip_compatible) {
 | 
						|
                            flags &= ~EB_UT_FL_ATIME;
 | 
						|
                            TTrace((stderr,
 | 
						|
                              "  UT access time range error: skip time!\n"));
 | 
						|
                        }
 | 
						|
                    } else {
 | 
						|
                        flags &= ~EB_UT_FL_ATIME;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                if (flags & EB_UT_FL_CTIME) {
 | 
						|
                    if ((eb_idx+4) <= eb_len) {
 | 
						|
                        z_utim->ctime = makelong((EB_HEADSIZE+eb_idx) + ef_buf);
 | 
						|
                        TTrace((stderr,"  UT e.f. creation time = %ld\n",
 | 
						|
                                z_utim->ctime));
 | 
						|
                        if (((ulg)(z_utim->ctime) & (ulg)(0x80000000L)) &&
 | 
						|
                            !ut_zip_unzip_compatible) {
 | 
						|
                            flags &= ~EB_UT_FL_CTIME;
 | 
						|
                            TTrace((stderr,
 | 
						|
                              "  UT creation time range error: skip time!\n"));
 | 
						|
                        }
 | 
						|
                    } else {
 | 
						|
                        flags &= ~EB_UT_FL_CTIME;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
            break;
 | 
						|
 | 
						|
          case EF_IZUNIX2:
 | 
						|
            if (!have_new_type_eb) {
 | 
						|
                flags &= ~0x0ff;        /* ignore any previous IZUNIX field */
 | 
						|
                have_new_type_eb = TRUE;
 | 
						|
            }
 | 
						|
            if (eb_len >= EB_UX2_MINLEN && z_uidgid != NULL) {
 | 
						|
                z_uidgid[0] = makeword((EB_HEADSIZE+EB_UX2_UID) + ef_buf);
 | 
						|
                z_uidgid[1] = makeword((EB_HEADSIZE+EB_UX2_GID) + ef_buf);
 | 
						|
                flags |= EB_UX2_VALID;   /* signal success */
 | 
						|
            }
 | 
						|
            break;
 | 
						|
 | 
						|
          case EF_IZUNIX:
 | 
						|
          case EF_PKUNIX:       /* PKUNIX e.f. layout is identical to IZUNIX */
 | 
						|
            if (eb_len >= EB_UX_MINLEN) {
 | 
						|
                TTrace((stderr,"ef_scan_for_izux: found %s extra field\n",
 | 
						|
                        (eb_id == EF_IZUNIX ? "IZUNIX" : "PKUNIX")));
 | 
						|
                if (have_new_type_eb) {
 | 
						|
                    break;      /* Ignore IZUNIX extra field block ! */
 | 
						|
                }
 | 
						|
                if (z_utim != NULL) {
 | 
						|
                    z_utim->atime = makelong((EB_HEADSIZE+EB_UX_ATIME)+ef_buf);
 | 
						|
                    z_utim->mtime = makelong((EB_HEADSIZE+EB_UX_MTIME)+ef_buf);
 | 
						|
                    TTrace((stderr,"  Unix EF actime = %ld\n", z_utim->atime));
 | 
						|
                    TTrace((stderr,"  Unix EF modtime = %ld\n", z_utim->mtime));
 | 
						|
                    flags |= (EB_UT_FL_MTIME | EB_UT_FL_ATIME);
 | 
						|
                    if ((ulg)(z_utim->mtime) & (ulg)(0x80000000L)) {
 | 
						|
                        ut_zip_unzip_compatible =
 | 
						|
                          ((time_t)0x80000000L < (time_t)0L)
 | 
						|
                          ? (dos_mdatetime == DOSTIME_MINIMUM)
 | 
						|
                          : (dos_mdatetime >= DOSTIME_2038_01_18);
 | 
						|
                        if (!ut_zip_unzip_compatible) {
 | 
						|
                            /* UnZip interpretes mtime differently than Zip;
 | 
						|
                               without modtime: ignore complete UT field */
 | 
						|
                            flags &= ~0x0ff;    /* no time_t times available */
 | 
						|
                            TTrace((stderr,
 | 
						|
                                  "  UX modtime range error: ignore e.f.!\n"));
 | 
						|
                        }
 | 
						|
                    } else {
 | 
						|
                        /* cannot determine, safe assumption is FALSE */
 | 
						|
                        ut_zip_unzip_compatible = FALSE;
 | 
						|
                    }
 | 
						|
                    if ((ulg)(z_utim->atime) & (ulg)(0x80000000L) &&
 | 
						|
                        !ut_zip_unzip_compatible && (flags & 0x0ff)) {
 | 
						|
                        /* atime not in range of UnZip's time_t */
 | 
						|
                        flags &= ~EB_UT_FL_ATIME;
 | 
						|
                        TTrace((stderr,
 | 
						|
                                "  UX access time range error: skip time!\n"));
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                if (eb_len >= EB_UX_FULLSIZE && z_uidgid != NULL) {
 | 
						|
                    z_uidgid[0] = makeword((EB_HEADSIZE+EB_UX_UID) + ef_buf);
 | 
						|
                    z_uidgid[1] = makeword((EB_HEADSIZE+EB_UX_GID) + ef_buf);
 | 
						|
                    flags |= EB_UX2_VALID;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            break;
 | 
						|
 | 
						|
          default:
 | 
						|
            break;
 | 
						|
        }
 | 
						|
 | 
						|
        /* Skip this extra field block */
 | 
						|
        ef_buf += (eb_len + EB_HEADSIZE);
 | 
						|
        ef_len -= (eb_len + EB_HEADSIZE);
 | 
						|
    }
 | 
						|
 | 
						|
    return flags;
 | 
						|
}
 | 
						|
 | 
						|
#endif /* USE_EF_UT_TIME */
 |