~ubuntu-branches/ubuntu/precise/unzip/precise-updates

1 by Santiago Vila
Import upstream version 5.51
1
/*
22 by Marc Deslauriers
* SECURITY UPDATE: CRC32 verification heap-based overflow
2
  Copyright (c) 1990-2014 Info-ZIP.  All rights reserved.
1 by Santiago Vila
Import upstream version 5.51
3
1.1.2 by Santiago Vila
Import upstream version 6.0
4
  See the accompanying file LICENSE, version 2009-Jan-02 or later
1 by Santiago Vila
Import upstream version 5.51
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()
1.1.2 by Santiago Vila
Import upstream version 6.0
19
             find_compr_idx()
1 by Santiago Vila
Import upstream version 5.51
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()
1.1.2 by Santiago Vila
Import upstream version 6.0
29
             dircomp()                (SET_DIR_ATTRIB only)
30
             UZbunzip2()              (USE_BZIP2 only)
1 by Santiago Vila
Import upstream version 5.51
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
1.1.2 by Santiago Vila
Import upstream version 6.0
45
#include "crc32.h"
1 by Santiago Vila
Import upstream version 5.51
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,
1.1.2 by Santiago Vila
Import upstream version 6.0
90
                ulg *pfilnum, ulg *pnum_bad_pwd, zoff_t *pold_extra_bytes,
1 by Santiago Vila
Import upstream version 5.51
91
                unsigned *pnum_dirs, direntry **pdirlist,
92
                int error_in_archive));
93
#else
94
static int extract_or_test_entrylist OF((__GPRO__ unsigned numchunk,
1.1.2 by Santiago Vila
Import upstream version 6.0
95
                ulg *pfilnum, ulg *pnum_bad_pwd, zoff_t *pold_extra_bytes,
1 by Santiago Vila
Import upstream version 5.51
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
1.1.1 by Florian Weimer
Import upstream version 5.52
114
   static int Cdecl dircomp OF((ZCONST zvoid *a, ZCONST zvoid *b));
1 by Santiago Vila
Import upstream version 5.51
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";
1.1.2 by Santiago Vila
Import upstream version 6.0
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";
1 by Santiago Vila
Import upstream version 5.51
144
   static ZCONST char Far *ComprNames[NUM_METHODS] = {
145
     CmprNone, CmprShrink, CmprReduce, CmprReduce, CmprReduce, CmprReduce,
1.1.2 by Santiago Vila
Import upstream version 6.0
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
1 by Santiago Vila
Import upstream version 5.51
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 */
1.1.2 by Santiago Vila
Import upstream version 6.0
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 */
1 by Santiago Vila
Import upstream version 5.51
170
static ZCONST char Far WrnStorUCSizCSizDiff[] =
1.1.2 by Santiago Vila
Import upstream version 6.0
171
  "%s:  ucsize %s <> csize %s for STORED entry\n\
1 by Santiago Vila
Import upstream version 5.51
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[] =
1.1.2 by Santiago Vila
Import upstream version 6.0
181
     "%s  %s:  %s bytes required to uncompress to %s bytes;\n    %s\
182
      supposed to require %s bytes%s%s%s\n";
1 by Santiago Vila
Import upstream version 5.51
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";
1.1.1 by Florian Weimer
Import upstream version 5.52
206
   static ZCONST char Far DirlistFailAttrSum[] =
1.1.2 by Santiago Vila
Import upstream version 6.0
207
     "     failed setting times/attribs for %lu dir entries";
1 by Santiago Vila
Import upstream version 5.51
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[] =
1.1.2 by Santiago Vila
Import upstream version 6.0
225
# ifdef VMS
226
     "new version of %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: ";
227
# else
1 by Santiago Vila
Import upstream version 5.51
228
     "replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: ";
1.1.2 by Santiago Vila
Import upstream version 6.0
229
# endif
230
   static ZCONST char Far AssumeNone[] =
231
     " NULL\n(EOF or read error, treating as \"[N]one\" ...)\n";
1 by Santiago Vila
Import upstream version 5.51
232
   static ZCONST char Far NewNameQuery[] = "new name: ";
1.1.2 by Santiago Vila
Import upstream version 6.0
233
   static ZCONST char Far InvalidResponse[] =
234
     "error:  invalid response [%s]\n";
1 by Santiago Vila
Import upstream version 5.51
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";
1.1.2 by Santiago Vila
Import upstream version 6.0
273
#ifdef USE_BZIP2
274
  static ZCONST char Far BUnzip[] = "bunzip";
275
#endif
1 by Santiago Vila
Import upstream version 5.51
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";
24 by Marc Deslauriers
* SECURITY UPDATE: heap overflow in charset_to_intern()
301
   static ZCONST char Far TooSmallEBlength[] = "bad extra-field entry:\n \
22 by Marc Deslauriers
* SECURITY UPDATE: CRC32 verification heap-based overflow
302
     EF block length (%u bytes) invalid (< %d)\n";
1 by Santiago Vila
Import upstream version 5.51
303
   static ZCONST char Far InvalidComprDataEAs[] =
304
     " invalid compressed data for EAs\n";
305
#  if (defined(WIN32) && defined(NTSD_EAS))
306
     static ZCONST char Far InvalidSecurityEAs[] =
307
       " EAs fail security check\n";
308
#  endif
309
   static ZCONST char Far UnsuppNTSDVersEAs[] =
310
     " unsupported NTSD EAs version %d\n";
311
   static ZCONST char Far BadCRC_EAs[] = " bad CRC for extended attributes\n";
312
   static ZCONST char Far UnknComprMethodEAs[] =
313
     " unknown compression method for EAs (%u)\n";
314
   static ZCONST char Far NotEnoughMemEAs[] =
315
     " out of memory while inflating EAs\n";
316
   static ZCONST char Far UnknErrorEAs[] =
317
     " unknown error on extended attributes\n";
318
#endif /* !SFX */
319
320
static ZCONST char Far UnsupportedExtraField[] =
321
  "\nerror:  unsupported extra-field compression type (%u)--skipping\n";
322
static ZCONST char Far BadExtraFieldCRC[] =
323
  "error [%s]:  bad extra-field CRC %08lx (should be %08lx)\n";
324
325
326
327
328
329
/**************************************/
330
/*  Function extract_or_test_files()  */
331
/**************************************/
332
333
int extract_or_test_files(__G)    /* return PK-type error code */
334
     __GDEF
