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