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 87static int store_info OF((__GPRO)); 88#ifdef SET_DIR_ATTRIB 89static 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 94static 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 98static 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 123static ZCONST char Far VersionMsg[] = 124 " skipping: %-22s need %s compat. v%u.%u (can do v%u.%u)\n"; 125static 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 */ 155static 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 */ 170static ZCONST char Far WrnStorUCSizCSizDiff[] = 171 "%s: ucsize %s <> csize %s for STORED entry\n\ 172 continuing with \"compressed\" size value\n"; 173static ZCONST char Far ExtFieldMsg[] = 174 "%s: bad extra field length (%s)\n"; 175static ZCONST char Far OffsetMsg[] = 176 "file #%lu: bad zipfile offset (%s): %ld\n"; 177static 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 185static ZCONST char Far BadFileCommLength[] = "%s: bad file comment length\n"; 186static ZCONST char Far LocalHdrSig[] = "local header sig"; 187static ZCONST char Far BadLocalHdr[] = "file #%lu: bad local header\n"; 188static 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 194static ZCONST char Far AbsolutePathWarning[] = 195 "warning: stripped absolute path spec from %s\n"; 196static 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 237static ZCONST char Far ErrorInArchive[] = 238 "At least one %serror was detected in %s.\n"; 239static 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 261static ZCONST char Far NoErrInCompData[] = 262 "No errors detected in compressed data of %s.\n"; 263static ZCONST char Far NoErrInTestedFiles[] = 264 "No errors detected in %s for the %lu file%s tested.\n"; 265static ZCONST char Far FilesSkipped[] = 266 "%lu file%s skipped because of unsupported compression or encoding.\n"; 267 268static ZCONST char Far ErrUnzipFile[] = " error: %s%s %s\n"; 269static ZCONST char Far ErrUnzipNoFile[] = "\n error: %s%s\n"; 270static ZCONST char Far NotEnoughMem[] = "not enough memory to "; 271static ZCONST char Far InvalidComprData[] = "invalid compressed data to "; 272static 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 289static ZCONST char Far FileUnknownCompMethod[] = 290 "%s: unknown compression method\n"; 291static ZCONST char Far BadCRC[] = " bad CRC %08lx (should be %08lx)\n"; 292 293 /* TruncEAs[] also used in OS/2 mapname(), close_outfile() */ 294char ZCONST Far TruncEAs[] = " compressed EA data missing (%d bytes)%s"; 295char 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 318static ZCONST char Far UnsupportedExtraField[] = 319 "\nerror: unsupported extra-field compression type (%u)--skipping\n"; 320static 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 331int 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 820static 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 997unsigned 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 1017static 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 1307startover: 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; 1485reprompt: 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 1618static 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 2009static 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 2201static 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 */ 2209static 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 2258int 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 2347int 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 */ 2387uch *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 */ 2449static 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 2495static 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 2552char *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 2678static 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 2695int 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 2813uzbunzip_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