335
{
336
    unsigned i, j;
1.1.2 by Santiago Vila
Import upstream version 6.0
337
    zoff_t cd_bufstart;
1 by Santiago Vila
Import upstream version 5.51
338
    uch *cd_inptr;
339
    int cd_incnt;
340
    ulg filnum=0L, blknum=0L;
1.1.2 by Santiago Vila
Import upstream version 6.0
341
    int reached_end;
342
#ifndef SFX
343
    int no_endsig_found;
344
#endif
1 by Santiago Vila
Import upstream version 5.51
345
    int error, error_in_archive=PK_COOL;
346
    int *fn_matched=NULL, *xn_matched=NULL;
1.1.2 by Santiago Vila
Import upstream version 6.0
347
    zucn_t members_processed;
1 by Santiago Vila
Import upstream version 5.51
348
    ulg num_skipped=0L, num_bad_pwd=0L;
1.1.2 by Santiago Vila
Import upstream version 6.0
349
    zoff_t old_extra_bytes = 0L;
1 by Santiago Vila
Import upstream version 5.51
350
#ifdef SET_DIR_ATTRIB
351
    unsigned num_dirs=0;
352
    direntry *dirlist=(direntry *)NULL, **sorted_dirlist=(direntry **)NULL;
353
#endif
354
1.1.2 by Santiago Vila
Import upstream version 6.0
355
    /*
356
     * First, two general initializations are applied. These have been moved
357
     * here from process_zipfiles() because they are only needed for accessing
358
     * and/or extracting the data content of the zip archive.
359
     */
360
361
    /* a) initialize the CRC table pointer (once) */
362
    if (CRC_32_TAB == NULL) {
363
        if ((CRC_32_TAB = get_crc_table()) == NULL) {
364
            return PK_MEM;
365
        }
366
    }
367
368
#if (!defined(SFX) || defined(SFX_EXDIR))
369
    /* b) check out if specified extraction root directory exists */
370
    if (uO.exdir != (char *)NULL && G.extract_flag) {
371
        G.create_dirs = !uO.fflag;
372
        if ((error = checkdir(__G__ uO.exdir, ROOT)) > MPN_INF_SKIP) {
373
            /* out of memory, or file in way */
374
            return (error == MPN_NOMEM ? PK_MEM : PK_ERR);
375
        }
376
    }
377
#endif /* !SFX || SFX_EXDIR */
378
1 by Santiago Vila
Import upstream version 5.51
379
/*---------------------------------------------------------------------------
380
    The basic idea of this function is as follows.  Since the central di-
381
    rectory lies at the end of the zipfile and the member files lie at the
382
    beginning or middle or wherever, it is not very desirable to simply
383
    read a central directory entry, jump to the member and extract it, and
384
    then jump back to the central directory.  In the case of a large zipfile
385
    this would lead to a whole lot of disk-grinding, especially if each mem-
386
    ber file is small.  Instead, we read from the central directory the per-
387
    tinent information for a block of files, then go extract/test the whole
388
    block.  Thus this routine contains two small(er) loops within a very
389
    large outer loop:  the first of the small ones reads a block of files
390
    from the central directory; the second extracts or tests each file; and
391
    the outer one loops over blocks.  There's some file-pointer positioning
392
    stuff in between, but that's about it.  Btw, it's because of this jump-
393
    ing around that we can afford to be lenient if an error occurs in one of
394
    the member files:  we should still be able to go find the other members,
395
    since we know the offset of each from the beginning of the zipfile.
396
  ---------------------------------------------------------------------------*/
397
398
    G.pInfo = G.info;
399
400
#if CRYPT
401
    G.newzip = TRUE;
402
#endif
403
#ifndef SFX
404
    G.reported_backslash = FALSE;
405
#endif
406
407
    /* malloc space for check on unmatched filespecs (OK if one or both NULL) */
408
    if (G.filespecs > 0  &&
409
        (fn_matched=(int *)malloc(G.filespecs*sizeof(int))) != (int *)NULL)
410
        for (i = 0;  i < G.filespecs;  ++i)
411
            fn_matched[i] = FALSE;
412
    if (G.xfilespecs > 0  &&
413
        (xn_matched=(int *)malloc(G.xfilespecs*sizeof(int))) != (int *)NULL)
414
        for (i = 0;  i < G.xfilespecs;  ++i)
415
            xn_matched[i] = FALSE;
416
417
/*---------------------------------------------------------------------------
418
    Begin main loop over blocks of member files.  We know the entire central
419
    directory is on this disk:  we would not have any of this information un-
420
    less the end-of-central-directory record was on this disk, and we would
421
    not have gotten to this routine unless this is also the disk on which
422
    the central directory starts.  In practice, this had better be the ONLY
423
    disk in the archive, but we'll add multi-disk support soon.
424
  ---------------------------------------------------------------------------*/
425
426
    members_processed = 0;
1.1.2 by Santiago Vila
Import upstream version 6.0
427
#ifndef SFX
1 by Santiago Vila
Import upstream version 5.51
428
    no_endsig_found = FALSE;
1.1.2 by Santiago Vila
Import upstream version 6.0
429
#endif
1 by Santiago Vila
Import upstream version 5.51
430
    reached_end = FALSE;
431
    while (!reached_end) {
432
        j = 0;
433
#ifdef AMIGA
434
        memzero(G.filenotes, DIR_BLKSIZ * sizeof(char *));
435
#endif
436
437
        /*
438
         * Loop through files in central directory, storing offsets, file
439
         * attributes, case-conversion and text-conversion flags until block
440
         * size is reached.
441
         */
442
443
        while ((j < DIR_BLKSIZ)) {
444
            G.pInfo = &G.info[j];
445
446
            if (readbuf(__G__ G.sig, 4) == 0) {
447
                error_in_archive = PK_EOF;
448
                reached_end = TRUE;     /* ...so no more left to do */
449
                break;
450
            }
1.1.2 by Santiago Vila
Import upstream version 6.0
451
            if (memcmp(G.sig, central_hdr_sig, 4)) {  /* is it a new entry? */
1 by Santiago Vila
Import upstream version 5.51
452
                /* no new central directory entry
453
                 * -> is the number of processed entries compatible with the
454
                 *    number of entries as stored in the end_central record?
455
                 */
1.1.2 by Santiago Vila
Import upstream version 6.0
456
                if ((members_processed
457
                     & (G.ecrec.have_ecr64 ? MASK_ZUCN64 : MASK_ZUCN16))
458
                    == G.ecrec.total_entries_central_dir) {
459
#ifndef SFX
1 by Santiago Vila
Import upstream version 5.51
460
                    /* yes, so look if we ARE back at the end_central record
461
                     */
462
                    no_endsig_found =
1.1.2 by Santiago Vila
Import upstream version 6.0
463
                      ( (memcmp(G.sig,
464
                                (G.ecrec.have_ecr64 ?
465
                                 end_central64_sig : end_central_sig),
466
                                4) != 0)
467
                       && (!G.ecrec.is_zip64_archive)
468
                       && (memcmp(G.sig, end_central_sig, 4) != 0)
469
                      );
470
#endif /* !SFX */
1 by Santiago Vila
Import upstream version 5.51
471
                } else {
472
                    /* no; we have found an error in the central directory
473
                     * -> report it and stop searching for more Zip entries
474
                     */
475
                    Info(slide, 0x401, ((char *)slide,
476
                      LoadFarString(CentSigMsg), j + blknum*DIR_BLKSIZ + 1));
477
                    Info(slide, 0x401, ((char *)slide,
478
                      LoadFarString(ReportMsg)));
479
                    error_in_archive = PK_BADERR;
480
                }
481
                reached_end = TRUE;     /* ...so no more left to do */
482
                break;
483
            }
484
            /* process_cdir_file_hdr() sets pInfo->hostnum, pInfo->lcflag */
485
            if ((error = process_cdir_file_hdr(__G)) != PK_COOL) {
486
                error_in_archive = error;   /* only PK_EOF defined */
487
                reached_end = TRUE;     /* ...so no more left to do */
488
                break;
489
            }
490
            if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) !=
491
                 PK_COOL)
492
            {
493
                if (error > error_in_archive)
494
                    error_in_archive = error;
495
                if (error > PK_WARN) {  /* fatal:  no more left to do */
496
                    Info(slide, 0x401, ((char *)slide,
497
                      LoadFarString(FilNamMsg),
498
                      FnFilter1(G.filename), "central"));
499
                    reached_end = TRUE;
500
                    break;
501
                }
502
            }
503
            if ((error = do_string(__G__ G.crec.extra_field_length,
504
                EXTRA_FIELD)) != 0)
505
            {
506
                if (error > error_in_archive)
507
                    error_in_archive = error;
508
                if (error > PK_WARN) {  /* fatal */
509
                    Info(slide, 0x401, ((char *)slide,
510
                      LoadFarString(ExtFieldMsg),
511
                      FnFilter1(G.filename), "central"));
512
                    reached_end = TRUE;
513
                    break;
514
                }
515
            }
516
#ifdef AMIGA
517
            G.filenote_slot = j;
518
            if ((error = do_string(__G__ G.crec.file_comment_length,
519
                                   uO.N_flag ? FILENOTE : SKIP)) != PK_COOL)
520
#else
521
            if ((error = do_string(__G__ G.crec.file_comment_length, SKIP))
522
                != PK_COOL)
523
#endif
524
            {
525
                if (error > error_in_archive)
526
                    error_in_archive = error;
527
                if (error > PK_WARN) {  /* fatal */
528
                    Info(slide, 0x421, ((char *)slide,
529
                      LoadFarString(BadFileCommLength),
530
                      FnFilter1(G.filename)));
531
                    reached_end = TRUE;
532
                    break;
533
                }
534
            }
535
            if (G.process_all_files) {
536
                if (store_info(__G))
537
                    ++j;  /* file is OK; info[] stored; continue with next */
538
                else
539
                    ++num_skipped;
540
            } else {
541
                int   do_this_file;
542
543
                if (G.filespecs == 0)
544
                    do_this_file = TRUE;
545
                else {  /* check if this entry matches an `include' argument */
546
                    do_this_file = FALSE;
547
                    for (i = 0; i < G.filespecs; i++)
1.1.1 by Florian Weimer
Import upstream version 5.52
548
                        if (match(G.filename, G.pfnames[i], uO.C_flag WISEP)) {
1 by Santiago Vila
Import upstream version 5.51
549
                            do_this_file = TRUE;  /* ^-- ignore case or not? */
550
                            if (fn_matched)
551
                                fn_matched[i] = TRUE;
552
                            break;       /* found match, so stop looping */
553
                        }
554
                }
555
                if (do_this_file) {  /* check if this is an excluded file */
556
                    for (i = 0; i < G.xfilespecs; i++)
1.1.1 by Florian Weimer
Import upstream version 5.52
557
                        if (match(G.filename, G.pxnames[i], uO.C_flag WISEP)) {
1 by Santiago Vila
Import upstream version 5.51
558
                            do_this_file = FALSE; /* ^-- ignore case or not? */
559
                            if (xn_matched)
560
                                xn_matched[i] = TRUE;
561
                            break;
562
                        }
563
                }
564
                if (do_this_file) {
565
                    if (store_info(__G))
566
                        ++j;            /* file is OK */
567
                    else
568
                        ++num_skipped;  /* unsupp. compression or encryption */
569
                }
570
            } /* end if (process_all_files) */
571
572
            members_processed++;
573
574
        } /* end while-loop (adding files to current block) */
575
576
        /* save position in central directory so can come back later */
577
        cd_bufstart = G.cur_zipfile_bufstart;
578
        cd_inptr = G.inptr;
579
        cd_incnt = G.incnt;
580
581
    /*-----------------------------------------------------------------------
582
        Second loop:  process files in current block, extracting or testing
583
        each one.
584
      -----------------------------------------------------------------------*/
585
586
        error = extract_or_test_entrylist(__G__ j,
587
                        &filnum, &num_bad_pwd, &old_extra_bytes,
588
#ifdef SET_DIR_ATTRIB
589
                        &num_dirs, &dirlist,
590
#endif
591
                        error_in_archive);
592
        if (error != PK_COOL) {
593
            if (error > error_in_archive)
594
                error_in_archive = error;
595
            /* ...and keep going (unless disk full or user break) */
596
            if (G.disk_full > 1 || error_in_archive == IZ_CTRLC) {
597
                /* clear reached_end to signal premature stop ... */
598
                reached_end = FALSE;
599
                /* ... and cancel scanning the central directory */
600
                break;
601
            }
602
        }
603
604
605
        /*
606
         * Jump back to where we were in the central directory, then go and do
607
         * the next batch of files.
608
         */
