home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / unzip532.zip / extract.c < prev    next >
C/C++ Source or Header  |  1997-10-21  |  74KB  |  1,905 lines

  1. /*---------------------------------------------------------------------------
  2.  
  3.   extract.c
  4.  
  5.   This file contains the high-level routines ("driver routines") for extrac-
  6.   ting and testing zipfile members.  It calls the low-level routines in files
  7.   explode.c, inflate.c, unreduce.c and unshrink.c.
  8.  
  9.   Contains:  extract_or_test_files()
  10.              store_info()
  11.              extract_or_test_member()
  12.              TestExtraField()
  13.              test_compr_eb()
  14.              memextract()
  15.              memflush()
  16.              fnfilter()
  17.  
  18.   ---------------------------------------------------------------------------*/
  19.  
  20.  
  21. #define EXTRACT_C
  22. #define UNZIP_INTERNAL
  23. #include "unzip.h"
  24. #include "crypt.h"
  25. #ifdef WINDLL
  26. #  ifdef POCKET_UNZIP
  27. #    include "wince/intrface.h"
  28. #  else
  29. #    include "windll/windll.h"
  30. #  endif
  31. #endif
  32.  
  33. #define GRRDUMP(buf,len) { \
  34.     int i, j; \
  35.  \
  36.     for (j = 0;  j < (len)/16;  ++j) { \
  37.         printf("        "); \
  38.         for (i = 0;  i < 16;  ++i) \
  39.             printf("%02x ", (uch)(buf)[i+(j<<4)]); \
  40.         printf("\n        "); \
  41.         for (i = 0;  i < 16;  ++i) { \
  42.             char c = (char)(buf)[i+(j<<4)]; \
  43.  \
  44.             if (c == '\n') \
  45.                 printf("\\n "); \
  46.             else if (c == '\r') \
  47.                 printf("\\r "); \
  48.             else \
  49.                 printf(" %c ", c); \
  50.         } \
  51.         printf("\n"); \
  52.     } \
  53.     if ((len) % 16) { \
  54.         printf("        "); \
  55.         for (i = j<<4;  i < (len);  ++i) \
  56.             printf("%02x ", (uch)(buf)[i]); \
  57.         printf("\n        "); \
  58.         for (i = j<<4;  i < (len);  ++i) { \
  59.             char c = (char)(buf)[i]; \
  60.  \
  61.             if (c == '\n') \
  62.                 printf("\\n "); \
  63.             else if (c == '\r') \
  64.                 printf("\\r "); \
  65.             else \
  66.                 printf(" %c ", c); \
  67.         } \
  68.         printf("\n"); \
  69.     } \
  70. }
  71.  
  72. static int store_info OF((__GPRO));
  73. static int extract_or_test_member OF((__GPRO));
  74. #ifndef SFX
  75.    static int TestExtraField OF((__GPRO__ uch *ef, unsigned ef_len));
  76.    static int test_compr_eb OF((__GPRO__ uch *eb, unsigned eb_size,
  77.         unsigned compr_offset,
  78.         int (*test_uc_ebdata)(__GPRO__ uch *eb, unsigned eb_size,
  79.                               uch *eb_ucptr, ulg eb_ucsize)));
  80. #endif
  81. #ifdef UNIX
  82.    static int dircomp OF((ZCONST zvoid *a, ZCONST zvoid *b));
  83. #endif
  84.  
  85.  
  86.  
  87. /*******************************/
  88. /*  Strings used in extract.c  */
  89. /*******************************/
  90.  
  91. static char Far VersionMsg[] =
  92.   "   skipping: %-22s  need %s compat. v%u.%u (can do v%u.%u)\n";
  93. static char Far ComprMsgNum[] =
  94.   "   skipping: %-22s  unsupported compression method %d\n";
  95. #ifndef SFX
  96.    static char Far ComprMsgName[] =
  97.      "   skipping: %-22s  `%s' method not supported\n";
  98.    static char Far CmprNone[]       = "store";
  99.    static char Far CmprShrink[]     = "shrink";
  100.    static char Far CmprReduce[]     = "reduce";
  101.    static char Far CmprImplode[]    = "implode";
  102.    static char Far CmprTokenize[]   = "tokenize";
  103.    static char Far CmprDeflate[]    = "deflate";
  104.    static char Far CmprEnDeflate[]  = "enhanced deflate";
  105.    static char Far CmprDCLImplode[] = "DCL implode";
  106.    static char Far *ComprNames[NUM_METHODS] = {
  107.      CmprNone, CmprShrink, CmprReduce, CmprReduce, CmprReduce, CmprReduce,
  108.      CmprImplode, CmprTokenize, CmprDeflate, CmprEnDeflate, CmprDCLImplode
  109.    };
  110. #endif /* !SFX */
  111. static char Far FilNamMsg[] =
  112.   "%s:  bad filename length (%s)\n";
  113. static char Far ExtFieldMsg[] =
  114.   "%s:  bad extra field length (%s)\n";
  115. static char Far OffsetMsg[] =
  116.   "file #%d:  bad zipfile offset (%s):  %ld\n";
  117. static char Far ExtractMsg[] =
  118.   "%8sing: %-22s  %s%s";
  119. #ifndef SFX
  120.    static char Far LengthMsg[] =
  121.      "%s  %s:  %ld bytes required to uncompress to %lu bytes;\n    %s\
  122.       supposed to require %lu bytes%s%s%s\n";
  123. #endif
  124.  
  125. static char Far BadFileCommLength[] = "%s:  bad file comment length\n";
  126. static char Far LocalHdrSig[] = "local header sig";
  127. static char Far BadLocalHdr[] = "file #%d:  bad local header\n";
  128. static char Far AttemptRecompensate[] = "  (attempting to re-compensate)\n";
  129. #ifndef SFX
  130.    static char Far BackslashPathSep[] =
  131.      "warning:  %s appears to use backslashes as path separators\n";
  132. #endif
  133. static char Far SkipVolumeLabel[] = "   skipping: %-22s  %svolume label\n";
  134.  
  135. #ifdef UNIX  /* messages of code for setting directory attributes */
  136.    static char Far DirlistNoMem[] =
  137.      "warning:  cannot alloc memory for dir times/permissions/UIDs/GIDs\n";
  138.    static char Far DirlistEntryNoMem[] =
  139.      "cannot alloc memory for dir times/permissions/UID/GID\n";
  140.    static char Far DirlistSortNoMem[] =
  141.      "warning:  cannot alloc memory to sort dir times/perms/etc.\n";
  142.    static char Far DirlistUidGidFailed[] =
  143.      "warning:  cannot set UID %d and/or GID %d for %s\n";
  144.    static char Far DirlistUtimeFailed[] =
  145.      "warning:  cannot set modification, access times for %s\n";
  146. #  ifndef NO_CHMOD
  147.      static char Far DirlistChmodFailed[] =
  148.        "warning:  cannot set permissions for %s\n";
  149. #  endif
  150. #endif
  151.  
  152. #ifndef WINDLL
  153.    static char Far ReplaceQuery[] =
  154.      "replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: ";
  155.    static char Far AssumeNone[] = " NULL\n(assuming [N]one)\n";
  156.    static char Far NewNameQuery[] = "new name: ";
  157.    static char Far InvalidResponse[] = "error:  invalid response [%c]\n";
  158. #endif /* !WINDLL */
  159.  
  160. static char Far ErrorInArchive[] = "At least one %serror was detected in %s.\n";
  161. static char Far ZeroFilesTested[] = "Caution:  zero files tested in %s.\n";
  162.  
  163. #ifndef VMS
  164.    static char Far VMSFormatQuery[] =
  165.      "\n%s:  stored in VMS format.  Extract anyway? (y/n) ";
  166. #endif
  167.  
  168. #if CRYPT
  169.    static char Far SkipCannotGetPasswd[] =
  170.      "   skipping: %-22s  unable to get password\n";
  171.    static char Far SkipIncorrectPasswd[] =
  172.      "   skipping: %-22s  incorrect password\n";
  173.    static char Far FilesSkipBadPasswd[] =
  174.      "%d file%s skipped because of incorrect password.\n";
  175.    static char Far MaybeBadPasswd[] =
  176.      "    (may instead be incorrect password)\n";
  177. #else
  178.    static char Far SkipEncrypted[] =
  179.      "   skipping: %-22s  encrypted (not supported)\n";
  180. #endif
  181.  
  182. static char Far NoErrInCompData[] =
  183.   "No errors detected in compressed data of %s.\n";
  184. static char Far NoErrInTestedFiles[] =
  185.   "No errors detected in %s for the %d file%s tested.\n";
  186. static char Far FilesSkipped[] =
  187.   "%d file%s skipped because of unsupported compression or encoding.\n";
  188.  
  189. static char Far ErrUnzipFile[] = "  error:  %s%s %s\n";
  190. static char Far ErrUnzipNoFile[] = "\n  error:  %s%s\n";
  191. static char Far NotEnoughMem[] = "not enough memory to ";
  192. static char Far InvalidComprData[] = "invalid compressed data to ";
  193. static char Far Inflate[] = "inflate";
  194.  
  195. #ifndef SFX
  196.    static char Far Explode[] = "explode";
  197. #ifndef LZW_CLEAN
  198.    static char Far Unshrink[] = "unshrink";
  199. #endif
  200. #endif
  201.  
  202. #if (!defined(DELETE_IF_FULL) || !defined(HAVE_UNLINK))
  203.    static char Far FileTruncated[] = "warning:  %s is probably truncated\n";
  204. #endif
  205.  
  206. static char Far FileUnknownCompMethod[] = "%s:  unknown compression method\n";
  207. static char Far BadCRC[] = " bad CRC %08lx  (should be %08lx)\n";
  208.  
  209.       /* TruncEAs[] also used in OS/2 mapname(), close_outfile() */
  210. char Far TruncEAs[] = " compressed EA data missing (%d bytes)%s";
  211. char Far TruncNTSD[] = " compressed WinNT security data missing (%d bytes)%s";
  212.  
  213. #ifndef SFX
  214.    static char Far InconsistEFlength[] = "bad extra-field entry:\n \
  215.      EF block length (%u bytes) exceeds remaining EF data (%u bytes)\n";
  216.    static char Far InvalidComprDataEAs[] = " invalid compressed data for EAs\n";
  217. #  if (defined(WIN32) && defined(NTSD_EAS))
  218.      static char Far InvalidSecurityEAs[] = " EAs fail security check\n";
  219. #  endif
  220.    static char Far UnsuppNTSDVersEAs[] = " unsupported NTSD EAs version %d\n";
  221.    static char Far BadCRC_EAs[] = " bad CRC for extended attributes\n";
  222.    static char Far UnknComprMethodEAs[] =
  223.      " unknown compression method for EAs (%u)\n";
  224.    static char Far NotEnoughMemEAs[] = " out of memory while inflating EAs\n";
  225.    static char Far UnknErrorEAs[] = " unknown error on extended attributes\n";
  226. #endif /* !SFX */
  227.  
  228. static char Far UnsupportedExtraField[] =
  229.   "\nerror:  unsupported extra-field compression type (%u)--skipping\n";
  230. static char Far BadExtraFieldCRC[] =
  231.   "error [%s]:  bad extra-field CRC %08lx (should be %08lx)\n";
  232.  
  233.  
  234.  
  235.  
  236.  
  237. /**************************************/
  238. /*  Function extract_or_test_files()  */
  239. /**************************************/
  240.  
  241. int extract_or_test_files(__G)    /* return PK-type error code */
  242.      __GDEF
  243. {
  244.     uch *cd_inptr;
  245.     int i, j, cd_incnt, renamed, query, filnum=(-1), blknum=0;
  246.     int error, error_in_archive=PK_COOL, *fn_matched=NULL, *xn_matched=NULL;
  247. #ifdef WINDLL
  248.     int done_once = 0;
  249. #else
  250.     int len;
  251. #endif
  252.     ush members_remaining, num_skipped=0, num_bad_pwd=0;
  253.     long cd_bufstart, bufstart, inbuf_offset, request;
  254.     LONGINT old_extra_bytes = 0L;
  255. #ifdef UNIX
  256.     int do_dirtimes=TRUE, num_dirs=0;
  257.     dirtime *dirlist=(dirtime *)NULL, **sorted_dirlist=(dirtime **)NULL;
  258. #endif
  259.  
  260.  
  261. /*---------------------------------------------------------------------------
  262.     The basic idea of this function is as follows.  Since the central di-
  263.     rectory lies at the end of the zipfile and the member files lie at the
  264.     beginning or middle or wherever, it is not very desirable to simply
  265.     read a central directory entry, jump to the member and extract it, and
  266.     then jump back to the central directory.  In the case of a large zipfile
  267.     this would lead to a whole lot of disk-grinding, especially if each mem-
  268.     ber file is small.  Instead, we read from the central directory the per-
  269.     tinent information for a block of files, then go extract/test the whole
  270.     block.  Thus this routine contains two small(er) loops within a very
  271.     large outer loop:  the first of the small ones reads a block of files
  272.     from the central directory; the second extracts or tests each file; and
  273.     the outer one loops over blocks.  There's some file-pointer positioning
  274.     stuff in between, but that's about it.  Btw, it's because of this jump-
  275.     ing around that we can afford to be lenient if an error occurs in one of
  276.     the member files:  we should still be able to go find the other members,
  277.     since we know the offset of each from the beginning of the zipfile.
  278.   ---------------------------------------------------------------------------*/
  279.  
  280.     G.pInfo = G.info;
  281.     members_remaining = G.ecrec.total_entries_central_dir;
  282.  
  283. #ifdef UNIX
  284.     dirlist = (dirtime *)malloc(members_remaining*sizeof(dirtime));
  285.     if (dirlist == (dirtime *)NULL) {
  286.         Info(slide, 0x401, ((char *)slide, LoadFarString(DirlistNoMem)));
  287.         do_dirtimes = FALSE;
  288.     }
  289. #endif /* UNIX */
  290.  
  291. #if CRYPT
  292.     G.newzip = TRUE;
  293. #endif
  294. #ifndef SFX
  295.     G.reported_backslash = FALSE;
  296. #endif
  297.  
  298.     /* malloc space for check on unmatched filespecs (OK if one or both NULL) */
  299.     if (G.filespecs > 0  &&
  300.         (fn_matched=(int *)malloc(G.filespecs*sizeof(int))) != (int *)NULL)
  301.         for (i = 0;  i < G.filespecs;  ++i)
  302.             fn_matched[i] = FALSE;
  303.     if (G.xfilespecs > 0  &&
  304.         (xn_matched=(int *)malloc(G.xfilespecs*sizeof(int))) != (int *)NULL)
  305.         for (i = 0;  i < G.xfilespecs;  ++i)
  306.             xn_matched[i] = FALSE;
  307.  
  308. /*---------------------------------------------------------------------------
  309.     Begin main loop over blocks of member files.  We know the entire central
  310.     directory is on this disk:  we would not have any of this information un-
  311.     less the end-of-central-directory record was on this disk, and we would
  312.     not have gotten to this routine unless this is also the disk on which
  313.     the central directory starts.  In practice, this had better be the ONLY
  314.     disk in the archive, but we'll add multi-disk support soon.
  315.   ---------------------------------------------------------------------------*/
  316.  
  317.     while (members_remaining) {
  318.         j = 0;
  319. #ifdef AMIGA
  320.         memzero(G.filenotes, DIR_BLKSIZ * sizeof(char *));
  321. #endif
  322.  
  323.         /*
  324.          * Loop through files in central directory, storing offsets, file
  325.          * attributes, case-conversion and text-conversion flags until block
  326.          * size is reached.
  327.          */
  328.  
  329.         while (members_remaining && (j < DIR_BLKSIZ)) {
  330.             --members_remaining;
  331.             G.pInfo = &G.info[j];
  332.  
  333.             if (readbuf(__G__ G.sig, 4) == 0) {
  334.                 error_in_archive = PK_EOF;
  335.                 members_remaining = 0;  /* ...so no more left to do */
  336.                 break;
  337.             }
  338.             if (strncmp(G.sig, G.central_hdr_sig, 4)) {  /* just to make sure */
  339.                 Info(slide, 0x401, ((char *)slide, LoadFarString(CentSigMsg),
  340.                   j));
  341.                 Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg)));
  342.                 error_in_archive = PK_BADERR;
  343.                 members_remaining = 0;  /* ...so no more left to do */
  344.                 break;
  345.             }
  346.             /* process_cdir_file_hdr() sets pInfo->hostnum, pInfo->lcflag */
  347.             if ((error = process_cdir_file_hdr(__G)) != PK_COOL) {
  348.                 error_in_archive = error;   /* only PK_EOF defined */
  349.                 members_remaining = 0;  /* ...so no more left to do */
  350.                 break;
  351.             }
  352.             if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) !=
  353.                  PK_COOL)
  354.             {
  355.                 if (error > error_in_archive)
  356.                     error_in_archive = error;
  357.                 if (error > PK_WARN) {  /* fatal:  no more left to do */
  358.                     Info(slide, 0x401, ((char *)slide, LoadFarString(FilNamMsg),
  359.                       FnFilter1(G.filename), "central"));
  360.                     members_remaining = 0;
  361.                     break;
  362.                 }
  363.             }
  364.             if ((error = do_string(__G__ G.crec.extra_field_length,
  365.                 EXTRA_FIELD)) != 0)
  366.             {
  367.                 if (error > error_in_archive)
  368.                     error_in_archive = error;
  369.                 if (error > PK_WARN) {  /* fatal */
  370.                     Info(slide, 0x401, ((char *)slide,
  371.                       LoadFarString(ExtFieldMsg),
  372.                       FnFilter1(G.filename), "central"));
  373.                     members_remaining = 0;
  374.                     break;
  375.                 }
  376.             }
  377. #ifdef AMIGA
  378.             G.filenote_slot = j;
  379.             if ((error = do_string(__G__ G.crec.file_comment_length,
  380.                                    G.N_flag ? FILENOTE : SKIP)) != PK_COOL)
  381. #else
  382.             if ((error = do_string(__G__ G.crec.file_comment_length, SKIP))
  383.                 != PK_COOL)
  384. #endif
  385.             {
  386.                 if (error > error_in_archive)
  387.                     error_in_archive = error;
  388.                 if (error > PK_WARN) {  /* fatal */
  389.                     Info(slide, 0x421, ((char *)slide,
  390.                       LoadFarString(BadFileCommLength),
  391.                       FnFilter1(G.filename)));
  392.                     members_remaining = 0;
  393.                     break;
  394.                 }
  395.             }
  396.             if (G.process_all_files) {
  397.                 if (store_info(__G))
  398.                     ++j;  /* file is OK; info[] stored; continue with next */
  399.                 else
  400.                     ++num_skipped;
  401.             } else {
  402.                 int   do_this_file = FALSE;
  403.                 char  **pfn = G.pfnames-1;
  404.  
  405.                 while (*++pfn)
  406.                     if (match(G.filename, *pfn, G.C_flag)) {
  407.                         do_this_file = TRUE;   /* ^-- ignore case or not? */
  408.                         if (fn_matched)
  409.                             fn_matched[(int)(pfn-G.pfnames)] = TRUE;
  410.                         break;       /* found match, so stop looping */
  411.                     }
  412.                 if (do_this_file) {  /* check if this is an excluded file */
  413.                     char  **pxn = G.pxnames-1;
  414.  
  415.                     while (*++pxn)
  416.                         if (match(G.filename, *pxn, G.C_flag)) {
  417.                             do_this_file = FALSE;  /* ^-- ignore case or not? */
  418.                             if (xn_matched)
  419.                                 xn_matched[(int)(pxn-G.pxnames)] = TRUE;
  420.                             break;
  421.                         }
  422.                 }
  423.                 if (do_this_file)
  424.                     if (store_info(__G))
  425.                         ++j;            /* file is OK */
  426.                     else
  427.                         ++num_skipped;  /* unsupp. compression or encryption */
  428.             } /* end if (process_all_files) */
  429.  
  430.  
  431.         } /* end while-loop (adding files to current block) */
  432.  
  433.         /* save position in central directory so can come back later */
  434.         cd_bufstart = G.cur_zipfile_bufstart;
  435.         cd_inptr = G.inptr;
  436.         cd_incnt = G.incnt;
  437.  
  438.     /*-----------------------------------------------------------------------
  439.         Second loop:  process files in current block, extracting or testing
  440.         each one.
  441.       -----------------------------------------------------------------------*/
  442.  
  443.         for (i = 0; i < j; ++i) {
  444.             filnum = i + blknum*DIR_BLKSIZ;
  445.             G.pInfo = &G.info[i];
  446. #ifdef NOVELL_BUG_FAILSAFE
  447.             G.dne = FALSE;  /* assume file exists until stat() says otherwise */
  448. #endif
  449.  
  450.             /* if the target position is not within the current input buffer
  451.              * (either haven't yet read far enough, or (maybe) skipping back-
  452.              * ward), skip to the target position and reset readbuf(). */
  453.  
  454.             /* ZLSEEK(pInfo->offset):  */
  455.             request = G.pInfo->offset + G.extra_bytes;
  456.             inbuf_offset = request % INBUFSIZ;
  457.             bufstart = request - inbuf_offset;
  458.  
  459.             Trace((stderr, "\ndebug: request = %ld, inbuf_offset = %ld\n",
  460.               request, inbuf_offset));
  461.             Trace((stderr,
  462.               "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n",
  463.               bufstart, G.cur_zipfile_bufstart));
  464.             if (request < 0) {
  465.                 Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(SeekMsg),
  466.                   G.zipfn, LoadFarString(ReportMsg)));
  467.                 error_in_archive = PK_ERR;
  468.                 if (filnum == 0 && G.extra_bytes != 0L) {
  469.                     Info(slide, 0x401, ((char *)slide,
  470.                       LoadFarString(AttemptRecompensate)));
  471.                     old_extra_bytes = G.extra_bytes;
  472.                     G.extra_bytes = 0L;
  473.                     request = G.pInfo->offset;  /* could also check if != 0 */
  474.                     inbuf_offset = request % INBUFSIZ;
  475.                     bufstart = request - inbuf_offset;
  476.                     Trace((stderr, "debug: request = %ld, inbuf_offset = %ld\n",
  477.                       request, inbuf_offset));
  478.                     Trace((stderr,
  479.                       "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n",
  480.                       bufstart, G.cur_zipfile_bufstart));
  481.                 } else {
  482.                     error_in_archive = PK_BADERR;
  483.                     continue;  /* this one hosed; try next */
  484.                 }
  485.             }
  486.             /* try again */
  487.             if (request < 0) {
  488.                 Trace((stderr, "debug: recompensated request still < 0\n"));
  489.                 Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(SeekMsg),
  490.                   G.zipfn, LoadFarString(ReportMsg)));
  491.                 error_in_archive = PK_BADERR;
  492.                 continue;
  493.             } else if (bufstart != G.cur_zipfile_bufstart) {
  494.                 Trace((stderr, "debug: bufstart != cur_zipfile_bufstart\n"));
  495. #ifdef USE_STRM_INPUT
  496.                 fseek((FILE *)G.zipfd,(LONGINT)bufstart,SEEK_SET);
  497.                 G.cur_zipfile_bufstart = ftell((FILE *)G.zipfd);
  498. #else /* !USE_STRM_INPUT */
  499.                 G.cur_zipfile_bufstart =
  500.                   lseek(G.zipfd,(LONGINT)bufstart,SEEK_SET);
  501. #endif /* ?USE_STRM_INPUT */
  502.                 if ((G.incnt = read(G.zipfd,(char *)G.inbuf,INBUFSIZ)) <= 0)
  503.                 {
  504.                     Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg),
  505.                       filnum, "lseek", bufstart));
  506.                     error_in_archive = PK_BADERR;
  507.                     continue;   /* can still do next file */
  508.                 }
  509.                 G.inptr = G.inbuf + (int)inbuf_offset;
  510.                 G.incnt -= (int)inbuf_offset;
  511.             } else {
  512.                 G.incnt += (int)(G.inptr-G.inbuf) - (int)inbuf_offset;
  513.                 G.inptr = G.inbuf + (int)inbuf_offset;
  514.             }
  515.  
  516.             /* should be in proper position now, so check for sig */
  517.             if (readbuf(__G__ G.sig, 4) == 0) {  /* bad offset */
  518.                 Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg),
  519.                   filnum, "EOF", request));
  520.                 error_in_archive = PK_BADERR;
  521.                 continue;   /* but can still try next one */
  522.             }
  523.             if (strncmp(G.sig, G.local_hdr_sig, 4)) {
  524.                 Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg),
  525.                   filnum, LoadFarStringSmall(LocalHdrSig), request));
  526.                 /*
  527.                     GRRDUMP(G.sig, 4)
  528.                     GRRDUMP(G.local_hdr_sig, 4)
  529.                  */
  530.                 error_in_archive = PK_ERR;
  531.                 if ((filnum == 0 && G.extra_bytes != 0L) ||
  532.                     (G.extra_bytes == 0L && old_extra_bytes != 0L)) {
  533.                     Info(slide, 0x401, ((char *)slide,
  534.                       LoadFarString(AttemptRecompensate)));
  535.                     if (G.extra_bytes) {
  536.                         old_extra_bytes = G.extra_bytes;
  537.                         G.extra_bytes = 0L;
  538.                     } else
  539.                         G.extra_bytes = old_extra_bytes;  /* third attempt */
  540.                     ZLSEEK(G.pInfo->offset)
  541.                     if (readbuf(__G__ G.sig, 4) == 0) {  /* bad offset */
  542.                         Info(slide, 0x401, ((char *)slide,
  543.                           LoadFarString(OffsetMsg), filnum, "EOF", request));
  544.                         error_in_archive = PK_BADERR;
  545.                         continue;   /* but can still try next one */
  546.                     }
  547.                     if (strncmp(G.sig, G.local_hdr_sig, 4)) {
  548.                         Info(slide, 0x401, ((char *)slide,
  549.                           LoadFarString(OffsetMsg), filnum,
  550.                           LoadFarStringSmall(LocalHdrSig), request));
  551.                         error_in_archive = PK_BADERR;
  552.                         continue;
  553.                     }
  554.                 } else
  555.                     continue;  /* this one hosed; try next */
  556.             }
  557.             if ((error = process_local_file_hdr(__G)) != PK_COOL) {
  558.                 Info(slide, 0x421, ((char *)slide, LoadFarString(BadLocalHdr),
  559.                   filnum));
  560.                 error_in_archive = error;   /* only PK_EOF defined */
  561.                 continue;   /* can still try next one */
  562.             }
  563.             if ((error = do_string(__G__ G.lrec.filename_length, DS_FN)) !=
  564.                  PK_COOL)
  565.             {
  566.                 if (error > error_in_archive)
  567.                     error_in_archive = error;
  568.                 if (error > PK_WARN) {
  569.                     Info(slide, 0x401, ((char *)slide, LoadFarString(FilNamMsg),
  570.                       FnFilter1(G.filename), "local"));
  571.                     continue;   /* go on to next one */
  572.                 }
  573.             }
  574.             if (G.extra_field != (uch *)NULL) {
  575.                 free(G.extra_field);
  576.                 G.extra_field = (uch *)NULL;
  577.             }
  578.             if ((error =
  579.                  do_string(__G__ G.lrec.extra_field_length, EXTRA_FIELD)) != 0)
  580.             {
  581.                 if (error > error_in_archive)
  582.                     error_in_archive = error;
  583.                 if (error > PK_WARN) {
  584.                     Info(slide, 0x401, ((char *)slide,
  585.                       LoadFarString(ExtFieldMsg),
  586.                       FnFilter1(G.filename), "local"));
  587.                     continue;   /* go on */
  588.                 }
  589.             }
  590.  
  591.             /*
  592.              * just about to extract file:  if extracting to disk, check if
  593.              * already exists, and if so, take appropriate action according to
  594.              * fflag/uflag/overwrite_all/etc. (we couldn't do this in upper
  595.              * loop because we don't store the possibly renamed filename[] in
  596.              * info[])
  597.              */
  598. #ifdef DLL
  599.             if (!G.tflag && !G.cflag && !G.redirect_data)
  600. #else
  601.             if (!G.tflag && !G.cflag)
  602. #endif
  603.             {
  604.                 renamed = FALSE;   /* user hasn't renamed output file yet */
  605.  
  606. startover:
  607.                 query = FALSE;
  608. #ifdef MACOS
  609.                 G.macflag = (G.pInfo->hostnum == MAC_);
  610. #endif
  611.                 /* for files from DOS FAT, check for use of backslash instead
  612.                  *  of slash as directory separator (bug in some zipper(s); so
  613.                  *  far, not a problem in HPFS, NTFS or VFAT systems)
  614.                  */
  615. #ifndef SFX
  616.                 if (G.pInfo->hostnum == FS_FAT_ && !strchr(G.filename, '/')) {
  617.                     char *p=G.filename-1;
  618.  
  619.                     while (*++p) {
  620.                         if (*p == '\\') {
  621.                             if (!G.reported_backslash) {
  622.                                 Info(slide, 0x21, ((char *)slide,
  623.                                   LoadFarString(BackslashPathSep), G.zipfn));
  624.                                 G.reported_backslash = TRUE;
  625.                                 if (!error_in_archive)
  626.                                     error_in_archive = PK_WARN;
  627.                             }
  628.                             *p = '/';
  629.                         }
  630.                     }
  631.                 }
  632. #endif /* !SFX */
  633.  
  634.                 /* mapname can create dirs if not freshening or if renamed */
  635.                 if ((error = mapname(__G__ renamed)) > PK_WARN) {
  636.                     if (error == IZ_CREATED_DIR) {
  637. #ifdef UNIX
  638.                         if (do_dirtimes) {
  639.                             unsigned eb_izux_flg;
  640.  
  641.                             dirlist[num_dirs].fn =
  642.                               (char *)malloc(strlen(G.filename) + 1);
  643.                             if (dirlist[num_dirs].fn == (char *)NULL) {
  644.                                 Info(slide, 0x401, ((char *)slide,
  645.                                   LoadFarString(DirlistEntryNoMem)));
  646.                                 if (!error_in_archive)
  647.                                     error_in_archive = PK_WARN;
  648.                                 continue;
  649.                             }
  650.                             strcpy(dirlist[num_dirs].fn, G.filename);
  651.                             dirlist[num_dirs].perms = G.pInfo->file_attr;
  652.                             eb_izux_flg = G.extra_field? ef_scan_for_izux(
  653.                               G.extra_field, G.lrec.extra_field_length, 0,
  654.                               G.lrec.last_mod_file_date,
  655.                               &dirlist[num_dirs].u.t3, dirlist[num_dirs].uidgid)
  656.                               : 0;
  657.                             if (eb_izux_flg & EB_UT_FL_MTIME) {
  658.                                 TTrace((stderr,
  659.                                   "\nextract:  Unix dir e.f. modtime = %ld\n",
  660.                                   dirlist[num_dirs].u.t3.mtime));
  661.                             } else {
  662.                                 dirlist[num_dirs].u.t3.mtime =
  663.                                   dos_to_unix_time(G.lrec.last_mod_file_date,
  664.                                                    G.lrec.last_mod_file_time);
  665.                             }
  666.                             if (eb_izux_flg & EB_UT_FL_ATIME) {
  667.                                 TTrace((stderr,
  668.                                   "\nextract:  Unix dir e.f. actime = %ld\n",
  669.                                   dirlist[num_dirs].u.t3.atime));
  670.                             } else {
  671.                                 dirlist[num_dirs].u.t3.atime =
  672.                                   dirlist[num_dirs].u.t3.mtime;
  673.                             }
  674.                             dirlist[num_dirs].have_uidgid =
  675.                                 (G.X_flag && (eb_izux_flg & EB_UX2_VALID));
  676.                             ++num_dirs;
  677.                         }
  678. #endif /* UNIX */
  679.                     } else if (error == IZ_VOL_LABEL) {
  680. #ifdef DOS_OS2_W32
  681.                         Info(slide, 0x401, ((char *)slide,
  682.                           LoadFarString(SkipVolumeLabel),
  683.                           FnFilter1(G.filename),
  684.                           G.volflag? "hard disk " : ""));
  685. #else
  686.                         Info(slide, 1, ((char *)slide,
  687.                           LoadFarString(SkipVolumeLabel),
  688.                           FnFilter1(G.filename), ""));
  689. #endif
  690.                     /*  if (!error_in_archive)
  691.                             error_in_archive = PK_WARN;  */
  692.                     } else if (error > PK_ERR  &&  error_in_archive < PK_ERR)
  693.                         error_in_archive = PK_ERR;
  694.                     Trace((stderr, "mapname(%s) returns error = %d\n",
  695.                       FnFilter1(G.filename), error));
  696.                     continue;   /* go on to next file */
  697.                 }
  698.  
  699. #ifdef QDOS
  700.                 QFilename(__G__ G.filename);
  701. #endif
  702.                 switch (check_for_newer(__G__ G.filename)) {
  703.                     case DOES_NOT_EXIST:
  704. #ifdef NOVELL_BUG_FAILSAFE
  705.                         G.dne = TRUE;   /* stat() says file DOES NOT EXIST */
  706. #endif
  707.                         /* if freshening, don't skip if just renamed */
  708.                         if (G.fflag && !renamed)
  709.                             continue;   /* freshen (no new files):  skip */
  710.                         break;
  711.                     case EXISTS_AND_OLDER:
  712.                         if (G.overwrite_none) {
  713. #ifdef WINDLL
  714.                             char szStr[PATH_MAX];
  715.  
  716.                             if ((!lpDCL->PromptToOverwrite) || (done_once)) {
  717.                                 sprintf(szStr,
  718.                                   "Target file exists.\nSkipping %s\n",
  719.                                   FnFilter1(G.filename));
  720.                                 win_fprintf(stdout, strlen(szStr), szStr);
  721.                             } else {
  722.                                 query = TRUE;
  723.                                 break;
  724.                             }
  725. #endif /* WINDLL */
  726.                             continue;   /* never overwrite:  skip file */
  727.                         }
  728. #ifdef UNIXBACKUP
  729.                         if (!G.overwrite_all && !G.B_flag)
  730. #else
  731.                         if (!G.overwrite_all)
  732. #endif
  733.                             query = TRUE;
  734.                         break;
  735.                     case EXISTS_AND_NEWER:             /* (or equal) */
  736.                         if (G.overwrite_none || (G.uflag && !renamed)) {
  737. #ifdef WINDLL
  738.                             char szStr[PATH_MAX];
  739.  
  740.                             if ((!lpDCL->PromptToOverwrite) || (done_once)) {
  741.                                 sprintf(szStr,
  742.                                   "Target file newer.\nSkipping %s\n",
  743.                                   FnFilter1(G.filename));
  744.                                 win_fprintf(stdout, strlen(szStr), szStr);
  745.                             } else {
  746.                                 query = TRUE;
  747.                                 break;
  748.                             }
  749. #endif /* WINDLL */
  750.                             continue;  /* skip if update/freshen & orig name */
  751.                         }
  752. #ifdef UNIXBACKUP
  753.                         if (!G.overwrite_all && !G.B_flag)
  754. #else
  755.                         if (!G.overwrite_all)
  756. #endif
  757.                             query = TRUE;
  758.                         break;
  759.                 }
  760.                 if (query) {
  761. #ifdef WINDLL
  762.                     switch (G.replace != NULL ?
  763.                             (*G.replace)(G.filename) : IDM_REPLACE_NONE) {
  764.                         case IDM_REPLACE_RENAME:
  765.                             _ISO_INTERN(G.filename);
  766.                             renamed = TRUE;
  767.                             goto startover;
  768.                         case IDM_REPLACE_YES:
  769.                             break;
  770.                         case IDM_REPLACE_ALL:
  771.                             G.overwrite_all = TRUE;
  772.                             G.overwrite_none = FALSE;  /* just to make sure */
  773.                             break;
  774.                         case IDM_REPLACE_NONE:
  775.                             G.overwrite_none = TRUE;
  776.                             G.overwrite_all = FALSE;  /* make sure */
  777.                             done_once = TRUE;
  778.                             /* FALL THROUGH, skip */
  779.                         case IDM_REPLACE_NO:
  780.                             {
  781.                                 char szStr[PATH_MAX];
  782.  
  783.                                 sprintf(szStr,
  784.                                   "Target file newer.\nSkipping %s\n",
  785.                                   FnFilter1(G.filename));
  786.                                 win_fprintf(stdout, strlen(szStr), szStr);
  787.                             }
  788.                             continue;
  789.                     }
  790. #else /* !WINDLL */
  791. reprompt:
  792.                     Info(slide, 0x81, ((char *)slide,
  793.                       LoadFarString(ReplaceQuery),
  794.                       FnFilter1(G.filename)));
  795.                     if (fgets(G.answerbuf, 9, stdin) == (char *)NULL) {
  796.                         Info(slide, 1, ((char *)slide,
  797.                           LoadFarString(AssumeNone)));
  798.                         *G.answerbuf = 'N';
  799.                         if (!error_in_archive)
  800.                             error_in_archive = 1;  /* not extracted:  warning */
  801.                     }
  802.                     switch (*G.answerbuf) {
  803.                         case 'A':   /* dangerous option:  force caps */
  804.                             G.overwrite_all = TRUE;
  805.                             G.overwrite_none = FALSE;  /* just to make sure */
  806.                             break;
  807.                         case 'r':
  808.                         case 'R':
  809.                             do {
  810.                                 Info(slide, 0x81, ((char *)slide,
  811.                                   LoadFarString(NewNameQuery)));
  812.                                 fgets(G.filename, FILNAMSIZ, stdin);
  813.                                 /* usually get \n here:  better check for it */
  814.                                 len = strlen(G.filename);
  815.                                 if (G.filename[len-1] == '\n')
  816.                                     G.filename[--len] = 0;
  817.                             } while (len == 0);
  818. #ifdef WIN32  /* WIN32 fgets( ... , stdin) returns OEM coded strings */
  819.                             _OEM_INTERN(G.filename);
  820. #endif
  821.                             renamed = TRUE;
  822.                             goto startover;   /* sorry for a goto */
  823.                         case 'y':
  824.                         case 'Y':
  825.                             break;
  826.                         case 'N':
  827.                             G.overwrite_none = TRUE;
  828.                             G.overwrite_all = FALSE;  /* make sure */
  829.                             /* FALL THROUGH, skip */
  830.                         case 'n':
  831.                             continue;   /* skip file */
  832.                         default:
  833.                             Info(slide, 1, ((char *)slide,
  834.                               LoadFarString(InvalidResponse), *G.answerbuf));
  835.                             goto reprompt;   /* yet another goto? */
  836.                     } /* end switch (*answerbuf) */
  837. #endif /* ?WINDLL */
  838.                 } /* end if (query) */
  839.             } /* end if (extracting to disk) */
  840.  
  841. #if CRYPT
  842.             if (G.pInfo->encrypted && (error = decrypt(__G)) != PK_COOL) {
  843.                 if (error == PK_WARN) {
  844.                     if (!((G.tflag && G.qflag) || (!G.tflag && !QCOND2)))
  845.                         Info(slide, 0x401, ((char *)slide,
  846.                           LoadFarString(SkipIncorrectPasswd),
  847.                           FnFilter1(G.filename)));
  848.                     ++num_bad_pwd;
  849.                 } else {  /* (error > PK_WARN) */
  850.                     if (error > error_in_archive)
  851.                         error_in_archive = error;
  852.                     Info(slide, 0x401, ((char *)slide,
  853.                       LoadFarString(SkipCannotGetPasswd),
  854.                       FnFilter1(G.filename)));
  855.                 }
  856.                 continue;   /* go on to next file */
  857.             }
  858. #endif /* CRYPT */
  859. #ifdef WINDLL         /* GRR:  this should be made generic:  ifdef SOUND? */
  860.             /* play sound during extraction or test, if requested */
  861.             if (G.sound != NULL)
  862.                 (*G.sound)();
  863. #endif
  864. #ifdef AMIGA
  865.             G.filenote_slot = i;
  866. #endif
  867.             G.disk_full = 0;
  868.             if ((error = extract_or_test_member(__G)) != PK_COOL) {
  869.                 if (error > error_in_archive)
  870.                     error_in_archive = error;       /* ...and keep going */
  871.                 if (G.disk_full > 1) {
  872.                     if (fn_matched)
  873.                         free((zvoid *)fn_matched);
  874.                     if (xn_matched)
  875.                         free((zvoid *)xn_matched);
  876.                     return error_in_archive;        /* (unless disk full) */
  877.                 }
  878.             }
  879.         } /* end for-loop (i:  files in current block) */
  880.  
  881.  
  882.         /*
  883.          * Jump back to where we were in the central directory, then go and do
  884.          * the next batch of files.
  885.          */
  886.  
  887. #ifdef USE_STRM_INPUT
  888.         fseek((FILE *)G.zipfd, (LONGINT)cd_bufstart, SEEK_SET);
  889.         G.cur_zipfile_bufstart = ftell((FILE *)G.zipfd);
  890. #else /* !USE_STRM_INPUT */
  891.         G.cur_zipfile_bufstart = lseek(G.zipfd,(LONGINT)cd_bufstart,SEEK_SET);
  892. #endif /* ?USE_STRM_INPUT */
  893.         read(G.zipfd, (char *)G.inbuf, INBUFSIZ);  /* been here before... */
  894.         G.inptr = cd_inptr;
  895.         G.incnt = cd_incnt;
  896.         ++blknum;
  897.  
  898. #ifdef TEST
  899.         printf("\ncd_bufstart = %ld (%.8lXh)\n", cd_bufstart, cd_bufstart);
  900.         printf("cur_zipfile_bufstart = %ld (%.8lXh)\n", cur_zipfile_bufstart,
  901.           cur_zipfile_bufstart);
  902.         printf("inptr-inbuf = %d\n", G.inptr-G.inbuf);
  903.         printf("incnt = %d\n\n", G.incnt);
  904. #endif
  905.  
  906.     } /* end while-loop (blocks of files in central directory) */
  907.  
  908. /*---------------------------------------------------------------------------
  909.     Go back through saved list of directories, sort and set times/perms/UIDs
  910.     and GIDs from the deepest level on up.
  911.   ---------------------------------------------------------------------------*/
  912.  
  913. #ifdef UNIX
  914.     if (num_dirs > 0) {
  915.         sorted_dirlist = (dirtime **)malloc(num_dirs*sizeof(dirtime *));
  916.         if (sorted_dirlist == (dirtime **)NULL) {
  917.             Info(slide, 0x401, ((char *)slide,
  918.               LoadFarString(DirlistSortNoMem)));
  919.         } else {
  920.             if (num_dirs == 1)
  921.                 sorted_dirlist[0] = dirlist;
  922.             else {
  923.                 for (i = 0;  i < num_dirs;  ++i)
  924.                     sorted_dirlist[i] = &dirlist[i];
  925.                 qsort((char *)sorted_dirlist, num_dirs, sizeof(dirtime *),
  926.                   dircomp);
  927.             }
  928.  
  929.             Trace((stderr, "setting Unix dir times/perms/UIDs/GIDs\n"));
  930.             for (i = 0;  i < num_dirs;  ++i) {
  931.                 dirtime *d = sorted_dirlist[i];
  932.  
  933.                 Trace((stderr, "dir = %s\n", d->fn));
  934.                 if (d->have_uidgid &&
  935.                     chown(d->fn, (uid_t)d->uidgid[0], (gid_t)d->uidgid[1]))
  936.                 {
  937.                     Info(slide, 0x201, ((char *)slide,
  938.                       LoadFarString(DirlistUidGidFailed),
  939.                       d->uidgid[0], d->uidgid[1], d->fn));
  940.                     if (!error_in_archive)
  941.                         error_in_archive = PK_WARN;
  942.                 }
  943.                 if (utime(d->fn, &d->u.t2)) {
  944.                     Info(slide, 0x201, ((char *)slide,
  945.                       LoadFarString(DirlistUtimeFailed), d->fn));
  946.                     if (!error_in_archive)
  947.                         error_in_archive = PK_WARN;
  948.                 }
  949. #ifndef NO_CHMOD
  950.                 if (chmod(d->fn, 0xffff & d->perms)) {
  951.                     Info(slide, 0x201, ((char *)slide,
  952.                       LoadFarString(DirlistChmodFailed), d->fn));
  953.                     /* perror("chmod (file attributes) error"); */
  954.                     if (!error_in_archive)
  955.                         error_in_archive = PK_WARN;
  956.                 }
  957. #endif /* !NO_CHMOD */
  958.                 free(d->fn);
  959.             }
  960.             free(sorted_dirlist);
  961.         }
  962.         free(dirlist);
  963.     }
  964. #endif /* UNIX */
  965.  
  966. #if (defined(WIN32) && defined(NTSD_EAS))
  967.     process_defer_NT(__G);  /* process any deferred items for this .zip file */
  968. #endif
  969.  
  970. /*---------------------------------------------------------------------------
  971.     Check for unmatched filespecs on command line and print warning if any
  972.     found.  Free allocated memory.
  973.   ---------------------------------------------------------------------------*/
  974.  
  975.     if (fn_matched) {
  976.         for (i = 0;  i < G.filespecs;  ++i)
  977.             if (!fn_matched[i]) {
  978. #ifdef DLL
  979.                 if (!G.redirect_data && !G.redirect_text)
  980.                     Info(slide, 0x401, ((char *)slide,
  981.                       LoadFarString(FilenameNotMatched), G.pfnames[i]));
  982.                 else
  983.                     setFileNotFound(__G);
  984. #else
  985.                 Info(slide, 1, ((char *)slide,
  986.                   LoadFarString(FilenameNotMatched), G.pfnames[i]));
  987. #endif
  988.                 if (error_in_archive <= PK_WARN)
  989.                     error_in_archive = PK_FIND;   /* some files not found */
  990.             }
  991.         free((zvoid *)fn_matched);
  992.     }
  993.     if (xn_matched) {
  994.         for (i = 0;  i < G.xfilespecs;  ++i)
  995.             if (!xn_matched[i])
  996.                 Info(slide, 0x401, ((char *)slide,
  997.                   LoadFarString(ExclFilenameNotMatched), G.pxnames[i]));
  998.         free((zvoid *)xn_matched);
  999.     }
  1000.  
  1001. /*---------------------------------------------------------------------------
  1002.     Double-check that we're back at the end-of-central-directory record, and
  1003.     print quick summary of results, if we were just testing the archive.  We
  1004.     send the summary to stdout so that people doing the testing in the back-
  1005.     ground and redirecting to a file can just do a "tail" on the output file.
  1006.   ---------------------------------------------------------------------------*/
  1007.  
  1008. #ifndef SFX
  1009.     if (readbuf(__G__ G.sig, 4) == 0)
  1010.         error_in_archive = PK_EOF;
  1011.     if (strncmp(G.sig, G.end_central_sig, 4)) {         /* just to make sure */
  1012.         Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg)));
  1013.         Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg)));
  1014.         if (!error_in_archive)       /* don't overwrite stronger error */
  1015.             error_in_archive = PK_WARN;
  1016.     }
  1017. #endif /* !SFX */
  1018.     ++filnum;  /* initialized to -1, so now zero if no files found */
  1019.     if (G.tflag) {
  1020.         int num=filnum - num_bad_pwd;
  1021.  
  1022.         if (G.qflag < 2) {         /* GRR 930710:  was (G.qflag == 1) */
  1023.             if (error_in_archive)
  1024.                 Info(slide, 0, ((char *)slide, LoadFarString(ErrorInArchive),
  1025.                   (error_in_archive == 1)? "warning-" : "", G.zipfn));
  1026.             else if (num == 0)
  1027.                 Info(slide, 0, ((char *)slide, LoadFarString(ZeroFilesTested),
  1028.                   G.zipfn));
  1029.             else if (G.process_all_files && (num_skipped+num_bad_pwd == 0))
  1030.                 Info(slide, 0, ((char *)slide, LoadFarString(NoErrInCompData),
  1031.                   G.zipfn));
  1032.             else
  1033.                 Info(slide, 0, ((char *)slide, LoadFarString(NoErrInTestedFiles)
  1034.                   , G.zipfn, num, (num==1)? "":"s"));
  1035.             if (num_skipped > 0)
  1036.                 Info(slide, 0, ((char *)slide, LoadFarString(FilesSkipped),
  1037.                   num_skipped, (num_skipped==1)? "":"s"));
  1038. #if CRYPT
  1039.             if (num_bad_pwd > 0)
  1040.                 Info(slide, 0, ((char *)slide, LoadFarString(FilesSkipBadPasswd)
  1041.                   , num_bad_pwd, (num_bad_pwd==1)? "":"s"));
  1042. #endif /* CRYPT */
  1043.         } else if ((G.qflag == 0) && !error_in_archive && (num == 0))
  1044.             Info(slide, 0, ((char *)slide, LoadFarString(ZeroFilesTested),
  1045.               G.zipfn));
  1046.     }
  1047.  
  1048.     /* give warning if files not tested or extracted (first condition can still
  1049.      * happen if zipfile is empty and no files specified on command line) */
  1050.  
  1051.     if ((filnum == 0) && error_in_archive <= PK_WARN) {
  1052.         if (num_skipped > 0)
  1053.             error_in_archive = IZ_UNSUP; /* unsupport. compression/encryption */
  1054.         else
  1055.             error_in_archive = PK_FIND;  /* no files found at all */
  1056.     }
  1057. #if CRYPT
  1058.     else if ((filnum == num_bad_pwd) && error_in_archive <= PK_WARN)
  1059.         error_in_archive = IZ_BADPWD;    /* bad passwd => all files skipped */
  1060. #endif
  1061.     else if ((num_skipped > 0) && error_in_archive <= PK_WARN)
  1062.         error_in_archive = IZ_UNSUP;     /* was PK_WARN; Jean-loup complained */
  1063. #if CRYPT
  1064.     else if ((num_bad_pwd > 0) && !error_in_archive)
  1065.         error_in_archive = PK_WARN;
  1066. #endif
  1067.  
  1068.     return error_in_archive;
  1069.  
  1070. } /* end function extract_or_test_files() */
  1071.  
  1072.  
  1073.  
  1074.  
  1075.  
  1076. /***************************/
  1077. /*  Function store_info()  */
  1078. /***************************/
  1079.  
  1080. static int store_info(__G)   /* return 0 if skipping, 1 if OK */
  1081.     __GDEF
  1082. {
  1083. #ifdef SFX
  1084. #  define UNKN_COMPR \
  1085.    (G.crec.compression_method!=STORED && G.crec.compression_method!=DEFLATED)
  1086. #else
  1087. #  ifdef COPYRIGHT_CLEAN  /* no reduced files */
  1088. #    define UNKN_RED (G.crec.compression_method >= REDUCED1 && \
  1089.                       G.crec.compression_method <= REDUCED4)
  1090. #  else
  1091. #    define UNKN_RED  FALSE  /* reducing not unknown */
  1092. #  endif
  1093. #  ifdef LZW_CLEAN  /* no shrunk files */
  1094. #    define UNKN_SHR (G.crec.compression_method == SHRUNK)
  1095. #  else
  1096. #    define UNKN_SHR  FALSE  /* unshrinking not unknown */
  1097. #  endif
  1098. #  define UNKN_COMPR (UNKN_RED || UNKN_SHR || \
  1099.    G.crec.compression_method==TOKENIZED || G.crec.compression_method>DEFLATED)
  1100. #endif
  1101.  
  1102. /*---------------------------------------------------------------------------
  1103.     Check central directory info for version/compatibility requirements.
  1104.   ---------------------------------------------------------------------------*/
  1105.  
  1106.     G.pInfo->encrypted = G.crec.general_purpose_bit_flag & 1;   /* bit field */
  1107.     G.pInfo->ExtLocHdr = (G.crec.general_purpose_bit_flag & 8) == 8;  /* bit */
  1108.     G.pInfo->textfile = G.crec.internal_file_attributes & 1;    /* bit field */
  1109.     G.pInfo->crc = G.crec.crc32;
  1110.     G.pInfo->compr_size = G.crec.csize;
  1111.  
  1112.     switch (G.aflag) {
  1113.         case 0:
  1114.             G.pInfo->textmode = FALSE;   /* bit field */
  1115.             break;
  1116.         case 1:
  1117.             G.pInfo->textmode = G.pInfo->textfile;   /* auto-convert mode */
  1118.             break;
  1119.         default:  /* case 2: */
  1120.             G.pInfo->textmode = TRUE;
  1121.             break;
  1122.     }
  1123.  
  1124.     if (G.crec.version_needed_to_extract[1] == VMS_) {
  1125.         if (G.crec.version_needed_to_extract[0] > VMS_UNZIP_VERSION) {
  1126.             if (!((G.tflag && G.qflag) || (!G.tflag && !QCOND2)))
  1127.                 Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg),
  1128.                   FnFilter1(G.filename), "VMS",
  1129.                   G.crec.version_needed_to_extract[0] / 10,
  1130.                   G.crec.version_needed_to_extract[0] % 10,
  1131.                   VMS_UNZIP_VERSION / 10, VMS_UNZIP_VERSION % 10));
  1132.             return 0;
  1133.         }
  1134. #ifndef VMS   /* won't be able to use extra field, but still have data */
  1135.         else if (!G.tflag && !G.overwrite_all) {   /* if -o, extract anyway */
  1136.             Info(slide, 0x481, ((char *)slide, LoadFarString(VMSFormatQuery),
  1137.               FnFilter1(G.filename)));
  1138.             fgets(G.answerbuf, 9, stdin);
  1139.             if ((*G.answerbuf != 'y') && (*G.answerbuf != 'Y'))
  1140.                 return 0;
  1141.         }
  1142. #endif /* !VMS */
  1143.     /* usual file type:  don't need VMS to extract */
  1144.     } else if (G.crec.version_needed_to_extract[0] > UNZIP_VERSION) {
  1145.         if (!((G.tflag && G.qflag) || (!G.tflag && !QCOND2)))
  1146.             Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg),
  1147.               FnFilter1(G.filename), "PK",
  1148.               G.crec.version_needed_to_extract[0] / 10,
  1149.               G.crec.version_needed_to_extract[0] % 10,
  1150.               UNZIP_VERSION / 10, UNZIP_VERSION % 10));
  1151.         return 0;
  1152.     }
  1153.  
  1154.     if UNKN_COMPR {
  1155.         if (!((G.tflag && G.qflag) || (!G.tflag && !QCOND2)))
  1156. #ifndef SFX
  1157.             if (G.crec.compression_method < NUM_METHODS)
  1158.                 Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgName),
  1159.                   FnFilter1(G.filename),
  1160.                   LoadFarStringSmall(ComprNames[G.crec.compression_method])));
  1161.             else
  1162. #endif
  1163.                 Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgNum),
  1164.                   FnFilter1(G.filename),
  1165.                   G.crec.compression_method));
  1166.         return 0;
  1167.     }
  1168. #if (!CRYPT)
  1169.     if (G.pInfo->encrypted) {
  1170.         if (!((G.tflag && G.qflag) || (!G.tflag && !QCOND2)))
  1171.             Info(slide, 0x401, ((char *)slide, LoadFarString(SkipEncrypted),
  1172.               FnFilter1(G.filename)));
  1173.         return 0;
  1174.     }
  1175. #endif /* !CRYPT */
  1176.  
  1177.     /* map whatever file attributes we have into the local format */
  1178.     mapattr(__G);   /* GRR:  worry about return value later */
  1179.  
  1180.     G.pInfo->offset = (long)G.crec.relative_offset_local_header;
  1181.     return 1;
  1182.  
  1183. } /* end function store_info() */
  1184.  
  1185.  
  1186.  
  1187.  
  1188.  
  1189. /***************************************/
  1190. /*  Function extract_or_test_member()  */
  1191. /***************************************/
  1192.  
  1193. static int extract_or_test_member(__G)    /* return PK-type error code */
  1194.      __GDEF
  1195. {
  1196.     char *nul="[empty] ", *txt="[text]  ", *bin="[binary]";
  1197. #ifdef CMS_MVS
  1198.     char *ebc="[ebcdic]";
  1199. #endif
  1200.     register int b;
  1201.     int r, error=PK_COOL;
  1202.     ulg wsize;
  1203.  
  1204.  
  1205. /*---------------------------------------------------------------------------
  1206.     Initialize variables, buffers, etc.
  1207.   ---------------------------------------------------------------------------*/
  1208.  
  1209.     G.bits_left = 0;
  1210.     G.bitbuf = 0L;       /* unreduce and unshrink only */
  1211.     G.zipeof = 0;
  1212.     G.newfile = TRUE;
  1213.     G.crc32val = CRCVAL_INITIAL;
  1214.  
  1215. #ifdef SYMLINKS
  1216.     /* if file came from Unix and is a symbolic link and we are extracting
  1217.      * to disk, prepare to restore the link */
  1218.     if (S_ISLNK(G.pInfo->file_attr) &&
  1219.         (G.pInfo->hostnum == UNIX_ || G.pInfo->hostnum == ATARI_ ||
  1220.          G.pInfo->hostnum == BEOS_) &&
  1221.         !G.tflag && !G.cflag && (G.lrec.ucsize > 0))
  1222.         G.symlnk = TRUE;
  1223.     else
  1224.         G.symlnk = FALSE;
  1225. #endif /* SYMLINKS */
  1226.  
  1227.     if (G.tflag) {
  1228.         if (!G.qflag)
  1229.             Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), "test",
  1230.               FnFilter1(G.filename), "", ""));
  1231.     } else {
  1232. #ifdef DLL
  1233.         if (G.cflag && !G.redirect_data)
  1234. #else
  1235.         if (G.cflag)
  1236. #endif
  1237.         {
  1238. #if (defined(OS2) && defined(__IBMC__) && (__IBMC__ >= 200))
  1239.             G.outfile = freopen("", "wb", stdout);   /* VAC++ ignores setmode */
  1240. #else
  1241.             G.outfile = stdout;
  1242. #endif
  1243. #ifdef DOS_FLX_H68_OS2_W32
  1244. #if (defined(__HIGHC__) && !defined(FLEXOS))
  1245.             setmode(G.outfile, _BINARY);
  1246. #else /* !(defined(__HIGHC__) && !defined(FLEXOS)) */
  1247.             setmode(fileno(G.outfile), O_BINARY);
  1248. #endif /* ?(defined(__HIGHC__) && !defined(FLEXOS)) */
  1249. #           define NEWLINE "\r\n"
  1250. #else /* !DOS_FLX_H68_OS2_W32 */
  1251. #           define NEWLINE "\n"
  1252. #endif /* ?DOS_FLX_H68_OS2_W32 */
  1253. #ifdef VMS
  1254.             if (open_outfile(__G))   /* VMS:  required even for stdout! */
  1255.                 return PK_DISK;
  1256. #endif
  1257.         } else if (open_outfile(__G))
  1258.             return PK_DISK;
  1259.     }
  1260.  
  1261. /*---------------------------------------------------------------------------
  1262.     Unpack the file.
  1263.   ---------------------------------------------------------------------------*/
  1264.  
  1265.     defer_leftover_input(__G);    /* so NEXTBYTE bounds check will work */
  1266.     switch (G.lrec.compression_method) {
  1267.         case STORED:
  1268.             if (!G.tflag && QCOND2) {
  1269. #ifdef SYMLINKS
  1270.                 if (G.symlnk)   /* can also be deflated, but rarer... */
  1271.                     Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
  1272.                       "link", FnFilter1(G.filename), "", ""));
  1273.                 else
  1274. #endif /* SYMLINKS */
  1275.                 Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
  1276.                   "extract", FnFilter1(G.filename),
  1277.                   (G.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
  1278.                   "" : (G.lrec.ucsize == 0L? nul : (G.pInfo->textfile? txt :
  1279.                   bin)), G.cflag? NEWLINE : ""));
  1280.             }
  1281. #ifdef DLL
  1282.             if (G.redirect_data)
  1283.                 wsize = G.redirect_size+1, G.outptr = G.redirect_buffer;
  1284.             else
  1285. #endif
  1286.                 wsize = WSIZE, G.outptr = slide;
  1287.             G.outcnt = 0L;
  1288.             while ((b = NEXTBYTE) != EOF && !G.disk_full) {
  1289.                 *G.outptr++ = (uch)b;
  1290.                 if (++G.outcnt == wsize) {
  1291.                     flush(__G__ slide, G.outcnt, 0);
  1292.                     G.outptr = slide;
  1293.                     G.outcnt = 0L;
  1294.                 }
  1295.             }
  1296. #ifdef DLL
  1297.             if (G.outcnt && !G.redirect_data)
  1298. #else
  1299.             if (G.outcnt)          /* flush final (partial) buffer */
  1300. #endif
  1301.                 flush(__G__ slide, G.outcnt, 0);
  1302.             break;
  1303.  
  1304. #ifndef SFX
  1305. #ifndef LZW_CLEAN
  1306.         case SHRUNK:
  1307.             if (!G.tflag && QCOND2) {
  1308.                 Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
  1309.                   LoadFarStringSmall(Unshrink), FnFilter1(G.filename),
  1310.                   (G.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
  1311.                   "" : (G.pInfo->textfile? txt : bin), G.cflag? NEWLINE : ""));
  1312.             }
  1313.             if ((r = unshrink(__G)) != PK_COOL) {
  1314.                 if ((G.tflag && G.qflag) || (!G.tflag && !QCOND2))
  1315.                     Info(slide, 0x401, ((char *)slide,
  1316.                       LoadFarStringSmall(ErrUnzipFile),
  1317.                       LoadFarString(NotEnoughMem),
  1318.                       LoadFarStringSmall2(Unshrink),
  1319.                       FnFilter1(G.filename)));
  1320.                 else
  1321.                     Info(slide, 0x401, ((char *)slide,
  1322.                       LoadFarStringSmall(ErrUnzipNoFile),
  1323.                       LoadFarString(NotEnoughMem),
  1324.                       LoadFarStringSmall2(Unshrink)));
  1325.                 error = r;
  1326.             }
  1327.             break;
  1328. #endif /* !LZW_CLEAN */
  1329.  
  1330. #ifndef COPYRIGHT_CLEAN
  1331.         case REDUCED1:
  1332.         case REDUCED2:
  1333.         case REDUCED3:
  1334.         case REDUCED4:
  1335.             if (!G.tflag && QCOND2) {
  1336.                 Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
  1337.                   "unreduc", FnFilter1(G.filename),
  1338.                   (G.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
  1339.                   "" : (G.pInfo->textfile? txt : bin), G.cflag? NEWLINE : ""));
  1340.             }
  1341.             unreduce(__G);
  1342.             break;
  1343. #endif /* !COPYRIGHT_CLEAN */
  1344.  
  1345.         case IMPLODED:
  1346.             if (!G.tflag && QCOND2) {
  1347.                 Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
  1348.                   "explod", FnFilter1(G.filename),
  1349.                   (G.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
  1350.                   "" : (G.pInfo->textfile? txt : bin), G.cflag? NEWLINE : ""));
  1351.             }
  1352.             if (((r = explode(__G)) != 0) && (r != 5)) { /* treat 5 specially */
  1353.                 if ((G.tflag && G.qflag) || (!G.tflag && !QCOND2))
  1354.                     Info(slide, 0x401, ((char *)slide,
  1355.                       LoadFarStringSmall(ErrUnzipFile), r == 3?
  1356.                       LoadFarString(NotEnoughMem) :
  1357.                       LoadFarString(InvalidComprData),
  1358.                       LoadFarStringSmall2(Explode),
  1359.                       FnFilter1(G.filename)));
  1360.                 else
  1361.                     Info(slide, 0x401, ((char *)slide,
  1362.                       LoadFarStringSmall(ErrUnzipNoFile), r == 3?
  1363.                       LoadFarString(NotEnoughMem) :
  1364.                       LoadFarString(InvalidComprData),
  1365.                       LoadFarStringSmall2(Explode)));
  1366.                 error = (r == 3)? PK_MEM3 : PK_ERR;
  1367.             }
  1368.             if (r == 5) {
  1369.                 int warning = ((ulg)G.used_csize <= G.lrec.csize);
  1370.  
  1371.                 if ((G.tflag && G.qflag) || (!G.tflag && !QCOND2))
  1372.                     Info(slide, 0x401, ((char *)slide, LoadFarString(LengthMsg),
  1373.                       "", warning?  "warning" : "error", G.used_csize,
  1374.                       G.lrec.ucsize, warning?  "  " : "", G.lrec.csize,
  1375.                       " [", FnFilter1(G.filename), "]"));
  1376.                 else
  1377.                     Info(slide, 0x401, ((char *)slide, LoadFarString(LengthMsg),
  1378.                       "\n", warning? "warning" : "error", G.used_csize,
  1379.                       G.lrec.ucsize, warning? "  ":"", G.lrec.csize,
  1380.                       "", "", "."));
  1381.                 error = warning? PK_WARN : PK_ERR;
  1382.             }
  1383.             break;
  1384. #endif /* !SFX */
  1385.  
  1386.         case DEFLATED:
  1387.             if (!G.tflag && QCOND2) {
  1388.                 Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
  1389.                   "inflat", FnFilter1(G.filename),
  1390.                   (G.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
  1391.                   "" : (G.pInfo->textfile? txt : bin), G.cflag? NEWLINE : ""));
  1392.             }
  1393. #ifndef USE_ZLIB  /* zlib's function is called inflate(), too */
  1394. #  define UZinflate inflate
  1395. #endif
  1396.             if ((r = UZinflate(__G)) != 0) {
  1397.                 if ((G.tflag && G.qflag) || (!G.tflag && !QCOND2))
  1398.                     Info(slide, 0x401, ((char *)slide,
  1399.                       LoadFarStringSmall(ErrUnzipFile), r == 3?
  1400.                       LoadFarString(NotEnoughMem) :
  1401.                       LoadFarString(InvalidComprData),
  1402.                       LoadFarStringSmall2(Inflate),
  1403.                       FnFilter1(G.filename)));
  1404.                 else
  1405.                     Info(slide, 0x401, ((char *)slide,
  1406.                       LoadFarStringSmall(ErrUnzipNoFile), r == 3?
  1407.                       LoadFarString(NotEnoughMem) :
  1408.                       LoadFarString(InvalidComprData),
  1409.                       LoadFarStringSmall2(Inflate)));
  1410.                 error = (r == 3)? PK_MEM3 : PK_ERR;
  1411.             }
  1412.             break;
  1413.  
  1414.         default:   /* should never get to this point */
  1415.             Info(slide, 0x401, ((char *)slide,
  1416.               LoadFarString(FileUnknownCompMethod), FnFilter1(G.filename)));
  1417.             /* close and delete file before return? */
  1418.             undefer_input(__G);
  1419.             return PK_WARN;
  1420.  
  1421.     } /* end switch (compression method) */
  1422.  
  1423. /*---------------------------------------------------------------------------
  1424.     Close the file and set its date and time (not necessarily in that order),
  1425.     and make sure the CRC checked out OK.  Logical-AND the CRC for 64-bit
  1426.     machines (redundant on 32-bit machines).
  1427.   ---------------------------------------------------------------------------*/
  1428.  
  1429. #ifdef VMS                  /* VMS:  required even for stdout! (final flush) */
  1430.     if (!G.tflag)           /* don't close NULL file */
  1431.         close_outfile(__G);
  1432. #else
  1433. #ifdef DLL
  1434.     if (!G.tflag && (!G.cflag || G.redirect_data))
  1435.         if (G.redirect_data)
  1436.             FINISH_REDIRECT();
  1437.         else
  1438.             close_outfile(__G);
  1439. #else
  1440.     if (!G.tflag && !G.cflag)   /* don't close NULL file or stdout */
  1441.         close_outfile(__G);
  1442. #endif
  1443. #endif /* VMS */
  1444.  
  1445.             /* GRR: CONVERT close_outfile() TO NON-VOID:  CHECK FOR ERRORS! */
  1446.  
  1447.  
  1448.     if (G.disk_full) {            /* set by flush() */
  1449.         if (G.disk_full > 1) {
  1450. #if (defined(DELETE_IF_FULL) && defined(HAVE_UNLINK))
  1451.             /* delete the incomplete file if we can */
  1452.             if (unlink(G.filename) != 0)
  1453.                 Trace((stderr, "extract.c:  could not delete %s\n",
  1454.                   FnFilter1(G.filename)));
  1455. #else
  1456.             /* warn user about the incomplete file */
  1457.             Info(slide, 0x421, ((char *)slide, LoadFarString(FileTruncated),
  1458.               FnFilter1(G.filename)));
  1459. #endif
  1460.             error = PK_DISK;
  1461.         } else {
  1462.             error = PK_WARN;
  1463.         }
  1464.     }
  1465.  
  1466.     if (error > PK_WARN) {/* don't print redundant CRC error if error already */
  1467.         undefer_input(__G);
  1468.         return error;
  1469.     }
  1470.     if (G.crc32val != G.lrec.crc32) {
  1471.         /* if quiet enough, we haven't output the filename yet:  do it */
  1472.         if ((G.tflag && G.qflag) || (!G.tflag && !QCOND2))
  1473.             Info(slide, 0x401, ((char *)slide, "%-22s ",
  1474.               FnFilter1(G.filename)));
  1475.         Info(slide, 0x401, ((char *)slide, LoadFarString(BadCRC), G.crc32val,
  1476.           G.lrec.crc32));
  1477. #if CRYPT
  1478.         if (G.pInfo->encrypted)
  1479.             Info(slide, 0x401, ((char *)slide, LoadFarString(MaybeBadPasswd)));
  1480. #endif
  1481.         error = PK_ERR;
  1482.     } else if (G.tflag) {
  1483. #ifndef SFX
  1484.         if (G.extra_field) {
  1485.             if ((r = TestExtraField(__G__ G.extra_field,
  1486.                                     G.lrec.extra_field_length)) > error)
  1487.                 error = r;
  1488.         } else
  1489. #endif /* !SFX */
  1490.         if (!G.qflag)
  1491.             Info(slide, 0, ((char *)slide, " OK\n"));
  1492.     } else {
  1493.         if (QCOND2 && !error)   /* GRR:  is stdout reset to text mode yet? */
  1494.             Info(slide, 0, ((char *)slide, "\n"));
  1495.     }
  1496.  
  1497.     undefer_input(__G);
  1498.     return error;
  1499.  
  1500. } /* end function extract_or_test_member() */
  1501.  
  1502.  
  1503.  
  1504.  
  1505.  
  1506. #ifndef SFX
  1507.  
  1508. /*******************************/
  1509. /*  Function TestExtraField()  */
  1510. /*******************************/
  1511.  
  1512. static int TestExtraField(__G__ ef, ef_len)
  1513.     __GDEF
  1514.     uch *ef;
  1515.     unsigned ef_len;
  1516. {
  1517.     ush ebID;
  1518.     unsigned ebLen;
  1519.     int r;
  1520.  
  1521.     /* we know the regular compressed file data tested out OK, or else we
  1522.      * wouldn't be here ==> print filename if any extra-field errors found
  1523.      */
  1524.     while (ef_len >= EB_HEADSIZE) {
  1525.         ebID = makeword(ef);
  1526.         ebLen = (unsigned)makeword(ef+EB_LEN);
  1527.  
  1528.         if (ebLen > (ef_len - EB_HEADSIZE)) {
  1529.            /* Discovered some extra field inconsistency! */
  1530.             if (G.qflag)
  1531.                 Info(slide, 1, ((char *)slide, "%-22s ",
  1532.                   FnFilter1(G.filename)));
  1533.             Info(slide, 1, ((char *)slide, LoadFarString(InconsistEFlength),
  1534.               ebLen, (ef_len - EB_HEADSIZE)));
  1535.             return PK_ERR;
  1536.         }
  1537.  
  1538.         switch (ebID) {
  1539.             case EF_OS2:
  1540.             case EF_ACL:
  1541.                 if ((r = test_compr_eb(__G__ ef, ebLen, EB_OS2_CHEAD, NULL))
  1542.                     != PK_OK) {
  1543.                     if (G.qflag)
  1544.                         Info(slide, 1, ((char *)slide, "%-22s ",
  1545.                           FnFilter1(G.filename)));
  1546.                     switch (r) {
  1547.                         case IZ_EF_TRUNC:
  1548.                             Info(slide, 1, ((char *)slide,
  1549.                               LoadFarString(TruncEAs),
  1550.                               ebLen-(EB_OS2_CHEAD+EB_CMPRHEADLEN), "\n"));
  1551.                             break;
  1552.                         case PK_ERR:
  1553.                             Info(slide, 1, ((char *)slide,
  1554.                               LoadFarString(InvalidComprDataEAs)));
  1555.                             break;
  1556.                         case PK_MEM3:
  1557.                         case PK_MEM4:
  1558.                             Info(slide, 1, ((char *)slide,
  1559.                               LoadFarString(NotEnoughMemEAs)));
  1560.                             break;
  1561.                         default:
  1562.                             if ((r & 0xff) != PK_ERR)
  1563.                                 Info(slide, 1, ((char *)slide,
  1564.                                   LoadFarString(UnknErrorEAs)));
  1565.                             else {
  1566.                                 ush m = (ush)(r >> 8);
  1567.                                 if (m == DEFLATED)            /* GRR KLUDGE! */
  1568.                                     Info(slide, 1, ((char *)slide,
  1569.                                       LoadFarString(BadCRC_EAs)));
  1570.                                 else
  1571.                                     Info(slide, 1, ((char *)slide,
  1572.                                       LoadFarString(UnknComprMethodEAs), m));
  1573.                             }
  1574.                             break;
  1575.                     }
  1576.                     return r;
  1577.                 }
  1578.                 break;
  1579.  
  1580.             case EF_NTSD:
  1581.                 Trace((stderr, "ebID: %i / ebLen: %u\n", ebID, ebLen));
  1582.                 r = ebLen < EB_NTSD_L_LEN ? IZ_EF_TRUNC :
  1583.                     ((ef[EB_HEADSIZE+EB_NTSD_VERSION] > EB_NTSD_MAX_VER) ?
  1584.                      (PK_WARN | 0x4000) :
  1585.                      test_compr_eb(__G__ ef, ebLen, EB_NTSD_L_LEN, TEST_NTSD));
  1586.                 if (r != PK_OK) {
  1587.                     if (G.qflag)
  1588.                         Info(slide, 1, ((char *)slide, "%-22s ",
  1589.                           FnFilter1(G.filename)));
  1590.                     switch (r) {
  1591.                         case IZ_EF_TRUNC:
  1592.                             Info(slide, 1, ((char *)slide,
  1593.                               LoadFarString(TruncNTSD),
  1594.                               ebLen-(EB_NTSD_L_LEN+EB_CMPRHEADLEN), "\n"));
  1595.                             break;
  1596. #if (defined(WIN32) && defined(NTSD_EAS))
  1597.                         case PK_WARN:
  1598.                             Info(slide, 1, ((char *)slide,
  1599.                               LoadFarString(InvalidSecurityEAs)));
  1600.                             break;
  1601. #endif
  1602.                         case PK_ERR:
  1603.                             Info(slide, 1, ((char *)slide,
  1604.                               LoadFarString(InvalidComprDataEAs)));
  1605.                             break;
  1606.                         case PK_MEM3:
  1607.                         case PK_MEM4:
  1608.                             Info(slide, 1, ((char *)slide,
  1609.                               LoadFarString(NotEnoughMemEAs)));
  1610.                             break;
  1611.                         case (PK_WARN | 0x4000):
  1612.                             Info(slide, 1, ((char *)slide,
  1613.                               LoadFarString(UnsuppNTSDVersEAs),
  1614.                               (int)ef[EB_HEADSIZE+EB_NTSD_VERSION]));
  1615.                             r = PK_WARN;
  1616.                             break;
  1617.                         default:
  1618.                             if ((r & 0xff) != PK_ERR)
  1619.                                 Info(slide, 1, ((char *)slide,
  1620.                                   LoadFarString(UnknErrorEAs)));
  1621.                             else {
  1622.                                 ush m = (ush)(r >> 8);
  1623.                                 if (m == DEFLATED)            /* GRR KLUDGE! */
  1624.                                     Info(slide, 1, ((char *)slide,
  1625.                                       LoadFarString(BadCRC_EAs)));
  1626.                                 else
  1627.                                     Info(slide, 1, ((char *)slide,
  1628.                                       LoadFarString(UnknComprMethodEAs), m));
  1629.                             }
  1630.                             break;
  1631.                     }
  1632.                     return r;
  1633.                 }
  1634.                 break;
  1635.             case EF_PKVMS:
  1636.             case EF_ASIUNIX:
  1637.             case EF_IZVMS:
  1638.             case EF_IZUNIX:
  1639.             case EF_VMCMS:
  1640.             case EF_MVS:
  1641.             case EF_SPARK:
  1642.             case EF_AV:
  1643.             default:
  1644.                 break;
  1645.         }
  1646.         ef_len -= (ebLen + EB_HEADSIZE);
  1647.         ef += (ebLen + EB_HEADSIZE);
  1648.     }
  1649.  
  1650.     if (!G.qflag)
  1651.         Info(slide, 0, ((char *)slide, " OK\n"));
  1652.  
  1653.     return PK_COOL;
  1654.  
  1655. } /* end function TestExtraField() */
  1656.  
  1657.  
  1658.  
  1659.  
  1660.  
  1661. /******************************/
  1662. /*  Function test_compr_eb()  */
  1663. /******************************/
  1664.  
  1665. static int test_compr_eb(__G__ eb, eb_size, compr_offset, test_uc_ebdata)
  1666.     __GDEF
  1667.     uch *eb;
  1668.     unsigned eb_size;
  1669.     unsigned compr_offset;
  1670.     int (*test_uc_ebdata) OF((__GPRO__ uch *eb, unsigned eb_size,
  1671.                               uch *eb_ucptr, ulg eb_ucsize));
  1672. {
  1673.     ulg eb_ucsize;
  1674.     uch *eb_ucptr;
  1675.     int r;
  1676.  
  1677.     if ((eb_size < (EB_UCSIZE_P + 4)) ||
  1678.         ((eb_ucsize = makelong(eb+(EB_HEADSIZE+EB_UCSIZE_P))) > 0L &&
  1679.          eb_size <= (compr_offset + EB_CMPRHEADLEN)))
  1680.         return IZ_EF_TRUNC;               /* no compressed data! */
  1681.  
  1682.     if ((eb_ucptr = (uch *)malloc((extent)eb_ucsize)) == (uch *)NULL)
  1683.         return PK_MEM4;
  1684.  
  1685.     r = memextract(__G__ eb_ucptr, eb_ucsize,
  1686.                    eb + (EB_HEADSIZE + compr_offset),
  1687.                    (ulg)(eb_size - compr_offset));
  1688.  
  1689.     if (r == PK_OK && test_uc_ebdata != NULL)
  1690.         r = (*test_uc_ebdata)(__G__ eb, eb_size, eb_ucptr, eb_ucsize);
  1691.  
  1692.     free(eb_ucptr);
  1693.     return r;
  1694.  
  1695. } /* end function test_compr_eb() */
  1696.  
  1697. #endif /* !SFX */
  1698.  
  1699.  
  1700.  
  1701.  
  1702.  
  1703. /***************************/
  1704. /*  Function memextract()  */
  1705. /***************************/
  1706.  
  1707. int memextract(__G__ tgt, tgtsize, src, srcsize)  /* extract compressed */
  1708.     __GDEF                                        /*  extra field block; */
  1709.     uch *tgt, *src;                               /*  return PK-type error */
  1710.     ulg tgtsize, srcsize;                         /*  level */
  1711. {
  1712.     uch *old_inptr=G.inptr;
  1713.     int  old_incnt=G.incnt, r, error=PK_OK;
  1714.     ush  method;
  1715.     ulg  extra_field_crc;
  1716.  
  1717.  
  1718.     method = makeword(src);
  1719.     extra_field_crc = makelong(src+2);
  1720.  
  1721.     /* compressed extra field exists completely in memory at this location: */
  1722.     G.inptr = src + 2 + 4;      /* method and extra_field_crc */
  1723.     G.incnt = (int)(G.csize = (long)(srcsize - (2 + 4)));
  1724.     G.mem_mode = TRUE;
  1725.     G.outbufptr = tgt;
  1726.     G.outsize = tgtsize;
  1727.  
  1728.     switch (method) {
  1729.         case STORED:
  1730.             memcpy((char *)tgt, (char *)G.inptr, (extent)G.incnt);
  1731.             G.outcnt = G.csize;   /* for CRC calculation */
  1732.             break;
  1733.         case DEFLATED:
  1734.             G.outcnt = 0L;
  1735.             if ((r = UZinflate(__G)) != 0) {
  1736.                 if (!G.tflag)
  1737.                     Info(slide, 0x401, ((char *)slide,
  1738.                       LoadFarStringSmall(ErrUnzipNoFile), r == 3?
  1739.                       LoadFarString(NotEnoughMem) :
  1740.                       LoadFarString(InvalidComprData),
  1741.                       LoadFarStringSmall2(Inflate)));
  1742.                 error = (r == 3)? PK_MEM3 : PK_ERR;
  1743.             }
  1744.             if (G.outcnt == 0L)   /* inflate's final FLUSH sets outcnt */
  1745.                 break;
  1746.             break;
  1747.         default:
  1748.             if (G.tflag)
  1749.                 error = PK_ERR | ((int)method << 8);
  1750.             else {
  1751.                 Info(slide, 0x401, ((char *)slide,
  1752.                   LoadFarString(UnsupportedExtraField), method));
  1753.                 error = PK_ERR;  /* GRR:  should be passed on up via SetEAs() */
  1754.             }
  1755.             break;
  1756.     }
  1757.  
  1758.     G.inptr = old_inptr;
  1759.     G.incnt = old_incnt;
  1760.     G.mem_mode = FALSE;
  1761.  
  1762.     if (!error) {
  1763.         register ulg crcval = crc32(CRCVAL_INITIAL, tgt, (extent)G.outcnt);
  1764.  
  1765.         if (crcval != extra_field_crc) {
  1766.             if (G.tflag)
  1767.                 error = PK_ERR | (DEFLATED << 8);  /* kludge for now */
  1768.             else {
  1769.                 Info(slide, 0x401, ((char *)slide,
  1770.                   LoadFarString(BadExtraFieldCRC), G.zipfn, crcval,
  1771.                   extra_field_crc));
  1772.                 error = PK_ERR;
  1773.             }
  1774.         }
  1775.     }
  1776.     return error;
  1777.  
  1778. } /* end function memextract() */
  1779.  
  1780.  
  1781.  
  1782.  
  1783.  
  1784. /*************************/
  1785. /*  Function memflush()  */
  1786. /*************************/
  1787.  
  1788. int memflush(__G__ rawbuf, size)
  1789.     __GDEF
  1790.     uch *rawbuf;
  1791.     ulg size;
  1792. {
  1793.     if (size > G.outsize)
  1794.         return 50;   /* more data than output buffer can hold */
  1795.  
  1796.     memcpy((char *)G.outbufptr, (char *)rawbuf, (extent)size);
  1797.     G.outbufptr += (unsigned int)size;
  1798.     G.outsize -= size;
  1799.     G.outcnt += size;
  1800.  
  1801.     return 0;
  1802.  
  1803. } /* end function memflush() */
  1804.  
  1805.  
  1806.  
  1807.  
  1808.  
  1809. /*************************/
  1810. /*  Function fnfilter()  */        /* here instead of in list.c for SFX */
  1811. /*************************/
  1812.  
  1813. char *fnfilter(raw, space)         /* convert name to safely printable form */
  1814.     char *raw;
  1815.     uch *space;
  1816. {
  1817. #ifndef NATIVE   /* ASCII:  filter ANSI escape codes, etc. */
  1818.     uch *r=(uch *)raw, *s=space;
  1819.  
  1820.     while (*r) {
  1821. #ifdef QDOS
  1822.         if (qlflag & 2) {
  1823.             if (*r == '/' || *r == '.') {
  1824.                 ++r;
  1825.                 *s++ = '_';
  1826.                 continue;
  1827.             }
  1828.         } else
  1829. #endif
  1830.         if (*r < 32)
  1831.             *s++ = '^', *s++ = (uch)(64 + *r++);
  1832.         else
  1833.             *s++ = *r++;
  1834.     }
  1835.     *s = 0;
  1836.  
  1837. #ifdef WINDLL
  1838.     INTERN_TO_ISO((char *)space, (char *)space);  /* translate to ANSI */
  1839. #else
  1840. #ifdef WIN32
  1841.     if ( !IsWinNT() ) {
  1842.         /* Win95 console uses OEM character coding */
  1843.         INTERN_TO_OEM((char *)space, (char *)space);
  1844.     } else {
  1845.         /* >>>>> this guess has to be checked !!!! <<<<<< */
  1846.         /* WinNT console uses ISO character coding */
  1847.         INTERN_TO_ISO((char *)space, (char *)space);
  1848.     }
  1849. #endif /* WIN32 */
  1850. #endif /* ?WINDLL */
  1851.  
  1852.     return (char *)space;
  1853.  
  1854. #else /* NATIVE:  EBCDIC or whatever */
  1855.     return raw;
  1856. #endif
  1857.  
  1858. } /* end function fnfilter() */
  1859.  
  1860.  
  1861.  
  1862.  
  1863.  
  1864. #ifdef UNIX   /* must sort saved directories so can set perms from bottom up */
  1865.  
  1866. /************************/
  1867. /*  Function dircomp()  */
  1868. /************************/
  1869.  
  1870. static int dircomp(a, b)   /* used by qsort(); swiped from Zip */
  1871.     ZCONST zvoid *a, *b;
  1872. {
  1873.     /* order is significant:  this sorts in reverse order (deepest first) */
  1874.     return strcmp((*(dirtime **)b)->fn, (*(dirtime **)a)->fn);
  1875.  /* return namecmp((*(dirtime **)b)->fn, (*(dirtime **)a)->fn); */
  1876. }
  1877.  
  1878.  
  1879.  
  1880. #if 0   /* not used in Unix, but maybe for future OSes? */
  1881.  
  1882. /************************/
  1883. /*  Function namecmp()  */
  1884. /************************/
  1885.  
  1886. static int namecmp(s1, s2)   /* [not] used by dircomp(); swiped from Zip */
  1887.     ZCONST char *s1, *s2;
  1888. {
  1889.     int d;
  1890.  
  1891.     for (;;) {
  1892.         d = (int)(uch)case_map(*s1)
  1893.           - (int)(uch)case_map(*s2);
  1894.  
  1895.         if (d || *s1 == 0 || *s2 == 0)
  1896.             return d;
  1897.  
  1898.         s1++;
  1899.         s2++;
  1900.     }
  1901. }
  1902.  
  1903. #endif /* 0 */
  1904. #endif /* UNIX */
  1905.