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 
extract_or_test_files(__G)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     if (num_dirs > 0) {
657         sorted_dirlist = (direntry **)malloc(num_dirs*sizeof(direntry *));
658         if (sorted_dirlist == (direntry **)NULL) {
659             Info(slide, 0x401, ((char *)slide,
660               LoadFarString(DirlistSortNoMem)));
661             while (dirlist != (direntry *)NULL) {
662                 direntry *d = dirlist;
663 
664                 dirlist = dirlist->next;
665                 free(d);
666             }
667         } else {
668             ulg ndirs_fail = 0;
669 
670             if (num_dirs == 1)
671                 sorted_dirlist[0] = dirlist;
672             else {
673                 for (i = 0;  i < num_dirs;  ++i) {
674                     sorted_dirlist[i] = dirlist;
675                     dirlist = dirlist->next;
676                 }
677                 qsort((char *)sorted_dirlist, num_dirs, sizeof(direntry *),
678                   dircomp);
679             }
680 
681             Trace((stderr, "setting directory times/perms/attributes\n"));
682             for (i = 0;  i < num_dirs;  ++i) {
683                 direntry *d = sorted_dirlist[i];
684 
685                 Trace((stderr, "dir = %s\n", d->fn));
686                 if ((error = set_direc_attribs(__G__ d)) != PK_OK) {
687                     ndirs_fail++;
688                     Info(slide, 0x201, ((char *)slide,
689                       LoadFarString(DirlistSetAttrFailed), d->fn));
690                     if (!error_in_archive)
691                         error_in_archive = error;
692                 }
693                 free(d);
694             }
695             free(sorted_dirlist);
696             if (!uO.tflag && QCOND2) {
697                 if (ndirs_fail > 0)
698                     Info(slide, 0, ((char *)slide,
699                       LoadFarString(DirlistFailAttrSum), ndirs_fail));
700             }
701         }
702     }
703 #endif /* SET_DIR_ATTRIB */
704 
705 /*---------------------------------------------------------------------------
706     Check for unmatched filespecs on command line and print warning if any
707     found.  Free allocated memory.  (But suppress check when central dir
708     scan was interrupted prematurely.)
709   ---------------------------------------------------------------------------*/
710 
711     if (fn_matched) {
712         if (reached_end) for (i = 0;  i < G.filespecs;  ++i)
713             if (!fn_matched[i]) {
714 #ifdef DLL
715                 if (!G.redirect_data && !G.redirect_text)
716                     Info(slide, 0x401, ((char *)slide,
717                       LoadFarString(FilenameNotMatched), G.pfnames[i]));
718                 else
719                     setFileNotFound(__G);
720 #else
721                 Info(slide, 1, ((char *)slide,
722                   LoadFarString(FilenameNotMatched), G.pfnames[i]));
723 #endif
724                 if (error_in_archive <= PK_WARN)
725                     error_in_archive = PK_FIND;   /* some files not found */
726             }
727         free((zvoid *)fn_matched);
728     }
729     if (xn_matched) {
730         if (reached_end) for (i = 0;  i < G.xfilespecs;  ++i)
731             if (!xn_matched[i])
732                 Info(slide, 0x401, ((char *)slide,
733                   LoadFarString(ExclFilenameNotMatched), G.pxnames[i]));
734         free((zvoid *)xn_matched);
735     }
736 
737 /*---------------------------------------------------------------------------
738     Now, all locally allocated memory has been released.  When the central
739     directory processing has been interrupted prematurely, it is safe to
740     return immediately.  All completeness checks and summary messages are
741     skipped in this case.
742   ---------------------------------------------------------------------------*/
743     if (!reached_end)
744         return error_in_archive;
745 
746 /*---------------------------------------------------------------------------
747     Double-check that we're back at the end-of-central-directory record, and
748     print quick summary of results, if we were just testing the archive.  We
749     send the summary to stdout so that people doing the testing in the back-
750     ground and redirecting to a file can just do a "tail" on the output file.
751   ---------------------------------------------------------------------------*/
752 
753 #ifndef SFX
754     if (no_endsig_found) {                      /* just to make sure */
755         Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg)));
756         Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg)));
757         if (!error_in_archive)       /* don't overwrite stronger error */
758             error_in_archive = PK_WARN;
759     }
760 #endif /* !SFX */
761     if (uO.tflag) {
762         ulg num = filnum - num_bad_pwd;
763 
764         if (uO.qflag < 2) {        /* GRR 930710:  was (uO.qflag == 1) */
765             if (error_in_archive)
766                 Info(slide, 0, ((char *)slide, LoadFarString(ErrorInArchive),
767                   (error_in_archive == PK_WARN)? "warning-" : "", G.zipfn));
768             else if (num == 0L)
769                 Info(slide, 0, ((char *)slide, LoadFarString(ZeroFilesTested),
770                   G.zipfn));
771             else if (G.process_all_files && (num_skipped+num_bad_pwd == 0L))
772                 Info(slide, 0, ((char *)slide, LoadFarString(NoErrInCompData),
773                   G.zipfn));
774             else
775                 Info(slide, 0, ((char *)slide, LoadFarString(NoErrInTestedFiles)
776                   , G.zipfn, num, (num==1L)? "":"s"));
777             if (num_skipped > 0L)
778                 Info(slide, 0, ((char *)slide, LoadFarString(FilesSkipped),
779                   num_skipped, (num_skipped==1L)? "":"s"));
780 #if CRYPT
781             if (num_bad_pwd > 0L)
782                 Info(slide, 0, ((char *)slide, LoadFarString(FilesSkipBadPasswd)
783                   , num_bad_pwd, (num_bad_pwd==1L)? "":"s"));
784 #endif /* CRYPT */
785         }
786     }
787 
788     /* give warning if files not tested or extracted (first condition can still
789      * happen if zipfile is empty and no files specified on command line) */
790 
791     if ((filnum == 0) && error_in_archive <= PK_WARN) {
792         if (num_skipped > 0L)
793             error_in_archive = IZ_UNSUP; /* unsupport. compression/encryption */
794         else
795             error_in_archive = PK_FIND;  /* no files found at all */
796     }
797 #if CRYPT
798     else if ((filnum == num_bad_pwd) && error_in_archive <= PK_WARN)
799         error_in_archive = IZ_BADPWD;    /* bad passwd => all files skipped */
800 #endif
801     else if ((num_skipped > 0L) && error_in_archive <= PK_WARN)
802         error_in_archive = IZ_UNSUP;     /* was PK_WARN; Jean-loup complained */
803 #if CRYPT
804     else if ((num_bad_pwd > 0L) && !error_in_archive)
805         error_in_archive = PK_WARN;
806 #endif
807 
808     return error_in_archive;
809 
810 } /* end function extract_or_test_files() */
811 
812 
813 
814 
815 
816 /***************************/
817 /*  Function store_info()  */
818 /***************************/
819 
store_info(__G)820 static int store_info(__G)   /* return 0 if skipping, 1 if OK */
821     __GDEF
822 {
823 #ifdef USE_BZIP2
824 #  define UNKN_BZ2 (G.crec.compression_method!=BZIPPED)
825 #else
826 #  define UNKN_BZ2 TRUE       /* bzip2 unknown */
827 #endif
828 
829 #ifdef USE_LZMA
830 #  define UNKN_LZMA (G.crec.compression_method!=LZMAED)
831 #else
832 #  define UNKN_LZMA TRUE      /* LZMA unknown */
833 #endif
834 
835 #ifdef USE_WAVP
836 #  define UNKN_WAVP (G.crec.compression_method!=WAVPACKED)
837 #else
838 #  define UNKN_WAVP TRUE      /* WavPack unknown */
839 #endif
840 
841 #ifdef USE_PPMD
842 #  define UNKN_PPMD (G.crec.compression_method!=PPMDED)
843 #else
844 #  define UNKN_PPMD TRUE      /* PPMd unknown */
845 #endif
846 
847 #ifdef SFX
848 #  ifdef USE_DEFLATE64
849 #    define UNKN_COMPR \
850      (G.crec.compression_method!=STORED && G.crec.compression_method<DEFLATED \
851       && G.crec.compression_method>ENHDEFLATED \
852       && UNKN_BZ2 && UNKN_LZMA && UNKN_WAVP && UNKN_PPMD)
853 #  else
854 #    define UNKN_COMPR \
855      (G.crec.compression_method!=STORED && G.crec.compression_method!=DEFLATED\
856       && UNKN_BZ2 && UNKN_LZMA && UNKN_WAVP && UNKN_PPMD)
857 #  endif
858 #else
859 #  ifdef COPYRIGHT_CLEAN  /* no reduced files */
860 #    define UNKN_RED (G.crec.compression_method >= REDUCED1 && \
861                       G.crec.compression_method <= REDUCED4)
862 #  else
863 #    define UNKN_RED  FALSE  /* reducing not unknown */
864 #  endif
865 #  ifdef LZW_CLEAN  /* no shrunk files */
866 #    define UNKN_SHR (G.crec.compression_method == SHRUNK)
867 #  else
868 #    define UNKN_SHR  FALSE  /* unshrinking not unknown */
869 #  endif
870 #  ifdef USE_DEFLATE64
871 #    define UNKN_COMPR (UNKN_RED || UNKN_SHR || \
872      G.crec.compression_method==TOKENIZED || \
873      (G.crec.compression_method>ENHDEFLATED && UNKN_BZ2 && UNKN_LZMA \
874       && UNKN_WAVP && UNKN_PPMD))
875 #  else
876 #    define UNKN_COMPR (UNKN_RED || UNKN_SHR || \
877      G.crec.compression_method==TOKENIZED || \
878      (G.crec.compression_method>DEFLATED && UNKN_BZ2 && UNKN_LZMA \
879       && UNKN_WAVP && UNKN_PPMD))
880 #  endif
881 #endif
882 
883 #if (defined(USE_BZIP2) && (UNZIP_VERSION < UNZIP_BZ2VERS))
884     int unzvers_support = (UNKN_BZ2 ? UNZIP_VERSION : UNZIP_BZ2VERS);
885 #   define UNZVERS_SUPPORT  unzvers_support
886 #else
887 #   define UNZVERS_SUPPORT  UNZIP_VERSION
888 #endif
889 
890 /*---------------------------------------------------------------------------
891     Check central directory info for version/compatibility requirements.
892   ---------------------------------------------------------------------------*/
893 
894     G.pInfo->encrypted = G.crec.general_purpose_bit_flag & 1;   /* bit field */
895     G.pInfo->ExtLocHdr = (G.crec.general_purpose_bit_flag & 8) == 8;  /* bit */
896     G.pInfo->textfile = G.crec.internal_file_attributes & 1;    /* bit field */
897     G.pInfo->crc = G.crec.crc32;
898     G.pInfo->compr_size = G.crec.csize;
899     G.pInfo->uncompr_size = G.crec.ucsize;
900 
901     switch (uO.aflag) {
902         case 0:
903             G.pInfo->textmode = FALSE;   /* bit field */
904             break;
905         case 1:
906             G.pInfo->textmode = G.pInfo->textfile;   /* auto-convert mode */
907             break;
908         default:  /* case 2: */
909             G.pInfo->textmode = TRUE;
910             break;
911     }
912 
913     if (G.crec.version_needed_to_extract[1] == VMS_) {
914         if (G.crec.version_needed_to_extract[0] > VMS_UNZIP_VERSION) {
915             if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))
916                 Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg),
917                   FnFilter1(G.filename), "VMS",
918                   G.crec.version_needed_to_extract[0] / 10,
919                   G.crec.version_needed_to_extract[0] % 10,
920                   VMS_UNZIP_VERSION / 10, VMS_UNZIP_VERSION % 10));
921             return 0;
922         }
923 #ifndef VMS   /* won't be able to use extra field, but still have data */
924         else if (!uO.tflag && !IS_OVERWRT_ALL) { /* if -o, extract anyway */
925             Info(slide, 0x481, ((char *)slide, LoadFarString(VMSFormatQuery),
926               FnFilter1(G.filename)));
927             fgets(G.answerbuf, sizeof(G.answerbuf), stdin);
928             if ((*G.answerbuf != 'y') && (*G.answerbuf != 'Y'))
929                 return 0;
930         }
931 #endif /* !VMS */
932     /* usual file type:  don't need VMS to extract */
933     } else if (G.crec.version_needed_to_extract[0] > UNZVERS_SUPPORT) {
934         if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))
935             Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg),
936               FnFilter1(G.filename), "PK",
937               G.crec.version_needed_to_extract[0] / 10,
938               G.crec.version_needed_to_extract[0] % 10,
939               UNZVERS_SUPPORT / 10, UNZVERS_SUPPORT % 10));
940         return 0;
941     }
942 
943     if (UNKN_COMPR) {
944         if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) {
945 #ifndef SFX
946             unsigned cmpridx;
947 
948             if ((cmpridx = find_compr_idx(G.crec.compression_method))
949                 < NUM_METHODS)
950                 Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgName),
951                   FnFilter1(G.filename),
952                   LoadFarStringSmall(ComprNames[cmpridx])));
953             else
954 #endif
955                 Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgNum),
956                   FnFilter1(G.filename),
957                   G.crec.compression_method));
958         }
959         return 0;
960     }
961 #if (!CRYPT)
962     if (G.pInfo->encrypted) {
963         if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))
964             Info(slide, 0x401, ((char *)slide, LoadFarString(SkipEncrypted),
965               FnFilter1(G.filename)));
966         return 0;
967     }
968 #endif /* !CRYPT */
969 
970 #ifndef SFX
971     /* store a copy of the central header filename for later comparison */
972     if ((G.pInfo->cfilname = zfmalloc(strlen(G.filename) + 1)) == NULL) {
973         Info(slide, 0x401, ((char *)slide, LoadFarString(WarnNoMemCFName),
974           FnFilter1(G.filename)));
975     } else
976         zfstrcpy(G.pInfo->cfilname, G.filename);
977 #endif /* !SFX */
978 
979     /* map whatever file attributes we have into the local format */
980     mapattr(__G);   /* GRR:  worry about return value later */
981 
982     G.pInfo->diskstart = G.crec.disk_number_start;
983     G.pInfo->offset = (zoff_t)G.crec.relative_offset_local_header;
984     return 1;
985 
986 } /* end function store_info() */
987 
988 
989 
990 
991 
992 #ifndef SFX
993 /*******************************/
994 /*  Function find_compr_idx()  */
995 /*******************************/
996 
find_compr_idx(compr_methodnum)997 unsigned find_compr_idx(compr_methodnum)
998     unsigned compr_methodnum;
999 {
1000     unsigned i;
1001 
1002     for (i = 0; i < NUM_METHODS; i++) {
1003         if (ComprIDs[i] == compr_methodnum) break;
1004     }
1005     return i;
1006 }
1007 #endif /* !SFX */
1008 
1009 
1010 
1011 
1012 
1013 /******************************************/
1014 /*  Function extract_or_test_entrylist()  */
1015 /******************************************/
1016 
1017 static int extract_or_test_entrylist(__G__ numchunk,
1018                 pfilnum, pnum_bad_pwd, pold_extra_bytes,
1019 #ifdef SET_DIR_ATTRIB
1020                 pnum_dirs, pdirlist,
1021 #endif
1022                 error_in_archive)    /* return PK-type error code */
1023     __GDEF
1024     unsigned numchunk;
1025     ulg *pfilnum;
1026     ulg *pnum_bad_pwd;
1027     zoff_t *pold_extra_bytes;
1028 #ifdef SET_DIR_ATTRIB
1029     unsigned *pnum_dirs;
1030     direntry **pdirlist;
1031 #endif
1032     int error_in_archive;
1033 {
1034     unsigned i;
1035     int renamed, query;
1036     int skip_entry;
1037     zoff_t bufstart, inbuf_offset, request;
1038     int error, errcode;
1039 
1040 /* possible values for local skip_entry flag: */
1041 #define SKIP_NO         0       /* do not skip this entry */
1042 #define SKIP_Y_EXISTING 1       /* skip this entry, do not overwrite file */
1043 #define SKIP_Y_NONEXIST 2       /* skip this entry, do not create new file */
1044 
1045     /*-----------------------------------------------------------------------
1046         Second loop:  process files in current block, extracting or testing
1047         each one.
1048       -----------------------------------------------------------------------*/
1049 
1050     for (i = 0; i < numchunk; ++i) {
1051         (*pfilnum)++;   /* *pfilnum = i + blknum*DIR_BLKSIZ + 1; */
1052         G.pInfo = &G.info[i];
1053 #ifdef NOVELL_BUG_FAILSAFE
1054         G.dne = FALSE;  /* assume file exists until stat() says otherwise */
1055 #endif
1056 
1057         /* if the target position is not within the current input buffer
1058          * (either haven't yet read far enough, or (maybe) skipping back-
1059          * ward), skip to the target position and reset readbuf(). */
1060 
1061         /* seek_zipf(__G__ pInfo->offset);  */
1062         request = G.pInfo->offset + G.extra_bytes;
1063         inbuf_offset = request % INBUFSIZ;
1064         bufstart = request - inbuf_offset;
1065 
1066         Trace((stderr, "\ndebug: request = %ld, inbuf_offset = %ld\n",
1067           (long)request, (long)inbuf_offset));
1068         Trace((stderr,
1069           "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n",
1070           (long)bufstart, (long)G.cur_zipfile_bufstart));
1071         if (request < 0) {
1072             Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(SeekMsg),
1073               G.zipfn, LoadFarString(ReportMsg)));
1074             error_in_archive = PK_ERR;
1075             if (*pfilnum == 1 && G.extra_bytes != 0L) {
1076                 Info(slide, 0x401, ((char *)slide,
1077                   LoadFarString(AttemptRecompensate)));
1078                 *pold_extra_bytes = G.extra_bytes;
1079                 G.extra_bytes = 0L;
1080                 request = G.pInfo->offset;  /* could also check if != 0 */
1081                 inbuf_offset = request % INBUFSIZ;
1082                 bufstart = request - inbuf_offset;
1083                 Trace((stderr, "debug: request = %ld, inbuf_offset = %ld\n",
1084                   (long)request, (long)inbuf_offset));
1085                 Trace((stderr,
1086                   "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n",
1087                   (long)bufstart, (long)G.cur_zipfile_bufstart));
1088                 /* try again */
1089                 if (request < 0) {
1090                     Trace((stderr,
1091                       "debug: recompensated request still < 0\n"));
1092                     Info(slide, 0x401, ((char *)slide,
1093                       LoadFarStringSmall(SeekMsg),
1094                       G.zipfn, LoadFarString(ReportMsg)));
1095                     error_in_archive = PK_BADERR;
1096                     continue;
1097                 }
1098             } else {
1099                 error_in_archive = PK_BADERR;
1100                 continue;  /* this one hosed; try next */
1101             }
1102         }
1103 
1104         if (bufstart != G.cur_zipfile_bufstart) {
1105             Trace((stderr, "debug: bufstart != cur_zipfile_bufstart\n"));
1106 #ifdef USE_STRM_INPUT
1107             zfseeko(G.zipfd, bufstart, SEEK_SET);
1108             G.cur_zipfile_bufstart = zftello(G.zipfd);
1109 #else /* !USE_STRM_INPUT */
1110             G.cur_zipfile_bufstart =
1111               zlseek(G.zipfd, bufstart, SEEK_SET);
1112 #endif /* ?USE_STRM_INPUT */
1113             if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) <= 0)
1114             {
1115                 Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg),
1116                   *pfilnum, "lseek", (long)bufstart));
1117                 error_in_archive = PK_BADERR;
1118                 continue;   /* can still do next file */
1119             }
1120             G.inptr = G.inbuf + (int)inbuf_offset;
1121             G.incnt -= (int)inbuf_offset;
1122         } else {
1123             G.incnt += (int)(G.inptr-G.inbuf) - (int)inbuf_offset;
1124             G.inptr = G.inbuf + (int)inbuf_offset;
1125         }
1126 
1127         /* should be in proper position now, so check for sig */
1128         if (readbuf(__G__ G.sig, 4) == 0) {  /* bad offset */
1129             Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg),
1130               *pfilnum, "EOF", (long)request));
1131             error_in_archive = PK_BADERR;
1132             continue;   /* but can still try next one */
1133         }
1134         if (memcmp(G.sig, local_hdr_sig, 4)) {
1135             Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg),
1136               *pfilnum, LoadFarStringSmall(LocalHdrSig), (long)request));
1137             /*
1138                 GRRDUMP(G.sig, 4)
1139                 GRRDUMP(local_hdr_sig, 4)
1140              */
1141             error_in_archive = PK_ERR;
1142             if ((*pfilnum == 1 && G.extra_bytes != 0L) ||
1143                 (G.extra_bytes == 0L && *pold_extra_bytes != 0L)) {
1144                 Info(slide, 0x401, ((char *)slide,
1145                   LoadFarString(AttemptRecompensate)));
1146                 if (G.extra_bytes) {
1147                     *pold_extra_bytes = G.extra_bytes;
1148                     G.extra_bytes = 0L;
1149                 } else
1150                     G.extra_bytes = *pold_extra_bytes; /* third attempt */
1151                 if (((error = seek_zipf(__G__ G.pInfo->offset)) != PK_OK) ||
1152                     (readbuf(__G__ G.sig, 4) == 0)) {  /* bad offset */
1153                     if (error != PK_BADERR)
1154                       Info(slide, 0x401, ((char *)slide,
1155                         LoadFarString(OffsetMsg), *pfilnum, "EOF",
1156                         (long)request));
1157                     error_in_archive = PK_BADERR;
1158                     continue;   /* but can still try next one */
1159                 }
1160                 if (memcmp(G.sig, local_hdr_sig, 4)) {
1161                     Info(slide, 0x401, ((char *)slide,
1162                       LoadFarString(OffsetMsg), *pfilnum,
1163                       LoadFarStringSmall(LocalHdrSig), (long)request));
1164                     error_in_archive = PK_BADERR;
1165                     continue;
1166                 }
1167             } else
1168                 continue;  /* this one hosed; try next */
1169         }
1170         if ((error = process_local_file_hdr(__G)) != PK_COOL) {
1171             Info(slide, 0x421, ((char *)slide, LoadFarString(BadLocalHdr),
1172               *pfilnum));
1173             error_in_archive = error;   /* only PK_EOF defined */
1174             continue;   /* can still try next one */
1175         }
1176 #if (!defined(SFX) && defined(UNICODE_SUPPORT))
1177         if (((G.lrec.general_purpose_bit_flag & (1 << 11)) == (1 << 11))
1178             != (G.pInfo->GPFIsUTF8 != 0)) {
1179             if (QCOND2) {
1180 #  ifdef SMALL_MEM
1181                 char *temp_cfilnam = slide + (7 * (WSIZE>>3));
1182 
1183                 zfstrcpy((char Far *)temp_cfilnam, G.pInfo->cfilname);
1184 #    define  cFile_PrintBuf  temp_cfilnam
1185 #  else
1186 #    define  cFile_PrintBuf  G.pInfo->cfilname
1187 #  endif
1188                 Info(slide, 0x421, ((char *)slide,
1189                   LoadFarStringSmall2(GP11FlagsDiffer),
1190                   *pfilnum, FnFilter1(cFile_PrintBuf), G.pInfo->GPFIsUTF8));
1191 #  undef    cFile_PrintBuf
1192             }
1193             if (error_in_archive < PK_WARN)
1194                 error_in_archive = PK_WARN;
1195         }
1196 #endif /* !SFX && UNICODE_SUPPORT */
1197         if ((error = do_string(__G__ G.lrec.filename_length, DS_FN_L)) !=
1198              PK_COOL)
1199         {
1200             if (error > error_in_archive)
1201                 error_in_archive = error;
1202             if (error > PK_WARN) {
1203                 Info(slide, 0x401, ((char *)slide, LoadFarString(FilNamMsg),
1204                   FnFilter1(G.filename), "local"));
1205                 continue;   /* go on to next one */
1206             }
1207         }
1208         if (G.extra_field != (uch *)NULL) {
1209             free(G.extra_field);
1210             G.extra_field = (uch *)NULL;
1211         }
1212         if ((error =
1213              do_string(__G__ G.lrec.extra_field_length, EXTRA_FIELD)) != 0)
1214         {
1215             if (error > error_in_archive)
1216                 error_in_archive = error;
1217             if (error > PK_WARN) {
1218                 Info(slide, 0x401, ((char *)slide,
1219                   LoadFarString(ExtFieldMsg),
1220                   FnFilter1(G.filename), "local"));
1221                 continue;   /* go on */
1222             }
1223         }
1224 #ifndef SFX
1225         /* Filename consistency checks must come after reading in the local
1226          * extra field, so that a UTF-8 entry name e.f. block has already
1227          * been processed.
1228          */
1229         if (G.pInfo->cfilname != (char Far *)NULL) {
1230             if (zfstrcmp(G.pInfo->cfilname, G.filename) != 0) {
1231 #  ifdef SMALL_MEM
1232                 char *temp_cfilnam = slide + (7 * (WSIZE>>3));
1233 
1234                 zfstrcpy((char Far *)temp_cfilnam, G.pInfo->cfilname);
1235 #    define  cFile_PrintBuf  temp_cfilnam
1236 #  else
1237 #    define  cFile_PrintBuf  G.pInfo->cfilname
1238 #  endif
1239                 Info(slide, 0x401, ((char *)slide,
1240                   LoadFarStringSmall2(LvsCFNamMsg),
1241                   FnFilter2(cFile_PrintBuf), FnFilter1(G.filename)));
1242 #  undef    cFile_PrintBuf
1243                 zfstrcpy(G.filename, G.pInfo->cfilname);
1244                 if (error_in_archive < PK_WARN)
1245                     error_in_archive = PK_WARN;
1246             }
1247             zffree(G.pInfo->cfilname);
1248             G.pInfo->cfilname = (char Far *)NULL;
1249         }
1250 #endif /* !SFX */
1251         /* Size consistency checks must come after reading in the local extra
1252          * field, so that any Zip64 extension local e.f. block has already
1253          * been processed.
1254          */
1255         if (G.lrec.compression_method == STORED) {
1256             zusz_t csiz_decrypted = G.lrec.csize;
1257 
1258             if (G.pInfo->encrypted)
1259                 csiz_decrypted -= 12;
1260             if (G.lrec.ucsize != csiz_decrypted) {
1261                 Info(slide, 0x401, ((char *)slide,
1262                   LoadFarStringSmall2(WrnStorUCSizCSizDiff),
1263                   FnFilter1(G.filename),
1264                   FmZofft(G.lrec.ucsize, NULL, "u"),
1265                   FmZofft(csiz_decrypted, NULL, "u")));
1266                 G.lrec.ucsize = csiz_decrypted;
1267                 if (error_in_archive < PK_WARN)
1268                     error_in_archive = PK_WARN;
1269             }
1270         }
1271 
1272 #if CRYPT
1273         if (G.pInfo->encrypted &&
1274             (error = decrypt(__G__ uO.pwdarg)) != PK_COOL) {
1275             if (error == PK_WARN) {
1276                 if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))
1277                     Info(slide, 0x401, ((char *)slide,
1278                       LoadFarString(SkipIncorrectPasswd),
1279                       FnFilter1(G.filename)));
1280                 ++(*pnum_bad_pwd);
1281             } else {  /* (error > PK_WARN) */
1282                 if (error > error_in_archive)
1283                     error_in_archive = error;
1284                 Info(slide, 0x401, ((char *)slide,
1285                   LoadFarString(SkipCannotGetPasswd),
1286                   FnFilter1(G.filename)));
1287             }
1288             continue;   /* go on to next file */
1289         }
1290 #endif /* CRYPT */
1291 
1292         /*
1293          * just about to extract file:  if extracting to disk, check if
1294          * already exists, and if so, take appropriate action according to
1295          * fflag/uflag/overwrite_all/etc. (we couldn't do this in upper
1296          * loop because we don't store the possibly renamed filename[] in
1297          * info[])
1298          */
1299 #ifdef DLL
1300         if (!uO.tflag && !uO.cflag && !G.redirect_data)
1301 #else
1302         if (!uO.tflag && !uO.cflag)
1303 #endif
1304         {
1305             renamed = FALSE;   /* user hasn't renamed output file yet */
1306 
1307 startover:
1308             query = FALSE;
1309             skip_entry = SKIP_NO;
1310             /* for files from DOS FAT, check for use of backslash instead
1311              *  of slash as directory separator (bug in some zipper(s); so
1312              *  far, not a problem in HPFS, NTFS or VFAT systems)
1313              */
1314 #ifndef SFX
1315             if (G.pInfo->hostnum == FS_FAT_ && !MBSCHR(G.filename, '/')) {
1316                 char *p=G.filename;
1317 
1318                 if (*p) do {
1319                     if (*p == '\\') {
1320                         if (!G.reported_backslash) {
1321                             Info(slide, 0x21, ((char *)slide,
1322                               LoadFarString(BackslashPathSep), G.zipfn));
1323                             G.reported_backslash = TRUE;
1324                             if (!error_in_archive)
1325                                 error_in_archive = PK_WARN;
1326                         }
1327                         *p = '/';
1328                     }
1329                 } while (*PREINCSTR(p));
1330             }
1331 #endif /* !SFX */
1332 
1333             if (!renamed) {
1334                /* remove absolute path specs */
1335                if (G.filename[0] == '/') {
1336                    Info(slide, 0x401, ((char *)slide,
1337                         LoadFarString(AbsolutePathWarning),
1338                         FnFilter1(G.filename)));
1339                    if (!error_in_archive)
1340                        error_in_archive = PK_WARN;
1341                    do {
1342                        char *p = G.filename + 1;
1343                        do {
1344                            *(p-1) = *p;
1345                        } while (*p++ != '\0');
1346                    } while (G.filename[0] == '/');
1347                }
1348             }
1349 
1350             /* mapname can create dirs if not freshening or if renamed */
1351             error = mapname(__G__ renamed);
1352             if ((errcode = error & ~MPN_MASK) != PK_OK &&
1353                 error_in_archive < errcode)
1354                 error_in_archive = errcode;
1355             if ((errcode = error & MPN_MASK) > MPN_INF_TRUNC) {
1356                 if (errcode == MPN_CREATED_DIR) {
1357 #ifdef SET_DIR_ATTRIB
1358                     direntry *d_entry;
1359 
1360                     error = defer_dir_attribs(__G__ &d_entry);
1361                     if (d_entry == (direntry *)NULL) {
1362                         /* There may be no dir_attribs info available, or
1363                          * we have encountered a mem allocation error.
1364                          * In case of an error, report it and set program
1365                          * error state to warning level.
1366                          */
1367                         if (error) {
1368                             Info(slide, 0x401, ((char *)slide,
1369                                  LoadFarString(DirlistEntryNoMem)));
1370                             if (!error_in_archive)
1371                                 error_in_archive = PK_WARN;
1372                         }
1373                     } else {
1374                         d_entry->next = (*pdirlist);
1375                         (*pdirlist) = d_entry;
1376                         ++(*pnum_dirs);
1377                     }
1378 #endif /* SET_DIR_ATTRIB */
1379                 } else if (errcode == MPN_VOL_LABEL) {
1380 #ifdef DOS_OS2_W32
1381                     Info(slide, 0x401, ((char *)slide,
1382                       LoadFarString(SkipVolumeLabel),
1383                       FnFilter1(G.filename),
1384                       uO.volflag? "hard disk " : ""));
1385 #else
1386                     Info(slide, 1, ((char *)slide,
1387                       LoadFarString(SkipVolumeLabel),
1388                       FnFilter1(G.filename), ""));
1389 #endif
1390                 } else if (errcode > MPN_INF_SKIP &&
1391                            error_in_archive < PK_ERR)
1392                     error_in_archive = PK_ERR;
1393                 Trace((stderr, "mapname(%s) returns error code = %d\n",
1394                   FnFilter1(G.filename), error));
1395                 continue;   /* go on to next file */
1396             }
1397 
1398 #ifdef QDOS
1399             QFilename(__G__ G.filename);
1400 #endif
1401             switch (check_for_newer(__G__ G.filename)) {
1402                 case DOES_NOT_EXIST:
1403 #ifdef NOVELL_BUG_FAILSAFE
1404                     G.dne = TRUE;   /* stat() says file DOES NOT EXIST */
1405 #endif
1406                     /* freshen (no new files): skip unless just renamed */
1407                     if (uO.fflag && !renamed)
1408                         skip_entry = SKIP_Y_NONEXIST;
1409                     break;
1410                 case EXISTS_AND_OLDER:
1411 #ifdef UNIXBACKUP
1412                     if (!uO.B_flag)
1413 #endif
1414                     {
1415                         if (IS_OVERWRT_NONE)
1416                             /* never overwrite:  skip file */
1417                             skip_entry = SKIP_Y_EXISTING;
1418                         else if (!IS_OVERWRT_ALL)
1419                             query = TRUE;
1420                     }
1421                     break;
1422                 case EXISTS_AND_NEWER:             /* (or equal) */
1423 #ifdef UNIXBACKUP
1424                     if ((!uO.B_flag && IS_OVERWRT_NONE) ||
1425 #else
1426                     if (IS_OVERWRT_NONE ||
1427 #endif
1428                         (uO.uflag && !renamed)) {
1429                         /* skip if update/freshen & orig name */
1430                         skip_entry = SKIP_Y_EXISTING;
1431                     } else {
1432 #ifdef UNIXBACKUP
1433                         if (!IS_OVERWRT_ALL && !uO.B_flag)
1434 #else
1435                         if (!IS_OVERWRT_ALL)
1436 #endif
1437                             query = TRUE;
1438                     }
1439                     break;
1440             }
1441 #ifdef VMS
1442             /* 2008-07-24 SMS.
1443              * On VMS, if the file name includes a version number,
1444              * and "-V" ("retain VMS version numbers", V_flag) is in
1445              * effect, then the VMS-specific code will handle any
1446              * conflicts with an existing file, making this query
1447              * redundant.  (Implicit "y" response here.)
1448              */
1449             if (query && uO.V_flag) {
1450                 /* Not discarding file versions.  Look for one. */
1451                 int cndx = strlen(G.filename) - 1;
1452 
1453                 while ((cndx > 0) && (isdigit(G.filename[cndx])))
1454                     cndx--;
1455                 if (G.filename[cndx] == ';')
1456                     /* File version found; skip the generic query,
1457                      * proceeding with its default response "y".
1458                      */
1459                     query = FALSE;
1460             }
1461 #endif /* VMS */
1462             if (query) {
1463 #ifdef WINDLL
1464                 switch (G.lpUserFunctions->replace != NULL ?
1465                         (*G.lpUserFunctions->replace)(G.filename, FILNAMSIZ) :
1466                         IDM_REPLACE_NONE) {
1467                     case IDM_REPLACE_RENAME:
1468                         _ISO_INTERN(G.filename);
1469                         renamed = TRUE;
1470                         goto startover;
1471                     case IDM_REPLACE_ALL:
1472                         G.overwrite_mode = OVERWRT_ALWAYS;
1473                         /* FALL THROUGH, extract */
1474                     case IDM_REPLACE_YES:
1475                         break;
1476                     case IDM_REPLACE_NONE:
1477                         G.overwrite_mode = OVERWRT_NEVER;
1478                         /* FALL THROUGH, skip */
1479                     case IDM_REPLACE_NO:
1480                         skip_entry = SKIP_Y_EXISTING;
1481                         break;
1482                 }
1483 #else /* !WINDLL */
1484                 extent fnlen;
1485 reprompt:
1486                 Info(slide, 0x81, ((char *)slide,
1487                   LoadFarString(ReplaceQuery),
1488                   FnFilter1(G.filename)));
1489                 if (fgets(G.answerbuf, sizeof(G.answerbuf), stdin)
1490                     == (char *)NULL) {
1491                     Info(slide, 1, ((char *)slide,
1492                       LoadFarString(AssumeNone)));
1493                     *G.answerbuf = 'N';
1494                     if (!error_in_archive)
1495                         error_in_archive = 1;  /* not extracted:  warning */
1496                 }
1497                 switch (*G.answerbuf) {
1498                     case 'r':
1499                     case 'R':
1500                         do {
1501                             Info(slide, 0x81, ((char *)slide,
1502                               LoadFarString(NewNameQuery)));
1503                             fgets(G.filename, FILNAMSIZ, stdin);
1504                             /* usually get \n here:  better check for it */
1505                             fnlen = strlen(G.filename);
1506                             if (lastchar(G.filename, fnlen) == '\n')
1507                                 G.filename[--fnlen] = '\0';
1508                         } while (fnlen == 0);
1509 #ifdef WIN32  /* WIN32 fgets( ... , stdin) returns OEM coded strings */
1510                         _OEM_INTERN(G.filename);
1511 #endif
1512                         renamed = TRUE;
1513                         goto startover;   /* sorry for a goto */
1514                     case 'A':   /* dangerous option:  force caps */
1515                         G.overwrite_mode = OVERWRT_ALWAYS;
1516                         /* FALL THROUGH, extract */
1517                     case 'y':
1518                     case 'Y':
1519                         break;
1520                     case 'N':
1521                         G.overwrite_mode = OVERWRT_NEVER;
1522                         /* FALL THROUGH, skip */
1523                     case 'n':
1524                         /* skip file */
1525                         skip_entry = SKIP_Y_EXISTING;
1526                         break;
1527                     case '\n':
1528                     case '\r':
1529                         /* Improve echo of '\n' and/or '\r'
1530                            (sizeof(G.answerbuf) == 10 (see globals.h), so
1531                            there is enough space for the provided text...) */
1532                         strcpy(G.answerbuf, "{ENTER}");
1533                         /* fall through ... */
1534                     default:
1535                         /* usually get \n here:  remove it for nice display
1536                            (fnlen can be re-used here, we are outside the
1537                            "enter new filename" loop) */
1538                         fnlen = strlen(G.answerbuf);
1539                         if (lastchar(G.answerbuf, fnlen) == '\n')
1540                             G.answerbuf[--fnlen] = '\0';
1541                         Info(slide, 1, ((char *)slide,
1542                           LoadFarString(InvalidResponse), G.answerbuf));
1543                         goto reprompt;   /* yet another goto? */
1544                 } /* end switch (*answerbuf) */
1545 #endif /* ?WINDLL */
1546             } /* end if (query) */
1547             if (skip_entry != SKIP_NO) {
1548 #ifdef WINDLL
1549                 if (skip_entry == SKIP_Y_EXISTING) {
1550                     /* report skipping of an existing entry */
1551                     Info(slide, 0, ((char *)slide,
1552                       ((IS_OVERWRT_NONE || !uO.uflag || renamed) ?
1553                        "Target file exists.  Skipping %s\n" :
1554                        "Target file newer.  Skipping %s\n"),
1555                       FnFilter1(G.filename)));
1556                 }
1557 #endif /* WINDLL */
1558                 continue;
1559             }
1560         } /* end if (extracting to disk) */
1561 
1562 #ifdef DLL
1563         if ((G.statreportcb != NULL) &&
1564             (*G.statreportcb)(__G__ UZ_ST_START_EXTRACT, G.zipfn,
1565                               G.filename, NULL)) {
1566             return IZ_CTRLC;        /* cancel operation by user request */
1567         }
1568 #endif
1569 #ifdef MACOS  /* MacOS is no preemptive OS, thus call event-handling by hand */
1570         UserStop();
1571 #endif
1572 #ifdef AMIGA
1573         G.filenote_slot = i;
1574 #endif
1575         G.disk_full = 0;
1576         if ((error = extract_or_test_member(__G)) != PK_COOL) {
1577             if (error > error_in_archive)
1578                 error_in_archive = error;       /* ...and keep going */
1579 #ifdef DLL
1580             if (G.disk_full > 1 || error_in_archive == IZ_CTRLC) {
1581 #else
1582             if (G.disk_full > 1) {
1583 #endif
1584                 return error_in_archive;        /* (unless disk full) */
1585             }
1586         }
1587 #ifdef DLL
1588         if ((G.statreportcb != NULL) &&
1589             (*G.statreportcb)(__G__ UZ_ST_FINISH_MEMBER, G.zipfn,
1590                               G.filename, (zvoid *)&G.lrec.ucsize)) {
1591             return IZ_CTRLC;        /* cancel operation by user request */
1592         }
1593 #endif
1594 #ifdef MACOS  /* MacOS is no preemptive OS, thus call event-handling by hand */
1595         UserStop();
1596 #endif
1597     } /* end for-loop (i:  files in current block) */
1598 
1599     return error_in_archive;
1600 
1601 } /* end function extract_or_test_entrylist() */
1602 
1603 
1604 
1605 
1606 
1607 /* wsize is used in extract_or_test_member() and UZbunzip2() */
1608 #if (defined(DLL) && !defined(NO_SLIDE_REDIR))
1609 #  define wsize G._wsize    /* wsize is a variable */
1610 #else
1611 #  define wsize WSIZE       /* wsize is a constant */
1612 #endif
1613 
1614 /***************************************/
1615 /*  Function extract_or_test_member()  */
1616 /***************************************/
1617 
extract_or_test_member(__G)1618 static int extract_or_test_member(__G)    /* return PK-type error code */
1619      __GDEF
1620 {
1621     char *nul="[empty] ", *txt="[text]  ", *bin="[binary]";
1622 #ifdef CMS_MVS
1623     char *ebc="[ebcdic]";
1624 #endif
1625     register int b;
1626     int r, error=PK_COOL;
1627 
1628 
1629 /*---------------------------------------------------------------------------
1630     Initialize variables, buffers, etc.
1631   ---------------------------------------------------------------------------*/
1632 
1633     G.bits_left = 0;
1634     G.bitbuf = 0L;       /* unreduce and unshrink only */
1635     G.zipeof = 0;
1636     G.newfile = TRUE;
1637     G.crc32val = CRCVAL_INITIAL;
1638 
1639 #ifdef SYMLINKS
1640     /* If file is a (POSIX-compatible) symbolic link and we are extracting
1641      * to disk, prepare to restore the link. */
1642     G.symlnk = (G.pInfo->symlink &&
1643                 !uO.tflag && !uO.cflag && (G.lrec.ucsize > 0));
1644 #endif /* SYMLINKS */
1645 
1646     if (uO.tflag) {
1647         if (!uO.qflag)
1648             Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), "test",
1649               FnFilter1(G.filename), "", ""));
1650     } else {
1651 #ifdef DLL
1652         if (uO.cflag && !G.redirect_data)
1653 #else
1654         if (uO.cflag)
1655 #endif
1656         {
1657 #if (defined(OS2) && defined(__IBMC__) && (__IBMC__ >= 200))
1658             G.outfile = freopen("", "wb", stdout);   /* VAC++ ignores setmode */
1659 #else
1660             G.outfile = stdout;
1661 #endif
1662 #ifdef DOS_FLX_NLM_OS2_W32
1663 #if (defined(__HIGHC__) && !defined(FLEXOS))
1664             setmode(G.outfile, _BINARY);
1665 #else /* !(defined(__HIGHC__) && !defined(FLEXOS)) */
1666             setmode(fileno(G.outfile), O_BINARY);
1667 #endif /* ?(defined(__HIGHC__) && !defined(FLEXOS)) */
1668 #           define NEWLINE "\r\n"
1669 #else /* !DOS_FLX_NLM_OS2_W32 */
1670 #           define NEWLINE "\n"
1671 #endif /* ?DOS_FLX_NLM_OS2_W32 */
1672 #ifdef VMS
1673             /* VMS:  required even for stdout! */
1674             if ((r = open_outfile(__G)) != 0)
1675                 switch (r) {
1676                   case OPENOUT_SKIPOK:
1677                     return PK_OK;
1678                   case OPENOUT_SKIPWARN:
1679                     return PK_WARN;
1680                   default:
1681                     return PK_DISK;
1682                 }
1683         } else if ((r = open_outfile(__G)) != 0)
1684             switch (r) {
1685               case OPENOUT_SKIPOK:
1686                 return PK_OK;
1687               case OPENOUT_SKIPWARN:
1688                 return PK_WARN;
1689               default:
1690                 return PK_DISK;
1691             }
1692 #else /* !VMS */
1693         } else if (open_outfile(__G))
1694             return PK_DISK;
1695 #endif /* ?VMS */
1696     }
1697 
1698 /*---------------------------------------------------------------------------
1699     Unpack the file.
1700   ---------------------------------------------------------------------------*/
1701 
1702     defer_leftover_input(__G);    /* so NEXTBYTE bounds check will work */
1703     switch (G.lrec.compression_method) {
1704         case STORED:
1705             if (!uO.tflag && QCOND2) {
1706 #ifdef SYMLINKS
1707                 if (G.symlnk)   /* can also be deflated, but rarer... */
1708                     Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
1709                       "link", FnFilter1(G.filename), "", ""));
1710                 else
1711 #endif /* SYMLINKS */
1712                 Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
1713                   "extract", FnFilter1(G.filename),
1714                   (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
1715                   "" : (G.lrec.ucsize == 0L? nul : (G.pInfo->textfile? txt :
1716                   bin)), uO.cflag? NEWLINE : ""));
1717             }
1718 #if (defined(DLL) && !defined(NO_SLIDE_REDIR))
1719             if (G.redirect_slide) {
1720                 wsize = G.redirect_size; redirSlide = G.redirect_buffer;
1721             } else {
1722                 wsize = WSIZE; redirSlide = slide;
1723             }
1724 #endif
1725             G.outptr = redirSlide;
1726             G.outcnt = 0L;
1727             while ((b = NEXTBYTE) != EOF) {
1728                 *G.outptr++ = (uch)b;
1729                 if (++G.outcnt == wsize) {
1730                     error = flush(__G__ redirSlide, G.outcnt, 0);
1731                     G.outptr = redirSlide;
1732                     G.outcnt = 0L;
1733                     if (error != PK_COOL || G.disk_full) break;
1734                 }
1735             }
1736             if (G.outcnt) {        /* flush final (partial) buffer */
1737                 r = flush(__G__ redirSlide, G.outcnt, 0);
1738                 if (error < r) error = r;
1739             }
1740             break;
1741 
1742 #ifndef SFX
1743 #ifndef LZW_CLEAN
1744         case SHRUNK:
1745             if (!uO.tflag && QCOND2) {
1746                 Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
1747                   LoadFarStringSmall(Unshrink), FnFilter1(G.filename),
1748                   (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
1749                   "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : ""));
1750             }
1751             if ((r = unshrink(__G)) != PK_COOL) {
1752                 if (r < PK_DISK) {
1753                     if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
1754                         Info(slide, 0x401, ((char *)slide,
1755                           LoadFarStringSmall(ErrUnzipFile), r == PK_MEM3 ?
1756                           LoadFarString(NotEnoughMem) :
1757                           LoadFarString(InvalidComprData),
1758                           LoadFarStringSmall2(Unshrink),
1759                           FnFilter1(G.filename)));
1760                     else
1761                         Info(slide, 0x401, ((char *)slide,
1762                           LoadFarStringSmall(ErrUnzipNoFile), r == PK_MEM3 ?
1763                           LoadFarString(NotEnoughMem) :
1764                           LoadFarString(InvalidComprData),
1765                           LoadFarStringSmall2(Unshrink)));
1766                 }
1767                 error = r;
1768             }
1769             break;
1770 #endif /* !LZW_CLEAN */
1771 
1772 #ifndef COPYRIGHT_CLEAN
1773         case REDUCED1:
1774         case REDUCED2:
1775         case REDUCED3:
1776         case REDUCED4:
1777             if (!uO.tflag && QCOND2) {
1778                 Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
1779                   "unreduc", FnFilter1(G.filename),
1780                   (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
1781                   "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : ""));
1782             }
1783             if ((r = unreduce(__G)) != PK_COOL) {
1784                 /* unreduce() returns only PK_COOL, PK_DISK, or IZ_CTRLC */
1785                 error = r;
1786             }
1787             break;
1788 #endif /* !COPYRIGHT_CLEAN */
1789 
1790         case IMPLODED:
1791             if (!uO.tflag && QCOND2) {
1792                 Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
1793                   "explod", FnFilter1(G.filename),
1794                   (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
1795                   "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : ""));
1796             }
1797             if ((r = explode(__G)) != 0) {
1798                 if (r == 5) { /* treat 5 specially */
1799                     int warning = ((zusz_t)G.used_csize <= G.lrec.csize);
1800 
1801                     if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
1802                         Info(slide, 0x401, ((char *)slide,
1803                           LoadFarString(LengthMsg),
1804                           "", warning ? "warning" : "error",
1805                           FmZofft(G.used_csize, NULL, NULL),
1806                           FmZofft(G.lrec.ucsize, NULL, "u"),
1807                           warning ? "  " : "",
1808                           FmZofft(G.lrec.csize, NULL, "u"),
1809                           " [", FnFilter1(G.filename), "]"));
1810                     else
1811                         Info(slide, 0x401, ((char *)slide,
1812                           LoadFarString(LengthMsg),
1813                           "\n", warning ? "warning" : "error",
1814                           FmZofft(G.used_csize, NULL, NULL),
1815                           FmZofft(G.lrec.ucsize, NULL, "u"),
1816                           warning ? "  " : "",
1817                           FmZofft(G.lrec.csize, NULL, "u"),
1818                           "", "", "."));
1819                     error = warning ? PK_WARN : PK_ERR;
1820                 } else if (r < PK_DISK) {
1821                     if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
1822                         Info(slide, 0x401, ((char *)slide,
1823                           LoadFarStringSmall(ErrUnzipFile), r == 3?
1824                           LoadFarString(NotEnoughMem) :
1825                           LoadFarString(InvalidComprData),
1826                           LoadFarStringSmall2(Explode),
1827                           FnFilter1(G.filename)));
1828                     else
1829                         Info(slide, 0x401, ((char *)slide,
1830                           LoadFarStringSmall(ErrUnzipNoFile), r == 3?
1831                           LoadFarString(NotEnoughMem) :
1832                           LoadFarString(InvalidComprData),
1833                           LoadFarStringSmall2(Explode)));
1834                     error = ((r == 3) ? PK_MEM3 : PK_ERR);
1835                 } else {
1836                     error = r;
1837                 }
1838             }
1839             break;
1840 #endif /* !SFX */
1841 
1842         case DEFLATED:
1843 #ifdef USE_DEFLATE64
1844         case ENHDEFLATED:
1845 #endif
1846             if (!uO.tflag && QCOND2) {
1847                 Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
1848                   "inflat", FnFilter1(G.filename),
1849                   (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
1850                   "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : ""));
1851             }
1852 #ifndef USE_ZLIB  /* zlib's function is called inflate(), too */
1853 #  define UZinflate inflate
1854 #endif
1855             if ((r = UZinflate(__G__
1856                                (G.lrec.compression_method == ENHDEFLATED)))
1857                 != 0) {
1858                 if (r < PK_DISK) {
1859                     if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
1860                         Info(slide, 0x401, ((char *)slide,
1861                           LoadFarStringSmall(ErrUnzipFile), r == 3?
1862                           LoadFarString(NotEnoughMem) :
1863                           LoadFarString(InvalidComprData),
1864                           LoadFarStringSmall2(Inflate),
1865                           FnFilter1(G.filename)));
1866                     else
1867                         Info(slide, 0x401, ((char *)slide,
1868                           LoadFarStringSmall(ErrUnzipNoFile), r == 3?
1869                           LoadFarString(NotEnoughMem) :
1870                           LoadFarString(InvalidComprData),
1871                           LoadFarStringSmall2(Inflate)));
1872                     error = ((r == 3) ? PK_MEM3 : PK_ERR);
1873                 } else {
1874                     error = r;
1875                 }
1876             }
1877             break;
1878 
1879 #ifdef USE_BZIP2
1880         case BZIPPED:
1881             if (!uO.tflag && QCOND2) {
1882                 Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
1883                   "bunzipp", FnFilter1(G.filename),
1884                   (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
1885                   "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : ""));
1886             }
1887             if ((r = UZbunzip2(__G)) != 0) {
1888                 if (r < PK_DISK) {
1889                     if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
1890                         Info(slide, 0x401, ((char *)slide,
1891                           LoadFarStringSmall(ErrUnzipFile), r == 3?
1892                           LoadFarString(NotEnoughMem) :
1893                           LoadFarString(InvalidComprData),
1894                           LoadFarStringSmall2(BUnzip),
1895                           FnFilter1(G.filename)));
1896                     else
1897                         Info(slide, 0x401, ((char *)slide,
1898                           LoadFarStringSmall(ErrUnzipNoFile), r == 3?
1899                           LoadFarString(NotEnoughMem) :
1900                           LoadFarString(InvalidComprData),
1901                           LoadFarStringSmall2(BUnzip)));
1902                     error = ((r == 3) ? PK_MEM3 : PK_ERR);
1903                 } else {
1904                     error = r;
1905                 }
1906             }
1907             break;
1908 #endif /* USE_BZIP2 */
1909 
1910         default:   /* should never get to this point */
1911             Info(slide, 0x401, ((char *)slide,
1912               LoadFarString(FileUnknownCompMethod), FnFilter1(G.filename)));
1913             /* close and delete file before return? */
1914             undefer_input(__G);
1915             return PK_WARN;
1916 
1917     } /* end switch (compression method) */
1918 
1919 /*---------------------------------------------------------------------------
1920     Close the file and set its date and time (not necessarily in that order),
1921     and make sure the CRC checked out OK.  Logical-AND the CRC for 64-bit
1922     machines (redundant on 32-bit machines).
1923   ---------------------------------------------------------------------------*/
1924 
1925 #ifdef VMS                  /* VMS:  required even for stdout! (final flush) */
1926     if (!uO.tflag)           /* don't close NULL file */
1927         close_outfile(__G);
1928 #else
1929 #ifdef DLL
1930     if (!uO.tflag && (!uO.cflag || G.redirect_data)) {
1931         if (G.redirect_data)
1932             FINISH_REDIRECT();
1933         else
1934             close_outfile(__G);
1935     }
1936 #else
1937     if (!uO.tflag && !uO.cflag)   /* don't close NULL file or stdout */
1938         close_outfile(__G);
1939 #endif
1940 #endif /* VMS */
1941 
1942             /* GRR: CONVERT close_outfile() TO NON-VOID:  CHECK FOR ERRORS! */
1943 
1944 
1945     if (G.disk_full) {            /* set by flush() */
1946         if (G.disk_full > 1) {
1947 #if (defined(DELETE_IF_FULL) && defined(HAVE_UNLINK))
1948             /* delete the incomplete file if we can */
1949             if (unlink(G.filename) != 0)
1950                 Trace((stderr, "extract.c:  could not delete %s\n",
1951                   FnFilter1(G.filename)));
1952 #else
1953             /* warn user about the incomplete file */
1954             Info(slide, 0x421, ((char *)slide, LoadFarString(FileTruncated),
1955               FnFilter1(G.filename)));
1956 #endif
1957             error = PK_DISK;
1958         } else {
1959             error = PK_WARN;
1960         }
1961     }
1962 
1963     if (error > PK_WARN) {/* don't print redundant CRC error if error already */
1964         undefer_input(__G);
1965         return error;
1966     }
1967     if (G.crc32val != G.lrec.crc32) {
1968         /* if quiet enough, we haven't output the filename yet:  do it */
1969         if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
1970             Info(slide, 0x401, ((char *)slide, "%-22s ",
1971               FnFilter1(G.filename)));
1972         Info(slide, 0x401, ((char *)slide, LoadFarString(BadCRC), G.crc32val,
1973           G.lrec.crc32));
1974 #if CRYPT
1975         if (G.pInfo->encrypted)
1976             Info(slide, 0x401, ((char *)slide, LoadFarString(MaybeBadPasswd)));
1977 #endif
1978         error = PK_ERR;
1979     } else if (uO.tflag) {
1980 #ifndef SFX
1981         if (G.extra_field) {
1982             if ((r = TestExtraField(__G__ G.extra_field,
1983                                     G.lrec.extra_field_length)) > error)
1984                 error = r;
1985         } else
1986 #endif /* !SFX */
1987         if (!uO.qflag)
1988             Info(slide, 0, ((char *)slide, " OK\n"));
1989     } else {
1990         if (QCOND2 && !error)   /* GRR:  is stdout reset to text mode yet? */
1991             Info(slide, 0, ((char *)slide, "\n"));
1992     }
1993 
1994     undefer_input(__G);
1995     return error;
1996 
1997 } /* end function extract_or_test_member() */
1998 
1999 
2000 
2001 
2002 
2003 #ifndef SFX
2004 
2005 /*******************************/
2006 /*  Function TestExtraField()  */
2007 /*******************************/
2008 
2009 static int TestExtraField(__G__ ef, ef_len)
2010     __GDEF
2011     uch *ef;
2012     unsigned ef_len;
2013 {
2014     ush ebID;
2015     unsigned ebLen;
2016     unsigned eb_cmpr_offs = 0;
2017     int r;
2018 
2019     /* we know the regular compressed file data tested out OK, or else we
2020      * wouldn't be here ==> print filename if any extra-field errors found
2021      */
2022     while (ef_len >= EB_HEADSIZE) {
2023         ebID = makeword(ef);
2024         ebLen = (unsigned)makeword(ef+EB_LEN);
2025 
2026         if (ebLen > (ef_len - EB_HEADSIZE)) {
2027            /* Discovered some extra field inconsistency! */
2028             if (uO.qflag)
2029                 Info(slide, 1, ((char *)slide, "%-22s ",
2030                   FnFilter1(G.filename)));
2031             Info(slide, 1, ((char *)slide, LoadFarString(InconsistEFlength),
2032               ebLen, (ef_len - EB_HEADSIZE)));
2033             return PK_ERR;
2034         }
2035 
2036         switch (ebID) {
2037             case EF_OS2:
2038             case EF_ACL:
2039             case EF_MAC3:
2040             case EF_BEOS:
2041             case EF_ATHEOS:
2042                 switch (ebID) {
2043                   case EF_OS2:
2044                   case EF_ACL:
2045                     eb_cmpr_offs = EB_OS2_HLEN;
2046                     break;
2047                   case EF_MAC3:
2048                     if (ebLen >= EB_MAC3_HLEN &&
2049                         (makeword(ef+(EB_HEADSIZE+EB_FLGS_OFFS))
2050                          & EB_M3_FL_UNCMPR) &&
2051                         (makelong(ef+EB_HEADSIZE) == ebLen - EB_MAC3_HLEN))
2052                         eb_cmpr_offs = 0;
2053                     else
2054                         eb_cmpr_offs = EB_MAC3_HLEN;
2055                     break;
2056                   case EF_BEOS:
2057                   case EF_ATHEOS:
2058                     if (ebLen >= EB_BEOS_HLEN &&
2059                         (*(ef+(EB_HEADSIZE+EB_FLGS_OFFS)) & EB_BE_FL_UNCMPR) &&
2060                         (makelong(ef+EB_HEADSIZE) == ebLen - EB_BEOS_HLEN))
2061                         eb_cmpr_offs = 0;
2062                     else
2063                         eb_cmpr_offs = EB_BEOS_HLEN;
2064                     break;
2065                 }
2066                 if ((r = test_compr_eb(__G__ ef, ebLen, eb_cmpr_offs, NULL))
2067                     != PK_OK) {
2068                     if (uO.qflag)
2069                         Info(slide, 1, ((char *)slide, "%-22s ",
2070                           FnFilter1(G.filename)));
2071                     switch (r) {
2072                         case IZ_EF_TRUNC:
2073                             Info(slide, 1, ((char *)slide,
2074                               LoadFarString(TruncEAs),
2075                               ebLen-(eb_cmpr_offs+EB_CMPRHEADLEN), "\n"));
2076                             break;
2077                         case PK_ERR:
2078                             Info(slide, 1, ((char *)slide,
2079                               LoadFarString(InvalidComprDataEAs)));
2080                             break;
2081                         case PK_MEM3:
2082                         case PK_MEM4:
2083                             Info(slide, 1, ((char *)slide,
2084                               LoadFarString(NotEnoughMemEAs)));
2085                             break;
2086                         default:
2087                             if ((r & 0xff) != PK_ERR)
2088                                 Info(slide, 1, ((char *)slide,
2089                                   LoadFarString(UnknErrorEAs)));
2090                             else {
2091                                 ush m = (ush)(r >> 8);
2092                                 if (m == DEFLATED)            /* GRR KLUDGE! */
2093                                     Info(slide, 1, ((char *)slide,
2094                                       LoadFarString(BadCRC_EAs)));
2095                                 else
2096                                     Info(slide, 1, ((char *)slide,
2097                                       LoadFarString(UnknComprMethodEAs), m));
2098                             }
2099                             break;
2100                     }
2101                     return r;
2102                 }
2103                 break;
2104 
2105             case EF_NTSD:
2106                 Trace((stderr, "ebID: %i / ebLen: %u\n", ebID, ebLen));
2107                 r = ebLen < EB_NTSD_L_LEN ? IZ_EF_TRUNC :
2108                     ((ef[EB_HEADSIZE+EB_NTSD_VERSION] > EB_NTSD_MAX_VER) ?
2109                      (PK_WARN | 0x4000) :
2110                      test_compr_eb(__G__ ef, ebLen, EB_NTSD_L_LEN, TEST_NTSD));
2111                 if (r != PK_OK) {
2112                     if (uO.qflag)
2113                         Info(slide, 1, ((char *)slide, "%-22s ",
2114                           FnFilter1(G.filename)));
2115                     switch (r) {
2116                         case IZ_EF_TRUNC:
2117                             Info(slide, 1, ((char *)slide,
2118                               LoadFarString(TruncNTSD),
2119                               ebLen-(EB_NTSD_L_LEN+EB_CMPRHEADLEN), "\n"));
2120                             break;
2121 #if (defined(WIN32) && defined(NTSD_EAS))
2122                         case PK_WARN:
2123                             Info(slide, 1, ((char *)slide,
2124                               LoadFarString(InvalidSecurityEAs)));
2125                             break;
2126 #endif
2127                         case PK_ERR:
2128                             Info(slide, 1, ((char *)slide,
2129                               LoadFarString(InvalidComprDataEAs)));
2130                             break;
2131                         case PK_MEM3:
2132                         case PK_MEM4:
2133                             Info(slide, 1, ((char *)slide,
2134                               LoadFarString(NotEnoughMemEAs)));
2135                             break;
2136                         case (PK_WARN | 0x4000):
2137                             Info(slide, 1, ((char *)slide,
2138                               LoadFarString(UnsuppNTSDVersEAs),
2139                               (int)ef[EB_HEADSIZE+EB_NTSD_VERSION]));
2140                             r = PK_WARN;
2141                             break;
2142                         default:
2143                             if ((r & 0xff) != PK_ERR)
2144                                 Info(slide, 1, ((char *)slide,
2145                                   LoadFarString(UnknErrorEAs)));
2146                             else {
2147                                 ush m = (ush)(r >> 8);
2148                                 if (m == DEFLATED)            /* GRR KLUDGE! */
2149                                     Info(slide, 1, ((char *)slide,
2150                                       LoadFarString(BadCRC_EAs)));
2151                                 else
2152                                     Info(slide, 1, ((char *)slide,
2153                                       LoadFarString(UnknComprMethodEAs), m));
2154                             }
2155                             break;
2156                     }
2157                     return r;
2158                 }
2159                 break;
2160             case EF_PKVMS:
2161                 if (makelong(ef+EB_HEADSIZE) !=
2162                     crc32(CRCVAL_INITIAL, ef+(EB_HEADSIZE+4),
2163                           (extent)(ebLen-4)))
2164                     Info(slide, 1, ((char *)slide,
2165                       LoadFarString(BadCRC_EAs)));
2166                 break;
2167             case EF_PKW32:
2168             case EF_PKUNIX:
2169             case EF_ASIUNIX:
2170             case EF_IZVMS:
2171             case EF_IZUNIX:
2172             case EF_VMCMS:
2173             case EF_MVS:
2174             case EF_SPARK:
2175             case EF_TANDEM:
2176             case EF_THEOS:
2177             case EF_AV:
2178             default:
2179                 break;
2180         }
2181         ef_len -= (ebLen + EB_HEADSIZE);
2182         ef += (ebLen + EB_HEADSIZE);
2183     }
2184 
2185     if (!uO.qflag)
2186         Info(slide, 0, ((char *)slide, " OK\n"));
2187 
2188     return PK_COOL;
2189 
2190 } /* end function TestExtraField() */
2191 
2192 
2193 
2194 
2195 
2196 /******************************/
2197 /*  Function test_compr_eb()  */
2198 /******************************/
2199 
2200 #ifdef PROTO
test_compr_eb(__GPRO__ uch * eb,unsigned eb_size,unsigned compr_offset,int (* test_uc_ebdata)(__GPRO__ uch * eb,unsigned eb_size,uch * eb_ucptr,ulg eb_ucsize))2201 static int test_compr_eb(
2202     __GPRO__
2203     uch *eb,
2204     unsigned eb_size,
2205     unsigned compr_offset,
2206     int (*test_uc_ebdata)(__GPRO__ uch *eb, unsigned eb_size,
2207                           uch *eb_ucptr, ulg eb_ucsize))
2208 #else /* !PROTO */
2209 static int test_compr_eb(__G__ eb, eb_size, compr_offset, test_uc_ebdata)
2210     __GDEF
2211     uch *eb;
2212     unsigned eb_size;
2213     unsigned compr_offset;
2214     int (*test_uc_ebdata)();
2215 #endif /* ?PROTO */
2216 {
2217     ulg eb_ucsize;
2218     uch *eb_ucptr;
2219     int r;
2220 
2221     if (compr_offset < 4)                /* field is not compressed: */
2222         return PK_OK;                    /* do nothing and signal OK */
2223 
2224     if ((eb_size < (EB_UCSIZE_P + 4)) ||
2225         ((eb_ucsize = makelong(eb+(EB_HEADSIZE+EB_UCSIZE_P))) > 0L &&
2226          eb_size <= (compr_offset + EB_CMPRHEADLEN)))
2227         return IZ_EF_TRUNC;               /* no compressed data! */
2228 
2229     if (
2230 #ifdef INT_16BIT
2231         (((ulg)(extent)eb_ucsize) != eb_ucsize) ||
2232 #endif
2233         (eb_ucptr = (uch *)malloc((extent)eb_ucsize)) == (uch *)NULL)
2234         return PK_MEM4;
2235 
2236     r = memextract(__G__ eb_ucptr, eb_ucsize,
2237                    eb + (EB_HEADSIZE + compr_offset),
2238                    (ulg)(eb_size - compr_offset));
2239 
2240     if (r == PK_OK && test_uc_ebdata != NULL)
2241         r = (*test_uc_ebdata)(__G__ eb, eb_size, eb_ucptr, eb_ucsize);
2242 
2243     free(eb_ucptr);
2244     return r;
2245 
2246 } /* end function test_compr_eb() */
2247 
2248 #endif /* !SFX */
2249 
2250 
2251 
2252 
2253 
2254 /***************************/
2255 /*  Function memextract()  */
2256 /***************************/
2257 
2258 int memextract(__G__ tgt, tgtsize, src, srcsize)  /* extract compressed */
2259     __GDEF                                        /*  extra field block; */
2260     uch *tgt;                                     /*  return PK-type error */
2261     ulg tgtsize;                                  /*  level */
2262     ZCONST uch *src;
2263     ulg srcsize;
2264 {
2265     zoff_t old_csize=G.csize;
2266     uch   *old_inptr=G.inptr;
2267     int    old_incnt=G.incnt;
2268     int    r, error=PK_OK;
2269     ush    method;
2270     ulg    extra_field_crc;
2271 
2272 
2273     method = makeword(src);
2274     extra_field_crc = makelong(src+2);
2275 
2276     /* compressed extra field exists completely in memory at this location: */
2277     G.inptr = (uch *)src + (2 + 4);     /* method and extra_field_crc */
2278     G.incnt = (int)(G.csize = (long)(srcsize - (2 + 4)));
2279     G.mem_mode = TRUE;
2280     G.outbufptr = tgt;
2281     G.outsize = tgtsize;
2282 
2283     switch (method) {
2284         case STORED:
2285             memcpy((char *)tgt, (char *)G.inptr, (extent)G.incnt);
2286             G.outcnt = (ulg)G.csize;    /* for CRC calculation */
2287             break;
2288         case DEFLATED:
2289 #ifdef USE_DEFLATE64
2290         case ENHDEFLATED:
2291 #endif
2292             G.outcnt = 0L;
2293             if ((r = UZinflate(__G__ (method == ENHDEFLATED))) != 0) {
2294                 if (!uO.tflag)
2295                     Info(slide, 0x401, ((char *)slide,
2296                       LoadFarStringSmall(ErrUnzipNoFile), r == 3?
2297                       LoadFarString(NotEnoughMem) :
2298                       LoadFarString(InvalidComprData),
2299                       LoadFarStringSmall2(Inflate)));
2300                 error = (r == 3)? PK_MEM3 : PK_ERR;
2301             }
2302             if (G.outcnt == 0L)   /* inflate's final FLUSH sets outcnt */
2303                 break;
2304             break;
2305         default:
2306             if (uO.tflag)
2307                 error = PK_ERR | ((int)method << 8);
2308             else {
2309                 Info(slide, 0x401, ((char *)slide,
2310                   LoadFarString(UnsupportedExtraField), method));
2311                 error = PK_ERR;  /* GRR:  should be passed on up via SetEAs() */
2312             }
2313             break;
2314     }
2315 
2316     G.inptr = old_inptr;
2317     G.incnt = old_incnt;
2318     G.csize = old_csize;
2319     G.mem_mode = FALSE;
2320 
2321     if (!error) {
2322         register ulg crcval = crc32(CRCVAL_INITIAL, tgt, (extent)G.outcnt);
2323 
2324         if (crcval != extra_field_crc) {
2325             if (uO.tflag)
2326                 error = PK_ERR | (DEFLATED << 8);  /* kludge for now */
2327             else {
2328                 Info(slide, 0x401, ((char *)slide,
2329                   LoadFarString(BadExtraFieldCRC), G.zipfn, crcval,
2330                   extra_field_crc));
2331                 error = PK_ERR;
2332             }
2333         }
2334     }
2335     return error;
2336 
2337 } /* end function memextract() */
2338 
2339 
2340 
2341 
2342 
2343 /*************************/
2344 /*  Function memflush()  */
2345 /*************************/
2346 
2347 int memflush(__G__ rawbuf, size)
2348     __GDEF
2349     ZCONST uch *rawbuf;
2350     ulg size;
2351 {
2352     if (size > G.outsize)
2353         /* Here, PK_DISK is a bit off-topic, but in the sense of marking
2354            "overflow of output space", its use may be tolerated. */
2355         return PK_DISK;   /* more data than output buffer can hold */
2356 
2357 
2358 
2359     memcpy((char *)G.outbufptr, (char *)rawbuf, (extent)size);
2360     G.outbufptr += (unsigned int)size;
2361     G.outsize -= size;
2362     G.outcnt += size;
2363 
2364     return 0;
2365 
2366 } /* end function memflush() */
2367 
2368 
2369 
2370 
2371 
2372 #if (defined(VMS) || defined(VMS_TEXT_CONV))
2373 
2374 /************************************/
2375 /*  Function extract_izvms_block()  */
2376 /************************************/
2377 
2378 /*
2379  * Extracts block from p. If resulting length is less than needed, fill
2380  * extra space with corresponding bytes from 'init'.
2381  * Currently understands 3 formats of block compression:
2382  * - Simple storing
2383  * - Compression of zero bytes to zero bits
2384  * - Deflation (see memextract())
2385  * The IZVMS block data is returned in malloc'd space.
2386  */
2387 uch *extract_izvms_block(__G__ ebdata, size, retlen, init, needlen)
2388     __GDEF
2389     ZCONST uch *ebdata;
2390     unsigned size;
2391     unsigned *retlen;
2392     ZCONST uch *init;
2393     unsigned needlen;
2394 {
2395     uch *ucdata;       /* Pointer to block allocated */
2396     int cmptype;
2397     unsigned usiz, csiz;
2398 
2399     cmptype = (makeword(ebdata+EB_IZVMS_FLGS) & EB_IZVMS_BCMASK);
2400     csiz = size - EB_IZVMS_HLEN;
2401     usiz = (cmptype == EB_IZVMS_BCSTOR ?
2402             csiz : makeword(ebdata+EB_IZVMS_UCSIZ));
2403 
2404     if (retlen)
2405         *retlen = usiz;
2406 
2407     if ((ucdata = (uch *)malloc(MAX(needlen, usiz))) == NULL)
2408         return NULL;
2409 
2410     if (init && (usiz < needlen))
2411         memcpy((char *)ucdata, (ZCONST char *)init, needlen);
2412 
2413     switch (cmptype)
2414     {
2415         case EB_IZVMS_BCSTOR: /* The simplest case */
2416             memcpy(ucdata, ebdata+EB_IZVMS_HLEN, usiz);
2417             break;
2418         case EB_IZVMS_BC00:
2419             decompress_bits(ucdata, usiz, ebdata+EB_IZVMS_HLEN);
2420             break;
2421         case EB_IZVMS_BCDEFL:
2422             memextract(__G__ ucdata, (ulg)usiz,
2423                        ebdata+EB_IZVMS_HLEN, (ulg)csiz);
2424             break;
2425         default:
2426             free(ucdata);
2427             ucdata = NULL;
2428     }
2429     return ucdata;
2430 
2431 } /* end of extract_izvms_block */
2432 
2433 
2434 
2435 
2436 
2437 /********************************/
2438 /*  Function decompress_bits()  */
2439 /********************************/
2440 /*
2441  *  Simple uncompression routine. The compression uses bit stream.
2442  *  Compression scheme:
2443  *
2444  *  if (byte!=0)
2445  *      putbit(1),putbyte(byte)
2446  *  else
2447  *      putbit(0)
2448  */
decompress_bits(outptr,needlen,bitptr)2449 static void decompress_bits(outptr, needlen, bitptr)
2450     uch *outptr;        /* Pointer into output block */
2451     unsigned needlen;   /* Size of uncompressed block */
2452     ZCONST uch *bitptr; /* Pointer into compressed data */
2453 {
2454     ulg bitbuf = 0;
2455     int bitcnt = 0;
2456 
2457 #define _FILL   {       bitbuf |= (*bitptr++) << bitcnt;\
2458                         bitcnt += 8;                    \
2459                 }
2460 
2461     while (needlen--)
2462     {
2463         if (bitcnt <= 0)
2464             _FILL;
2465 
2466         if (bitbuf & 1)
2467         {
2468             bitbuf >>= 1;
2469             if ((bitcnt -= 1) < 8)
2470                 _FILL;
2471             *outptr++ = (uch)bitbuf;
2472             bitcnt -= 8;
2473             bitbuf >>= 8;
2474         }
2475         else
2476         {
2477             *outptr++ = '\0';
2478             bitcnt -= 1;
2479             bitbuf >>= 1;
2480         }
2481     }
2482 } /* end function decompress_bits() */
2483 
2484 #endif /* VMS || VMS_TEXT_CONV */
2485 
2486 
2487 
2488 
2489 
2490 #ifdef SYMLINKS
2491 /***********************************/
2492 /* Function set_deferred_symlink() */
2493 /***********************************/
2494 
2495 static void set_deferred_symlink(__G__ slnk_entry)
2496     __GDEF
2497     slinkentry *slnk_entry;
2498 {
2499     extent ucsize = slnk_entry->targetlen;
2500     char *linkfname = slnk_entry->fname;
2501     char *linktarget = (char *)malloc(ucsize+1);
2502 
2503     if (!linktarget) {
2504         Info(slide, 0x201, ((char *)slide,
2505           LoadFarString(SymLnkWarnNoMem), FnFilter1(linkfname)));
2506         return;
2507     }
2508     linktarget[ucsize] = '\0';
2509     G.outfile = zfopen(linkfname, FOPR); /* open link placeholder for reading */
2510     /* Check that the following conditions are all fulfilled:
2511      * a) the placeholder file exists,
2512      * b) the placeholder file contains exactly "ucsize" bytes
2513      *    (read the expected placeholder content length + 1 extra byte, this
2514      *    should return the expected content length),
2515      * c) the placeholder content matches the link target specification as
2516      *    stored in the symlink control structure.
2517      */
2518     if (!G.outfile ||
2519         fread(linktarget, 1, ucsize+1, G.outfile) != ucsize ||
2520         strcmp(slnk_entry->target, linktarget))
2521     {
2522         Info(slide, 0x201, ((char *)slide,
2523           LoadFarString(SymLnkWarnInvalid), FnFilter1(linkfname)));
2524         free(linktarget);
2525         if (G.outfile)
2526             fclose(G.outfile);
2527         return;
2528     }
2529     fclose(G.outfile);                  /* close "data" file for good... */
2530     unlink(linkfname);                  /* ...and delete it */
2531     if (QCOND2)
2532         Info(slide, 0, ((char *)slide, LoadFarString(SymLnkFinish),
2533           FnFilter1(linkfname), FnFilter2(linktarget)));
2534     if (symlink(linktarget, linkfname))  /* create the real link */
2535         perror("symlink error");
2536     free(linktarget);
2537 #ifdef SET_SYMLINK_ATTRIBS
2538     set_symlnk_attribs(__G__ slnk_entry);
2539 #endif
2540     return;                             /* can't set time on symlinks */
2541 
2542 } /* end function set_deferred_symlink() */
2543 #endif /* SYMLINKS */
2544 
2545 
2546 
2547 
2548 /*************************/
2549 /*  Function fnfilter()  */        /* here instead of in list.c for SFX */
2550 /*************************/
2551 
fnfilter(raw,space,size)2552 char *fnfilter(raw, space, size)   /* convert name to safely printable form */
2553     ZCONST char *raw;
2554     uch *space;
2555     extent size;
2556 {
2557 #ifndef NATIVE   /* ASCII:  filter ANSI escape codes, etc. */
2558     ZCONST uch *r=(ZCONST uch *)raw;
2559     uch *s=space;
2560     uch *slim=NULL;
2561     uch *se=NULL;
2562     int have_overflow = FALSE;
2563 
2564     if (size > 0) {
2565         slim = space + size
2566 #ifdef _MBCS
2567                      - (MB_CUR_MAX - 1)
2568 #endif
2569                      - 4;
2570     }
2571     while (*r) {
2572         if (size > 0 && s >= slim && se == NULL) {
2573             se = s;
2574         }
2575 #ifdef QDOS
2576         if (qlflag & 2) {
2577             if (*r == '/' || *r == '.') {
2578                 if (se != NULL && (s > (space + (size-3)))) {
2579                     have_overflow = TRUE;
2580                     break;
2581                 }
2582                 ++r;
2583                 *s++ = '_';
2584                 continue;
2585             }
2586         } else
2587 #endif
2588 #ifdef HAVE_WORKING_ISPRINT
2589 # ifndef UZ_FNFILTER_REPLACECHAR
2590     /* A convenient choice for the replacement of unprintable char codes is
2591      * the "single char wildcard", as this character is quite unlikely to
2592      * appear in filenames by itself.  The following default definition
2593      * sets the replacement char to a question mark as the most common
2594      * "single char wildcard"; this setting should be overridden in the
2595      * appropiate system-specific configuration header when needed.
2596      */
2597 #   define UZ_FNFILTER_REPLACECHAR      '?'
2598 # endif
2599         if (!isprint(*r)) {
2600             if (*r < 32) {
2601                 /* ASCII control codes are escaped as "^{letter}". */
2602                 if (se != NULL && (s > (space + (size-4)))) {
2603                     have_overflow = TRUE;
2604                     break;
2605                 }
2606                 *s++ = '^', *s++ = (uch)(64 + *r++);
2607             } else {
2608                 /* Other unprintable codes are replaced by the
2609                  * placeholder character. */
2610                 if (se != NULL && (s > (space + (size-3)))) {
2611                     have_overflow = TRUE;
2612                     break;
2613                 }
2614                 *s++ = UZ_FNFILTER_REPLACECHAR;
2615                 INCSTR(r);
2616             }
2617 #else /* !HAVE_WORKING_ISPRINT */
2618         if (*r < 32) {
2619             /* ASCII control codes are escaped as "^{letter}". */
2620             if (se != NULL && (s > (space + (size-4)))) {
2621                 have_overflow = TRUE;
2622                 break;
2623             }
2624             *s++ = '^', *s++ = (uch)(64 + *r++);
2625 #endif /* ?HAVE_WORKING_ISPRINT */
2626         } else {
2627 #ifdef _MBCS
2628             unsigned i = CLEN(r);
2629             if (se != NULL && (s > (space + (size-i-2)))) {
2630                 have_overflow = TRUE;
2631                 break;
2632             }
2633             for (; i > 0; i--)
2634                 *s++ = *r++;
2635 #else
2636             if (se != NULL && (s > (space + (size-3)))) {
2637                 have_overflow = TRUE;
2638                 break;
2639             }
2640             *s++ = *r++;
2641 #endif
2642          }
2643     }
2644     if (have_overflow) {
2645         strcpy((char *)se, "...");
2646     } else {
2647         *s = '\0';
2648     }
2649 
2650 #ifdef WINDLL
2651     INTERN_TO_ISO((char *)space, (char *)space);  /* translate to ANSI */
2652 #else
2653 #if (defined(WIN32) && !defined(_WIN32_WCE))
2654     /* Win9x console always uses OEM character coding, and
2655        WinNT console is set to OEM charset by default, too */
2656     INTERN_TO_OEM((char *)space, (char *)space);
2657 #endif /* (WIN32 && !_WIN32_WCE) */
2658 #endif /* ?WINDLL */
2659 
2660     return (char *)space;
2661 
2662 #else /* NATIVE:  EBCDIC or whatever */
2663     return (char *)raw;
2664 #endif
2665 
2666 } /* end function fnfilter() */
2667 
2668 
2669 
2670 
2671 #ifdef SET_DIR_ATTRIB
2672 /* must sort saved directories so can set perms from bottom up */
2673 
2674 /************************/
2675 /*  Function dircomp()  */
2676 /************************/
2677 
dircomp(a,b)2678 static int Cdecl dircomp(a, b)  /* used by qsort(); swiped from Zip */
2679     ZCONST zvoid *a, *b;
2680 {
2681     /* order is significant:  this sorts in reverse order (deepest first) */
2682     return strcmp((*(direntry **)b)->fn, (*(direntry **)a)->fn);
2683  /* return namecmp((*(direntry **)b)->fn, (*(direntry **)a)->fn); */
2684 }
2685 
2686 #endif /* SET_DIR_ATTRIB */
2687 
2688 
2689 #ifdef USE_BZIP2
2690 
2691 /**************************/
2692 /*  Function UZbunzip2()  */
2693 /**************************/
2694 
UZbunzip2(__G)2695 int UZbunzip2(__G)
2696 __GDEF
2697 /* decompress a bzipped entry using the libbz2 routines */
2698 {
2699     int retval = 0;     /* return code: 0 = "no error" */
2700     int err=BZ_OK;
2701     int repeated_buf_err;
2702     bz_stream bstrm;
2703 
2704 #if (defined(DLL) && !defined(NO_SLIDE_REDIR))
2705     if (G.redirect_slide)
2706         wsize = G.redirect_size, redirSlide = G.redirect_buffer;
2707     else
2708         wsize = WSIZE, redirSlide = slide;
2709 #endif
2710 
2711     bstrm.next_out = (char *)redirSlide;
2712     bstrm.avail_out = wsize;
2713 
2714     bstrm.next_in = (char *)G.inptr;
2715     bstrm.avail_in = G.incnt;
2716 
2717     {
2718         /* local buffer for efficiency */
2719         /* $TODO Check for BZIP LIB version? */
2720 
2721         bstrm.bzalloc = NULL;
2722         bstrm.bzfree = NULL;
2723         bstrm.opaque = NULL;
2724 
2725         Trace((stderr, "initializing bzlib()\n"));
2726         err = BZ2_bzDecompressInit(&bstrm, 0, 0);
2727 
2728         if (err == BZ_MEM_ERROR)
2729             return 3;
2730         else if (err != BZ_OK)
2731             Trace((stderr, "oops!  (BZ2_bzDecompressInit() err = %d)\n", err));
2732     }
2733 
2734 #ifdef FUNZIP
2735     while (err != BZ_STREAM_END) {
2736 #else /* !FUNZIP */
2737     while (G.csize > 0) {
2738         Trace((stderr, "first loop:  G.csize = %ld\n", G.csize));
2739 #endif /* ?FUNZIP */
2740         while (bstrm.avail_out > 0) {
2741             err = BZ2_bzDecompress(&bstrm);
2742 
2743             if (err == BZ_DATA_ERROR) {
2744                 retval = 2; goto uzbunzip_cleanup_exit;
2745             } else if (err == BZ_MEM_ERROR) {
2746                 retval = 3; goto uzbunzip_cleanup_exit;
2747             } else if (err != BZ_OK && err != BZ_STREAM_END)
2748                 Trace((stderr, "oops!  (bzip(first loop) err = %d)\n", err));
2749 
2750 #ifdef FUNZIP
2751             if (err == BZ_STREAM_END)    /* "END-of-entry-condition" ? */
2752 #else /* !FUNZIP */
2753             if (G.csize <= 0L)          /* "END-of-entry-condition" ? */
2754 #endif /* ?FUNZIP */
2755                 break;
2756 
2757             if (bstrm.avail_in == 0) {
2758                 if (fillinbuf(__G) == 0) {
2759                     /* no "END-condition" yet, but no more data */
2760                     retval = 2; goto uzbunzip_cleanup_exit;
2761                 }
2762 
2763                 bstrm.next_in = (char *)G.inptr;
2764                 bstrm.avail_in = G.incnt;
2765             }
2766             Trace((stderr, "     avail_in = %u\n", bstrm.avail_in));
2767         }
2768         /* flush slide[] */
2769         if ((retval = FLUSH(wsize - bstrm.avail_out)) != 0)
2770             goto uzbunzip_cleanup_exit;
2771         Trace((stderr, "inside loop:  flushing %ld bytes (ptr diff = %ld)\n",
2772           (long)(wsize - bstrm.avail_out),
2773           (long)(bstrm.next_out-(char *)redirSlide)));
2774         bstrm.next_out = (char *)redirSlide;
2775         bstrm.avail_out = wsize;
2776     }
2777 
2778     /* no more input, so loop until we have all output */
2779     Trace((stderr, "beginning final loop:  err = %d\n", err));
2780     repeated_buf_err = FALSE;
2781     while (err != BZ_STREAM_END) {
2782         err = BZ2_bzDecompress(&bstrm);
2783         if (err == BZ_DATA_ERROR) {
2784             retval = 2; goto uzbunzip_cleanup_exit;
2785         } else if (err == BZ_MEM_ERROR) {
2786             retval = 3; goto uzbunzip_cleanup_exit;
2787         } else if (err != BZ_OK && err != BZ_STREAM_END) {
2788             Trace((stderr, "oops!  (bzip(final loop) err = %d)\n", err));
2789             DESTROYGLOBALS();
2790             EXIT(PK_MEM3);
2791         }
2792         /* final flush of slide[] */
2793         if ((retval = FLUSH(wsize - bstrm.avail_out)) != 0)
2794             goto uzbunzip_cleanup_exit;
2795         Trace((stderr, "final loop:  flushing %ld bytes (ptr diff = %ld)\n",
2796           (long)(wsize - bstrm.avail_out),
2797           (long)(bstrm.next_out-(char *)redirSlide)));
2798         bstrm.next_out = (char *)redirSlide;
2799         bstrm.avail_out = wsize;
2800     }
2801 #ifdef LARGE_FILE_SUPPORT
2802     Trace((stderr, "total in = %llu, total out = %llu\n",
2803       (zusz_t)(bstrm.total_in_lo32) + ((zusz_t)(bstrm.total_in_hi32))<<32,
2804       (zusz_t)(bstrm.total_out_lo32) + ((zusz_t)(bstrm.total_out_hi32))<<32));
2805 #else
2806     Trace((stderr, "total in = %lu, total out = %lu\n", bstrm.total_in_lo32,
2807       bstrm.total_out_lo32));
2808 #endif
2809 
2810     G.inptr = (uch *)bstrm.next_in;
2811     G.incnt = (G.inbuf + INBUFSIZ) - G.inptr;  /* reset for other routines */
2812 
2813 uzbunzip_cleanup_exit:
2814     err = BZ2_bzDecompressEnd(&bstrm);
2815     if (err != BZ_OK)
2816         Trace((stderr, "oops!  (BZ2_bzDecompressEnd() err = %d)\n", err));
2817 
2818     return retval;
2819 } /* end function UZbunzip2() */
2820 #endif /* USE_BZIP2 */
2821