609
610
#ifdef USE_STRM_INPUT
1.1.2 by Santiago Vila
Import upstream version 6.0
611
        zfseeko(G.zipfd, cd_bufstart, SEEK_SET);
612
        G.cur_zipfile_bufstart = zftello(G.zipfd);
1 by Santiago Vila
Import upstream version 5.51
613
#else /* !USE_STRM_INPUT */
614
        G.cur_zipfile_bufstart =
1.1.2 by Santiago Vila
Import upstream version 6.0
615
          zlseek(G.zipfd, cd_bufstart, SEEK_SET);
1 by Santiago Vila
Import upstream version 5.51
616
#endif /* ?USE_STRM_INPUT */
617
        read(G.zipfd, (char *)G.inbuf, INBUFSIZ);  /* been here before... */
618
        G.inptr = cd_inptr;
619
        G.incnt = cd_incnt;
620
        ++blknum;
621
622
#ifdef TEST
623
        printf("\ncd_bufstart = %ld (%.8lXh)\n", cd_bufstart, cd_bufstart);
624
        printf("cur_zipfile_bufstart = %ld (%.8lXh)\n", cur_zipfile_bufstart,
625
          cur_zipfile_bufstart);
626
        printf("inptr-inbuf = %d\n", G.inptr-G.inbuf);
627
        printf("incnt = %d\n\n", G.incnt);
628
#endif
629
630
    } /* end while-loop (blocks of files in central directory) */
631
632
/*---------------------------------------------------------------------------
633
    Process the list of deferred symlink extractions and finish up
634
    the symbolic links.
635
  ---------------------------------------------------------------------------*/
636
637
#ifdef SYMLINKS
638
    if (G.slink_last != NULL) {
639
        if (QCOND2)
640
            Info(slide, 0, ((char *)slide, LoadFarString(SymLnkDeferred)));
641
        while (G.slink_head != NULL) {
642
           set_deferred_symlink(__G__ G.slink_head);
643
           /* remove the processed entry from the chain and free its memory */
644
           G.slink_last = G.slink_head;
645
           G.slink_head = G.slink_last->next;
646
           free(G.slink_last);
647
       }
648
       G.slink_last = NULL;
649
    }
650
#endif /* SYMLINKS */
651
652
/*---------------------------------------------------------------------------
653
    Go back through saved list of directories, sort and set times/perms/UIDs
654
    and GIDs from the deepest level on up.
655
  ---------------------------------------------------------------------------*/
656
657
#ifdef SET_DIR_ATTRIB
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 {
1.1.1 by Florian Weimer
Import upstream version 5.52
670
            ulg ndirs_fail = 0;
671
1 by Santiago Vila
Import upstream version 5.51
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) {
1.1.1 by Florian Weimer
Import upstream version 5.52
689
                    ndirs_fail++;
1 by Santiago Vila
Import upstream version 5.51
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);
1.1.1 by Florian Weimer
Import upstream version 5.52
698
            if (!uO.tflag && QCOND2) {
699
                if (ndirs_fail > 0)
700
                    Info(slide, 0, ((char *)slide,
701
                      LoadFarString(DirlistFailAttrSum), ndirs_fail));
702
            }
1 by Santiago Vila
Import upstream version 5.51
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 */
1.1.2 by Santiago Vila
Import upstream version 6.0
787
        }
1 by Santiago Vila
Import upstream version 5.51
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
{
1.1.2 by Santiago Vila
Import upstream version 6.0
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
1 by Santiago Vila
Import upstream version 5.51
849
#ifdef SFX
850
#  ifdef USE_DEFLATE64
851
#    define UNKN_COMPR \
852
     (G.crec.compression_method!=STORED && G.crec.compression_method<DEFLATED \
1.1.2 by Santiago Vila
Import upstream version 6.0
853
      && G.crec.compression_method>ENHDEFLATED \
854
      && UNKN_BZ2 && UNKN_LZMA && UNKN_WAVP && UNKN_PPMD)
1 by Santiago Vila
Import upstream version 5.51
855
#  else
856
#    define UNKN_COMPR \
1.1.2 by Santiago Vila
Import upstream version 6.0
857
     (G.crec.compression_method!=STORED && G.crec.compression_method!=DEFLATED\
858
      && UNKN_BZ2 && UNKN_LZMA && UNKN_WAVP && UNKN_PPMD)
1 by Santiago Vila
Import upstream version 5.51
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 || \
1.1.2 by Santiago Vila
Import upstream version 6.0
875
     (G.crec.compression_method>ENHDEFLATED && UNKN_BZ2 && UNKN_LZMA \
876
      && UNKN_WAVP && UNKN_PPMD))
1 by Santiago Vila
Import upstream version 5.51
877
#  else
878
#    define UNKN_COMPR (UNKN_RED || UNKN_SHR || \
879
     G.crec.compression_method==TOKENIZED || \
1.1.2 by Santiago Vila
Import upstream version 6.0
880
     (G.crec.compression_method>DEFLATED && UNKN_BZ2 && UNKN_LZMA \
881
      && UNKN_WAVP && UNKN_PPMD))
1 by Santiago Vila
Import upstream version 5.51
882
#  endif
883
#endif
884
1.1.2 by Santiago Vila
Import upstream version 6.0
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
1 by Santiago Vila
Import upstream version 5.51
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)));
1.1.2 by Santiago Vila
Import upstream version 6.0
929
            fgets(G.answerbuf, sizeof(G.answerbuf), stdin);
1 by Santiago Vila
Import upstream version 5.51
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 */
1.1.2 by Santiago Vila
Import upstream version 6.0
935
    } else if (G.crec.version_needed_to_extract[0] > UNZVERS_SUPPORT) {
1 by Santiago Vila
Import upstream version 5.51
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,
1.1.2 by Santiago Vila
Import upstream version 6.0
941
              UNZVERS_SUPPORT / 10, UNZVERS_SUPPORT % 10));
1 by Santiago Vila
Import upstream version 5.51
942
        return 0;
943
    }
944
1.1.2 by Santiago Vila
Import upstream version 6.0
945
    if (UNKN_COMPR) {
1 by Santiago Vila
Import upstream version 5.51
946
        if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) {
947
#ifndef SFX
1.1.2 by Santiago Vila
Import upstream version 6.0
948
            unsigned cmpridx;
949
950
            if ((cmpridx = find_compr_idx(G.crec.compression_method))
951
                < NUM_METHODS)
1 by Santiago Vila
Import upstream version 5.51
952
                Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgName),
953
                  FnFilter1(G.filename),
1.1.2 by Santiago Vila
Import upstream version 6.0
954
                  LoadFarStringSmall(ComprNames[cmpridx])));
1 by Santiago Vila
Import upstream version 5.51
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;
1.1.2 by Santiago Vila
Import upstream version 6.0
985
    G.pInfo->offset = (zoff_t)G.crec.relative_offset_local_header;
1 by Santiago Vila
Import upstream version 5.51
986
    return 1;
987
988
} /* end function store_info() */
989
990
991
992
993
1.1.2 by Santiago Vila
Import upstream version 6.0
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
1 by Santiago Vila
Import upstream version 5.51
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;
1.1.2 by Santiago Vila
Import upstream version 6.0
1029
    zoff_t *pold_extra_bytes;
1 by Santiago Vila
Import upstream version 5.51
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;
1.1.2 by Santiago Vila
Import upstream version 6.0
1039
    zoff_t bufstart, inbuf_offset, request;
1 by Santiago Vila
Import upstream version 5.51
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",
1.1.1 by Florian Weimer
Import upstream version 5.52
1069
          (long)request, (long)inbuf_offset));
1 by Santiago Vila
Import upstream version 5.51
1070
        Trace((stderr,
1071
          "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n",
1.1.1 by Florian Weimer
Import upstream version 5.52
1072
          (long)bufstart, (long)G.cur_zipfile_bufstart));
1 by Santiago Vila
Import upstream version 5.51
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",
1.1.1 by Florian Weimer
Import upstream version 5.52
1086
                  (long)request, (long)inbuf_offset));
1 by Santiago Vila
Import upstream version 5.51
1087
                Trace((stderr,
1088
                  "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n",
1.1.1 by Florian Weimer
Import upstream version 5.52
1089
                  (long)bufstart, (long)G.cur_zipfile_bufstart));
1 by Santiago Vila
Import upstream version 5.51
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
1.1.2 by Santiago Vila
Import upstream version 6.0
1109
            zfseeko(G.zipfd, bufstart, SEEK_SET);
1110
            G.cur_zipfile_bufstart = zftello(G.zipfd);
1 by Santiago Vila
Import upstream version 5.51
1111
#else /* !USE_STRM_INPUT */
1112
            G.cur_zipfile_bufstart =
1.1.2 by Santiago Vila
Import upstream version 6.0
1113
              zlseek(G.zipfd, bufstart, SEEK_SET);
1 by Santiago Vila
Import upstream version 5.51
1114
#endif /* ?USE_STRM_INPUT */
1.1.1 by Florian Weimer
Import upstream version 5.52
1115
            if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) <= 0)
1 by Santiago Vila
Import upstream version 5.51
1116
            {
1117
                Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg),
1.1.1 by Florian Weimer
Import upstream version 5.52
1118
                  *pfilnum, "lseek", (long)bufstart));
1 by Santiago Vila
Import upstream version 5.51
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),
1.1.1 by Florian Weimer
Import upstream version 5.52
1132
              *pfilnum, "EOF", (long)request));
1 by Santiago Vila
Import upstream version 5.51
1133
            error_in_archive = PK_BADERR;
