Subversion Repositories Kolibri OS

Rev

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

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