Subversion Repositories Kolibri OS

Rev

Rev 6725 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.   Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.
  3.  
  4.   See the accompanying file LICENSE, version 2009-Jan-02 or later
  5.   (the contents of which are also included in unzip.h) for terms of use.
  6.   If, for some reason, all these files are missing, the Info-ZIP license
  7.   also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
  8. */
  9. /*---------------------------------------------------------------------------
  10.  
  11.   extract.c
  12.  
  13.   This file contains the high-level routines ("driver routines") for extrac-
  14.   ting and testing zipfile members.  It calls the low-level routines in files
  15.   explode.c, inflate.c, unreduce.c and unshrink.c.
  16.  
  17.   Contains:  extract_or_test_files()
  18.              store_info()
  19.              find_compr_idx()
  20.              extract_or_test_entrylist()
  21.              extract_or_test_member()
  22.              TestExtraField()
  23.              test_compr_eb()
  24.              memextract()
  25.              memflush()
  26.              extract_izvms_block()    (VMS or VMS_TEXT_CONV)
  27.              set_deferred_symlink()   (SYMLINKS only)
  28.              fnfilter()
  29.              dircomp()                (SET_DIR_ATTRIB only)
  30.              UZbunzip2()              (USE_BZIP2 only)
  31.  
  32.   ---------------------------------------------------------------------------*/
  33.  
  34.  
  35. #define __EXTRACT_C     /* identifies this source module */
  36. #define UNZIP_INTERNAL
  37. #include "unzip.h"
  38. #ifdef WINDLL
  39. #  ifdef POCKET_UNZIP
  40. #    include "wince/intrface.h"
  41. #  else
  42. #    include "windll/windll.h"
  43. #  endif
  44. #endif
  45. #include "crc32.h"
  46. #include "crypt.h"
  47.  
  48. #define GRRDUMP(buf,len) { \
  49.     int i, j; \
  50.  \
  51.     for (j = 0;  j < (len)/16;  ++j) { \
  52.         printf("        "); \
  53.         for (i = 0;  i < 16;  ++i) \
  54.             printf("%02x ", (uch)(buf)[i+(j<<4)]); \
  55.         printf("\n        "); \
  56.         for (i = 0;  i < 16;  ++i) { \
  57.             char c = (char)(buf)[i+(j<<4)]; \
  58.  \
  59.             if (c == '\n') \
  60.                 printf("\\n "); \
  61.             else if (c == '\r') \
  62.                 printf("\\r "); \
  63.             else \
  64.                 printf(" %c ", c); \
  65.         } \
  66.         printf("\n"); \
  67.     } \
  68.     if ((len) % 16) { \
  69.         printf("        "); \
  70.         for (i = j<<4;  i < (len);  ++i) \
  71.             printf("%02x ", (uch)(buf)[i]); \
  72.         printf("\n        "); \
  73.         for (i = j<<4;  i < (len);  ++i) { \
  74.             char c = (char)(buf)[i]; \
  75.  \
  76.             if (c == '\n') \
  77.                 printf("\\n "); \
  78.             else if (c == '\r') \
  79.                 printf("\\r "); \
  80.             else \
  81.                 printf(" %c ", c); \
  82.         } \
  83.         printf("\n"); \
  84.     } \
  85. }
  86.  
  87. static int store_info OF((__GPRO));
  88. #ifdef SET_DIR_ATTRIB
  89. static int extract_or_test_entrylist OF((__GPRO__ unsigned numchunk,
  90.                 ulg *pfilnum, ulg *pnum_bad_pwd, zoff_t *pold_extra_bytes,
  91.                 unsigned *pnum_dirs, direntry **pdirlist,
  92.                 int error_in_archive));
  93. #else
  94. static int extract_or_test_entrylist OF((__GPRO__ unsigned numchunk,
  95.                 ulg *pfilnum, ulg *pnum_bad_pwd, zoff_t *pold_extra_bytes,
  96.                 int error_in_archive));
  97. #endif
  98. static int extract_or_test_member OF((__GPRO));
  99. #ifndef SFX
  100.    static int TestExtraField OF((__GPRO__ uch *ef, unsigned ef_len));
  101.    static int test_compr_eb OF((__GPRO__ uch *eb, unsigned eb_size,
  102.         unsigned compr_offset,
  103.         int (*test_uc_ebdata)(__GPRO__ uch *eb, unsigned eb_size,
  104.                               uch *eb_ucptr, ulg eb_ucsize)));
  105. #endif
  106. #if (defined(VMS) || defined(VMS_TEXT_CONV))
  107.    static void decompress_bits OF((uch *outptr, unsigned needlen,
  108.                                    ZCONST uch *bitptr));
  109. #endif
  110. #ifdef SYMLINKS
  111.    static void set_deferred_symlink OF((__GPRO__ slinkentry *slnk_entry));
  112. #endif
  113. #ifdef SET_DIR_ATTRIB
  114.    static int Cdecl dircomp OF((ZCONST zvoid *a, ZCONST zvoid *b));
  115. #endif
  116.  
  117.  
  118.  
  119. /*******************************/
  120. /*  Strings used in extract.c  */
  121. /*******************************/
  122.  
  123. static ZCONST char Far VersionMsg[] =
  124.   "   skipping: %-22s  need %s compat. v%u.%u (can do v%u.%u)\n";
  125. static ZCONST char Far ComprMsgNum[] =
  126.   "   skipping: %-22s  unsupported compression method %u\n";
  127. #ifndef SFX
  128.    static ZCONST char Far ComprMsgName[] =
  129.      "   skipping: %-22s  `%s' method not supported\n";
  130.    static ZCONST char Far CmprNone[]       = "store";
  131.    static ZCONST char Far CmprShrink[]     = "shrink";
  132.    static ZCONST char Far CmprReduce[]     = "reduce";
  133.    static ZCONST char Far CmprImplode[]    = "implode";
  134.    static ZCONST char Far CmprTokenize[]   = "tokenize";
  135.    static ZCONST char Far CmprDeflate[]    = "deflate";
  136.    static ZCONST char Far CmprDeflat64[]   = "deflate64";
  137.    static ZCONST char Far CmprDCLImplode[] = "DCL implode";
  138.    static ZCONST char Far CmprBzip[]       = "bzip2";
  139.    static ZCONST char Far CmprLZMA[]       = "LZMA";
  140.    static ZCONST char Far CmprIBMTerse[]   = "IBM/Terse";
  141.    static ZCONST char Far CmprIBMLZ77[]    = "IBM LZ77";
  142.    static ZCONST char Far CmprWavPack[]    = "WavPack";
  143.    static ZCONST char Far CmprPPMd[]       = "PPMd";
  144.    static ZCONST char Far *ComprNames[NUM_METHODS] = {
  145.      CmprNone, CmprShrink, CmprReduce, CmprReduce, CmprReduce, CmprReduce,
  146.      CmprImplode, CmprTokenize, CmprDeflate, CmprDeflat64, CmprDCLImplode,
  147.      CmprBzip, CmprLZMA, CmprIBMTerse, CmprIBMLZ77, CmprWavPack, CmprPPMd
  148.    };
  149.    static ZCONST unsigned ComprIDs[NUM_METHODS] = {
  150.      STORED, SHRUNK, REDUCED1, REDUCED2, REDUCED3, REDUCED4,
  151.      IMPLODED, TOKENIZED, DEFLATED, ENHDEFLATED, DCLIMPLODED,
  152.      BZIPPED, LZMAED, IBMTERSED, IBMLZ77ED, WAVPACKED, PPMDED
  153.    };
  154. #endif /* !SFX */
  155. static ZCONST char Far FilNamMsg[] =
  156.   "%s:  bad filename length (%s)\n";
  157. #ifndef SFX
  158.    static ZCONST char Far WarnNoMemCFName[] =
  159.      "%s:  warning, no memory for comparison with local header\n";
  160.    static ZCONST char Far LvsCFNamMsg[] =
  161.      "%s:  mismatching \"local\" filename (%s),\n\
  162.         continuing with \"central\" filename version\n";
  163. #endif /* !SFX */
  164. #if (!defined(SFX) && defined(UNICODE_SUPPORT))
  165.    static ZCONST char Far GP11FlagsDiffer[] =
  166.      "file #%lu (%s):\n\
  167.         mismatch between local and central GPF bit 11 (\"UTF-8\"),\n\
  168.         continuing with central flag (IsUTF8 = %d)\n";
  169. #endif /* !SFX && UNICODE_SUPPORT */
  170. static ZCONST char Far WrnStorUCSizCSizDiff[] =
  171.   "%s:  ucsize %s <> csize %s for STORED entry\n\
  172.         continuing with \"compressed\" size value\n";
  173. static ZCONST char Far ExtFieldMsg[] =
  174.   "%s:  bad extra field length (%s)\n";
  175. static ZCONST char Far OffsetMsg[] =
  176.   "file #%lu:  bad zipfile offset (%s):  %ld\n";
  177. static ZCONST char Far ExtractMsg[] =
  178.   "%8sing: %-22s  %s%s";
  179. #ifndef SFX
  180.    static ZCONST char Far LengthMsg[] =
  181.      "%s  %s:  %s bytes required to uncompress to %s bytes;\n    %s\
  182.      supposed to require %s bytes%s%s%s\n";
  183. #endif
  184.  
  185. static ZCONST char Far BadFileCommLength[] = "%s:  bad file comment length\n";
  186. static ZCONST char Far LocalHdrSig[] = "local header sig";
  187. static ZCONST char Far BadLocalHdr[] = "file #%lu:  bad local header\n";
  188. static ZCONST char Far AttemptRecompensate[] =
  189.   "  (attempting to re-compensate)\n";
  190. #ifndef SFX
  191.    static ZCONST char Far BackslashPathSep[] =
  192.      "warning:  %s appears to use backslashes as path separators\n";
  193. #endif
  194. static ZCONST char Far AbsolutePathWarning[] =
  195.   "warning:  stripped absolute path spec from %s\n";
  196. static ZCONST char Far SkipVolumeLabel[] =
  197.   "   skipping: %-22s  %svolume label\n";
  198.  
  199. #ifdef SET_DIR_ATTRIB   /* messages of code for setting directory attributes */
  200.    static ZCONST char Far DirlistEntryNoMem[] =
  201.      "warning:  cannot alloc memory for dir times/permissions/UID/GID\n";
  202.    static ZCONST char Far DirlistSortNoMem[] =
  203.      "warning:  cannot alloc memory to sort dir times/perms/etc.\n";
  204.    static ZCONST char Far DirlistSetAttrFailed[] =
  205.      "warning:  set times/attribs failed for %s\n";
  206.    static ZCONST char Far DirlistFailAttrSum[] =
  207.      "     failed setting times/attribs for %lu dir entries";
  208. #endif
  209.  
  210. #ifdef SYMLINKS         /* messages of the deferred symlinks handler */
  211.    static ZCONST char Far SymLnkWarnNoMem[] =
  212.      "warning:  deferred symlink (%s) failed:\n\
  213.          out of memory\n";
  214.    static ZCONST char Far SymLnkWarnInvalid[] =
  215.      "warning:  deferred symlink (%s) failed:\n\
  216.          invalid placeholder file\n";
  217.    static ZCONST char Far SymLnkDeferred[] =
  218.      "finishing deferred symbolic links:\n";
  219.    static ZCONST char Far SymLnkFinish[] =
  220.      "  %-22s -> %s\n";
  221. #endif
  222.  
  223. #ifndef WINDLL
  224.    static ZCONST char Far ReplaceQuery[] =
  225. # ifdef VMS
  226.      "new version of %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: ";
  227. # else
  228.      "replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: ";
  229. # endif
  230.    static ZCONST char Far AssumeNone[] =
  231.      " NULL\n(EOF or read error, treating as \"[N]one\" ...)\n";
  232.    static ZCONST char Far NewNameQuery[] = "new name: ";
  233.    static ZCONST char Far InvalidResponse[] =
  234.      "error:  invalid response [%s]\n";
  235. #endif /* !WINDLL */
  236.  
  237. static ZCONST char Far ErrorInArchive[] =
  238.   "At least one %serror was detected in %s.\n";
  239. static ZCONST char Far ZeroFilesTested[] =
  240.   "Caution:  zero files tested in %s.\n";
  241.  
  242. #ifndef VMS
  243.    static ZCONST char Far VMSFormatQuery[] =
  244.      "\n%s:  stored in VMS format.  Extract anyway? (y/n) ";
  245. #endif
  246.  
  247. #if CRYPT
  248.    static ZCONST char Far SkipCannotGetPasswd[] =
  249.      "   skipping: %-22s  unable to get password\n";
  250.    static ZCONST char Far SkipIncorrectPasswd[] =
  251.      "   skipping: %-22s  incorrect password\n";
  252.    static ZCONST char Far FilesSkipBadPasswd[] =
  253.      "%lu file%s skipped because of incorrect password.\n";
  254.    static ZCONST char Far MaybeBadPasswd[] =
  255.      "    (may instead be incorrect password)\n";
  256. #else
  257.    static ZCONST char Far SkipEncrypted[] =
  258.      "   skipping: %-22s  encrypted (not supported)\n";
  259. #endif
  260.  
  261. static ZCONST char Far NoErrInCompData[] =
  262.   "No errors detected in compressed data of %s.\n";
  263. static ZCONST char Far NoErrInTestedFiles[] =
  264.   "No errors detected in %s for the %lu file%s tested.\n";
  265. static ZCONST char Far FilesSkipped[] =
  266.   "%lu file%s skipped because of unsupported compression or encoding.\n";
  267.  
  268. static ZCONST char Far ErrUnzipFile[] = "  error:  %s%s %s\n";
  269. static ZCONST char Far ErrUnzipNoFile[] = "\n  error:  %s%s\n";
  270. static ZCONST char Far NotEnoughMem[] = "not enough memory to ";
  271. static ZCONST char Far InvalidComprData[] = "invalid compressed data to ";
  272. static ZCONST char Far Inflate[] = "inflate";
  273. #ifdef USE_BZIP2
  274.   static ZCONST char Far BUnzip[] = "bunzip";
  275. #endif
  276.  
  277. #ifndef SFX
  278.    static ZCONST char Far Explode[] = "explode";
  279. #ifndef LZW_CLEAN
  280.    static ZCONST char Far Unshrink[] = "unshrink";
  281. #endif
  282. #endif
  283.  
  284. #if (!defined(DELETE_IF_FULL) || !defined(HAVE_UNLINK))
  285.    static ZCONST char Far FileTruncated[] =
  286.      "warning:  %s is probably truncated\n";
  287. #endif
  288.  
  289. static ZCONST char Far FileUnknownCompMethod[] =
  290.   "%s:  unknown compression method\n";
  291. static ZCONST char Far BadCRC[] = " bad CRC %08lx  (should be %08lx)\n";
  292.  
  293.       /* TruncEAs[] also used in OS/2 mapname(), close_outfile() */
  294. char ZCONST Far TruncEAs[] = " compressed EA data missing (%d bytes)%s";
  295. char ZCONST Far TruncNTSD[] =
  296.   " compressed WinNT security data missing (%d bytes)%s";
  297.  
  298. #ifndef SFX
  299.    static ZCONST char Far InconsistEFlength[] = "bad extra-field entry:\n \
  300.     EF block length (%u bytes) exceeds remaining EF data (%u bytes)\n";
  301.    static ZCONST char Far InvalidComprDataEAs[] =
  302.      " invalid compressed data for EAs\n";
  303. #  if (defined(WIN32) && defined(NTSD_EAS))
  304.      static ZCONST char Far InvalidSecurityEAs[] =
  305.        " EAs fail security check\n";
  306. #  endif
  307.    static ZCONST char Far UnsuppNTSDVersEAs[] =
  308.      " unsupported NTSD EAs version %d\n";
  309.    static ZCONST char Far BadCRC_EAs[] = " bad CRC for extended attributes\n";
  310.    static ZCONST char Far UnknComprMethodEAs[] =
  311.      " unknown compression method for EAs (%u)\n";
  312.    static ZCONST char Far NotEnoughMemEAs[] =
  313.      " out of memory while inflating EAs\n";
  314.    static ZCONST char Far UnknErrorEAs[] =
  315.      " unknown error on extended attributes\n";
  316. #endif /* !SFX */
  317.  
  318. static ZCONST char Far UnsupportedExtraField[] =
  319.   "\nerror:  unsupported extra-field compression type (%u)--skipping\n";
  320. static ZCONST char Far BadExtraFieldCRC[] =
  321.   "error [%s]:  bad extra-field CRC %08lx (should be %08lx)\n";
  322.  
  323.  
  324.  
  325.  
  326.  
  327. /**************************************/
  328. /*  Function extract_or_test_files()  */
  329. /**************************************/
  330.  
  331. int extract_or_test_files(__G)    /* return PK-type error code */
  332.      __GDEF
  333. {
  334.     unsigned i, j;
  335.     zoff_t cd_bufstart;
  336.     uch *cd_inptr;
  337.     int cd_incnt;
  338.     ulg filnum=0L, blknum=0L;
  339.     int reached_end;
  340. #ifndef SFX
  341.     int no_endsig_found;
  342. #endif
  343.     int error, error_in_archive=PK_COOL;
  344.     int *fn_matched=NULL, *xn_matched=NULL;
  345.     zucn_t members_processed;
  346.     ulg num_skipped=0L, num_bad_pwd=0L;
  347.     zoff_t old_extra_bytes = 0L;
  348. #ifdef SET_DIR_ATTRIB
  349.     unsigned num_dirs=0;
  350.     direntry *dirlist=(direntry *)NULL, **sorted_dirlist=(direntry **)NULL;
  351. #endif
  352.  
  353.     /*
  354.      * First, two general initializations are applied. These have been moved
  355.      * here from process_zipfiles() because they are only needed for accessing
  356.      * and/or extracting the data content of the zip archive.
  357.      */
  358.  
  359.     /* a) initialize the CRC table pointer (once) */
  360.     if (CRC_32_TAB == NULL) {
  361.         if ((CRC_32_TAB = get_crc_table()) == NULL) {
  362.             return PK_MEM;
  363.         }
  364.     }
  365.  
  366. #if (!defined(SFX) || defined(SFX_EXDIR))
  367.     /* b) check out if specified extraction root directory exists */
  368.     if (uO.exdir != (char *)NULL && G.extract_flag) {
  369.         G.create_dirs = !uO.fflag;
  370.         if ((error = checkdir(__G__ uO.exdir, ROOT)) > MPN_INF_SKIP) {
  371.             /* out of memory, or file in way */
  372.             return (error == MPN_NOMEM ? PK_MEM : PK_ERR);
  373.         }
  374.     }
  375. #endif /* !SFX || SFX_EXDIR */
  376.  
  377. /*---------------------------------------------------------------------------
  378.     The basic idea of this function is as follows.  Since the central di-
  379.     rectory lies at the end of the zipfile and the member files lie at the
  380.     beginning or middle or wherever, it is not very desirable to simply
  381.     read a central directory entry, jump to the member and extract it, and
  382.     then jump back to the central directory.  In the case of a large zipfile
  383.     this would lead to a whole lot of disk-grinding, especially if each mem-
  384.     ber file is small.  Instead, we read from the central directory the per-
  385.     tinent information for a block of files, then go extract/test the whole
  386.     block.  Thus this routine contains two small(er) loops within a very
  387.     large outer loop:  the first of the small ones reads a block of files
  388.     from the central directory; the second extracts or tests each file; and
  389.     the outer one loops over blocks.  There's some file-pointer positioning
  390.     stuff in between, but that's about it.  Btw, it's because of this jump-
  391.     ing around that we can afford to be lenient if an error occurs in one of
  392.     the member files:  we should still be able to go find the other members,
  393.     since we know the offset of each from the beginning of the zipfile.
  394.   ---------------------------------------------------------------------------*/
  395.  
  396.     G.pInfo = G.info;
  397.  
  398. #if CRYPT
  399.     G.newzip = TRUE;
  400. #endif
  401. #ifndef SFX
  402.     G.reported_backslash = FALSE;
  403. #endif
  404.  
  405.     /* malloc space for check on unmatched filespecs (OK if one or both NULL) */
  406.     if (G.filespecs > 0  &&
  407.         (fn_matched=(int *)malloc(G.filespecs*sizeof(int))) != (int *)NULL)
  408.         for (i = 0;  i < G.filespecs;  ++i)
  409.             fn_matched[i] = FALSE;
  410.     if (G.xfilespecs > 0  &&
  411.         (xn_matched=(int *)malloc(G.xfilespecs*sizeof(int))) != (int *)NULL)
  412.         for (i = 0;  i < G.xfilespecs;  ++i)
  413.             xn_matched[i] = FALSE;
  414.  
  415. /*---------------------------------------------------------------------------
  416.     Begin main loop over blocks of member files.  We know the entire central
  417.     directory is on this disk:  we would not have any of this information un-
  418.     less the end-of-central-directory record was on this disk, and we would
  419.     not have gotten to this routine unless this is also the disk on which
  420.     the central directory starts.  In practice, this had better be the ONLY
  421.     disk in the archive, but we'll add multi-disk support soon.
  422.   ---------------------------------------------------------------------------*/
  423.  
  424.     members_processed = 0;
  425. #ifndef SFX
  426.     no_endsig_found = FALSE;
  427. #endif
  428.     reached_end = FALSE;
  429.     while (!reached_end) {
  430.         j = 0;
  431. #ifdef AMIGA
  432.         memzero(G.filenotes, DIR_BLKSIZ * sizeof(char *));
  433. #endif
  434.  
  435.         /*
  436.          * Loop through files in central directory, storing offsets, file
  437.          * attributes, case-conversion and text-conversion flags until block
  438.          * size is reached.
  439.          */
  440.  
  441.         while ((j < DIR_BLKSIZ)) {
  442.             G.pInfo = &G.info[j];
  443.  
  444.             if (readbuf(__G__ G.sig, 4) == 0) {
  445.                 error_in_archive = PK_EOF;
  446.                 reached_end = TRUE;     /* ...so no more left to do */
  447.                 break;
  448.             }
  449.             if (memcmp(G.sig, central_hdr_sig, 4)) {  /* is it a new entry? */
  450.                 /* no new central directory entry
  451.                  * -> is the number of processed entries compatible with the
  452.                  *    number of entries as stored in the end_central record?
  453.                  */
  454.                 if ((members_processed
  455.                      & (G.ecrec.have_ecr64 ? MASK_ZUCN64 : MASK_ZUCN16))
  456.                     == G.ecrec.total_entries_central_dir) {
  457. #ifndef SFX
  458.                     /* yes, so look if we ARE back at the end_central record
  459.                      */
  460.                     no_endsig_found =
  461.                       ( (memcmp(G.sig,
  462.                                 (G.ecrec.have_ecr64 ?
  463.                                  end_central64_sig : end_central_sig),
  464.                                 4) != 0)
  465.                        && (!G.ecrec.is_zip64_archive)
  466.                        && (memcmp(G.sig, end_central_sig, 4) != 0)
  467.                       );
  468. #endif /* !SFX */
  469.                 } else {
  470.                     /* no; we have found an error in the central directory
  471.                      * -> report it and stop searching for more Zip entries
  472.                      */
  473.                     Info(slide, 0x401, ((char *)slide,
  474.                       LoadFarString(CentSigMsg), j + blknum*DIR_BLKSIZ + 1));
  475.                     Info(slide, 0x401, ((char *)slide,
  476.                       LoadFarString(ReportMsg)));
  477.                     error_in_archive = PK_BADERR;
  478.                 }
  479.                 reached_end = TRUE;     /* ...so no more left to do */
  480.                 break;
  481.             }
  482.             /* process_cdir_file_hdr() sets pInfo->hostnum, pInfo->lcflag */
  483.             if ((error = process_cdir_file_hdr(__G)) != PK_COOL) {
  484.                 error_in_archive = error;   /* only PK_EOF defined */
  485.                 reached_end = TRUE;     /* ...so no more left to do */
  486.                 break;
  487.             }
  488.             if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) !=
  489.                  PK_COOL)
  490.             {
  491.                 if (error > error_in_archive)
  492.                     error_in_archive = error;
  493.                 if (error > PK_WARN) {  /* fatal:  no more left to do */
  494.                     Info(slide, 0x401, ((char *)slide,
  495.                       LoadFarString(FilNamMsg),
  496.                       FnFilter1(G.filename), "central"));
  497.                     reached_end = TRUE;
  498.                     break;
  499.                 }
  500.             }
  501.             if ((error = do_string(__G__ G.crec.extra_field_length,
  502.                 EXTRA_FIELD)) != 0)
  503.             {
  504.                 if (error > error_in_archive)
  505.                     error_in_archive = error;
  506.                 if (error > PK_WARN) {  /* fatal */
  507.                     Info(slide, 0x401, ((char *)slide,
  508.                       LoadFarString(ExtFieldMsg),
  509.                       FnFilter1(G.filename), "central"));
  510.                     reached_end = TRUE;
  511.                     break;
  512.                 }
  513.             }
  514. #ifdef AMIGA
  515.             G.filenote_slot = j;
  516.             if ((error = do_string(__G__ G.crec.file_comment_length,
  517.                                    uO.N_flag ? FILENOTE : SKIP)) != PK_COOL)
  518. #else
  519.             if ((error = do_string(__G__ G.crec.file_comment_length, SKIP))
  520.                 != PK_COOL)
  521. #endif
  522.             {
  523.                 if (error > error_in_archive)
  524.                     error_in_archive = error;
  525.                 if (error > PK_WARN) {  /* fatal */
  526.                     Info(slide, 0x421, ((char *)slide,
  527.                       LoadFarString(BadFileCommLength),
  528.                       FnFilter1(G.filename)));
  529.                     reached_end = TRUE;
  530.                     break;
  531.                 }
  532.             }
  533.             if (G.process_all_files) {
  534.                 if (store_info(__G))
  535.                     ++j;  /* file is OK; info[] stored; continue with next */
  536.                 else
  537.                     ++num_skipped;
  538.             } else {
  539.                 int   do_this_file;
  540.  
  541.                 if (G.filespecs == 0)
  542.                     do_this_file = TRUE;
  543.                 else {  /* check if this entry matches an `include' argument */
  544.                     do_this_file = FALSE;
  545.                     for (i = 0; i < G.filespecs; i++)
  546.                         if (match(G.filename, G.pfnames[i], uO.C_flag WISEP)) {
  547.                             do_this_file = TRUE;  /* ^-- ignore case or not? */
  548.                             if (fn_matched)
  549.                                 fn_matched[i] = TRUE;
  550.                             break;       /* found match, so stop looping */
  551.                         }
  552.                 }
  553.                 if (do_this_file) {  /* check if this is an excluded file */
  554.                     for (i = 0; i < G.xfilespecs; i++)
  555.                         if (match(G.filename, G.pxnames[i], uO.C_flag WISEP)) {
  556.                             do_this_file = FALSE; /* ^-- ignore case or not? */
  557.                             if (xn_matched)
  558.                                 xn_matched[i] = TRUE;
  559.                             break;
  560.                         }
  561.                 }
  562.                 if (do_this_file) {
  563.                     if (store_info(__G))
  564.                         ++j;            /* file is OK */
  565.                     else
  566.                         ++num_skipped;  /* unsupp. compression or encryption */
  567.                 }
  568.             } /* end if (process_all_files) */
  569.  
  570.             members_processed++;
  571.  
  572.         } /* end while-loop (adding files to current block) */
  573.  
  574.         /* save position in central directory so can come back later */
  575.         cd_bufstart = G.cur_zipfile_bufstart;
  576.         cd_inptr = G.inptr;
  577.         cd_incnt = G.incnt;
  578.  
  579.     /*-----------------------------------------------------------------------
  580.         Second loop:  process files in current block, extracting or testing
  581.         each one.
  582.       -----------------------------------------------------------------------*/
  583.  
  584.         error = extract_or_test_entrylist(__G__ j,
  585.                         &filnum, &num_bad_pwd, &old_extra_bytes,
  586. #ifdef SET_DIR_ATTRIB
  587.                         &num_dirs, &dirlist,
  588. #endif
  589.                         error_in_archive);
  590.         if (error != PK_COOL) {
  591.             if (error > error_in_archive)
  592.                 error_in_archive = error;
  593.             /* ...and keep going (unless disk full or user break) */
  594.             if (G.disk_full > 1 || error_in_archive == IZ_CTRLC) {
  595.                 /* clear reached_end to signal premature stop ... */
  596.                 reached_end = FALSE;
  597.                 /* ... and cancel scanning the central directory */
  598.                 break;
  599.             }
  600.         }
  601.  
  602.  
  603.         /*
  604.          * Jump back to where we were in the central directory, then go and do
  605.          * the next batch of files.
  606.          */
  607.  
  608. #ifdef USE_STRM_INPUT
  609.         zfseeko(G.zipfd, cd_bufstart, SEEK_SET);
  610.         G.cur_zipfile_bufstart = zftello(G.zipfd);
  611. #else /* !USE_STRM_INPUT */
  612.         G.cur_zipfile_bufstart =
  613.           zlseek(G.zipfd, cd_bufstart, SEEK_SET);
  614. #endif /* ?USE_STRM_INPUT */
  615.         read(G.zipfd, (char *)G.inbuf, INBUFSIZ);  /* been here before... */
  616.         G.inptr = cd_inptr;
  617.         G.incnt = cd_incnt;
  618.         ++blknum;
  619.  
  620. #ifdef TEST
  621.         printf("\ncd_bufstart = %ld (%.8lXh)\n", cd_bufstart, cd_bufstart);
  622.         printf("cur_zipfile_bufstart = %ld (%.8lXh)\n", cur_zipfile_bufstart,
  623.           cur_zipfile_bufstart);
  624.         printf("inptr-inbuf = %d\n", G.inptr-G.inbuf);
  625.         printf("incnt = %d\n\n", G.incnt);
  626. #endif
  627.  
  628.     } /* end while-loop (blocks of files in central directory) */
  629.  
  630. /*---------------------------------------------------------------------------
  631.     Process the list of deferred symlink extractions and finish up
  632.     the symbolic links.
  633.   ---------------------------------------------------------------------------*/
  634.  
  635. #ifdef SYMLINKS
  636.     if (G.slink_last != NULL) {
  637.         if (QCOND2)
  638.             Info(slide, 0, ((char *)slide, LoadFarString(SymLnkDeferred)));
  639.         while (G.slink_head != NULL) {
  640.            set_deferred_symlink(__G__ G.slink_head);
  641.            /* remove the processed entry from the chain and free its memory */
  642.            G.slink_last = G.slink_head;
  643.            G.slink_head = G.slink_last->next;
  644.            free(G.slink_last);
  645.        }
  646.        G.slink_last = NULL;
  647.     }
  648. #endif /* SYMLINKS */
  649.  
  650. /*---------------------------------------------------------------------------
  651.     Go back through saved list of directories, sort and set times/perms/UIDs
  652.     and GIDs from the deepest level on up.
  653.   ---------------------------------------------------------------------------*/
  654.  
  655. #ifdef SET_DIR_ATTRIB
  656. //Trace((stderr, "SET_DIR_ATTRIB[%d] \n", num_dirs));  hmm, too big number
  657.  
  658.     if (num_dirs > 0) {
  659.         sorted_dirlist = (direntry **)malloc(num_dirs*sizeof(direntry *));
  660.         if (sorted_dirlist == (direntry **)NULL) {
  661.             Info(slide, 0x401, ((char *)slide,
  662.               LoadFarString(DirlistSortNoMem)));
  663.             while (dirlist != (direntry *)NULL) {
  664.                 direntry *d = dirlist;
  665.  
  666.                 dirlist = dirlist->next;
  667.                 free(d);
  668.             }
  669.         } else {
  670.             ulg ndirs_fail = 0;
  671.  
  672.             if (num_dirs == 1)
  673.                 sorted_dirlist[0] = dirlist;
  674.             else {
  675.                 for (i = 0;  i < num_dirs;  ++i) {
  676.                     sorted_dirlist[i] = dirlist;
  677.                     dirlist = dirlist->next;
  678.                 }
  679.                 qsort((char *)sorted_dirlist, num_dirs, sizeof(direntry *),
  680.                   dircomp);
  681.             }
  682.  
  683.             Trace((stderr, "setting directory times/perms/attributes\n"));
  684.             for (i = 0;  i < num_dirs;  ++i) {
  685.                 direntry *d = sorted_dirlist[i];
  686.  
  687.                 Trace((stderr, "dir = %s\n", d->fn));
  688.                 if ((error = set_direc_attribs(__G__ d)) != PK_OK) {
  689.                     ndirs_fail++;
  690.                     Info(slide, 0x201, ((char *)slide,
  691.                       LoadFarString(DirlistSetAttrFailed), d->fn));
  692.                     if (!error_in_archive)
  693.                         error_in_archive = error;
  694.                 }
  695.                 free(d);
  696.             }
  697.             free(sorted_dirlist);
  698.             if (!uO.tflag && QCOND2) {
  699.                 if (ndirs_fail > 0)
  700.                     Info(slide, 0, ((char *)slide,
  701.                       LoadFarString(DirlistFailAttrSum), ndirs_fail));
  702.             }
  703.         }
  704.     }
  705. #endif /* SET_DIR_ATTRIB */
  706.  
  707. /*---------------------------------------------------------------------------
  708.     Check for unmatched filespecs on command line and print warning if any
  709.     found.  Free allocated memory.  (But suppress check when central dir
  710.     scan was interrupted prematurely.)
  711.   ---------------------------------------------------------------------------*/
  712.  
  713.     if (fn_matched) {
  714.         if (reached_end) for (i = 0;  i < G.filespecs;  ++i)
  715.             if (!fn_matched[i]) {
  716. #ifdef DLL
  717.                 if (!G.redirect_data && !G.redirect_text)
  718.                     Info(slide, 0x401, ((char *)slide,
  719.                       LoadFarString(FilenameNotMatched), G.pfnames[i]));
  720.                 else
  721.                     setFileNotFound(__G);
  722. #else
  723.                 Info(slide, 1, ((char *)slide,
  724.                   LoadFarString(FilenameNotMatched), G.pfnames[i]));
  725. #endif
  726.                 if (error_in_archive <= PK_WARN)
  727.                     error_in_archive = PK_FIND;   /* some files not found */
  728.             }
  729.         free((zvoid *)fn_matched);
  730.     }
  731.     if (xn_matched) {
  732.         if (reached_end) for (i = 0;  i < G.xfilespecs;  ++i)
  733.             if (!xn_matched[i])
  734.                 Info(slide, 0x401, ((char *)slide,
  735.                   LoadFarString(ExclFilenameNotMatched), G.pxnames[i]));
  736.         free((zvoid *)xn_matched);
  737.     }
  738.  
  739. /*---------------------------------------------------------------------------
  740.     Now, all locally allocated memory has been released.  When the central
  741.     directory processing has been interrupted prematurely, it is safe to
  742.     return immediately.  All completeness checks and summary messages are
  743.     skipped in this case.
  744.   ---------------------------------------------------------------------------*/
  745.     if (!reached_end)
  746.         return error_in_archive;
  747.  
  748. /*---------------------------------------------------------------------------
  749.     Double-check that we're back at the end-of-central-directory record, and
  750.     print quick summary of results, if we were just testing the archive.  We
  751.     send the summary to stdout so that people doing the testing in the back-
  752.     ground and redirecting to a file can just do a "tail" on the output file.
  753.   ---------------------------------------------------------------------------*/
  754.  
  755. #ifndef SFX
  756.     if (no_endsig_found) {                      /* just to make sure */
  757.         Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg)));
  758.         Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg)));
  759.         if (!error_in_archive)       /* don't overwrite stronger error */
  760.             error_in_archive = PK_WARN;
  761.     }
  762. #endif /* !SFX */
  763.     if (uO.tflag) {
  764.         ulg num = filnum - num_bad_pwd;
  765.  
  766.         if (uO.qflag < 2) {        /* GRR 930710:  was (uO.qflag == 1) */
  767.             if (error_in_archive)
  768.                 Info(slide, 0, ((char *)slide, LoadFarString(ErrorInArchive),
  769.                   (error_in_archive == PK_WARN)? "warning-" : "", G.zipfn));
  770.             else if (num == 0L)
  771.                 Info(slide, 0, ((char *)slide, LoadFarString(ZeroFilesTested),
  772.                   G.zipfn));
  773.             else if (G.process_all_files && (num_skipped+num_bad_pwd == 0L))
  774.                 Info(slide, 0, ((char *)slide, LoadFarString(NoErrInCompData),
  775.                   G.zipfn));
  776.             else
  777.                 Info(slide, 0, ((char *)slide, LoadFarString(NoErrInTestedFiles)
  778.                   , G.zipfn, num, (num==1L)? "":"s"));
  779.             if (num_skipped > 0L)
  780.                 Info(slide, 0, ((char *)slide, LoadFarString(FilesSkipped),
  781.                   num_skipped, (num_skipped==1L)? "":"s"));
  782. #if CRYPT
  783.             if (num_bad_pwd > 0L)
  784.                 Info(slide, 0, ((char *)slide, LoadFarString(FilesSkipBadPasswd)
  785.                   , num_bad_pwd, (num_bad_pwd==1L)? "":"s"));
  786. #endif /* CRYPT */
  787.         }
  788.     }
  789.  
  790.     /* give warning if files not tested or extracted (first condition can still
  791.      * happen if zipfile is empty and no files specified on command line) */
  792.  
  793.     if ((filnum == 0) && error_in_archive <= PK_WARN) {
  794.         if (num_skipped > 0L)
  795.             error_in_archive = IZ_UNSUP; /* unsupport. compression/encryption */
  796.         else
  797.             error_in_archive = PK_FIND;  /* no files found at all */
  798.     }
  799. #if CRYPT
  800.     else if ((filnum == num_bad_pwd) && error_in_archive <= PK_WARN)
  801.         error_in_archive = IZ_BADPWD;    /* bad passwd => all files skipped */
  802. #endif
  803.     else if ((num_skipped > 0L) && error_in_archive <= PK_WARN)
  804.         error_in_archive = IZ_UNSUP;     /* was PK_WARN; Jean-loup complained */
  805. #if CRYPT
  806.     else if ((num_bad_pwd > 0L) && !error_in_archive)
  807.         error_in_archive = PK_WARN;
  808. #endif
  809.  
  810.     return error_in_archive;
  811.  
  812. } /* end function extract_or_test_files() */
  813.  
  814.  
  815.  
  816.  
  817.  
  818. /***************************/
  819. /*  Function store_info()  */
  820. /***************************/
  821.  
  822. static int store_info(__G)   /* return 0 if skipping, 1 if OK */
  823.     __GDEF
  824. {
  825. #ifdef USE_BZIP2
  826. #  define UNKN_BZ2 (G.crec.compression_method!=BZIPPED)
  827. #else
  828. #  define UNKN_BZ2 TRUE       /* bzip2 unknown */
  829. #endif
  830.  
  831. #ifdef USE_LZMA
  832. #  define UNKN_LZMA (G.crec.compression_method!=LZMAED)
  833. #else
  834. #  define UNKN_LZMA TRUE      /* LZMA unknown */
  835. #endif
  836.  
  837. #ifdef USE_WAVP
  838. #  define UNKN_WAVP (G.crec.compression_method!=WAVPACKED)
  839. #else
  840. #  define UNKN_WAVP TRUE      /* WavPack unknown */
  841. #endif
  842.  
  843. #ifdef USE_PPMD
  844. #  define UNKN_PPMD (G.crec.compression_method!=PPMDED)
  845. #else
  846. #  define UNKN_PPMD TRUE      /* PPMd unknown */
  847. #endif
  848.  
  849. #ifdef SFX
  850. #  ifdef USE_DEFLATE64
  851. #    define UNKN_COMPR \
  852.      (G.crec.compression_method!=STORED && G.crec.compression_method<DEFLATED \
  853.       && G.crec.compression_method>ENHDEFLATED \
  854.       && UNKN_BZ2 && UNKN_LZMA && UNKN_WAVP && UNKN_PPMD)
  855. #  else
  856. #    define UNKN_COMPR \
  857.      (G.crec.compression_method!=STORED && G.crec.compression_method!=DEFLATED\
  858.       && UNKN_BZ2 && UNKN_LZMA && UNKN_WAVP && UNKN_PPMD)
  859. #  endif
  860. #else
  861. #  ifdef COPYRIGHT_CLEAN  /* no reduced files */
  862. #    define UNKN_RED (G.crec.compression_method >= REDUCED1 && \
  863.                       G.crec.compression_method <= REDUCED4)
  864. #  else
  865. #    define UNKN_RED  FALSE  /* reducing not unknown */
  866. #  endif
  867. #  ifdef LZW_CLEAN  /* no shrunk files */
  868. #    define UNKN_SHR (G.crec.compression_method == SHRUNK)
  869. #  else
  870. #    define UNKN_SHR  FALSE  /* unshrinking not unknown */
  871. #  endif
  872. #  ifdef USE_DEFLATE64
  873. #    define UNKN_COMPR (UNKN_RED || UNKN_SHR || \
  874.      G.crec.compression_method==TOKENIZED || \
  875.      (G.crec.compression_method>ENHDEFLATED && UNKN_BZ2 && UNKN_LZMA \
  876.       && UNKN_WAVP && UNKN_PPMD))
  877. #  else
  878. #    define UNKN_COMPR (UNKN_RED || UNKN_SHR || \
  879.      G.crec.compression_method==TOKENIZED || \
  880.      (G.crec.compression_method>DEFLATED && UNKN_BZ2 && UNKN_LZMA \
  881.       && UNKN_WAVP && UNKN_PPMD))
  882. #  endif
  883. #endif
  884.  
  885. #if (defined(USE_BZIP2) && (UNZIP_VERSION < UNZIP_BZ2VERS))
  886.     int unzvers_support = (UNKN_BZ2 ? UNZIP_VERSION : UNZIP_BZ2VERS);
  887. #   define UNZVERS_SUPPORT  unzvers_support
  888. #else
  889. #   define UNZVERS_SUPPORT  UNZIP_VERSION
  890. #endif
  891.  
  892. /*---------------------------------------------------------------------------
  893.     Check central directory info for version/compatibility requirements.
  894.   ---------------------------------------------------------------------------*/
  895.  
  896.     G.pInfo->encrypted = G.crec.general_purpose_bit_flag & 1;   /* bit field */
  897.     G.pInfo->ExtLocHdr = (G.crec.general_purpose_bit_flag & 8) == 8;  /* bit */
  898.     G.pInfo->textfile = G.crec.internal_file_attributes & 1;    /* bit field */
  899.     G.pInfo->crc = G.crec.crc32;
  900.     G.pInfo->compr_size = G.crec.csize;
  901.     G.pInfo->uncompr_size = G.crec.ucsize;
  902.  
  903.     switch (uO.aflag) {
  904.         case 0:
  905.             G.pInfo->textmode = FALSE;   /* bit field */
  906.             break;
  907.         case 1:
  908.             G.pInfo->textmode = G.pInfo->textfile;   /* auto-convert mode */
  909.             break;
  910.         default:  /* case 2: */
  911.             G.pInfo->textmode = TRUE;
  912.             break;
  913.     }
  914.  
  915.     if (G.crec.version_needed_to_extract[1] == VMS_) {
  916.         if (G.crec.version_needed_to_extract[0] > VMS_UNZIP_VERSION) {
  917.             if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))
  918.                 Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg),
  919.                   FnFilter1(G.filename), "VMS",
  920.                   G.crec.version_needed_to_extract[0] / 10,
  921.                   G.crec.version_needed_to_extract[0] % 10,
  922.                   VMS_UNZIP_VERSION / 10, VMS_UNZIP_VERSION % 10));
  923.             return 0;
  924.         }
  925. #ifndef VMS   /* won't be able to use extra field, but still have data */
  926.         else if (!uO.tflag && !IS_OVERWRT_ALL) { /* if -o, extract anyway */
  927.             Info(slide, 0x481, ((char *)slide, LoadFarString(VMSFormatQuery),
  928.               FnFilter1(G.filename)));
  929.             fgets(G.answerbuf, sizeof(G.answerbuf), stdin);
  930.             if ((*G.answerbuf != 'y') && (*G.answerbuf != 'Y'))
  931.                 return 0;
  932.         }
  933. #endif /* !VMS */
  934.     /* usual file type:  don't need VMS to extract */
  935.     } else if (G.crec.version_needed_to_extract[0] > UNZVERS_SUPPORT) {
  936.         if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))
  937.             Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg),
  938.               FnFilter1(G.filename), "PK",
  939.               G.crec.version_needed_to_extract[0] / 10,
  940.               G.crec.version_needed_to_extract[0] % 10,
  941.               UNZVERS_SUPPORT / 10, UNZVERS_SUPPORT % 10));
  942.         return 0;
  943.     }
  944.  
  945.     if (UNKN_COMPR) {
  946.         if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) {
  947. #ifndef SFX
  948.             unsigned cmpridx;
  949.  
  950.             if ((cmpridx = find_compr_idx(G.crec.compression_method))
  951.                 < NUM_METHODS)
  952.                 Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgName),
  953.                   FnFilter1(G.filename),
  954.                   LoadFarStringSmall(ComprNames[cmpridx])));
  955.             else
  956. #endif
  957.                 Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgNum),
  958.                   FnFilter1(G.filename),
  959.                   G.crec.compression_method));
  960.         }
  961.         return 0;
  962.     }
  963. #if (!CRYPT)
  964.     if (G.pInfo->encrypted) {
  965.         if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))
  966.             Info(slide, 0x401, ((char *)slide, LoadFarString(SkipEncrypted),
  967.               FnFilter1(G.filename)));
  968.         return 0;
  969.     }
  970. #endif /* !CRYPT */
  971.  
  972. #ifndef SFX
  973.     /* store a copy of the central header filename for later comparison */
  974.     if ((G.pInfo->cfilname = zfmalloc(strlen(G.filename) + 1)) == NULL) {
  975.         Info(slide, 0x401, ((char *)slide, LoadFarString(WarnNoMemCFName),
  976.           FnFilter1(G.filename)));
  977.     } else
  978.         zfstrcpy(G.pInfo->cfilname, G.filename);
  979. #endif /* !SFX */
  980.  
  981.     /* map whatever file attributes we have into the local format */
  982.     mapattr(__G);   /* GRR:  worry about return value later */
  983.  
  984.     G.pInfo->diskstart = G.crec.disk_number_start;
  985.     G.pInfo->offset = (zoff_t)G.crec.relative_offset_local_header;
  986.     return 1;
  987.  
  988. } /* end function store_info() */
  989.  
  990.  
  991.  
  992.  
  993.  
  994. #ifndef SFX
  995. /*******************************/
  996. /*  Function find_compr_idx()  */
  997. /*******************************/
  998.  
  999. unsigned find_compr_idx(compr_methodnum)
  1000.     unsigned compr_methodnum;
  1001. {
  1002.     unsigned i;
  1003.  
  1004.     for (i = 0; i < NUM_METHODS; i++) {
  1005.         if (ComprIDs[i] == compr_methodnum) break;
  1006.     }
  1007.     return i;
  1008. }
  1009. #endif /* !SFX */
  1010.  
  1011.  
  1012.  
  1013.  
  1014.  
  1015. /******************************************/
  1016. /*  Function extract_or_test_entrylist()  */
  1017. /******************************************/
  1018.  
  1019. static int extract_or_test_entrylist(__G__ numchunk,
  1020.                 pfilnum, pnum_bad_pwd, pold_extra_bytes,
  1021. #ifdef SET_DIR_ATTRIB
  1022.                 pnum_dirs, pdirlist,
  1023. #endif
  1024.                 error_in_archive)    /* return PK-type error code */
  1025.     __GDEF
  1026.     unsigned numchunk;
  1027.     ulg *pfilnum;
  1028.     ulg *pnum_bad_pwd;
  1029.     zoff_t *pold_extra_bytes;
  1030. #ifdef SET_DIR_ATTRIB
  1031.     unsigned *pnum_dirs;
  1032.     direntry **pdirlist;
  1033. #endif
  1034.     int error_in_archive;
  1035. {
  1036.     unsigned i;
  1037.     int renamed, query;
  1038.     int skip_entry;
  1039.     zoff_t bufstart, inbuf_offset, request;
  1040.     int error, errcode;
  1041.  
  1042. /* possible values for local skip_entry flag: */
  1043. #define SKIP_NO         0       /* do not skip this entry */
  1044. #define SKIP_Y_EXISTING 1       /* skip this entry, do not overwrite file */
  1045. #define SKIP_Y_NONEXIST 2       /* skip this entry, do not create new file */
  1046.  
  1047.     /*-----------------------------------------------------------------------
  1048.         Second loop:  process files in current block, extracting or testing
  1049.         each one.
  1050.       -----------------------------------------------------------------------*/
  1051.  
  1052.     for (i = 0; i < numchunk; ++i) {
  1053.         (*pfilnum)++;   /* *pfilnum = i + blknum*DIR_BLKSIZ + 1; */
  1054.         G.pInfo = &G.info[i];
  1055. #ifdef NOVELL_BUG_FAILSAFE
  1056.         G.dne = FALSE;  /* assume file exists until stat() says otherwise */
  1057. #endif
  1058.  
  1059.         /* if the target position is not within the current input buffer
  1060.          * (either haven't yet read far enough, or (maybe) skipping back-
  1061.          * ward), skip to the target position and reset readbuf(). */
  1062.  
  1063.         /* seek_zipf(__G__ pInfo->offset);  */
  1064.         request = G.pInfo->offset + G.extra_bytes;
  1065.         inbuf_offset = request % INBUFSIZ;
  1066.         bufstart = request - inbuf_offset;
  1067.  
  1068.         Trace((stderr, "\ndebug: request = %ld, inbuf_offset = %ld\n",
  1069.           (long)request, (long)inbuf_offset));
  1070.         Trace((stderr,
  1071.           "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n",
  1072.           (long)bufstart, (long)G.cur_zipfile_bufstart));
  1073.         if (request < 0) {
  1074.             Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(SeekMsg),
  1075.               G.zipfn, LoadFarString(ReportMsg)));
  1076.             error_in_archive = PK_ERR;
  1077.             if (*pfilnum == 1 && G.extra_bytes != 0L) {
  1078.                 Info(slide, 0x401, ((char *)slide,
  1079.                   LoadFarString(AttemptRecompensate)));
  1080.                 *pold_extra_bytes = G.extra_bytes;
  1081.                 G.extra_bytes = 0L;
  1082.                 request = G.pInfo->offset;  /* could also check if != 0 */
  1083.                 inbuf_offset = request % INBUFSIZ;
  1084.                 bufstart = request - inbuf_offset;
  1085.                 Trace((stderr, "debug: request = %ld, inbuf_offset = %ld\n",
  1086.                   (long)request, (long)inbuf_offset));
  1087.                 Trace((stderr,
  1088.                   "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n",
  1089.                   (long)bufstart, (long)G.cur_zipfile_bufstart));
  1090.                 /* try again */
  1091.                 if (request < 0) {
  1092.                     Trace((stderr,
  1093.                       "debug: recompensated request still < 0\n"));
  1094.                     Info(slide, 0x401, ((char *)slide,
  1095.                       LoadFarStringSmall(SeekMsg),
  1096.                       G.zipfn, LoadFarString(ReportMsg)));
  1097.                     error_in_archive = PK_BADERR;
  1098.                     continue;
  1099.                 }
  1100.             } else {
  1101.                 error_in_archive = PK_BADERR;
  1102.                 continue;  /* this one hosed; try next */
  1103.             }
  1104.         }
  1105.  
  1106.         if (bufstart != G.cur_zipfile_bufstart) {
  1107.             Trace((stderr, "debug: bufstart != cur_zipfile_bufstart\n"));
  1108. #ifdef USE_STRM_INPUT
  1109.             zfseeko(G.zipfd, bufstart, SEEK_SET);
  1110.             G.cur_zipfile_bufstart = zftello(G.zipfd);
  1111. #else /* !USE_STRM_INPUT */
  1112.             G.cur_zipfile_bufstart =
  1113.               zlseek(G.zipfd, bufstart, SEEK_SET);
  1114. #endif /* ?USE_STRM_INPUT */
  1115.             if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) <= 0)
  1116.             {
  1117.                 Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg),
  1118.                   *pfilnum, "lseek", (long)bufstart));
  1119.                 error_in_archive = PK_BADERR;
  1120.                 continue;   /* can still do next file */
  1121.             }
  1122.             G.inptr = G.inbuf + (int)inbuf_offset;
  1123.             G.incnt -= (int)inbuf_offset;
  1124.         } else {
  1125.             G.incnt += (int)(G.inptr-G.inbuf) - (int)inbuf_offset;
  1126.             G.inptr = G.inbuf + (int)inbuf_offset;
  1127.         }
  1128.  
  1129.         /* should be in proper position now, so check for sig */
  1130.         if (readbuf(__G__ G.sig, 4) == 0) {  /* bad offset */
  1131.             Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg),
  1132.               *pfilnum, "EOF", (long)request));
  1133.             error_in_archive = PK_BADERR;
  1134.             continue;   /* but can still try next one */
  1135.         }
  1136.         if (memcmp(G.sig, local_hdr_sig, 4)) {
  1137.             Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg),
  1138.               *pfilnum, LoadFarStringSmall(LocalHdrSig), (long)request));
  1139.             /*
  1140.                 GRRDUMP(G.sig, 4)
  1141.                 GRRDUMP(local_hdr_sig, 4)
  1142.              */
  1143.             error_in_archive = PK_ERR;
  1144.             if ((*pfilnum == 1 && G.extra_bytes != 0L) ||
  1145.                 (G.extra_bytes == 0L && *pold_extra_bytes != 0L)) {
  1146.                 Info(slide, 0x401, ((char *)slide,
  1147.                   LoadFarString(AttemptRecompensate)));
  1148.                 if (G.extra_bytes) {
  1149.                     *pold_extra_bytes = G.extra_bytes;
  1150.                     G.extra_bytes = 0L;
  1151.                 } else
  1152.                     G.extra_bytes = *pold_extra_bytes; /* third attempt */
  1153.                 if (((error = seek_zipf(__G__ G.pInfo->offset)) != PK_OK) ||
  1154.                     (readbuf(__G__ G.sig, 4) == 0)) {  /* bad offset */
  1155.                     if (error != PK_BADERR)
  1156.                       Info(slide, 0x401, ((char *)slide,
  1157.                         LoadFarString(OffsetMsg), *pfilnum, "EOF",
  1158.                         (long)request));
  1159.                     error_in_archive = PK_BADERR;
  1160.                     continue;   /* but can still try next one */
  1161.                 }
  1162.                 if (memcmp(G.sig, local_hdr_sig, 4)) {
  1163.                     Info(slide, 0x401, ((char *)slide,
  1164.                       LoadFarString(OffsetMsg), *pfilnum,
  1165.                       LoadFarStringSmall(LocalHdrSig), (long)request));
  1166.                     error_in_archive = PK_BADERR;
  1167.                     continue;
  1168.                 }
  1169.             } else
  1170.                 continue;  /* this one hosed; try next */
  1171.         }
  1172.         if ((error = process_local_file_hdr(__G)) != PK_COOL) {
  1173.             Info(slide, 0x421, ((char *)slide, LoadFarString(BadLocalHdr),
  1174.               *pfilnum));
  1175.             error_in_archive = error;   /* only PK_EOF defined */
  1176.             continue;   /* can still try next one */
  1177.         }
  1178. #if (!defined(SFX) && defined(UNICODE_SUPPORT))
  1179.         if (((G.lrec.general_purpose_bit_flag & (1 << 11)) == (1 << 11))
  1180.             != (G.pInfo->GPFIsUTF8 != 0)) {
  1181.             if (QCOND2) {
  1182. #  ifdef SMALL_MEM
  1183.                 char *temp_cfilnam = slide + (7 * (WSIZE>>3));
  1184.  
  1185.                 zfstrcpy((char Far *)temp_cfilnam, G.pInfo->cfilname);
  1186. #    define  cFile_PrintBuf  temp_cfilnam
  1187. #  else
  1188. #    define  cFile_PrintBuf  G.pInfo->cfilname
  1189. #  endif
  1190.                 Info(slide, 0x421, ((char *)slide,
  1191.                   LoadFarStringSmall2(GP11FlagsDiffer),
  1192.                   *pfilnum, FnFilter1(cFile_PrintBuf), G.pInfo->GPFIsUTF8));
  1193. #  undef    cFile_PrintBuf
  1194.             }
  1195.             if (error_in_archive < PK_WARN)
  1196.                 error_in_archive = PK_WARN;
  1197.         }
  1198. #endif /* !SFX && UNICODE_SUPPORT */
  1199.         if ((error = do_string(__G__ G.lrec.filename_length, DS_FN_L)) !=
  1200.              PK_COOL)
  1201.         {
  1202.             if (error > error_in_archive)
  1203.                 error_in_archive = error;
  1204.             if (error > PK_WARN) {
  1205.                 Info(slide, 0x401, ((char *)slide, LoadFarString(FilNamMsg),
  1206.                   FnFilter1(G.filename), "local"));
  1207.                 continue;   /* go on to next one */
  1208.             }
  1209.         }
  1210.         if (G.extra_field != (uch *)NULL) {
  1211.             free(G.extra_field);
  1212.             G.extra_field = (uch *)NULL;
  1213.         }
  1214.         if ((error =
  1215.              do_string(__G__ G.lrec.extra_field_length, EXTRA_FIELD)) != 0)
  1216.         {
  1217.             if (error > error_in_archive)
  1218.                 error_in_archive = error;
  1219.             if (error > PK_WARN) {
  1220.                 Info(slide, 0x401, ((char *)slide,
  1221.                   LoadFarString(ExtFieldMsg),
  1222.                   FnFilter1(G.filename), "local"));
  1223.                 continue;   /* go on */
  1224.             }
  1225.         }
  1226. #ifndef SFX
  1227.         /* Filename consistency checks must come after reading in the local
  1228.          * extra field, so that a UTF-8 entry name e.f. block has already
  1229.          * been processed.
  1230.          */
  1231.         if (G.pInfo->cfilname != (char Far *)NULL) {
  1232.             if (zfstrcmp(G.pInfo->cfilname, G.filename) != 0) {
  1233. #  ifdef SMALL_MEM
  1234.                 char *temp_cfilnam = slide + (7 * (WSIZE>>3));
  1235.  
  1236.                 zfstrcpy((char Far *)temp_cfilnam, G.pInfo->cfilname);
  1237. #    define  cFile_PrintBuf  temp_cfilnam
  1238. #  else
  1239. #    define  cFile_PrintBuf  G.pInfo->cfilname
  1240. #  endif
  1241.                 Info(slide, 0x401, ((char *)slide,
  1242.                   LoadFarStringSmall2(LvsCFNamMsg),
  1243.                   FnFilter2(cFile_PrintBuf), FnFilter1(G.filename)));
  1244. #  undef    cFile_PrintBuf
  1245.                 zfstrcpy(G.filename, G.pInfo->cfilname);
  1246.                 if (error_in_archive < PK_WARN)
  1247.                     error_in_archive = PK_WARN;
  1248.             }
  1249.             zffree(G.pInfo->cfilname);
  1250.             G.pInfo->cfilname = (char Far *)NULL;
  1251.         }
  1252. #endif /* !SFX */
  1253.         /* Size consistency checks must come after reading in the local extra
  1254.          * field, so that any Zip64 extension local e.f. block has already
  1255.          * been processed.
  1256.          */
  1257.         if (G.lrec.compression_method == STORED) {
  1258.             zusz_t csiz_decrypted = G.lrec.csize;
  1259.  
  1260.             if (G.pInfo->encrypted)
  1261.                 csiz_decrypted -= 12;
  1262.             if (G.lrec.ucsize != csiz_decrypted) {
  1263.                 Info(slide, 0x401, ((char *)slide,
  1264.                   LoadFarStringSmall2(WrnStorUCSizCSizDiff),
  1265.                   FnFilter1(G.filename),
  1266.                   FmZofft(G.lrec.ucsize, NULL, "u"),
  1267.                   FmZofft(csiz_decrypted, NULL, "u")));
  1268.                 G.lrec.ucsize = csiz_decrypted;
  1269.                 if (error_in_archive < PK_WARN)
  1270.                     error_in_archive = PK_WARN;
  1271.             }
  1272.         }
  1273.  
  1274. #if CRYPT
  1275.         if (G.pInfo->encrypted &&
  1276.             (error = decrypt(__G__ uO.pwdarg)) != PK_COOL) {
  1277.             if (error == PK_WARN) {
  1278.                 if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))
  1279.                     Info(slide, 0x401, ((char *)slide,
  1280.                       LoadFarString(SkipIncorrectPasswd),
  1281.                       FnFilter1(G.filename)));
  1282.                 ++(*pnum_bad_pwd);
  1283.             } else {  /* (error > PK_WARN) */
  1284.                 if (error > error_in_archive)
  1285.                     error_in_archive = error;
  1286.                 Info(slide, 0x401, ((char *)slide,
  1287.                   LoadFarString(SkipCannotGetPasswd),
  1288.                   FnFilter1(G.filename)));
  1289.             }
  1290.             continue;   /* go on to next file */
  1291.         }
  1292. #endif /* CRYPT */
  1293.  
  1294.         /*
  1295.          * just about to extract file:  if extracting to disk, check if
  1296.          * already exists, and if so, take appropriate action according to
  1297.          * fflag/uflag/overwrite_all/etc. (we couldn't do this in upper
  1298.          * loop because we don't store the possibly renamed filename[] in
  1299.          * info[])
  1300.          */
  1301. #ifdef DLL
  1302.         if (!uO.tflag && !uO.cflag && !G.redirect_data)
  1303. #else
  1304.         if (!uO.tflag && !uO.cflag)
  1305. #endif
  1306.         {
  1307.             renamed = FALSE;   /* user hasn't renamed output file yet */
  1308.  
  1309. startover:
  1310.             query = FALSE;
  1311.             skip_entry = SKIP_NO;
  1312.             /* for files from DOS FAT, check for use of backslash instead
  1313.              *  of slash as directory separator (bug in some zipper(s); so
  1314.              *  far, not a problem in HPFS, NTFS or VFAT systems)
  1315.              */
  1316. #ifndef SFX
  1317.             if (G.pInfo->hostnum == FS_FAT_ && !MBSCHR(G.filename, '/')) {
  1318.                 char *p=G.filename;
  1319.  
  1320.                 if (*p) do {
  1321.                     if (*p == '\\') {
  1322.                         if (!G.reported_backslash) {
  1323.                             Info(slide, 0x21, ((char *)slide,
  1324.                               LoadFarString(BackslashPathSep), G.zipfn));
  1325.                             G.reported_backslash = TRUE;
  1326.                             if (!error_in_archive)
  1327.                                 error_in_archive = PK_WARN;
  1328.                         }
  1329.                         *p = '/';
  1330.                     }
  1331.                 } while (*PREINCSTR(p));
  1332.             }
  1333. #endif /* !SFX */
  1334.  
  1335.             if (!renamed) {
  1336.                /* remove absolute path specs */
  1337.                if (G.filename[0] == '/') {
  1338.                    Info(slide, 0x401, ((char *)slide,
  1339.                         LoadFarString(AbsolutePathWarning),
  1340.                         FnFilter1(G.filename)));
  1341.                    if (!error_in_archive)
  1342.                        error_in_archive = PK_WARN;
  1343.                    do {
  1344.                        char *p = G.filename + 1;
  1345.                        do {
  1346.                            *(p-1) = *p;
  1347.                        } while (*p++ != '\0');
  1348.                    } while (G.filename[0] == '/');
  1349.                }
  1350.             }
  1351.  
  1352.             /* mapname can create dirs if not freshening or if renamed */
  1353.             error = mapname(__G__ renamed);
  1354.             if ((errcode = error & ~MPN_MASK) != PK_OK &&
  1355.                 error_in_archive < errcode)
  1356.                 error_in_archive = errcode;
  1357.             if ((errcode = error & MPN_MASK) > MPN_INF_TRUNC) {
  1358.                 if (errcode == MPN_CREATED_DIR) {
  1359. #ifdef SET_DIR_ATTRIB
  1360.                     direntry *d_entry;
  1361.  
  1362.                     error = defer_dir_attribs(__G__ &d_entry);
  1363.                     if (d_entry == (direntry *)NULL) {
  1364.                         /* There may be no dir_attribs info available, or
  1365.                          * we have encountered a mem allocation error.
  1366.                          * In case of an error, report it and set program
  1367.                          * error state to warning level.
  1368.                          */
  1369.                         if (error) {
  1370.                             Info(slide, 0x401, ((char *)slide,
  1371.                                  LoadFarString(DirlistEntryNoMem)));
  1372.                             if (!error_in_archive)
  1373.                                 error_in_archive = PK_WARN;
  1374.                         }
  1375.                     } else {
  1376.                         d_entry->next = (*pdirlist);
  1377.                         (*pdirlist) = d_entry;
  1378.                         ++(*pnum_dirs);
  1379.                     }
  1380. #endif /* SET_DIR_ATTRIB */
  1381.                 } else if (errcode == MPN_VOL_LABEL) {
  1382. #ifdef DOS_OS2_W32
  1383.                     Info(slide, 0x401, ((char *)slide,
  1384.                       LoadFarString(SkipVolumeLabel),
  1385.                       FnFilter1(G.filename),
  1386.                       uO.volflag? "hard disk " : ""));
  1387. #else
  1388.                     Info(slide, 1, ((char *)slide,
  1389.                       LoadFarString(SkipVolumeLabel),
  1390.                       FnFilter1(G.filename), ""));
  1391. #endif
  1392.                 } else if (errcode > MPN_INF_SKIP &&
  1393.                            error_in_archive < PK_ERR)
  1394.                     error_in_archive = PK_ERR;
  1395.                 Trace((stderr, "mapname(%s) returns error code = %d\n",
  1396.                   FnFilter1(G.filename), error));
  1397.                 continue;   /* go on to next file */
  1398.             }
  1399.  
  1400. #ifdef QDOS
  1401.             QFilename(__G__ G.filename);
  1402. #endif
  1403.             switch (check_for_newer(__G__ G.filename)) {
  1404.                 case DOES_NOT_EXIST:
  1405. #ifdef NOVELL_BUG_FAILSAFE
  1406.                     G.dne = TRUE;   /* stat() says file DOES NOT EXIST */
  1407. #endif
  1408.                     /* freshen (no new files): skip unless just renamed */
  1409.                     if (uO.fflag && !renamed)
  1410.                         skip_entry = SKIP_Y_NONEXIST;
  1411.                     break;
  1412.                 case EXISTS_AND_OLDER:
  1413. #ifdef UNIXBACKUP
  1414.                     if (!uO.B_flag)
  1415. #endif
  1416.                     {
  1417.                         if (IS_OVERWRT_NONE)
  1418.                             /* never overwrite:  skip file */
  1419.                             skip_entry = SKIP_Y_EXISTING;
  1420.                         else if (!IS_OVERWRT_ALL)
  1421.                             query = TRUE;
  1422.                     }
  1423.                     break;
  1424.                 case EXISTS_AND_NEWER:             /* (or equal) */
  1425. #ifdef UNIXBACKUP
  1426.                     if ((!uO.B_flag && IS_OVERWRT_NONE) ||
  1427. #else
  1428.                     if (IS_OVERWRT_NONE ||
  1429. #endif
  1430.                         (uO.uflag && !renamed)) {
  1431.                         /* skip if update/freshen & orig name */
  1432.                         skip_entry = SKIP_Y_EXISTING;
  1433.                     } else {
  1434. #ifdef UNIXBACKUP
  1435.                         if (!IS_OVERWRT_ALL && !uO.B_flag)
  1436. #else
  1437.                         if (!IS_OVERWRT_ALL)
  1438. #endif
  1439.                             query = TRUE;
  1440.                     }
  1441.                     break;
  1442.             }
  1443. #ifdef VMS
  1444.             /* 2008-07-24 SMS.
  1445.              * On VMS, if the file name includes a version number,
  1446.              * and "-V" ("retain VMS version numbers", V_flag) is in
  1447.              * effect, then the VMS-specific code will handle any
  1448.              * conflicts with an existing file, making this query
  1449.              * redundant.  (Implicit "y" response here.)
  1450.              */
  1451.             if (query && uO.V_flag) {
  1452.                 /* Not discarding file versions.  Look for one. */
  1453.                 int cndx = strlen(G.filename) - 1;
  1454.  
  1455.                 while ((cndx > 0) && (isdigit(G.filename[cndx])))
  1456.                     cndx--;
  1457.                 if (G.filename[cndx] == ';')
  1458.                     /* File version found; skip the generic query,
  1459.                      * proceeding with its default response "y".
  1460.                      */
  1461.                     query = FALSE;
  1462.             }
  1463. #endif /* VMS */
  1464.             if (query) {
  1465. #ifdef WINDLL
  1466.                 switch (G.lpUserFunctions->replace != NULL ?
  1467.                         (*G.lpUserFunctions->replace)(G.filename, FILNAMSIZ) :
  1468.                         IDM_REPLACE_NONE) {
  1469.                     case IDM_REPLACE_RENAME:
  1470.                         _ISO_INTERN(G.filename);
  1471.                         renamed = TRUE;
  1472.                         goto startover;
  1473.                     case IDM_REPLACE_ALL:
  1474.                         G.overwrite_mode = OVERWRT_ALWAYS;
  1475.                         /* FALL THROUGH, extract */
  1476.                     case IDM_REPLACE_YES:
  1477.                         break;
  1478.                     case IDM_REPLACE_NONE:
  1479.                         G.overwrite_mode = OVERWRT_NEVER;
  1480.                         /* FALL THROUGH, skip */
  1481.                     case IDM_REPLACE_NO:
  1482.                         skip_entry = SKIP_Y_EXISTING;
  1483.                         break;
  1484.                 }
  1485. #else /* !WINDLL */
  1486.                 extent fnlen;
  1487. reprompt:
  1488.                 Info(slide, 0x81 & 0xFE, ((char *)slide,
  1489.                   LoadFarString(ReplaceQuery),
  1490.                   FnFilter1(G.filename)));
  1491.                 if (fgets(G.answerbuf, sizeof(G.answerbuf), stdin)
  1492.                     == (char *)NULL) {
  1493.                     Info(slide, 1 & 0xFE, ((char *)slide,
  1494.                       LoadFarString(AssumeNone)));
  1495.                     *G.answerbuf = 'N';
  1496.                     if (!error_in_archive)
  1497.                         error_in_archive = 1;  /* not extracted:  warning */
  1498.                 }
  1499.                 switch (*G.answerbuf) {
  1500.                     case 'r':
  1501.                     case 'R':
  1502.                         do {
  1503.                             Info(slide, 0x81 & 0xFE, ((char *)slide,
  1504.                               LoadFarString(NewNameQuery)));
  1505.                             fgets(G.filename, FILNAMSIZ, stdin);
  1506.                             /* usually get \n here:  better check for it */
  1507.                             fnlen = strlen(G.filename);
  1508.                             if (lastchar(G.filename, fnlen) == '\n')
  1509.                                 G.filename[--fnlen] = '\0';
  1510.                         } while (fnlen == 0);
  1511. #ifdef WIN32  /* WIN32 fgets( ... , stdin) returns OEM coded strings */
  1512.                         _OEM_INTERN(G.filename);
  1513. #endif
  1514.                         renamed = TRUE;
  1515.                         goto startover;   /* sorry for a goto */
  1516.                     case 'A':   /* dangerous option:  force caps */
  1517.                         G.overwrite_mode = OVERWRT_ALWAYS;
  1518.                         /* FALL THROUGH, extract */
  1519.                     case 'y':
  1520.                     case 'Y':
  1521.                         break;
  1522.                     case 'N':
  1523.                         G.overwrite_mode = OVERWRT_NEVER;
  1524.                         /* FALL THROUGH, skip */
  1525.                     case 'n':
  1526.                         /* skip file */
  1527.                         skip_entry = SKIP_Y_EXISTING;
  1528.                         break;
  1529.                     case '\n':
  1530.                     case '\r':
  1531.                         /* Improve echo of '\n' and/or '\r'
  1532.                            (sizeof(G.answerbuf) == 10 (see globals.h), so
  1533.                            there is enough space for the provided text...) */
  1534.                         strcpy(G.answerbuf, "{ENTER}");
  1535.                         /* fall through ... */
  1536.                     default:
  1537.                         /* usually get \n here:  remove it for nice display
  1538.                            (fnlen can be re-used here, we are outside the
  1539.                            "enter new filename" loop) */
  1540.                         fnlen = strlen(G.answerbuf);
  1541.                         if (lastchar(G.answerbuf, fnlen) == '\n')
  1542.                             G.answerbuf[--fnlen] = '\0';
  1543.                         Info(slide, 1 & 0xFE, ((char *)slide,
  1544.                           LoadFarString(InvalidResponse), G.answerbuf));
  1545.                         goto reprompt;   /* yet another goto? */
  1546.                 } /* end switch (*answerbuf) */
  1547. #endif /* ?WINDLL */
  1548.             } /* end if (query) */
  1549.             if (skip_entry != SKIP_NO) {
  1550. #ifdef WINDLL
  1551.                 if (skip_entry == SKIP_Y_EXISTING) {
  1552.                     /* report skipping of an existing entry */
  1553.                     Info(slide, 0, ((char *)slide,
  1554.                       ((IS_OVERWRT_NONE || !uO.uflag || renamed) ?
  1555.                        "Target file exists.  Skipping %s\n" :
  1556.                        "Target file newer.  Skipping %s\n"),
  1557.                       FnFilter1(G.filename)));
  1558.                 }
  1559. #endif /* WINDLL */
  1560.                 continue;
  1561.             }
  1562.         } /* end if (extracting to disk) */
  1563.  
  1564. #ifdef DLL
  1565.         if ((G.statreportcb != NULL) &&
  1566.             (*G.statreportcb)(__G__ UZ_ST_START_EXTRACT, G.zipfn,
  1567.                               G.filename, NULL)) {
  1568.             return IZ_CTRLC;        /* cancel operation by user request */
  1569.         }
  1570. #endif
  1571. #ifdef MACOS  /* MacOS is no preemptive OS, thus call event-handling by hand */
  1572.         UserStop();
  1573. #endif
  1574. #ifdef AMIGA
  1575.         G.filenote_slot = i;
  1576. #endif
  1577.         G.disk_full = 0;
  1578.         if ((error = extract_or_test_member(__G)) != PK_COOL) {
  1579.             if (error > error_in_archive)
  1580.                 error_in_archive = error;       /* ...and keep going */
  1581. #ifdef DLL
  1582.             if (G.disk_full > 1 || error_in_archive == IZ_CTRLC) {
  1583. #else
  1584.             if (G.disk_full > 1) {
  1585. #endif
  1586.                 return error_in_archive;        /* (unless disk full) */
  1587.             }
  1588.         }
  1589. #ifdef DLL
  1590.         if ((G.statreportcb != NULL) &&
  1591.             (*G.statreportcb)(__G__ UZ_ST_FINISH_MEMBER, G.zipfn,
  1592.                               G.filename, (zvoid *)&G.lrec.ucsize)) {
  1593.             return IZ_CTRLC;        /* cancel operation by user request */
  1594.         }
  1595. #endif
  1596. #ifdef MACOS  /* MacOS is no preemptive OS, thus call event-handling by hand */
  1597.         UserStop();
  1598. #endif
  1599.     } /* end for-loop (i:  files in current block) */
  1600.  
  1601.     return error_in_archive;
  1602.  
  1603. } /* end function extract_or_test_entrylist() */
  1604.  
  1605.  
  1606.  
  1607.  
  1608.  
  1609. /* wsize is used in extract_or_test_member() and UZbunzip2() */
  1610. #if (defined(DLL) && !defined(NO_SLIDE_REDIR))
  1611. #  define wsize G._wsize    /* wsize is a variable */
  1612. #else
  1613. #  define wsize WSIZE       /* wsize is a constant */
  1614. #endif
  1615.  
  1616. /***************************************/
  1617. /*  Function extract_or_test_member()  */
  1618. /***************************************/
  1619.  
  1620. static int extract_or_test_member(__G)    /* return PK-type error code */
  1621.      __GDEF
  1622. {
  1623.     char *nul="[empty] ", *txt="[text]  ", *bin="[binary]";
  1624. #ifdef CMS_MVS
  1625.     char *ebc="[ebcdic]";
  1626. #endif
  1627.     register int b;
  1628.     int r, error=PK_COOL;
  1629.  
  1630.  
  1631. /*---------------------------------------------------------------------------
  1632.     Initialize variables, buffers, etc.
  1633.   ---------------------------------------------------------------------------*/
  1634.  
  1635.     G.bits_left = 0;
  1636.     G.bitbuf = 0L;       /* unreduce and unshrink only */
  1637.     G.zipeof = 0;
  1638.     G.newfile = TRUE;
  1639.     G.crc32val = CRCVAL_INITIAL;
  1640.  
  1641. #ifdef SYMLINKS
  1642.     /* If file is a (POSIX-compatible) symbolic link and we are extracting
  1643.      * to disk, prepare to restore the link. */
  1644.     G.symlnk = (G.pInfo->symlink &&
  1645.                 !uO.tflag && !uO.cflag && (G.lrec.ucsize > 0));
  1646. #endif /* SYMLINKS */
  1647.  
  1648.     if (uO.tflag) {
  1649.         if (!uO.qflag)
  1650.             Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), "test",
  1651.               FnFilter1(G.filename), "", ""));
  1652.     } else {
  1653. #ifdef DLL
  1654.         if (uO.cflag && !G.redirect_data)
  1655. #else
  1656.         if (uO.cflag)
  1657. #endif
  1658.         {
  1659. #if (defined(OS2) && defined(__IBMC__) && (__IBMC__ >= 200))
  1660.             G.outfile = freopen("", "wb", stdout);   /* VAC++ ignores setmode */
  1661. #else
  1662.             G.outfile = stdout;
  1663. #endif
  1664. #ifdef DOS_FLX_NLM_OS2_W32
  1665. #if (defined(__HIGHC__) && !defined(FLEXOS))
  1666.             setmode(G.outfile, _BINARY);
  1667. #else /* !(defined(__HIGHC__) && !defined(FLEXOS)) */
  1668.             setmode(fileno(G.outfile), O_BINARY);
  1669. #endif /* ?(defined(__HIGHC__) && !defined(FLEXOS)) */
  1670. #           define NEWLINE "\r\n"
  1671. #else /* !DOS_FLX_NLM_OS2_W32 */
  1672. #           define NEWLINE "\n"
  1673. #endif /* ?DOS_FLX_NLM_OS2_W32 */
  1674. #ifdef VMS
  1675.             /* VMS:  required even for stdout! */
  1676.             if ((r = open_outfile(__G)) != 0)
  1677.                 switch (r) {
  1678.                   case OPENOUT_SKIPOK:
  1679.                     return PK_OK;
  1680.                   case OPENOUT_SKIPWARN:
  1681.                     return PK_WARN;
  1682.                   default:
  1683.                     return PK_DISK;
  1684.                 }
  1685.         } else if ((r = open_outfile(__G)) != 0)
  1686.             switch (r) {
  1687.               case OPENOUT_SKIPOK:
  1688.                 return PK_OK;
  1689.               case OPENOUT_SKIPWARN:
  1690.                 return PK_WARN;
  1691.               default:
  1692.                 return PK_DISK;
  1693.             }
  1694. #else /* !VMS */
  1695.         } else if (open_outfile(__G))
  1696.             return PK_DISK;
  1697. #endif /* ?VMS */
  1698.     }
  1699.  
  1700. /*---------------------------------------------------------------------------
  1701.     Unpack the file.
  1702.   ---------------------------------------------------------------------------*/
  1703.  
  1704.     defer_leftover_input(__G);    /* so NEXTBYTE bounds check will work */
  1705.     switch (G.lrec.compression_method) {
  1706.         case STORED:
  1707.             if (!uO.tflag && QCOND2) {
  1708. #ifdef SYMLINKS
  1709.                 if (G.symlnk)   /* can also be deflated, but rarer... */
  1710.                     Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
  1711.                       "link", FnFilter1(G.filename), "", ""));
  1712.                 else
  1713. #endif /* SYMLINKS */
  1714.                 Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
  1715.                   "extract", FnFilter1(G.filename),
  1716.                   (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
  1717.                   "" : (G.lrec.ucsize == 0L? nul : (G.pInfo->textfile? txt :
  1718.                   bin)), uO.cflag? NEWLINE : ""));
  1719.             }
  1720. #if (defined(DLL) && !defined(NO_SLIDE_REDIR))
  1721.             if (G.redirect_slide) {
  1722.                 wsize = G.redirect_size; redirSlide = G.redirect_buffer;
  1723.             } else {
  1724.                 wsize = WSIZE; redirSlide = slide;
  1725.             }
  1726. #endif
  1727.             G.outptr = redirSlide;
  1728.             G.outcnt = 0L;
  1729.             while ((b = NEXTBYTE) != EOF) {
  1730.                 *G.outptr++ = (uch)b;
  1731.                 if (++G.outcnt == wsize) {
  1732.                     error = flush(__G__ redirSlide, G.outcnt, 0);
  1733.                     G.outptr = redirSlide;
  1734.                     G.outcnt = 0L;
  1735.                     if (error != PK_COOL || G.disk_full) break;
  1736.                 }
  1737.             }
  1738.             if (G.outcnt) {        /* flush final (partial) buffer */
  1739.                 r = flush(__G__ redirSlide, G.outcnt, 0);
  1740.                 if (error < r) error = r;
  1741.             }
  1742.             break;
  1743.  
  1744. #ifndef SFX
  1745. #ifndef LZW_CLEAN
  1746.         case SHRUNK:
  1747.             if (!uO.tflag && QCOND2) {
  1748.                 Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
  1749.                   LoadFarStringSmall(Unshrink), FnFilter1(G.filename),
  1750.                   (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
  1751.                   "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : ""));
  1752.             }
  1753.             if ((r = unshrink(__G)) != PK_COOL) {
  1754.                 if (r < PK_DISK) {
  1755.                     if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
  1756.                         Info(slide, 0x401, ((char *)slide,
  1757.                           LoadFarStringSmall(ErrUnzipFile), r == PK_MEM3 ?
  1758.                           LoadFarString(NotEnoughMem) :
  1759.                           LoadFarString(InvalidComprData),
  1760.                           LoadFarStringSmall2(Unshrink),
  1761.                           FnFilter1(G.filename)));
  1762.                     else
  1763.                         Info(slide, 0x401, ((char *)slide,
  1764.                           LoadFarStringSmall(ErrUnzipNoFile), r == PK_MEM3 ?
  1765.                           LoadFarString(NotEnoughMem) :
  1766.                           LoadFarString(InvalidComprData),
  1767.                           LoadFarStringSmall2(Unshrink)));
  1768.                 }
  1769.                 error = r;
  1770.             }
  1771.             break;
  1772. #endif /* !LZW_CLEAN */
  1773.  
  1774. #ifndef COPYRIGHT_CLEAN
  1775.         case REDUCED1:
  1776.         case REDUCED2:
  1777.         case REDUCED3:
  1778.         case REDUCED4:
  1779.             if (!uO.tflag && QCOND2) {
  1780.                 Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
  1781.                   "unreduc", FnFilter1(G.filename),
  1782.                   (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
  1783.                   "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : ""));
  1784.             }
  1785.             if ((r = unreduce(__G)) != PK_COOL) {
  1786.                 /* unreduce() returns only PK_COOL, PK_DISK, or IZ_CTRLC */
  1787.                 error = r;
  1788.             }
  1789.             break;
  1790. #endif /* !COPYRIGHT_CLEAN */
  1791.  
  1792.         case IMPLODED:
  1793.             if (!uO.tflag && QCOND2) {
  1794.                 Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
  1795.                   "explod", FnFilter1(G.filename),
  1796.                   (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
  1797.                   "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : ""));
  1798.             }
  1799.             if ((r = explode(__G)) != 0) {
  1800.                 if (r == 5) { /* treat 5 specially */
  1801.                     int warning = ((zusz_t)G.used_csize <= G.lrec.csize);
  1802.  
  1803.                     if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
  1804.                         Info(slide, 0x401, ((char *)slide,
  1805.                           LoadFarString(LengthMsg),
  1806.                           "", warning ? "warning" : "error",
  1807.                           FmZofft(G.used_csize, NULL, NULL),
  1808.                           FmZofft(G.lrec.ucsize, NULL, "u"),
  1809.                           warning ? "  " : "",
  1810.                           FmZofft(G.lrec.csize, NULL, "u"),
  1811.                           " [", FnFilter1(G.filename), "]"));
  1812.                     else
  1813.                         Info(slide, 0x401, ((char *)slide,
  1814.                           LoadFarString(LengthMsg),
  1815.                           "\n", warning ? "warning" : "error",
  1816.                           FmZofft(G.used_csize, NULL, NULL),
  1817.                           FmZofft(G.lrec.ucsize, NULL, "u"),
  1818.                           warning ? "  " : "",
  1819.                           FmZofft(G.lrec.csize, NULL, "u"),
  1820.                           "", "", "."));
  1821.                     error = warning ? PK_WARN : PK_ERR;
  1822.                 } else if (r < PK_DISK) {
  1823.                     if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
  1824.                         Info(slide, 0x401, ((char *)slide,
  1825.                           LoadFarStringSmall(ErrUnzipFile), r == 3?
  1826.                           LoadFarString(NotEnoughMem) :
  1827.                           LoadFarString(InvalidComprData),
  1828.                           LoadFarStringSmall2(Explode),
  1829.                           FnFilter1(G.filename)));
  1830.                     else
  1831.                         Info(slide, 0x401, ((char *)slide,
  1832.                           LoadFarStringSmall(ErrUnzipNoFile), r == 3?
  1833.                           LoadFarString(NotEnoughMem) :
  1834.                           LoadFarString(InvalidComprData),
  1835.                           LoadFarStringSmall2(Explode)));
  1836.                     error = ((r == 3) ? PK_MEM3 : PK_ERR);
  1837.                 } else {
  1838.                     error = r;
  1839.                 }
  1840.             }
  1841.             break;
  1842. #endif /* !SFX */
  1843.  
  1844.         case DEFLATED:
  1845. #ifdef USE_DEFLATE64
  1846.         case ENHDEFLATED:
  1847. #endif
  1848.             if (!uO.tflag && QCOND2) {
  1849.                 Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
  1850.                   "inflat", FnFilter1(G.filename),
  1851.                   (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
  1852.                   "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : ""));
  1853.             }
  1854. #ifndef USE_ZLIB  /* zlib's function is called inflate(), too */
  1855. #  define UZinflate inflate
  1856. #endif
  1857.             if ((r = UZinflate(__G__
  1858.                                (G.lrec.compression_method == ENHDEFLATED)))
  1859.                 != 0) {
  1860.                 if (r < PK_DISK) {
  1861.                     if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
  1862.                         Info(slide, 0x401, ((char *)slide,
  1863.                           LoadFarStringSmall(ErrUnzipFile), r == 3?
  1864.                           LoadFarString(NotEnoughMem) :
  1865.                           LoadFarString(InvalidComprData),
  1866.                           LoadFarStringSmall2(Inflate),
  1867.                           FnFilter1(G.filename)));
  1868.                     else
  1869.                         Info(slide, 0x401, ((char *)slide,
  1870.                           LoadFarStringSmall(ErrUnzipNoFile), r == 3?
  1871.                           LoadFarString(NotEnoughMem) :
  1872.                           LoadFarString(InvalidComprData),
  1873.                           LoadFarStringSmall2(Inflate)));
  1874.                     error = ((r == 3) ? PK_MEM3 : PK_ERR);
  1875.                 } else {
  1876.                     error = r;
  1877.                 }
  1878.             }
  1879.             break;
  1880.  
  1881. #ifdef USE_BZIP2
  1882.         case BZIPPED:
  1883.             if (!uO.tflag && QCOND2) {
  1884.                 Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
  1885.                   "bunzipp", FnFilter1(G.filename),
  1886.                   (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
  1887.                   "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : ""));
  1888.             }
  1889.             if ((r = UZbunzip2(__G)) != 0) {
  1890.                 if (r < PK_DISK) {
  1891.                     if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
  1892.                         Info(slide, 0x401, ((char *)slide,
  1893.                           LoadFarStringSmall(ErrUnzipFile), r == 3?
  1894.                           LoadFarString(NotEnoughMem) :
  1895.                           LoadFarString(InvalidComprData),
  1896.                           LoadFarStringSmall2(BUnzip),
  1897.                           FnFilter1(G.filename)));
  1898.                     else
  1899.                         Info(slide, 0x401, ((char *)slide,
  1900.                           LoadFarStringSmall(ErrUnzipNoFile), r == 3?
  1901.                           LoadFarString(NotEnoughMem) :
  1902.                           LoadFarString(InvalidComprData),
  1903.                           LoadFarStringSmall2(BUnzip)));
  1904.                     error = ((r == 3) ? PK_MEM3 : PK_ERR);
  1905.                 } else {
  1906.                     error = r;
  1907.                 }
  1908.             }
  1909.             break;
  1910. #endif /* USE_BZIP2 */
  1911.  
  1912.         default:   /* should never get to this point */
  1913.             Info(slide, 0x401, ((char *)slide,
  1914.               LoadFarString(FileUnknownCompMethod), FnFilter1(G.filename)));
  1915.             /* close and delete file before return? */
  1916.             undefer_input(__G);
  1917.             return PK_WARN;
  1918.  
  1919.     } /* end switch (compression method) */
  1920.  
  1921. /*---------------------------------------------------------------------------
  1922.     Close the file and set its date and time (not necessarily in that order),
  1923.     and make sure the CRC checked out OK.  Logical-AND the CRC for 64-bit
  1924.     machines (redundant on 32-bit machines).
  1925.   ---------------------------------------------------------------------------*/
  1926.  
  1927. #ifdef VMS                  /* VMS:  required even for stdout! (final flush) */
  1928.     if (!uO.tflag)           /* don't close NULL file */
  1929.         close_outfile(__G);
  1930. #else
  1931. #ifdef DLL
  1932.     if (!uO.tflag && (!uO.cflag || G.redirect_data)) {
  1933.         if (G.redirect_data)
  1934.             FINISH_REDIRECT();
  1935.         else
  1936.             close_outfile(__G);
  1937.     }
  1938. #else
  1939.     if (!uO.tflag && !uO.cflag)   /* don't close NULL file or stdout */
  1940.         close_outfile(__G);
  1941. #endif
  1942. #endif /* VMS */
  1943.  
  1944.             /* GRR: CONVERT close_outfile() TO NON-VOID:  CHECK FOR ERRORS! */
  1945.  
  1946.  
  1947.     if (G.disk_full) {            /* set by flush() */
  1948.         if (G.disk_full > 1) {
  1949. #if (defined(DELETE_IF_FULL) && defined(HAVE_UNLINK))
  1950.             /* delete the incomplete file if we can */
  1951.             if (unlink(G.filename) != 0)
  1952.                 Trace((stderr, "extract.c:  could not delete %s\n",
  1953.                   FnFilter1(G.filename)));
  1954. #else
  1955.             /* warn user about the incomplete file */
  1956.             Info(slide, 0x421, ((char *)slide, LoadFarString(FileTruncated),
  1957.               FnFilter1(G.filename)));
  1958. #endif
  1959.             error = PK_DISK;
  1960.         } else {
  1961.             error = PK_WARN;
  1962.         }
  1963.     }
  1964.  
  1965.     if (error > PK_WARN) {/* don't print redundant CRC error if error already */
  1966.         undefer_input(__G);
  1967.         return error;
  1968.     }
  1969.     if (G.crc32val != G.lrec.crc32) {
  1970.         /* if quiet enough, we haven't output the filename yet:  do it */
  1971.         if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
  1972.             Info(slide, 0x401, ((char *)slide, "%-22s ",
  1973.               FnFilter1(G.filename)));
  1974.         Info(slide, 0x401, ((char *)slide, LoadFarString(BadCRC), G.crc32val,
  1975.           G.lrec.crc32));
  1976. #if CRYPT
  1977.         if (G.pInfo->encrypted)
  1978.             Info(slide, 0x401, ((char *)slide, LoadFarString(MaybeBadPasswd)));
  1979. #endif
  1980.         error = PK_ERR;
  1981.     } else if (uO.tflag) {
  1982. #ifndef SFX
  1983.         if (G.extra_field) {
  1984.             if ((r = TestExtraField(__G__ G.extra_field,
  1985.                                     G.lrec.extra_field_length)) > error)
  1986.                 error = r;
  1987.         } else
  1988. #endif /* !SFX */
  1989.         if (!uO.qflag)
  1990.             Info(slide, 0, ((char *)slide, " OK\n"));
  1991.     } else {
  1992.         if (QCOND2 && !error)   /* GRR:  is stdout reset to text mode yet? */
  1993.             Info(slide, 0, ((char *)slide, "\n"));
  1994.     }
  1995.  
  1996.     undefer_input(__G);
  1997.     return error;
  1998.  
  1999. } /* end function extract_or_test_member() */
  2000.  
  2001.  
  2002.  
  2003.  
  2004.  
  2005. #ifndef SFX
  2006.  
  2007. /*******************************/
  2008. /*  Function TestExtraField()  */
  2009. /*******************************/
  2010.  
  2011. static int TestExtraField(__G__ ef, ef_len)
  2012.     __GDEF
  2013.     uch *ef;
  2014.     unsigned ef_len;
  2015. {
  2016.     ush ebID;
  2017.     unsigned ebLen;
  2018.     unsigned eb_cmpr_offs = 0;
  2019.     int r;
  2020.  
  2021.     /* we know the regular compressed file data tested out OK, or else we
  2022.      * wouldn't be here ==> print filename if any extra-field errors found
  2023.      */
  2024.     while (ef_len >= EB_HEADSIZE) {
  2025.         ebID = makeword(ef);
  2026.         ebLen = (unsigned)makeword(ef+EB_LEN);
  2027.  
  2028.         if (ebLen > (ef_len - EB_HEADSIZE)) {
  2029.            /* Discovered some extra field inconsistency! */
  2030.             if (uO.qflag)
  2031.                 Info(slide, 1, ((char *)slide, "%-22s ",
  2032.                   FnFilter1(G.filename)));
  2033.             Info(slide, 1, ((char *)slide, LoadFarString(InconsistEFlength),
  2034.               ebLen, (ef_len - EB_HEADSIZE)));
  2035.             return PK_ERR;
  2036.         }
  2037.  
  2038.         switch (ebID) {
  2039.             case EF_OS2:
  2040.             case EF_ACL:
  2041.             case EF_MAC3:
  2042.             case EF_BEOS:
  2043.             case EF_ATHEOS:
  2044.                 switch (ebID) {
  2045.                   case EF_OS2:
  2046.                   case EF_ACL:
  2047.                     eb_cmpr_offs = EB_OS2_HLEN;
  2048.                     break;
  2049.                   case EF_MAC3:
  2050.                     if (ebLen >= EB_MAC3_HLEN &&
  2051.                         (makeword(ef+(EB_HEADSIZE+EB_FLGS_OFFS))
  2052.                          & EB_M3_FL_UNCMPR) &&
  2053.                         (makelong(ef+EB_HEADSIZE) == ebLen - EB_MAC3_HLEN))
  2054.                         eb_cmpr_offs = 0;
  2055.                     else
  2056.                         eb_cmpr_offs = EB_MAC3_HLEN;
  2057.                     break;
  2058.                   case EF_BEOS:
  2059.                   case EF_ATHEOS:
  2060.                     if (ebLen >= EB_BEOS_HLEN &&
  2061.                         (*(ef+(EB_HEADSIZE+EB_FLGS_OFFS)) & EB_BE_FL_UNCMPR) &&
  2062.                         (makelong(ef+EB_HEADSIZE) == ebLen - EB_BEOS_HLEN))
  2063.                         eb_cmpr_offs = 0;
  2064.                     else
  2065.                         eb_cmpr_offs = EB_BEOS_HLEN;
  2066.                     break;
  2067.                 }
  2068.                 if ((r = test_compr_eb(__G__ ef, ebLen, eb_cmpr_offs, NULL))
  2069.                     != PK_OK) {
  2070.                     if (uO.qflag)
  2071.                         Info(slide, 1, ((char *)slide, "%-22s ",
  2072.                           FnFilter1(G.filename)));
  2073.                     switch (r) {
  2074.                         case IZ_EF_TRUNC:
  2075.                             Info(slide, 1, ((char *)slide,
  2076.                               LoadFarString(TruncEAs),
  2077.                               ebLen-(eb_cmpr_offs+EB_CMPRHEADLEN), "\n"));
  2078.                             break;
  2079.                         case PK_ERR:
  2080.                             Info(slide, 1, ((char *)slide,
  2081.                               LoadFarString(InvalidComprDataEAs)));
  2082.                             break;
  2083.                         case PK_MEM3:
  2084.                         case PK_MEM4:
  2085.                             Info(slide, 1, ((char *)slide,
  2086.                               LoadFarString(NotEnoughMemEAs)));
  2087.                             break;
  2088.                         default:
  2089.                             if ((r & 0xff) != PK_ERR)
  2090.                                 Info(slide, 1, ((char *)slide,
  2091.                                   LoadFarString(UnknErrorEAs)));
  2092.                             else {
  2093.                                 ush m = (ush)(r >> 8);
  2094.                                 if (m == DEFLATED)            /* GRR KLUDGE! */
  2095.                                     Info(slide, 1, ((char *)slide,
  2096.                                       LoadFarString(BadCRC_EAs)));
  2097.                                 else
  2098.                                     Info(slide, 1, ((char *)slide,
  2099.                                       LoadFarString(UnknComprMethodEAs), m));
  2100.                             }
  2101.                             break;
  2102.                     }
  2103.                     return r;
  2104.                 }
  2105.                 break;
  2106.  
  2107.             case EF_NTSD:
  2108.                 Trace((stderr, "ebID: %i / ebLen: %u\n", ebID, ebLen));
  2109.                 r = ebLen < EB_NTSD_L_LEN ? IZ_EF_TRUNC :
  2110.                     ((ef[EB_HEADSIZE+EB_NTSD_VERSION] > EB_NTSD_MAX_VER) ?
  2111.                      (PK_WARN | 0x4000) :
  2112.                      test_compr_eb(__G__ ef, ebLen, EB_NTSD_L_LEN, TEST_NTSD));
  2113.                 if (r != PK_OK) {
  2114.                     if (uO.qflag)
  2115.                         Info(slide, 1, ((char *)slide, "%-22s ",
  2116.                           FnFilter1(G.filename)));
  2117.                     switch (r) {
  2118.                         case IZ_EF_TRUNC:
  2119.                             Info(slide, 1, ((char *)slide,
  2120.                               LoadFarString(TruncNTSD),
  2121.                               ebLen-(EB_NTSD_L_LEN+EB_CMPRHEADLEN), "\n"));
  2122.                             break;
  2123. #if (defined(WIN32) && defined(NTSD_EAS))
  2124.                         case PK_WARN:
  2125.                             Info(slide, 1, ((char *)slide,
  2126.                               LoadFarString(InvalidSecurityEAs)));
  2127.                             break;
  2128. #endif
  2129.                         case PK_ERR:
  2130.                             Info(slide, 1, ((char *)slide,
  2131.                               LoadFarString(InvalidComprDataEAs)));
  2132.                             break;
  2133.                         case PK_MEM3:
  2134.                         case PK_MEM4:
  2135.                             Info(slide, 1, ((char *)slide,
  2136.                               LoadFarString(NotEnoughMemEAs)));
  2137.                             break;
  2138.                         case (PK_WARN | 0x4000):
  2139.                             Info(slide, 1, ((char *)slide,
  2140.                               LoadFarString(UnsuppNTSDVersEAs),
  2141.                               (int)ef[EB_HEADSIZE+EB_NTSD_VERSION]));
  2142.                             r = PK_WARN;
  2143.                             break;
  2144.                         default:
  2145.                             if ((r & 0xff) != PK_ERR)
  2146.                                 Info(slide, 1, ((char *)slide,
  2147.                                   LoadFarString(UnknErrorEAs)));
  2148.                             else {
  2149.                                 ush m = (ush)(r >> 8);
  2150.                                 if (m == DEFLATED)            /* GRR KLUDGE! */
  2151.                                     Info(slide, 1, ((char *)slide,
  2152.                                       LoadFarString(BadCRC_EAs)));
  2153.                                 else
  2154.                                     Info(slide, 1, ((char *)slide,
  2155.                                       LoadFarString(UnknComprMethodEAs), m));
  2156.                             }
  2157.                             break;
  2158.                     }
  2159.                     return r;
  2160.                 }
  2161.                 break;
  2162.             case EF_PKVMS:
  2163.                 if (makelong(ef+EB_HEADSIZE) !=
  2164.                     crc32(CRCVAL_INITIAL, ef+(EB_HEADSIZE+4),
  2165.                           (extent)(ebLen-4)))
  2166.                     Info(slide, 1, ((char *)slide,
  2167.                       LoadFarString(BadCRC_EAs)));
  2168.                 break;
  2169.             case EF_PKW32:
  2170.             case EF_PKUNIX:
  2171.             case EF_ASIUNIX:
  2172.             case EF_IZVMS:
  2173.             case EF_IZUNIX:
  2174.             case EF_VMCMS:
  2175.             case EF_MVS:
  2176.             case EF_SPARK:
  2177.             case EF_TANDEM:
  2178.             case EF_THEOS:
  2179.             case EF_AV:
  2180.             default:
  2181.                 break;
  2182.         }
  2183.         ef_len -= (ebLen + EB_HEADSIZE);
  2184.         ef += (ebLen + EB_HEADSIZE);
  2185.     }
  2186.  
  2187.     if (!uO.qflag)
  2188.         Info(slide, 0, ((char *)slide, " OK\n"));
  2189.  
  2190.     return PK_COOL;
  2191.  
  2192. } /* end function TestExtraField() */
  2193.  
  2194.  
  2195.  
  2196.  
  2197.  
  2198. /******************************/
  2199. /*  Function test_compr_eb()  */
  2200. /******************************/
  2201.  
  2202. #ifdef PROTO
  2203. static int test_compr_eb(
  2204.     __GPRO__
  2205.     uch *eb,
  2206.     unsigned eb_size,
  2207.     unsigned compr_offset,
  2208.     int (*test_uc_ebdata)(__GPRO__ uch *eb, unsigned eb_size,
  2209.                           uch *eb_ucptr, ulg eb_ucsize))
  2210. #else /* !PROTO */
  2211. static int test_compr_eb(__G__ eb, eb_size, compr_offset, test_uc_ebdata)
  2212.     __GDEF
  2213.     uch *eb;
  2214.     unsigned eb_size;
  2215.     unsigned compr_offset;
  2216.     int (*test_uc_ebdata)();
  2217. #endif /* ?PROTO */
  2218. {
  2219.     ulg eb_ucsize;
  2220.     uch *eb_ucptr;
  2221.     int r;
  2222.  
  2223.     if (compr_offset < 4)                /* field is not compressed: */
  2224.         return PK_OK;                    /* do nothing and signal OK */
  2225.  
  2226.     if ((eb_size < (EB_UCSIZE_P + 4)) ||
  2227.         ((eb_ucsize = makelong(eb+(EB_HEADSIZE+EB_UCSIZE_P))) > 0L &&
  2228.          eb_size <= (compr_offset + EB_CMPRHEADLEN)))
  2229.         return IZ_EF_TRUNC;               /* no compressed data! */
  2230.  
  2231.     if (
  2232. #ifdef INT_16BIT
  2233.         (((ulg)(extent)eb_ucsize) != eb_ucsize) ||
  2234. #endif
  2235.         (eb_ucptr = (uch *)malloc((extent)eb_ucsize)) == (uch *)NULL)
  2236.         return PK_MEM4;
  2237.  
  2238.     r = memextract(__G__ eb_ucptr, eb_ucsize,
  2239.                    eb + (EB_HEADSIZE + compr_offset),
  2240.                    (ulg)(eb_size - compr_offset));
  2241.  
  2242.     if (r == PK_OK && test_uc_ebdata != NULL)
  2243.         r = (*test_uc_ebdata)(__G__ eb, eb_size, eb_ucptr, eb_ucsize);
  2244.  
  2245.     free(eb_ucptr);
  2246.     return r;
  2247.  
  2248. } /* end function test_compr_eb() */
  2249.  
  2250. #endif /* !SFX */
  2251.  
  2252.  
  2253.  
  2254.  
  2255.  
  2256. /***************************/
  2257. /*  Function memextract()  */
  2258. /***************************/
  2259.  
  2260. int memextract(__G__ tgt, tgtsize, src, srcsize)  /* extract compressed */
  2261.     __GDEF                                        /*  extra field block; */
  2262.     uch *tgt;                                     /*  return PK-type error */
  2263.     ulg tgtsize;                                  /*  level */
  2264.     ZCONST uch *src;
  2265.     ulg srcsize;
  2266. {
  2267.     zoff_t old_csize=G.csize;
  2268.     uch   *old_inptr=G.inptr;
  2269.     int    old_incnt=G.incnt;
  2270.     int    r, error=PK_OK;
  2271.     ush    method;
  2272.     ulg    extra_field_crc;
  2273.  
  2274.  
  2275.     method = makeword(src);
  2276.     extra_field_crc = makelong(src+2);
  2277.  
  2278.     /* compressed extra field exists completely in memory at this location: */
  2279.     G.inptr = (uch *)src + (2 + 4);     /* method and extra_field_crc */
  2280.     G.incnt = (int)(G.csize = (long)(srcsize - (2 + 4)));
  2281.     G.mem_mode = TRUE;
  2282.     G.outbufptr = tgt;
  2283.     G.outsize = tgtsize;
  2284.  
  2285.     switch (method) {
  2286.         case STORED:
  2287.             memcpy((char *)tgt, (char *)G.inptr, (extent)G.incnt);
  2288.             G.outcnt = (ulg)G.csize;    /* for CRC calculation */
  2289.             break;
  2290.         case DEFLATED:
  2291. #ifdef USE_DEFLATE64
  2292.         case ENHDEFLATED:
  2293. #endif
  2294.             G.outcnt = 0L;
  2295.             if ((r = UZinflate(__G__ (method == ENHDEFLATED))) != 0) {
  2296.                 if (!uO.tflag)
  2297.                     Info(slide, 0x401, ((char *)slide,
  2298.                       LoadFarStringSmall(ErrUnzipNoFile), r == 3?
  2299.                       LoadFarString(NotEnoughMem) :
  2300.                       LoadFarString(InvalidComprData),
  2301.                       LoadFarStringSmall2(Inflate)));
  2302.                 error = (r == 3)? PK_MEM3 : PK_ERR;
  2303.             }
  2304.             if (G.outcnt == 0L)   /* inflate's final FLUSH sets outcnt */
  2305.                 break;
  2306.             break;
  2307.         default:
  2308.             if (uO.tflag)
  2309.                 error = PK_ERR | ((int)method << 8);
  2310.             else {
  2311.                 Info(slide, 0x401, ((char *)slide,
  2312.                   LoadFarString(UnsupportedExtraField), method));
  2313.                 error = PK_ERR;  /* GRR:  should be passed on up via SetEAs() */
  2314.             }
  2315.             break;
  2316.     }
  2317.  
  2318.     G.inptr = old_inptr;
  2319.     G.incnt = old_incnt;
  2320.     G.csize = old_csize;
  2321.     G.mem_mode = FALSE;
  2322.  
  2323.     if (!error) {
  2324.         register ulg crcval = crc32(CRCVAL_INITIAL, tgt, (extent)G.outcnt);
  2325.  
  2326.         if (crcval != extra_field_crc) {
  2327.             if (uO.tflag)
  2328.                 error = PK_ERR | (DEFLATED << 8);  /* kludge for now */
  2329.             else {
  2330.                 Info(slide, 0x401, ((char *)slide,
  2331.                   LoadFarString(BadExtraFieldCRC), G.zipfn, crcval,
  2332.                   extra_field_crc));
  2333.                 error = PK_ERR;
  2334.             }
  2335.         }
  2336.     }
  2337.     return error;
  2338.  
  2339. } /* end function memextract() */
  2340.  
  2341.  
  2342.  
  2343.  
  2344.  
  2345. /*************************/
  2346. /*  Function memflush()  */
  2347. /*************************/
  2348.  
  2349. int memflush(__G__ rawbuf, size)
  2350.     __GDEF
  2351.     ZCONST uch *rawbuf;
  2352.     ulg size;
  2353. {
  2354.     if (size > G.outsize)
  2355.         /* Here, PK_DISK is a bit off-topic, but in the sense of marking
  2356.            "overflow of output space", its use may be tolerated. */
  2357.         return PK_DISK;   /* more data than output buffer can hold */
  2358.  
  2359.  
  2360.  
  2361.     memcpy((char *)G.outbufptr, (char *)rawbuf, (extent)size);
  2362.     G.outbufptr += (unsigned int)size;
  2363.     G.outsize -= size;
  2364.     G.outcnt += size;
  2365.  
  2366.     return 0;
  2367.  
  2368. } /* end function memflush() */
  2369.  
  2370.  
  2371.  
  2372.  
  2373.  
  2374. #if (defined(VMS) || defined(VMS_TEXT_CONV))
  2375.  
  2376. /************************************/
  2377. /*  Function extract_izvms_block()  */
  2378. /************************************/
  2379.  
  2380. /*
  2381.  * Extracts block from p. If resulting length is less than needed, fill
  2382.  * extra space with corresponding bytes from 'init'.
  2383.  * Currently understands 3 formats of block compression:
  2384.  * - Simple storing
  2385.  * - Compression of zero bytes to zero bits
  2386.  * - Deflation (see memextract())
  2387.  * The IZVMS block data is returned in malloc'd space.
  2388.  */
  2389. uch *extract_izvms_block(__G__ ebdata, size, retlen, init, needlen)
  2390.     __GDEF
  2391.     ZCONST uch *ebdata;
  2392.     unsigned size;
  2393.     unsigned *retlen;
  2394.     ZCONST uch *init;
  2395.     unsigned needlen;
  2396. {
  2397.     uch *ucdata;       /* Pointer to block allocated */
  2398.     int cmptype;
  2399.     unsigned usiz, csiz;
  2400.  
  2401.     cmptype = (makeword(ebdata+EB_IZVMS_FLGS) & EB_IZVMS_BCMASK);
  2402.     csiz = size - EB_IZVMS_HLEN;
  2403.     usiz = (cmptype == EB_IZVMS_BCSTOR ?
  2404.             csiz : makeword(ebdata+EB_IZVMS_UCSIZ));
  2405.  
  2406.     if (retlen)
  2407.         *retlen = usiz;
  2408.  
  2409.     if ((ucdata = (uch *)malloc(MAX(needlen, usiz))) == NULL)
  2410.         return NULL;
  2411.  
  2412.     if (init && (usiz < needlen))
  2413.         memcpy((char *)ucdata, (ZCONST char *)init, needlen);
  2414.  
  2415.     switch (cmptype)
  2416.     {
  2417.         case EB_IZVMS_BCSTOR: /* The simplest case */
  2418.             memcpy(ucdata, ebdata+EB_IZVMS_HLEN, usiz);
  2419.             break;
  2420.         case EB_IZVMS_BC00:
  2421.             decompress_bits(ucdata, usiz, ebdata+EB_IZVMS_HLEN);
  2422.             break;
  2423.         case EB_IZVMS_BCDEFL:
  2424.             memextract(__G__ ucdata, (ulg)usiz,
  2425.                        ebdata+EB_IZVMS_HLEN, (ulg)csiz);
  2426.             break;
  2427.         default:
  2428.             free(ucdata);
  2429.             ucdata = NULL;
  2430.     }
  2431.     return ucdata;
  2432.  
  2433. } /* end of extract_izvms_block */
  2434.  
  2435.  
  2436.  
  2437.  
  2438.  
  2439. /********************************/
  2440. /*  Function decompress_bits()  */
  2441. /********************************/
  2442. /*
  2443.  *  Simple uncompression routine. The compression uses bit stream.
  2444.  *  Compression scheme:
  2445.  *
  2446.  *  if (byte!=0)
  2447.  *      putbit(1),putbyte(byte)
  2448.  *  else
  2449.  *      putbit(0)
  2450.  */
  2451. static void decompress_bits(outptr, needlen, bitptr)
  2452.     uch *outptr;        /* Pointer into output block */
  2453.     unsigned needlen;   /* Size of uncompressed block */
  2454.     ZCONST uch *bitptr; /* Pointer into compressed data */
  2455. {
  2456.     ulg bitbuf = 0;
  2457.     int bitcnt = 0;
  2458.  
  2459. #define _FILL   {       bitbuf |= (*bitptr++) << bitcnt;\
  2460.                         bitcnt += 8;                    \
  2461.                 }
  2462.  
  2463.     while (needlen--)
  2464.     {
  2465.         if (bitcnt <= 0)
  2466.             _FILL;
  2467.  
  2468.         if (bitbuf & 1)
  2469.         {
  2470.             bitbuf >>= 1;
  2471.             if ((bitcnt -= 1) < 8)
  2472.                 _FILL;
  2473.             *outptr++ = (uch)bitbuf;
  2474.             bitcnt -= 8;
  2475.             bitbuf >>= 8;
  2476.         }
  2477.         else
  2478.         {
  2479.             *outptr++ = '\0';
  2480.             bitcnt -= 1;
  2481.             bitbuf >>= 1;
  2482.         }
  2483.     }
  2484. } /* end function decompress_bits() */
  2485.  
  2486. #endif /* VMS || VMS_TEXT_CONV */
  2487.  
  2488.  
  2489.  
  2490.  
  2491.  
  2492. #ifdef SYMLINKS
  2493. /***********************************/
  2494. /* Function set_deferred_symlink() */
  2495. /***********************************/
  2496.  
  2497. static void set_deferred_symlink(__G__ slnk_entry)
  2498.     __GDEF
  2499.     slinkentry *slnk_entry;
  2500. {
  2501.     extent ucsize = slnk_entry->targetlen;
  2502.     char *linkfname = slnk_entry->fname;
  2503.     char *linktarget = (char *)malloc(ucsize+1);
  2504.  
  2505.     if (!linktarget) {
  2506.         Info(slide, 0x201, ((char *)slide,
  2507.           LoadFarString(SymLnkWarnNoMem), FnFilter1(linkfname)));
  2508.         return;
  2509.     }
  2510.     linktarget[ucsize] = '\0';
  2511.     G.outfile = zfopen(linkfname, FOPR); /* open link placeholder for reading */
  2512.     /* Check that the following conditions are all fulfilled:
  2513.      * a) the placeholder file exists,
  2514.      * b) the placeholder file contains exactly "ucsize" bytes
  2515.      *    (read the expected placeholder content length + 1 extra byte, this
  2516.      *    should return the expected content length),
  2517.      * c) the placeholder content matches the link target specification as
  2518.      *    stored in the symlink control structure.
  2519.      */
  2520.     if (!G.outfile ||
  2521.         fread(linktarget, 1, ucsize+1, G.outfile) != ucsize ||
  2522.         strcmp(slnk_entry->target, linktarget))
  2523.     {
  2524.         Info(slide, 0x201, ((char *)slide,
  2525.           LoadFarString(SymLnkWarnInvalid), FnFilter1(linkfname)));
  2526.         free(linktarget);
  2527.         if (G.outfile)
  2528.             fclose(G.outfile);
  2529.         return;
  2530.     }
  2531.     fclose(G.outfile);                  /* close "data" file for good... */
  2532.     unlink(linkfname);                  /* ...and delete it */
  2533.     if (QCOND2)
  2534.         Info(slide, 0, ((char *)slide, LoadFarString(SymLnkFinish),
  2535.           FnFilter1(linkfname), FnFilter2(linktarget)));
  2536.     if (symlink(linktarget, linkfname))  /* create the real link */
  2537.         perror("symlink error");
  2538.     free(linktarget);
  2539. #ifdef SET_SYMLINK_ATTRIBS
  2540.     set_symlnk_attribs(__G__ slnk_entry);
  2541. #endif
  2542.     return;                             /* can't set time on symlinks */
  2543.  
  2544. } /* end function set_deferred_symlink() */
  2545. #endif /* SYMLINKS */
  2546.  
  2547.  
  2548.  
  2549.  
  2550. /*************************/
  2551. /*  Function fnfilter()  */        /* here instead of in list.c for SFX */
  2552. /*************************/
  2553.  
  2554. char *fnfilter(raw, space, size)   /* convert name to safely printable form */
  2555.     ZCONST char *raw;
  2556.     uch *space;
  2557.     extent size;
  2558. {
  2559. #ifndef NATIVE   /* ASCII:  filter ANSI escape codes, etc. */
  2560.     ZCONST uch *r=(ZCONST uch *)raw;
  2561.     uch *s=space;
  2562.     uch *slim=NULL;
  2563.     uch *se=NULL;
  2564.     int have_overflow = FALSE;
  2565.  
  2566.     if (size > 0) {
  2567.         slim = space + size
  2568. #ifdef _MBCS
  2569.                      - (MB_CUR_MAX - 1)
  2570. #endif
  2571.                      - 4;
  2572.     }
  2573.     while (*r) {
  2574.         if (size > 0 && s >= slim && se == NULL) {
  2575.             se = s;
  2576.         }
  2577. #ifdef QDOS
  2578.         if (qlflag & 2) {
  2579.             if (*r == '/' || *r == '.') {
  2580.                 if (se != NULL && (s > (space + (size-3)))) {
  2581.                     have_overflow = TRUE;
  2582.                     break;
  2583.                 }
  2584.                 ++r;
  2585.                 *s++ = '_';
  2586.                 continue;
  2587.             }
  2588.         } else
  2589. #endif
  2590. #ifdef HAVE_WORKING_ISPRINT
  2591. # ifndef UZ_FNFILTER_REPLACECHAR
  2592.     /* A convenient choice for the replacement of unprintable char codes is
  2593.      * the "single char wildcard", as this character is quite unlikely to
  2594.      * appear in filenames by itself.  The following default definition
  2595.      * sets the replacement char to a question mark as the most common
  2596.      * "single char wildcard"; this setting should be overridden in the
  2597.      * appropiate system-specific configuration header when needed.
  2598.      */
  2599. #   define UZ_FNFILTER_REPLACECHAR      '?'
  2600. # endif
  2601.         if (!isprint(*r)) {
  2602.             if (*r < 32) {
  2603.                 /* ASCII control codes are escaped as "^{letter}". */
  2604.                 if (se != NULL && (s > (space + (size-4)))) {
  2605.                     have_overflow = TRUE;
  2606.                     break;
  2607.                 }
  2608.                 *s++ = '^', *s++ = (uch)(64 + *r++);
  2609.             } else {
  2610.                 /* Other unprintable codes are replaced by the
  2611.                  * placeholder character. */
  2612.                 if (se != NULL && (s > (space + (size-3)))) {
  2613.                     have_overflow = TRUE;
  2614.                     break;
  2615.                 }
  2616.                 *s++ = UZ_FNFILTER_REPLACECHAR;
  2617.                 INCSTR(r);
  2618.             }
  2619. #else /* !HAVE_WORKING_ISPRINT */
  2620.         if (*r < 32) {
  2621.             /* ASCII control codes are escaped as "^{letter}". */
  2622.             if (se != NULL && (s > (space + (size-4)))) {
  2623.                 have_overflow = TRUE;
  2624.                 break;
  2625.             }
  2626.             *s++ = '^', *s++ = (uch)(64 + *r++);
  2627. #endif /* ?HAVE_WORKING_ISPRINT */
  2628.         } else {
  2629. #ifdef _MBCS
  2630.             unsigned i = CLEN(r);
  2631.             if (se != NULL && (s > (space + (size-i-2)))) {
  2632.                 have_overflow = TRUE;
  2633.                 break;
  2634.             }
  2635.             for (; i > 0; i--)
  2636.                 *s++ = *r++;
  2637. #else
  2638.             if (se != NULL && (s > (space + (size-3)))) {
  2639.                 have_overflow = TRUE;
  2640.                 break;
  2641.             }
  2642.             *s++ = *r++;
  2643. #endif
  2644.          }
  2645.     }
  2646.     if (have_overflow) {
  2647.         strcpy((char *)se, "...");
  2648.     } else {
  2649.         *s = '\0';
  2650.     }
  2651.  
  2652. #ifdef WINDLL
  2653.     INTERN_TO_ISO((char *)space, (char *)space);  /* translate to ANSI */
  2654. #else
  2655. #if (defined(WIN32) && !defined(_WIN32_WCE))
  2656.     /* Win9x console always uses OEM character coding, and
  2657.        WinNT console is set to OEM charset by default, too */
  2658.     INTERN_TO_OEM((char *)space, (char *)space);
  2659. #endif /* (WIN32 && !_WIN32_WCE) */
  2660. #endif /* ?WINDLL */
  2661.  
  2662.     return (char *)space;
  2663.  
  2664. #else /* NATIVE:  EBCDIC or whatever */
  2665.     return (char *)raw;
  2666. #endif
  2667.  
  2668. } /* end function fnfilter() */
  2669.  
  2670.  
  2671.  
  2672.  
  2673. #ifdef SET_DIR_ATTRIB
  2674. /* must sort saved directories so can set perms from bottom up */
  2675.  
  2676. /************************/
  2677. /*  Function dircomp()  */
  2678. /************************/
  2679.  
  2680. static int Cdecl dircomp(a, b)  /* used by qsort(); swiped from Zip */
  2681.     ZCONST zvoid *a, *b;
  2682. {
  2683.     /* order is significant:  this sorts in reverse order (deepest first) */
  2684.     return strcmp((*(direntry **)b)->fn, (*(direntry **)a)->fn);
  2685.  /* return namecmp((*(direntry **)b)->fn, (*(direntry **)a)->fn); */
  2686. }
  2687.  
  2688. #endif /* SET_DIR_ATTRIB */
  2689.  
  2690.  
  2691. #ifdef USE_BZIP2
  2692.  
  2693. /**************************/
  2694. /*  Function UZbunzip2()  */
  2695. /**************************/
  2696.  
  2697. int UZbunzip2(__G)
  2698. __GDEF
  2699. /* decompress a bzipped entry using the libbz2 routines */
  2700. {
  2701.     int retval = 0;     /* return code: 0 = "no error" */
  2702.     int err=BZ_OK;
  2703.     int repeated_buf_err;
  2704.     bz_stream bstrm;
  2705.  
  2706. #if (defined(DLL) && !defined(NO_SLIDE_REDIR))
  2707.     if (G.redirect_slide)
  2708.         wsize = G.redirect_size, redirSlide = G.redirect_buffer;
  2709.     else
  2710.         wsize = WSIZE, redirSlide = slide;
  2711. #endif
  2712.  
  2713.     bstrm.next_out = (char *)redirSlide;
  2714.     bstrm.avail_out = wsize;
  2715.  
  2716.     bstrm.next_in = (char *)G.inptr;
  2717.     bstrm.avail_in = G.incnt;
  2718.  
  2719.     {
  2720.         /* local buffer for efficiency */
  2721.         /* $TODO Check for BZIP LIB version? */
  2722.  
  2723.         bstrm.bzalloc = NULL;
  2724.         bstrm.bzfree = NULL;
  2725.         bstrm.opaque = NULL;
  2726.  
  2727.         Trace((stderr, "initializing bzlib()\n"));
  2728.         err = BZ2_bzDecompressInit(&bstrm, 0, 0);
  2729.  
  2730.         if (err == BZ_MEM_ERROR)
  2731.             return 3;
  2732.         else if (err != BZ_OK)
  2733.             Trace((stderr, "oops!  (BZ2_bzDecompressInit() err = %d)\n", err));
  2734.     }
  2735.  
  2736. #ifdef FUNZIP
  2737.     while (err != BZ_STREAM_END) {
  2738. #else /* !FUNZIP */
  2739.     while (G.csize > 0) {
  2740.         Trace((stderr, "first loop:  G.csize = %ld\n", G.csize));
  2741. #endif /* ?FUNZIP */
  2742.         while (bstrm.avail_out > 0) {
  2743.             err = BZ2_bzDecompress(&bstrm);
  2744.  
  2745.             if (err == BZ_DATA_ERROR) {
  2746.                 retval = 2; goto uzbunzip_cleanup_exit;
  2747.             } else if (err == BZ_MEM_ERROR) {
  2748.                 retval = 3; goto uzbunzip_cleanup_exit;
  2749.             } else if (err != BZ_OK && err != BZ_STREAM_END)
  2750.                 Trace((stderr, "oops!  (bzip(first loop) err = %d)\n", err));
  2751.  
  2752. #ifdef FUNZIP
  2753.             if (err == BZ_STREAM_END)    /* "END-of-entry-condition" ? */
  2754. #else /* !FUNZIP */
  2755.             if (G.csize <= 0L)          /* "END-of-entry-condition" ? */
  2756. #endif /* ?FUNZIP */
  2757.                 break;
  2758.  
  2759.             if (bstrm.avail_in == 0) {
  2760.                 if (fillinbuf(__G) == 0) {
  2761.                     /* no "END-condition" yet, but no more data */
  2762.                     retval = 2; goto uzbunzip_cleanup_exit;
  2763.                 }
  2764.  
  2765.                 bstrm.next_in = (char *)G.inptr;
  2766.                 bstrm.avail_in = G.incnt;
  2767.             }
  2768.             Trace((stderr, "     avail_in = %u\n", bstrm.avail_in));
  2769.         }
  2770.         /* flush slide[] */
  2771.         if ((retval = FLUSH(wsize - bstrm.avail_out)) != 0)
  2772.             goto uzbunzip_cleanup_exit;
  2773.         Trace((stderr, "inside loop:  flushing %ld bytes (ptr diff = %ld)\n",
  2774.           (long)(wsize - bstrm.avail_out),
  2775.           (long)(bstrm.next_out-(char *)redirSlide)));
  2776.         bstrm.next_out = (char *)redirSlide;
  2777.         bstrm.avail_out = wsize;
  2778.     }
  2779.  
  2780.     /* no more input, so loop until we have all output */
  2781.     Trace((stderr, "beginning final loop:  err = %d\n", err));
  2782.     repeated_buf_err = FALSE;
  2783.     while (err != BZ_STREAM_END) {
  2784.         err = BZ2_bzDecompress(&bstrm);
  2785.         if (err == BZ_DATA_ERROR) {
  2786.             retval = 2; goto uzbunzip_cleanup_exit;
  2787.         } else if (err == BZ_MEM_ERROR) {
  2788.             retval = 3; goto uzbunzip_cleanup_exit;
  2789.         } else if (err != BZ_OK && err != BZ_STREAM_END) {
  2790.             Trace((stderr, "oops!  (bzip(final loop) err = %d)\n", err));
  2791.             DESTROYGLOBALS();
  2792.             EXIT(PK_MEM3);
  2793.         }
  2794.         /* final flush of slide[] */
  2795.         if ((retval = FLUSH(wsize - bstrm.avail_out)) != 0)
  2796.             goto uzbunzip_cleanup_exit;
  2797.         Trace((stderr, "final loop:  flushing %ld bytes (ptr diff = %ld)\n",
  2798.           (long)(wsize - bstrm.avail_out),
  2799.           (long)(bstrm.next_out-(char *)redirSlide)));
  2800.         bstrm.next_out = (char *)redirSlide;
  2801.         bstrm.avail_out = wsize;
  2802.     }
  2803. #ifdef LARGE_FILE_SUPPORT
  2804.     Trace((stderr, "total in = %llu, total out = %llu\n",
  2805.       (zusz_t)(bstrm.total_in_lo32) + ((zusz_t)(bstrm.total_in_hi32))<<32,
  2806.       (zusz_t)(bstrm.total_out_lo32) + ((zusz_t)(bstrm.total_out_hi32))<<32));
  2807. #else
  2808.     Trace((stderr, "total in = %lu, total out = %lu\n", bstrm.total_in_lo32,
  2809.       bstrm.total_out_lo32));
  2810. #endif
  2811.  
  2812.     G.inptr = (uch *)bstrm.next_in;
  2813.     G.incnt = (G.inbuf + INBUFSIZ) - G.inptr;  /* reset for other routines */
  2814.  
  2815. uzbunzip_cleanup_exit:
  2816.     err = BZ2_bzDecompressEnd(&bstrm);
  2817.     if (err != BZ_OK)
  2818.         Trace((stderr, "oops!  (BZ2_bzDecompressEnd() err = %d)\n", err));
  2819.  
  2820.     return retval;
  2821. } /* end function UZbunzip2() */
  2822. #endif /* USE_BZIP2 */
  2823.