1134
            continue;   /* but can still try next one */
1135
        }
1.1.2 by Santiago Vila
Import upstream version 6.0
1136
        if (memcmp(G.sig, local_hdr_sig, 4)) {
1 by Santiago Vila
Import upstream version 5.51
1137
            Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg),
1.1.1 by Florian Weimer
Import upstream version 5.52
1138
              *pfilnum, LoadFarStringSmall(LocalHdrSig), (long)request));
1 by Santiago Vila
Import upstream version 5.51
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,
1.1.1 by Florian Weimer
Import upstream version 5.52
1157
                        LoadFarString(OffsetMsg), *pfilnum, "EOF",
1158
                        (long)request));
1 by Santiago Vila
Import upstream version 5.51
1159
                    error_in_archive = PK_BADERR;
1160
                    continue;   /* but can still try next one */
1161
                }
1.1.2 by Santiago Vila
Import upstream version 6.0
1162
                if (memcmp(G.sig, local_hdr_sig, 4)) {
1 by Santiago Vila
Import upstream version 5.51
1163
                    Info(slide, 0x401, ((char *)slide,
1164
                      LoadFarString(OffsetMsg), *pfilnum,
1.1.1 by Florian Weimer
Import upstream version 5.52
1165
                      LoadFarStringSmall(LocalHdrSig), (long)request));
1 by Santiago Vila
Import upstream version 5.51
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
        }
1.1.2 by Santiago Vila
Import upstream version 6.0
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 */
1 by Santiago Vila
Import upstream version 5.51
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
        }
1.1.2 by Santiago Vila
Import upstream version 6.0
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
        }
1 by Santiago Vila
Import upstream version 5.51
1226
#ifndef SFX
1.1.2 by Santiago Vila
Import upstream version 6.0
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
         */
1 by Santiago Vila
Import upstream version 5.51
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 */
1.1.2 by Santiago Vila
Import upstream version 6.0
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
         */
1.1.1 by Florian Weimer
Import upstream version 5.52
1257
        if (G.lrec.compression_method == STORED) {
1.1.2 by Santiago Vila
Import upstream version 6.0
1258
            zusz_t csiz_decrypted = G.lrec.csize;
1.1.1 by Florian Weimer
Import upstream version 5.52
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),
1.1.2 by Santiago Vila
Import upstream version 6.0
1265
                  FnFilter1(G.filename),
1266
                  FmZofft(G.lrec.ucsize, NULL, "u"),
1267
                  FmZofft(csiz_decrypted, NULL, "u")));
1.1.1 by Florian Weimer
Import upstream version 5.52
1268
                G.lrec.ucsize = csiz_decrypted;
1269
                if (error_in_archive < PK_WARN)
1270
                    error_in_archive = PK_WARN;
1271
            }
1 by Santiago Vila
Import upstream version 5.51
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;
1.1.2 by Santiago Vila
Import upstream version 6.0
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 */
1 by Santiago Vila
Import upstream version 5.51
1464
            if (query) {
1465
#ifdef WINDLL
1466
                switch (G.lpUserFunctions->replace != NULL ?
1.1.2 by Santiago Vila
Import upstream version 6.0
1467
                        (*G.lpUserFunctions->replace)(G.filename, FILNAMSIZ) :
1 by Santiago Vila
Import upstream version 5.51
1468
                        IDM_REPLACE_NONE) {
1469
                    case IDM_REPLACE_RENAME:
1470
                        _ISO_INTERN(G.filename);
1471
                        renamed = TRUE;
1472
                        goto startover;
1473
                    case IDM_REPLACE_ALL:
1474
                        G.overwrite_mode = OVERWRT_ALWAYS;
1475
                        /* FALL THROUGH, extract */
1476
                    case IDM_REPLACE_YES:
1477
                        break;
1478
                    case IDM_REPLACE_NONE:
1479
                        G.overwrite_mode = OVERWRT_NEVER;
1480
                        /* FALL THROUGH, skip */
1481
                    case IDM_REPLACE_NO:
1482
                        skip_entry = SKIP_Y_EXISTING;
1483
                        break;
1484
                }
1485
#else /* !WINDLL */
1486
                extent fnlen;
1487
reprompt:
1488
                Info(slide, 0x81, ((char *)slide,
1489
                  LoadFarString(ReplaceQuery),
1490
                  FnFilter1(G.filename)));
1.1.2 by Santiago Vila
Import upstream version 6.0
1491
                if (fgets(G.answerbuf, sizeof(G.answerbuf), stdin)
1492
                    == (char *)NULL) {
1 by Santiago Vila
Import upstream version 5.51
1493
                    Info(slide, 1, ((char *)slide,
1494
                      LoadFarString(AssumeNone)));
1495
                    *G.answerbuf = 'N';
1496
                    if (!error_in_archive)
1497
                        error_in_archive = 1;  /* not extracted:  warning */
1498
                }
1499
                switch (*G.answerbuf) {
1500
                    case 'r':
1501
                    case 'R':
1502
                        do {
1503
                            Info(slide, 0x81, ((char *)slide,
1504
                              LoadFarString(NewNameQuery)));
1505
                            fgets(G.filename, FILNAMSIZ, stdin);
1506
                            /* usually get \n here:  better check for it */
1507
                            fnlen = strlen(G.filename);
1508
                            if (lastchar(G.filename, fnlen) == '\n')
1509
                                G.filename[--fnlen] = '\0';
1510
                        } while (fnlen == 0);
1511
#ifdef WIN32  /* WIN32 fgets( ... , stdin) returns OEM coded strings */
1512
                        _OEM_INTERN(G.filename);
1513
#endif
1514
                        renamed = TRUE;
1515
                        goto startover;   /* sorry for a goto */
1516
                    case 'A':   /* dangerous option:  force caps */
1517
                        G.overwrite_mode = OVERWRT_ALWAYS;
1518
                        /* FALL THROUGH, extract */
1519
                    case 'y':
1520
                    case 'Y':
1521
                        break;
1522
                    case 'N':
1523
                        G.overwrite_mode = OVERWRT_NEVER;
1524
                        /* FALL THROUGH, skip */
1525
                    case 'n':
1526
                        /* skip file */
1527
                        skip_entry = SKIP_Y_EXISTING;
1528
                        break;
1.1.2 by Santiago Vila
Import upstream version 6.0
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 ... */
1 by Santiago Vila
Import upstream version 5.51
1536
                    default:
1.1.2 by Santiago Vila
Import upstream version 6.0
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';
1 by Santiago Vila
Import upstream version 5.51
1543
                        Info(slide, 1, ((char *)slide,
1.1.2 by Santiago Vila
Import upstream version 6.0
1544
                          LoadFarString(InvalidResponse), G.answerbuf));
1 by Santiago Vila
Import upstream version 5.51
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) ?
1.1.2 by Santiago Vila
Import upstream version 6.0
1555
                       "Target file exists.  Skipping %s\n" :
1556
                       "Target file newer.  Skipping %s\n"),
1 by Santiago Vila
Import upstream version 5.51
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
1.1.2 by Santiago Vila
Import upstream version 6.0
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
1 by Santiago Vila
Import upstream version 5.51
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
1.1.2 by Santiago Vila
Import upstream version 6.0
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));
1 by Santiago Vila
Import upstream version 5.51
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
1.1.2 by Santiago Vila
Import upstream version 6.0
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:
1 by Santiago Vila
Import upstream version 5.51
1692
                return PK_DISK;
1.1.2 by Santiago Vila
Import upstream version 6.0
1693
            }
1694
#else /* !VMS */
1 by Santiago Vila
Import upstream version 5.51
1695
        } else if (open_outfile(__G))
1696
            return PK_DISK;
1.1.2 by Santiago Vila
Import upstream version 6.0
1697
#endif /* ?VMS */
1 by Santiago Vila
Import upstream version 5.51
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
            }
1.1.2 by Santiago Vila
Import upstream version 6.0
1738
            if (G.outcnt) {        /* flush final (partial) buffer */
1739
                r = flush(__G__ redirSlide, G.outcnt, 0);
1740
                if (error < r) error = r;
1741
            }
1 by Santiago Vila
Import upstream version 5.51
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,
2.1.1 by Santiago Vila
Fixed stack underflow in unshrink.c. Closes: #454037.
1757
                          LoadFarStringSmall(ErrUnzipFile), r == PK_MEM3 ?
1758
                          LoadFarString(NotEnoughMem) :
1759
                          LoadFarString(InvalidComprData),
1 by Santiago Vila
Import upstream version 5.51
1760
                          LoadFarStringSmall2(Unshrink),
1761
                          FnFilter1(G.filename)));
1762
                    else
1763
                        Info(slide, 0x401, ((char *)slide,
2.1.1 by Santiago Vila
Fixed stack underflow in unshrink.c. Closes: #454037.
1764
                          LoadFarStringSmall(ErrUnzipNoFile), r == PK_MEM3 ?
1765
                          LoadFarString(NotEnoughMem) :
1766
                          LoadFarString(InvalidComprData),
1 by Santiago Vila
Import upstream version 5.51
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
            }
1.1.2 by Santiago Vila
Import upstream version 6.0
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) {
1 by Santiago Vila
Import upstream version 5.51
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)));
1.1.2 by Santiago Vila
Import upstream version 6.0
1836
                    error = ((r == 3) ? PK_MEM3 : PK_ERR);
