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