1 by Santiago Vila
Import upstream version 5.51
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)));
1.1.2 by Santiago Vila
Import upstream version 6.0
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 */
1 by Santiago Vila
Import upstream version 5.51
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
22 by Marc Deslauriers
* SECURITY UPDATE: CRC32 verification heap-based overflow
2028
        if (ebLen > (ef_len - EB_HEADSIZE))
2029
        {
1 by Santiago Vila
Import upstream version 5.51
2030
           /* Discovered some extra field inconsistency! */
2031
            if (uO.qflag)
2032
                Info(slide, 1, ((char *)slide, "%-22s ",
2033
                  FnFilter1(G.filename)));
2034
            Info(slide, 1, ((char *)slide, LoadFarString(InconsistEFlength),
2035
              ebLen, (ef_len - EB_HEADSIZE)));
2036
            return PK_ERR;
2037
        }
2038
2039
        switch (ebID) {
2040
            case EF_OS2:
2041
            case EF_ACL:
2042
            case EF_MAC3:
2043
            case EF_BEOS:
1.1.1 by Florian Weimer
Import upstream version 5.52
2044
            case EF_ATHEOS:
1 by Santiago Vila
Import upstream version 5.51
2045
                switch (ebID) {
2046
                  case EF_OS2:
2047
                  case EF_ACL:
2048
                    eb_cmpr_offs = EB_OS2_HLEN;
2049
                    break;
2050
                  case EF_MAC3:
2051
                    if (ebLen >= EB_MAC3_HLEN &&
2052
                        (makeword(ef+(EB_HEADSIZE+EB_FLGS_OFFS))
2053
                         & EB_M3_FL_UNCMPR) &&
2054
                        (makelong(ef+EB_HEADSIZE) == ebLen - EB_MAC3_HLEN))
2055
                        eb_cmpr_offs = 0;
2056
                    else
2057
                        eb_cmpr_offs = EB_MAC3_HLEN;
2058
                    break;
2059
                  case EF_BEOS:
1.1.1 by Florian Weimer
Import upstream version 5.52
2060
                  case EF_ATHEOS:
1 by Santiago Vila
Import upstream version 5.51
2061
                    if (ebLen >= EB_BEOS_HLEN &&
2062
                        (*(ef+(EB_HEADSIZE+EB_FLGS_OFFS)) & EB_BE_FL_UNCMPR) &&
2063
                        (makelong(ef+EB_HEADSIZE) == ebLen - EB_BEOS_HLEN))
2064
                        eb_cmpr_offs = 0;
2065
                    else
2066
                        eb_cmpr_offs = EB_BEOS_HLEN;
2067
                    break;
2068
                }
2069
                if ((r = test_compr_eb(__G__ ef, ebLen, eb_cmpr_offs, NULL))
2070
                    != PK_OK) {
2071
                    if (uO.qflag)
2072
                        Info(slide, 1, ((char *)slide, "%-22s ",
2073
                          FnFilter1(G.filename)));
2074
                    switch (r) {
2075
                        case IZ_EF_TRUNC:
2076
                            Info(slide, 1, ((char *)slide,
2077
                              LoadFarString(TruncEAs),
2078
                              ebLen-(eb_cmpr_offs+EB_CMPRHEADLEN), "\n"));
2079
                            break;
2080
                        case PK_ERR:
2081
                            Info(slide, 1, ((char *)slide,
2082
                              LoadFarString(InvalidComprDataEAs)));
2083
                            break;
2084
                        case PK_MEM3:
2085
                        case PK_MEM4:
2086
                            Info(slide, 1, ((char *)slide,
2087
                              LoadFarString(NotEnoughMemEAs)));
2088
                            break;
2089
                        default:
2090
                            if ((r & 0xff) != PK_ERR)
2091
                                Info(slide, 1, ((char *)slide,
2092
                                  LoadFarString(UnknErrorEAs)));
2093
                            else {
2094
                                ush m = (ush)(r >> 8);
2095
                                if (m == DEFLATED)            /* GRR KLUDGE! */
2096
                                    Info(slide, 1, ((char *)slide,
2097
                                      LoadFarString(BadCRC_EAs)));
2098
                                else
2099
                                    Info(slide, 1, ((char *)slide,
2100
                                      LoadFarString(UnknComprMethodEAs), m));
2101
                            }
2102
                            break;
2103
                    }
2104
                    return r;
2105
                }
2106
                break;
2107
2108
            case EF_NTSD:
2109
                Trace((stderr, "ebID: %i / ebLen: %u\n", ebID, ebLen));
2110
                r = ebLen < EB_NTSD_L_LEN ? IZ_EF_TRUNC :
2111
                    ((ef[EB_HEADSIZE+EB_NTSD_VERSION] > EB_NTSD_MAX_VER) ?
2112
                     (PK_WARN | 0x4000) :
2113
                     test_compr_eb(__G__ ef, ebLen, EB_NTSD_L_LEN, TEST_NTSD));
2114
                if (r != PK_OK) {
2115
                    if (uO.qflag)
2116
                        Info(slide, 1, ((char *)slide, "%-22s ",
2117
                          FnFilter1(G.filename)));
2118
                    switch (r) {
2119
                        case IZ_EF_TRUNC:
2120
                            Info(slide, 1, ((char *)slide,
2121
                              LoadFarString(TruncNTSD),
2122
                              ebLen-(EB_NTSD_L_LEN+EB_CMPRHEADLEN), "\n"));
2123
                            break;
2124
#if (defined(WIN32) && defined(NTSD_EAS))
2125
                        case PK_WARN:
2126
                            Info(slide, 1, ((char *)slide,
2127
                              LoadFarString(InvalidSecurityEAs)));
2128
                            break;
2129
#endif
2130
                        case PK_ERR:
2131
                            Info(slide, 1, ((char *)slide,
2132
                              LoadFarString(InvalidComprDataEAs)));
2133
                            break;
2134
                        case PK_MEM3:
2135
                        case PK_MEM4:
2136
                            Info(slide, 1, ((char *)slide,
2137
                              LoadFarString(NotEnoughMemEAs)));
2138
                            break;
2139
                        case (PK_WARN | 0x4000):
2140
                            Info(slide, 1, ((char *)slide,
2141
                              LoadFarString(UnsuppNTSDVersEAs),
2142
                              (int)ef[EB_HEADSIZE+EB_NTSD_VERSION]));
2143
                            r = PK_WARN;
2144
                            break;
2145
                        default:
2146
                            if ((r & 0xff) != PK_ERR)
2147
                                Info(slide, 1, ((char *)slide,
2148
                                  LoadFarString(UnknErrorEAs)));
2149
                            else {
2150
                                ush m = (ush)(r >> 8);
2151
                                if (m == DEFLATED)            /* GRR KLUDGE! */
2152
                                    Info(slide, 1, ((char *)slide,
2153
                                      LoadFarString(BadCRC_EAs)));
2154
                                else
2155
                                    Info(slide, 1, ((char *)slide,
2156
                                      LoadFarString(UnknComprMethodEAs), m));
2157
                            }
2158
                            break;
2159
                    }
2160
                    return r;
2161
                }
2162
                break;
2163
            case EF_PKVMS:
24 by Marc Deslauriers
* SECURITY UPDATE: heap overflow in charset_to_intern()
2164
                if (ebLen < 4)
2165
                {
2166
                    Info(slide, 1,
2167
                     ((char *)slide, LoadFarString(TooSmallEBlength),
2168
                     ebLen, 4));
2169
                }
2170
                else if (makelong(ef+EB_HEADSIZE) !=
1 by Santiago Vila
Import upstream version 5.51
2171
                    crc32(CRCVAL_INITIAL, ef+(EB_HEADSIZE+4),
2172
                          (extent)(ebLen-4)))
24 by Marc Deslauriers
* SECURITY UPDATE: heap overflow in charset_to_intern()
2173
                {
1 by Santiago Vila
Import upstream version 5.51
2174
                    Info(slide, 1, ((char *)slide,
2175
                      LoadFarString(BadCRC_EAs)));
24 by Marc Deslauriers
* SECURITY UPDATE: heap overflow in charset_to_intern()
2176
                }
1 by Santiago Vila
Import upstream version 5.51
2177
                break;
2178
            case EF_PKW32:
2179
            case EF_PKUNIX:
2180
            case EF_ASIUNIX:
2181
            case EF_IZVMS:
2182
            case EF_IZUNIX:
2183
            case EF_VMCMS:
2184
            case EF_MVS:
2185
            case EF_SPARK:
2186
            case EF_TANDEM:
2187
            case EF_THEOS:
2188
            case EF_AV:
2189
            default:
2190
                break;
2191
        }
2192
        ef_len -= (ebLen + EB_HEADSIZE);
2193
        ef += (ebLen + EB_HEADSIZE);
2194
    }
2195
2196
    if (!uO.qflag)
2197
        Info(slide, 0, ((char *)slide, " OK\n"));
2198
2199
    return PK_COOL;
2200
2201
} /* end function TestExtraField() */
2202
2203
2204
2205
2206
2207
/******************************/
2208
/*  Function test_compr_eb()  */
2209
/******************************/
2210
2211
#ifdef PROTO
2212
static int test_compr_eb(
2213
    __GPRO__
2214
    uch *eb,
2215
    unsigned eb_size,
2216
    unsigned compr_offset,
2217
    int (*test_uc_ebdata)(__GPRO__ uch *eb, unsigned eb_size,
2218
                          uch *eb_ucptr, ulg eb_ucsize))
2219
#else /* !PROTO */
2220
static int test_compr_eb(__G__ eb, eb_size, compr_offset, test_uc_ebdata)
2221
    __GDEF
2222
    uch *eb;
2223
    unsigned eb_size;
2224
    unsigned compr_offset;
2225
    int (*test_uc_ebdata)();
2226
#endif /* ?PROTO */
2227
{
2228
    ulg eb_ucsize;
2229
    uch *eb_ucptr;
2230
    int r;
24 by Marc Deslauriers
* SECURITY UPDATE: heap overflow in charset_to_intern()
2231
    ush eb_compr_method;
1 by Santiago Vila
Import upstream version 5.51
2232
2233
    if (compr_offset < 4)                /* field is not compressed: */
2234
        return PK_OK;                    /* do nothing and signal OK */
2235
22 by Marc Deslauriers
* SECURITY UPDATE: CRC32 verification heap-based overflow
2236
    /* Return no/bad-data error status if any problem is found:
2237
     *    1. eb_size is too small to hold the uncompressed size
2238
     *       (eb_ucsize).  (Else extract eb_ucsize.)
2239
     *    2. eb_ucsize is zero (invalid).  2014-12-04 SMS.
2240
     *    3. eb_ucsize is positive, but eb_size is too small to hold
2241
     *       the compressed data header.
2242
     */
1 by Santiago Vila
Import upstream version 5.51
2243
    if ((eb_size < (EB_UCSIZE_P + 4)) ||
22 by Marc Deslauriers
* SECURITY UPDATE: CRC32 verification heap-based overflow
2244
     ((eb_ucsize = makelong( eb+ (EB_HEADSIZE+ EB_UCSIZE_P))) == 0L) ||
2245
     ((eb_ucsize > 0L) && (eb_size <= (compr_offset + EB_CMPRHEADLEN))))
2246
        return IZ_EF_TRUNC;             /* no/bad compressed data! */
1 by Santiago Vila
Import upstream version 5.51
2247
24 by Marc Deslauriers
* SECURITY UPDATE: heap overflow in charset_to_intern()
2248
    /* 2015-02-10 Mancha(?), Michal Zalewski, Tomas Hoger, SMS.
2249
     * For STORE method, compressed and uncompressed sizes must agree.
2250
     * http://www.info-zip.org/phpBB3/viewtopic.php?f=7&t=450
2251
     */
2252
    eb_compr_method = makeword( eb + (EB_HEADSIZE + compr_offset));
2253
    if ((eb_compr_method == STORED) &&
2254
     (eb_size != compr_offset + EB_CMPRHEADLEN + eb_ucsize))
2255
        return PK_ERR;
23 by Marc Deslauriers
* SECURITY UPDATE: heap overflow via mismatched block sizes
2256
1 by Santiago Vila
Import upstream version 5.51
2257
    if (
2258
#ifdef INT_16BIT
2259
        (((ulg)(extent)eb_ucsize) != eb_ucsize) ||
2260
#endif
2261
        (eb_ucptr = (uch *)malloc((extent)eb_ucsize)) == (uch *)NULL)
2262
        return PK_MEM4;
2263
2264
    r = memextract(__G__ eb_ucptr, eb_ucsize,
2265
                   eb + (EB_HEADSIZE + compr_offset),
2266
                   (ulg)(eb_size - compr_offset));
2267
2268
    if (r == PK_OK && test_uc_ebdata != NULL)
2269
        r = (*test_uc_ebdata)(__G__ eb, eb_size, eb_ucptr, eb_ucsize);
2270
2271
    free(eb_ucptr);
2272
    return r;
2273
2274
} /* end function test_compr_eb() */
2275
2276
#endif /* !SFX */
2277
2278
2279
2280
2281
2282
/***************************/
2283
/*  Function memextract()  */
2284
/***************************/
2285
2286
int memextract(__G__ tgt, tgtsize, src, srcsize)  /* extract compressed */
2287
    __GDEF                                        /*  extra field block; */
2288
    uch *tgt;                                     /*  return PK-type error */
2289
    ulg tgtsize;                                  /*  level */
2290
    ZCONST uch *src;
2291
    ulg srcsize;
2292
{
1.1.2 by Santiago Vila
Import upstream version 6.0
2293
    zoff_t old_csize=G.csize;
2294
    uch   *old_inptr=G.inptr;
2295
    int    old_incnt=G.incnt;
2296
    int    r, error=PK_OK;
2297
    ush    method;
2298
    ulg    extra_field_crc;
1 by Santiago Vila
Import upstream version 5.51
2299
2300
2301
    method = makeword(src);
2302
    extra_field_crc = makelong(src+2);
2303
2304
    /* compressed extra field exists completely in memory at this location: */
2305
    G.inptr = (uch *)src + (2 + 4);     /* method and extra_field_crc */
2306
    G.incnt = (int)(G.csize = (long)(srcsize - (2 + 4)));
2307
    G.mem_mode = TRUE;
2308
    G.outbufptr = tgt;
2309
    G.outsize = tgtsize;
2310
2311
    switch (method) {
2312
        case STORED:
2313
            memcpy((char *)tgt, (char *)G.inptr, (extent)G.incnt);
1.1.2 by Santiago Vila
Import upstream version 6.0
2314
            G.outcnt = (ulg)G.csize;    /* for CRC calculation */
1 by Santiago Vila
Import upstream version 5.51
2315
            break;
2316
        case DEFLATED:
2317
#ifdef USE_DEFLATE64
2318
        case ENHDEFLATED:
2319
#endif
2320
            G.outcnt = 0L;
2321
            if ((r = UZinflate(__G__ (method == ENHDEFLATED))) != 0) {
2322
                if (!uO.tflag)
2323
                    Info(slide, 0x401, ((char *)slide,
2324
                      LoadFarStringSmall(ErrUnzipNoFile), r == 3?
2325
                      LoadFarString(NotEnoughMem) :
2326
                      LoadFarString(InvalidComprData),
2327
                      LoadFarStringSmall2(Inflate)));
2328
                error = (r == 3)? PK_MEM3 : PK_ERR;
2329
            }
2330
            if (G.outcnt == 0L)   /* inflate's final FLUSH sets outcnt */
2331
                break;
2332
            break;
2333
        default:
2334
            if (uO.tflag)
2335
                error = PK_ERR | ((int)method << 8);
2336
            else {
2337
                Info(slide, 0x401, ((char *)slide,
2338
                  LoadFarString(UnsupportedExtraField), method));
2339
                error = PK_ERR;  /* GRR:  should be passed on up via SetEAs() */
2340
            }
2341
            break;
2342
    }
2343
2344
    G.inptr = old_inptr;
2345
    G.incnt = old_incnt;
2346
    G.csize = old_csize;
2347
    G.mem_mode = FALSE;
2348
2349
    if (!error) {
2350
        register ulg crcval = crc32(CRCVAL_INITIAL, tgt, (extent)G.outcnt);
2351
2352
        if (crcval != extra_field_crc) {
2353
            if (uO.tflag)
2354
                error = PK_ERR | (DEFLATED << 8);  /* kludge for now */
2355
            else {
2356
                Info(slide, 0x401, ((char *)slide,
2357
                  LoadFarString(BadExtraFieldCRC), G.zipfn, crcval,
2358
                  extra_field_crc));
2359
                error = PK_ERR;
2360
            }
2361
        }
2362
    }
2363
    return error;
2364
2365
} /* end function memextract() */
2366
2367
2368
2369
2370
2371
/*************************/
2372
/*  Function memflush()  */
2373
/*************************/
2374
2375
int memflush(__G__ rawbuf, size)
2376
    __GDEF
2377
    ZCONST uch *rawbuf;
2378
    ulg size;
2379
{
2380
    if (size > G.outsize)
2381
        /* Here, PK_DISK is a bit off-topic, but in the sense of marking
2382
           "overflow of output space", its use may be tolerated. */
2383
        return PK_DISK;   /* more data than output buffer can hold */
2384
2385
2386
2387
    memcpy((char *)G.outbufptr, (char *)rawbuf, (extent)size);
2388
    G.outbufptr += (unsigned int)size;
2389
    G.outsize -= size;
2390
    G.outcnt += size;
2391
2392
    return 0;
2393
2394
} /* end function memflush() */
2395
2396
2397
2398
2399
2400
#if (defined(VMS) || defined(VMS_TEXT_CONV))
2401
2402
/************************************/
2403
/*  Function extract_izvms_block()  */
2404
/************************************/
2405
2406
/*
2407
 * Extracts block from p. If resulting length is less than needed, fill
2408
 * extra space with corresponding bytes from 'init'.
2409
 * Currently understands 3 formats of block compression:
2410
 * - Simple storing
2411
 * - Compression of zero bytes to zero bits
2412
 * - Deflation (see memextract())
2413
 * The IZVMS block data is returned in malloc'd space.
2414
 */
2415
uch *extract_izvms_block(__G__ ebdata, size, retlen, init, needlen)
2416
    __GDEF
2417
    ZCONST uch *ebdata;
2418
    unsigned size;
2419
    unsigned *retlen;
2420
    ZCONST uch *init;
2421
    unsigned needlen;
2422
{
2423
    uch *ucdata;       /* Pointer to block allocated */
2424
    int cmptype;
2425
    unsigned usiz, csiz;
2426
2427
    cmptype = (makeword(ebdata+EB_IZVMS_FLGS) & EB_IZVMS_BCMASK);
2428
    csiz = size - EB_IZVMS_HLEN;
2429
    usiz = (cmptype == EB_IZVMS_BCSTOR ?
2430
            csiz : makeword(ebdata+EB_IZVMS_UCSIZ));
2431
2432
    if (retlen)
2433
        *retlen = usiz;
2434
2435
    if ((ucdata = (uch *)malloc(MAX(needlen, usiz))) == NULL)
2436
        return NULL;
2437
2438
    if (init && (usiz < needlen))
2439
        memcpy((char *)ucdata, (ZCONST char *)init, needlen);
2440
2441
    switch (cmptype)
2442
    {
2443
        case EB_IZVMS_BCSTOR: /* The simplest case */
2444
            memcpy(ucdata, ebdata+EB_IZVMS_HLEN, usiz);
2445
            break;
2446
        case EB_IZVMS_BC00:
2447
            decompress_bits(ucdata, usiz, ebdata+EB_IZVMS_HLEN);
2448
            break;
2449
        case EB_IZVMS_BCDEFL:
2450
            memextract(__G__ ucdata, (ulg)usiz,
2451
                       ebdata+EB_IZVMS_HLEN, (ulg)csiz);
2452
            break;
2453
        default:
2454
            free(ucdata);
2455
            ucdata = NULL;
2456
    }
2457
    return ucdata;
2458
2459
} /* end of extract_izvms_block */
2460
2461
2462
2463
2464
2465
/********************************/
2466
/*  Function decompress_bits()  */
2467
/********************************/
2468
/*
2469
 *  Simple uncompression routine. The compression uses bit stream.
2470
 *  Compression scheme:
2471
 *
2472
 *  if (byte!=0)
2473
 *      putbit(1),putbyte(byte)
2474
 *  else
2475
 *      putbit(0)
2476
 */
2477
static void decompress_bits(outptr, needlen, bitptr)
2478
    uch *outptr;        /* Pointer into output block */
2479
    unsigned needlen;   /* Size of uncompressed block */
2480
    ZCONST uch *bitptr; /* Pointer into compressed data */
2481
{
2482
    ulg bitbuf = 0;
2483
    int bitcnt = 0;
2484
2485
#define _FILL   {       bitbuf |= (*bitptr++) << bitcnt;\
2486
                        bitcnt += 8;                    \
2487
                }
2488
2489
    while (needlen--)
2490
    {
2491
        if (bitcnt <= 0)
2492
            _FILL;
2493
2494
        if (bitbuf & 1)
2495
        {
2496
            bitbuf >>= 1;
2497
            if ((bitcnt -= 1) < 8)
2498
                _FILL;
2499
            *outptr++ = (uch)bitbuf;
2500
            bitcnt -= 8;
2501
            bitbuf >>= 8;
2502
        }
2503
        else
2504
        {
2505
            *outptr++ = '\0';
2506
            bitcnt -= 1;
2507
            bitbuf >>= 1;
2508
        }
2509
    }
2510
} /* end function decompress_bits() */
2511
2512
#endif /* VMS || VMS_TEXT_CONV */
2513
2514
2515
2516
2517
2518
#ifdef SYMLINKS
2519
/***********************************/
2520
/* Function set_deferred_symlink() */
2521
/***********************************/
2522
2523
static void set_deferred_symlink(__G__ slnk_entry)
2524
    __GDEF
2525
    slinkentry *slnk_entry;
2526
{
1.1.2 by Santiago Vila
Import upstream version 6.0
2527
    extent ucsize = slnk_entry->targetlen;
1 by Santiago Vila
Import upstream version 5.51
2528
    char *linkfname = slnk_entry->fname;
2529
    char *linktarget = (char *)malloc(ucsize+1);
2530
2531
    if (!linktarget) {
2532
        Info(slide, 0x201, ((char *)slide,
2533
          LoadFarString(SymLnkWarnNoMem), FnFilter1(linkfname)));
2534
        return;
2535
    }
2536
    linktarget[ucsize] = '\0';
1.1.2 by Santiago Vila
Import upstream version 6.0
2537
    G.outfile = zfopen(linkfname, FOPR); /* open link placeholder for reading */
1 by Santiago Vila
Import upstream version 5.51
2538
    /* Check that the following conditions are all fulfilled:
2539
     * a) the placeholder file exists,
2540
     * b) the placeholder file contains exactly "ucsize" bytes
2541
     *    (read the expected placeholder content length + 1 extra byte, this
2542
     *    should return the expected content length),
2543
     * c) the placeholder content matches the link target specification as
2544
     *    stored in the symlink control structure.
2545
     */
2546
    if (!G.outfile ||
1.1.2 by Santiago Vila
Import upstream version 6.0
2547
        fread(linktarget, 1, ucsize+1, G.outfile) != ucsize ||
1 by Santiago Vila
Import upstream version 5.51
2548
        strcmp(slnk_entry->target, linktarget))
2549
    {
2550
        Info(slide, 0x201, ((char *)slide,
2551
          LoadFarString(SymLnkWarnInvalid), FnFilter1(linkfname)));
2552
        free(linktarget);
1.1.2 by Santiago Vila
Import upstream version 6.0
2553
        if (G.outfile)
2554
            fclose(G.outfile);
1 by Santiago Vila
Import upstream version 5.51
2555
        return;
2556
    }
2557
    fclose(G.outfile);                  /* close "data" file for good... */
2558
    unlink(linkfname);                  /* ...and delete it */
2559
    if (QCOND2)
2560
        Info(slide, 0, ((char *)slide, LoadFarString(SymLnkFinish),
2561
          FnFilter1(linkfname), FnFilter2(linktarget)));
2562
    if (symlink(linktarget, linkfname))  /* create the real link */
2563
        perror("symlink error");
2564
    free(linktarget);
2565
#ifdef SET_SYMLINK_ATTRIBS
2566
    set_symlnk_attribs(__G__ slnk_entry);
2567
#endif
2568
    return;                             /* can't set time on symlinks */
2569
2570
} /* end function set_deferred_symlink() */
2571
#endif /* SYMLINKS */
2572
2573
2574
2575
2576
/*************************/
2577
/*  Function fnfilter()  */        /* here instead of in list.c for SFX */
2578
/*************************/
2579
1.1.2 by Santiago Vila
Import upstream version 6.0
2580
char *fnfilter(raw, space, size)   /* convert name to safely printable form */
1 by Santiago Vila
Import upstream version 5.51
2581
    ZCONST char *raw;
2582
    uch *space;
1.1.2 by Santiago Vila
Import upstream version 6.0
2583
    extent size;
1 by Santiago Vila
Import upstream version 5.51
2584
{
2585
#ifndef NATIVE   /* ASCII:  filter ANSI escape codes, etc. */
2586
    ZCONST uch *r=(ZCONST uch *)raw;
2587
    uch *s=space;
1.1.2 by Santiago Vila
Import upstream version 6.0
2588
    uch *slim=NULL;
2589
    uch *se=NULL;
2590
    int have_overflow = FALSE;
1 by Santiago Vila
Import upstream version 5.51
2591
1.1.2 by Santiago Vila
Import upstream version 6.0
2592
    if (size > 0) {
2593
        slim = space + size
2594
#ifdef _MBCS
2595
                     - (MB_CUR_MAX - 1)
2596
#endif
2597
                     - 4;
2598
    }
1 by Santiago Vila
Import upstream version 5.51
2599
    while (*r) {
1.1.2 by Santiago Vila
Import upstream version 6.0
2600
        if (size > 0 && s >= slim && se == NULL) {
2601
            se = s;
2602
        }
1 by Santiago Vila
Import upstream version 5.51
2603
#ifdef QDOS
2604
        if (qlflag & 2) {
2605
            if (*r == '/' || *r == '.') {
1.1.2 by Santiago Vila
Import upstream version 6.0
2606
                if (se != NULL && (s > (space + (size-3)))) {
2607
                    have_overflow = TRUE;
2608
                    break;
2609
                }
1 by Santiago Vila
Import upstream version 5.51
2610
                ++r;
2611
                *s++ = '_';
2612
                continue;
2613
            }
2614
        } else
2615
#endif
1.1.2 by Santiago Vila
Import upstream version 6.0
2616
#ifdef HAVE_WORKING_ISPRINT
2617
# ifndef UZ_FNFILTER_REPLACECHAR
2618
    /* A convenient choice for the replacement of unprintable char codes is
2619
     * the "single char wildcard", as this character is quite unlikely to
2620
     * appear in filenames by itself.  The following default definition
2621
     * sets the replacement char to a question mark as the most common
2622
     * "single char wildcard"; this setting should be overridden in the
2623
     * appropiate system-specific configuration header when needed.
2624
     */
2625
#   define UZ_FNFILTER_REPLACECHAR      '?'
2626
# endif
2627
        if (!isprint(*r)) {
2628
            if (*r < 32) {
2629
                /* ASCII control codes are escaped as "^{letter}". */
2630
                if (se != NULL && (s > (space + (size-4)))) {
2631
                    have_overflow = TRUE;
2632
                    break;
2633
                }
2634
                *s++ = '^', *s++ = (uch)(64 + *r++);
2635
            } else {
2636
                /* Other unprintable codes are replaced by the
2637
                 * placeholder character. */
2638
                if (se != NULL && (s > (space + (size-3)))) {
2639
                    have_overflow = TRUE;
2640
                    break;
2641
                }
2642
                *s++ = UZ_FNFILTER_REPLACECHAR;
2643
                INCSTR(r);
2644
            }
2645
#else /* !HAVE_WORKING_ISPRINT */
1 by Santiago Vila
Import upstream version 5.51
2646
        if (*r < 32) {
1.1.2 by Santiago Vila
Import upstream version 6.0
2647
            /* ASCII control codes are escaped as "^{letter}". */
2648
            if (se != NULL && (s > (space + (size-4)))) {
2649
                have_overflow = TRUE;
2650
                break;
2651
            }
1 by Santiago Vila
Import upstream version 5.51
2652
            *s++ = '^', *s++ = (uch)(64 + *r++);
1.1.2 by Santiago Vila
Import upstream version 6.0
2653
#endif /* ?HAVE_WORKING_ISPRINT */
1 by Santiago Vila
Import upstream version 5.51
2654
        } else {
2655
#ifdef _MBCS
1.1.2 by Santiago Vila
Import upstream version 6.0
2656
            unsigned i = CLEN(r);
2657
            if (se != NULL && (s > (space + (size-i-2)))) {
2658
                have_overflow = TRUE;
2659
                break;
2660
            }
2661
            for (; i > 0; i--)
1 by Santiago Vila
Import upstream version 5.51
2662
                *s++ = *r++;
2663
#else
1.1.2 by Santiago Vila
Import upstream version 6.0
2664
            if (se != NULL && (s > (space + (size-3)))) {
2665
                have_overflow = TRUE;
2666
                break;
2667
            }
1 by Santiago Vila
Import upstream version 5.51
2668
            *s++ = *r++;
2669
#endif
2670
         }
2671
    }
1.1.2 by Santiago Vila
Import upstream version 6.0
2672
    if (have_overflow) {
2673
        strcpy((char *)se, "...");
2674
    } else {
2675
        *s = '\0';
2676
    }
1 by Santiago Vila
Import upstream version 5.51
2677
2678
#ifdef WINDLL
2679
    INTERN_TO_ISO((char *)space, (char *)space);  /* translate to ANSI */
2680
#else
2681
#if (defined(WIN32) && !defined(_WIN32_WCE))
2682
    /* Win9x console always uses OEM character coding, and
2683
       WinNT console is set to OEM charset by default, too */
2684
    INTERN_TO_OEM((char *)space, (char *)space);
2685
#endif /* (WIN32 && !_WIN32_WCE) */
2686
#endif /* ?WINDLL */
2687
2688
    return (char *)space;
2689
2690
#else /* NATIVE:  EBCDIC or whatever */
2691
    return (char *)raw;
2692
#endif
2693
2694
} /* end function fnfilter() */
2695
2696
2697
2698
2699
#ifdef SET_DIR_ATTRIB
2700
/* must sort saved directories so can set perms from bottom up */
2701
2702
/************************/
2703
/*  Function dircomp()  */
2704
/************************/
2705
1.1.1 by Florian Weimer
Import upstream version 5.52
2706
static int Cdecl dircomp(a, b)  /* used by qsort(); swiped from Zip */
1 by Santiago Vila
Import upstream version 5.51
2707
    ZCONST zvoid *a, *b;
2708
{
2709
    /* order is significant:  this sorts in reverse order (deepest first) */
2710
    return strcmp((*(direntry **)b)->fn, (*(direntry **)a)->fn);
2711
 /* return namecmp((*(direntry **)b)->fn, (*(direntry **)a)->fn); */
2712
}
2713
1.1.2 by Santiago Vila
Import upstream version 6.0
2714
#endif /* SET_DIR_ATTRIB */
2715
2716
2717
#ifdef USE_BZIP2
2718
2719
/**************************/
2720
/*  Function UZbunzip2()  */
2721
/**************************/
2722
2723
int UZbunzip2(__G)
2724
__GDEF
2725
/* decompress a bzipped entry using the libbz2 routines */
1 by Santiago Vila
Import upstream version 5.51
2726
{
1.1.2 by Santiago Vila
Import upstream version 6.0
2727
    int retval = 0;     /* return code: 0 = "no error" */
2728
    int err=BZ_OK;
2729
    int repeated_buf_err;
2730
    bz_stream bstrm;
2731
2732
#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
2733
    if (G.redirect_slide)
2734
        wsize = G.redirect_size, redirSlide = G.redirect_buffer;
2735
    else
2736
        wsize = WSIZE, redirSlide = slide;
2737
#endif
2738
2739
    bstrm.next_out = (char *)redirSlide;
2740
    bstrm.avail_out = wsize;
2741
2742
    bstrm.next_in = (char *)G.inptr;
2743
    bstrm.avail_in = G.incnt;
2744
2745
    {
2746
        /* local buffer for efficiency */
2747
        /* $TODO Check for BZIP LIB version? */
2748
2749
        bstrm.bzalloc = NULL;
2750
        bstrm.bzfree = NULL;
2751
        bstrm.opaque = NULL;
2752
2753
        Trace((stderr, "initializing bzlib()\n"));
2754
        err = BZ2_bzDecompressInit(&bstrm, 0, 0);
2755
2756
        if (err == BZ_MEM_ERROR)
2757
            return 3;
2758
        else if (err != BZ_OK)
2759
            Trace((stderr, "oops!  (BZ2_bzDecompressInit() err = %d)\n", err));
2760
    }
2761
2762
#ifdef FUNZIP
2763
    while (err != BZ_STREAM_END) {
2764
#else /* !FUNZIP */
2765
    while (G.csize > 0) {
2766
        Trace((stderr, "first loop:  G.csize = %ld\n", G.csize));
2767
#endif /* ?FUNZIP */
2768
        while (bstrm.avail_out > 0) {
2769
            err = BZ2_bzDecompress(&bstrm);
2770
2771
            if (err == BZ_DATA_ERROR) {
2772
                retval = 2; goto uzbunzip_cleanup_exit;
2773
            } else if (err == BZ_MEM_ERROR) {
2774
                retval = 3; goto uzbunzip_cleanup_exit;
2775
            } else if (err != BZ_OK && err != BZ_STREAM_END)
2776
                Trace((stderr, "oops!  (bzip(first loop) err = %d)\n", err));
2777
2778
#ifdef FUNZIP
2779
            if (err == BZ_STREAM_END)    /* "END-of-entry-condition" ? */
2780
#else /* !FUNZIP */
2781
            if (G.csize <= 0L)          /* "END-of-entry-condition" ? */
2782
#endif /* ?FUNZIP */
2783
                break;
2784
2785
            if (bstrm.avail_in == 0) {
2786
                if (fillinbuf(__G) == 0) {
2787
                    /* no "END-condition" yet, but no more data */
2788
                    retval = 2; goto uzbunzip_cleanup_exit;
2789
                }
2790
2791
                bstrm.next_in = (char *)G.inptr;
2792
                bstrm.avail_in = G.incnt;
2793
            }
2794
            Trace((stderr, "     avail_in = %u\n", bstrm.avail_in));
2795
        }
2796
        /* flush slide[] */
2797
        if ((retval = FLUSH(wsize - bstrm.avail_out)) != 0)
2798
            goto uzbunzip_cleanup_exit;
2799
        Trace((stderr, "inside loop:  flushing %ld bytes (ptr diff = %ld)\n",
2800
          (long)(wsize - bstrm.avail_out),
2801
          (long)(bstrm.next_out-(char *)redirSlide)));
2802
        bstrm.next_out = (char *)redirSlide;
2803
        bstrm.avail_out = wsize;
2804
    }
2805
2806
    /* no more input, so loop until we have all output */
2807
    Trace((stderr, "beginning final loop:  err = %d\n", err));
2808
    repeated_buf_err = FALSE;
2809
    while (err != BZ_STREAM_END) {
2810
        err = BZ2_bzDecompress(&bstrm);
2811
        if (err == BZ_DATA_ERROR) {
2812
            retval = 2; goto uzbunzip_cleanup_exit;
2813
        } else if (err == BZ_MEM_ERROR) {
2814
            retval = 3; goto uzbunzip_cleanup_exit;
2815
        } else if (err != BZ_OK && err != BZ_STREAM_END) {
2816
            Trace((stderr, "oops!  (bzip(final loop) err = %d)\n", err));
2817
            DESTROYGLOBALS();
2818
            EXIT(PK_MEM3);
2819
        }
2820
        /* final flush of slide[] */
2821
        if ((retval = FLUSH(wsize - bstrm.avail_out)) != 0)
2822
            goto uzbunzip_cleanup_exit;
2823
        Trace((stderr, "final loop:  flushing %ld bytes (ptr diff = %ld)\n",
2824
          (long)(wsize - bstrm.avail_out),
2825
          (long)(bstrm.next_out-(char *)redirSlide)));
2826
        bstrm.next_out = (char *)redirSlide;
2827
        bstrm.avail_out = wsize;
2828
    }
2829
#ifdef LARGE_FILE_SUPPORT
2830
    Trace((stderr, "total in = %llu, total out = %llu\n",
2831
      (zusz_t)(bstrm.total_in_lo32) + ((zusz_t)(bstrm.total_in_hi32))<<32,
2832
      (zusz_t)(bstrm.total_out_lo32) + ((zusz_t)(bstrm.total_out_hi32))<<32));
2833
#else
2834
    Trace((stderr, "total in = %lu, total out = %lu\n", bstrm.total_in_lo32,
2835
      bstrm.total_out_lo32));
2836
#endif
2837
2838
    G.inptr = (uch *)bstrm.next_in;
2839
    G.incnt = (G.inbuf + INBUFSIZ) - G.inptr;  /* reset for other routines */
2840
2841
uzbunzip_cleanup_exit:
2842
    err = BZ2_bzDecompressEnd(&bstrm);
2843
    if (err != BZ_OK)
2844
        Trace((stderr, "oops!  (BZ2_bzDecompressEnd() err = %d)\n", err));
2845
2846
    return retval;
2847
} /* end function UZbunzip2() */
2848
#endif /* USE_BZIP2 */