1 /* 2 Copyright (c) 1990-2002 Info-ZIP. All rights reserved. 3 4 See the accompanying file LICENSE, version 2000-Apr-09 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 extract_or_test_entrylist() 20 extract_or_test_member() 21 TestExtraField() 22 test_compr_eb() 23 memextract() 24 memflush() 25 extract_izvms_block() (VMS or VMS_TEXT_CONV) 26 fnfilter() 27 28 ---------------------------------------------------------------------------*/ 29 30 31 #define __EXTRACT_C /* identifies this source module */ 32 #define UNZIP_INTERNAL 33 #include "unzip.h" 34 #ifdef WINDLL 35 # ifdef POCKET_UNZIP 36 # include "wince/intrface.h" 37 # else 38 # include "windll/windll.h" 39 # endif 40 #endif 41 #include "crypt.h" 42 43 #define GRRDUMP(buf,len) { \ 44 int i, j; \ 45 \ 46 for (j = 0; j < (len)/16; ++j) { \ 47 printf(" "); \ 48 for (i = 0; i < 16; ++i) \ 49 printf("%02x ", (uch)(buf)[i+(j<<4)]); \ 50 printf("\n "); \ 51 for (i = 0; i < 16; ++i) { \ 52 char c = (char)(buf)[i+(j<<4)]; \ 53 \ 54 if (c == '\n') \ 55 printf("\\n "); \ 56 else if (c == '\r') \ 57 printf("\\r "); \ 58 else \ 59 printf(" %c ", c); \ 60 } \ 61 printf("\n"); \ 62 } \ 63 if ((len) % 16) { \ 64 printf(" "); \ 65 for (i = j<<4; i < (len); ++i) \ 66 printf("%02x ", (uch)(buf)[i]); \ 67 printf("\n "); \ 68 for (i = j<<4; i < (len); ++i) { \ 69 char c = (char)(buf)[i]; \ 70 \ 71 if (c == '\n') \ 72 printf("\\n "); \ 73 else if (c == '\r') \ 74 printf("\\r "); \ 75 else \ 76 printf(" %c ", c); \ 77 } \ 78 printf("\n"); \ 79 } \ 80 } 81 82 static int store_info OF((__GPRO)); 83 #ifdef SET_DIR_ATTRIB 84 static int extract_or_test_entrylist OF((__GPRO__ unsigned numchunk, 85 ulg *pfilnum, ulg *pnum_bad_pwd, LONGINT *pold_extra_bytes, 86 unsigned *pnum_dirs, dirtime **pdirlist, 87 int error_in_archive)); 88 #else 89 static int extract_or_test_entrylist OF((__GPRO__ unsigned numchunk, 90 ulg *pfilnum, ulg *pnum_bad_pwd, LONGINT *pold_extra_bytes, 91 int error_in_archive)); 92 #endif 93 static int extract_or_test_member OF((__GPRO)); 94 #ifndef SFX 95 static int TestExtraField OF((__GPRO__ uch *ef, unsigned ef_len)); 96 static int test_compr_eb OF((__GPRO__ uch *eb, unsigned eb_size, 97 unsigned compr_offset, 98 int (*test_uc_ebdata)(__GPRO__ uch *eb, unsigned eb_size, 99 uch *eb_ucptr, ulg eb_ucsize))); 100 #endif 101 #if (defined(VMS) || defined(VMS_TEXT_CONV)) 102 static void decompress_bits OF((uch *outptr, unsigned needlen, 103 ZCONST uch *bitptr)); 104 #endif 105 #ifdef SET_DIR_ATTRIB 106 static int dircomp OF((ZCONST zvoid *a, ZCONST zvoid *b)); 107 #endif 108 109 110 111 /*******************************/ 112 /* Strings used in extract.c */ 113 /*******************************/ 114 115 static ZCONST char Far VersionMsg[] = 116 " skipping: %-22s need %s compat. v%u.%u (can do v%u.%u)\n"; 117 static ZCONST char Far ComprMsgNum[] = 118 " skipping: %-22s unsupported compression method %u\n"; 119 #ifndef SFX 120 static ZCONST char Far ComprMsgName[] = 121 " skipping: %-22s `%s' method not supported\n"; 122 static ZCONST char Far CmprNone[] = "store"; 123 static ZCONST char Far CmprShrink[] = "shrink"; 124 static ZCONST char Far CmprReduce[] = "reduce"; 125 static ZCONST char Far CmprImplode[] = "implode"; 126 static ZCONST char Far CmprTokenize[] = "tokenize"; 127 static ZCONST char Far CmprDeflate[] = "deflate"; 128 static ZCONST char Far CmprDeflat64[] = "deflate64"; 129 static ZCONST char Far CmprDCLImplode[] = "DCL implode"; 130 static ZCONST char Far *ComprNames[NUM_METHODS] = { 131 CmprNone, CmprShrink, CmprReduce, CmprReduce, CmprReduce, CmprReduce, 132 CmprImplode, CmprTokenize, CmprDeflate, CmprDeflat64, CmprDCLImplode 133 }; 134 #endif /* !SFX */ 135 static ZCONST char Far FilNamMsg[] = 136 "%s: bad filename length (%s)\n"; 137 static ZCONST char Far ExtFieldMsg[] = 138 "%s: bad extra field length (%s)\n"; 139 static ZCONST char Far OffsetMsg[] = 140 "file #%lu: bad zipfile offset (%s): %ld\n"; 141 static ZCONST char Far ExtractMsg[] = 142 "%8sing: %-22s %s%s"; 143 #ifndef SFX 144 static ZCONST char Far LengthMsg[] = 145 "%s %s: %ld bytes required to uncompress to %lu bytes;\n %s\ 146 supposed to require %lu bytes%s%s%s\n"; 147 #endif 148 149 static ZCONST char Far BadFileCommLength[] = "%s: bad file comment length\n"; 150 static ZCONST char Far LocalHdrSig[] = "local header sig"; 151 static ZCONST char Far BadLocalHdr[] = "file #%lu: bad local header\n"; 152 static ZCONST char Far AttemptRecompensate[] = 153 " (attempting to re-compensate)\n"; 154 #ifndef SFX 155 static ZCONST char Far BackslashPathSep[] = 156 "warning: %s appears to use backslashes as path separators\n"; 157 #endif 158 static ZCONST char Far AbsolutePathWarning[] = 159 "warning: stripped absolute path spec from %s\n"; 160 static ZCONST char Far SkipVolumeLabel[] = 161 " skipping: %-22s %svolume label\n"; 162 163 #ifdef SET_DIR_ATTRIB /* messages of code for setting directory attributes */ 164 static ZCONST char Far DirlistEntryNoMem[] = 165 "warning: cannot alloc memory for dir times/permissions/UID/GID\n"; 166 static ZCONST char Far DirlistSortNoMem[] = 167 "warning: cannot alloc memory to sort dir times/perms/etc.\n"; 168 static ZCONST char Far DirlistSetAttrFailed[] = 169 "warning: set times/attribs failed for %s\n"; 170 #endif 171 172 #ifndef WINDLL 173 static ZCONST char Far ReplaceQuery[] = 174 "replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: "; 175 static ZCONST char Far AssumeNone[] = " NULL\n(assuming [N]one)\n"; 176 static ZCONST char Far NewNameQuery[] = "new name: "; 177 static ZCONST char Far InvalidResponse[] = "error: invalid response [%c]\n"; 178 #endif /* !WINDLL */ 179 180 static ZCONST char Far ErrorInArchive[] = 181 "At least one %serror was detected in %s.\n"; 182 static ZCONST char Far ZeroFilesTested[] = 183 "Caution: zero files tested in %s.\n"; 184 185 #ifndef VMS 186 static ZCONST char Far VMSFormatQuery[] = 187 "\n%s: stored in VMS format. Extract anyway? (y/n) "; 188 #endif 189 190 #if CRYPT 191 static ZCONST char Far SkipCannotGetPasswd[] = 192 " skipping: %-22s unable to get password\n"; 193 static ZCONST char Far SkipIncorrectPasswd[] = 194 " skipping: %-22s incorrect password\n"; 195 static ZCONST char Far FilesSkipBadPasswd[] = 196 "%lu file%s skipped because of incorrect password.\n"; 197 static ZCONST char Far MaybeBadPasswd[] = 198 " (may instead be incorrect password)\n"; 199 #else 200 static ZCONST char Far SkipEncrypted[] = 201 " skipping: %-22s encrypted (not supported)\n"; 202 #endif 203 204 static ZCONST char Far NoErrInCompData[] = 205 "No errors detected in compressed data of %s.\n"; 206 static ZCONST char Far NoErrInTestedFiles[] = 207 "No errors detected in %s for the %lu file%s tested.\n"; 208 static ZCONST char Far FilesSkipped[] = 209 "%lu file%s skipped because of unsupported compression or encoding.\n"; 210 211 static ZCONST char Far ErrUnzipFile[] = " error: %s%s %s\n"; 212 static ZCONST char Far ErrUnzipNoFile[] = "\n error: %s%s\n"; 213 static ZCONST char Far NotEnoughMem[] = "not enough memory to "; 214 static ZCONST char Far InvalidComprData[] = "invalid compressed data to "; 215 static ZCONST char Far Inflate[] = "inflate"; 216 217 #ifndef SFX 218 static ZCONST char Far Explode[] = "explode"; 219 #ifndef LZW_CLEAN 220 static ZCONST char Far Unshrink[] = "unshrink"; 221 #endif 222 #endif 223 224 #if (!defined(DELETE_IF_FULL) || !defined(HAVE_UNLINK)) 225 static ZCONST char Far FileTruncated[] = 226 "warning: %s is probably truncated\n"; 227 #endif 228 229 static ZCONST char Far FileUnknownCompMethod[] = 230 "%s: unknown compression method\n"; 231 static ZCONST char Far BadCRC[] = " bad CRC %08lx (should be %08lx)\n"; 232 233 /* TruncEAs[] also used in OS/2 mapname(), close_outfile() */ 234 char ZCONST Far TruncEAs[] = " compressed EA data missing (%d bytes)%s"; 235 char ZCONST Far TruncNTSD[] = 236 " compressed WinNT security data missing (%d bytes)%s"; 237 238 #ifndef SFX 239 static ZCONST char Far InconsistEFlength[] = "bad extra-field entry:\n \ 240 EF block length (%u bytes) exceeds remaining EF data (%u bytes)\n"; 241 static ZCONST char Far InvalidComprDataEAs[] = 242 " invalid compressed data for EAs\n"; 243 # if (defined(WIN32) && defined(NTSD_EAS)) 244 static ZCONST char Far InvalidSecurityEAs[] = 245 " EAs fail security check\n"; 246 # endif 247 static ZCONST char Far UnsuppNTSDVersEAs[] = 248 " unsupported NTSD EAs version %d\n"; 249 static ZCONST char Far BadCRC_EAs[] = " bad CRC for extended attributes\n"; 250 static ZCONST char Far UnknComprMethodEAs[] = 251 " unknown compression method for EAs (%u)\n"; 252 static ZCONST char Far NotEnoughMemEAs[] = 253 " out of memory while inflating EAs\n"; 254 static ZCONST char Far UnknErrorEAs[] = 255 " unknown error on extended attributes\n"; 256 #endif /* !SFX */ 257 258 static ZCONST char Far UnsupportedExtraField[] = 259 "\nerror: unsupported extra-field compression type (%u)--skipping\n"; 260 static ZCONST char Far BadExtraFieldCRC[] = 261 "error [%s]: bad extra-field CRC %08lx (should be %08lx)\n"; 262 263 264 265 266 267 /**************************************/ 268 /* Function extract_or_test_files() */ 269 /**************************************/ 270 271 int extract_or_test_files(__G) /* return PK-type error code */ 272 __GDEF 273 { 274 unsigned i, j; 275 long cd_bufstart; 276 uch *cd_inptr; 277 int cd_incnt; 278 ulg filnum=0L, blknum=0L; 279 int reached_end, no_endsig_found; 280 int error, error_in_archive=PK_COOL; 281 int *fn_matched=NULL, *xn_matched=NULL; 282 unsigned members_processed; 283 ulg num_skipped=0L, num_bad_pwd=0L; 284 LONGINT old_extra_bytes = 0L; 285 #ifdef SET_DIR_ATTRIB 286 unsigned num_dirs=0; 287 dirtime *dirlist=(dirtime *)NULL, **sorted_dirlist=(dirtime **)NULL; 288 #endif 289 290 /*--------------------------------------------------------------------------- 291 The basic idea of this function is as follows. Since the central di- 292 rectory lies at the end of the zipfile and the member files lie at the 293 beginning or middle or wherever, it is not very desirable to simply 294 read a central directory entry, jump to the member and extract it, and 295 then jump back to the central directory. In the case of a large zipfile 296 this would lead to a whole lot of disk-grinding, especially if each mem- 297 ber file is small. Instead, we read from the central directory the per- 298 tinent information for a block of files, then go extract/test the whole 299 block. Thus this routine contains two small(er) loops within a very 300 large outer loop: the first of the small ones reads a block of files 301 from the central directory; the second extracts or tests each file; and 302 the outer one loops over blocks. There's some file-pointer positioning 303 stuff in between, but that's about it. Btw, it's because of this jump- 304 ing around that we can afford to be lenient if an error occurs in one of 305 the member files: we should still be able to go find the other members, 306 since we know the offset of each from the beginning of the zipfile. 307 ---------------------------------------------------------------------------*/ 308 309 G.pInfo = G.info; 310 311 #if CRYPT 312 G.newzip = TRUE; 313 #endif 314 #ifndef SFX 315 G.reported_backslash = FALSE; 316 #endif 317 318 /* malloc space for check on unmatched filespecs (OK if one or both NULL) */ 319 if (G.filespecs > 0 && 320 (fn_matched=(int *)malloc(G.filespecs*sizeof(int))) != (int *)NULL) 321 for (i = 0; i < G.filespecs; ++i) 322 fn_matched[i] = FALSE; 323 if (G.xfilespecs > 0 && 324 (xn_matched=(int *)malloc(G.xfilespecs*sizeof(int))) != (int *)NULL) 325 for (i = 0; i < G.xfilespecs; ++i) 326 xn_matched[i] = FALSE; 327 328 /*--------------------------------------------------------------------------- 329 Begin main loop over blocks of member files. We know the entire central 330 directory is on this disk: we would not have any of this information un- 331 less the end-of-central-directory record was on this disk, and we would 332 not have gotten to this routine unless this is also the disk on which 333 the central directory starts. In practice, this had better be the ONLY 334 disk in the archive, but we'll add multi-disk support soon. 335 ---------------------------------------------------------------------------*/ 336 337 members_processed = 0; 338 no_endsig_found = FALSE; 339 reached_end = FALSE; 340 while (!reached_end) { 341 j = 0; 342 #ifdef AMIGA 343 memzero(G.filenotes, DIR_BLKSIZ * sizeof(char *)); 344 #endif 345 346 /* 347 * Loop through files in central directory, storing offsets, file 348 * attributes, case-conversion and text-conversion flags until block 349 * size is reached. 350 */ 351 352 while ((j < DIR_BLKSIZ)) { 353 G.pInfo = &G.info[j]; 354 355 if (readbuf(__G__ G.sig, 4) == 0) { 356 error_in_archive = PK_EOF; 357 reached_end = TRUE; /* ...so no more left to do */ 358 break; 359 } 360 if (strncmp(G.sig, central_hdr_sig, 4)) { /* is it a new entry? */ 361 /* no new central directory entry 362 * -> is the number of processed entries compatible with the 363 * number of entries as stored in the end_central record? 364 */ 365 if ((members_processed & (unsigned)0xFFFF) == 366 (unsigned)G.ecrec.total_entries_central_dir) { 367 /* yes, so look if we ARE back at the end_central record 368 */ 369 no_endsig_found = 370 (strncmp(G.sig, end_central_sig, 4) != 0); 371 } else { 372 /* no; we have found an error in the central directory 373 * -> report it and stop searching for more Zip entries 374 */ 375 Info(slide, 0x401, ((char *)slide, 376 LoadFarString(CentSigMsg), j + blknum*DIR_BLKSIZ + 1)); 377 Info(slide, 0x401, ((char *)slide, 378 LoadFarString(ReportMsg))); 379 error_in_archive = PK_BADERR; 380 } 381 reached_end = TRUE; /* ...so no more left to do */ 382 break; 383 } 384 /* process_cdir_file_hdr() sets pInfo->hostnum, pInfo->lcflag */ 385 if ((error = process_cdir_file_hdr(__G)) != PK_COOL) { 386 error_in_archive = error; /* only PK_EOF defined */ 387 reached_end = TRUE; /* ...so no more left to do */ 388 break; 389 } 390 if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) != 391 PK_COOL) 392 { 393 if (error > error_in_archive) 394 error_in_archive = error; 395 if (error > PK_WARN) { /* fatal: no more left to do */ 396 Info(slide, 0x401, ((char *)slide, LoadFarString(FilNamMsg), 397 FnFilter1(G.filename), "central")); 398 reached_end = TRUE; 399 break; 400 } 401 } 402 if ((error = do_string(__G__ G.crec.extra_field_length, 403 EXTRA_FIELD)) != 0) 404 { 405 if (error > error_in_archive) 406 error_in_archive = error; 407 if (error > PK_WARN) { /* fatal */ 408 Info(slide, 0x401, ((char *)slide, 409 LoadFarString(ExtFieldMsg), 410 FnFilter1(G.filename), "central")); 411 reached_end = TRUE; 412 break; 413 } 414 } 415 #ifdef AMIGA 416 G.filenote_slot = j; 417 if ((error = do_string(__G__ G.crec.file_comment_length, 418 uO.N_flag ? FILENOTE : SKIP)) != PK_COOL) 419 #else 420 if ((error = do_string(__G__ G.crec.file_comment_length, SKIP)) 421 != PK_COOL) 422 #endif 423 { 424 if (error > error_in_archive) 425 error_in_archive = error; 426 if (error > PK_WARN) { /* fatal */ 427 Info(slide, 0x421, ((char *)slide, 428 LoadFarString(BadFileCommLength), 429 FnFilter1(G.filename))); 430 reached_end = TRUE; 431 break; 432 } 433 } 434 if (G.process_all_files) { 435 if (store_info(__G)) 436 ++j; /* file is OK; info[] stored; continue with next */ 437 else 438 ++num_skipped; 439 } else { 440 int do_this_file; 441 442 if (G.filespecs == 0) 443 do_this_file = TRUE; 444 else { /* check if this entry matches an `include' argument */ 445 do_this_file = FALSE; 446 for (i = 0; i < G.filespecs; i++) 447 if (match(G.filename, G.pfnames[i], uO.C_flag)) { 448 do_this_file = TRUE; /* ^-- ignore case or not? */ 449 if (fn_matched) 450 fn_matched[i] = TRUE; 451 break; /* found match, so stop looping */ 452 } 453 } 454 if (do_this_file) { /* check if this is an excluded file */ 455 for (i = 0; i < G.xfilespecs; i++) 456 if (match(G.filename, G.pxnames[i], uO.C_flag)) { 457 do_this_file = FALSE; /* ^-- ignore case or not? */ 458 if (xn_matched) 459 xn_matched[i] = TRUE; 460 break; 461 } 462 } 463 if (do_this_file) { 464 if (store_info(__G)) 465 ++j; /* file is OK */ 466 else 467 ++num_skipped; /* unsupp. compression or encryption */ 468 } 469 } /* end if (process_all_files) */ 470 471 members_processed++; 472 473 } /* end while-loop (adding files to current block) */ 474 475 /* save position in central directory so can come back later */ 476 cd_bufstart = G.cur_zipfile_bufstart; 477 cd_inptr = G.inptr; 478 cd_incnt = G.incnt; 479 480 /*----------------------------------------------------------------------- 481 Second loop: process files in current block, extracting or testing 482 each one. 483 -----------------------------------------------------------------------*/ 484 485 error = extract_or_test_entrylist(__G__ j, 486 &filnum, &num_bad_pwd, &old_extra_bytes, 487 #ifdef SET_DIR_ATTRIB 488 &num_dirs, &dirlist, 489 #endif 490 error_in_archive); 491 if (error != PK_COOL) { 492 if (error > error_in_archive) 493 error_in_archive = error; /* ...and keep going */ 494 if (G.disk_full > 1 || error_in_archive == IZ_CTRLC) { 495 if (fn_matched) 496 free((zvoid *)fn_matched); 497 if (xn_matched) 498 free((zvoid *)xn_matched); 499 return error_in_archive; /* (unless disk full) */ 500 } 501 } 502 503 504 /* 505 * Jump back to where we were in the central directory, then go and do 506 * the next batch of files. 507 */ 508 509 #ifdef USE_STRM_INPUT 510 fseek((FILE *)G.zipfd, (LONGINT)cd_bufstart, SEEK_SET); 511 G.cur_zipfile_bufstart = ftell((FILE *)G.zipfd); 512 #else /* !USE_STRM_INPUT */ 513 G.cur_zipfile_bufstart = 514 lseek(G.zipfd, (LONGINT)cd_bufstart, SEEK_SET); 515 #endif /* ?USE_STRM_INPUT */ 516 read(G.zipfd, (char *)G.inbuf, INBUFSIZ); /* been here before... */ 517 G.inptr = cd_inptr; 518 G.incnt = cd_incnt; 519 ++blknum; 520 521 #ifdef TEST 522 printf("\ncd_bufstart = %ld (%.8lXh)\n", cd_bufstart, cd_bufstart); 523 printf("cur_zipfile_bufstart = %ld (%.8lXh)\n", cur_zipfile_bufstart, 524 cur_zipfile_bufstart); 525 printf("inptr-inbuf = %d\n", G.inptr-G.inbuf); 526 printf("incnt = %d\n\n", G.incnt); 527 #endif 528 529 } /* end while-loop (blocks of files in central directory) */ 530 531 /*--------------------------------------------------------------------------- 532 Go back through saved list of directories, sort and set times/perms/UIDs 533 and GIDs from the deepest level on up. 534 ---------------------------------------------------------------------------*/ 535 536 #ifdef SET_DIR_ATTRIB 537 if (num_dirs > 0) { 538 sorted_dirlist = (dirtime **)malloc(num_dirs*sizeof(dirtime *)); 539 if (sorted_dirlist == (dirtime **)NULL) { 540 Info(slide, 0x401, ((char *)slide, 541 LoadFarString(DirlistSortNoMem))); 542 while (dirlist != (dirtime *)NULL) { 543 dirtime *d = dirlist; 544 545 dirlist = dirlist->next; 546 free(d); 547 } 548 } else { 549 if (num_dirs == 1) 550 sorted_dirlist[0] = dirlist; 551 else { 552 for (i = 0; i < num_dirs; ++i) { 553 sorted_dirlist[i] = dirlist; 554 dirlist = dirlist->next; 555 } 556 qsort((char *)sorted_dirlist, num_dirs, sizeof(dirtime *), 557 dircomp); 558 } 559 560 Trace((stderr, "setting directory times/perms/attributes\n")); 561 for (i = 0; i < num_dirs; ++i) { 562 dirtime *d = sorted_dirlist[i]; 563 564 Trace((stderr, "dir = %s\n", d->fn)); 565 if ((error = set_direc_attribs(__G__ d)) != PK_OK) { 566 Info(slide, 0x201, ((char *)slide, 567 LoadFarString(DirlistSetAttrFailed), d->fn)); 568 if (!error_in_archive) 569 error_in_archive = error; 570 } 571 free(d->fn); 572 free(d); 573 } 574 free(sorted_dirlist); 575 } 576 } 577 #endif /* SET_DIR_ATTRIB */ 578 579 #if (defined(WIN32) && defined(NTSD_EAS)) 580 process_defer_NT(__G); /* process any deferred items for this .zip file */ 581 #endif 582 583 /*--------------------------------------------------------------------------- 584 Check for unmatched filespecs on command line and print warning if any 585 found. Free allocated memory. 586 ---------------------------------------------------------------------------*/ 587 588 if (fn_matched) { 589 for (i = 0; i < G.filespecs; ++i) 590 if (!fn_matched[i]) { 591 #ifdef DLL 592 if (!G.redirect_data && !G.redirect_text) 593 Info(slide, 0x401, ((char *)slide, 594 LoadFarString(FilenameNotMatched), G.pfnames[i])); 595 else 596 setFileNotFound(__G); 597 #else 598 Info(slide, 1, ((char *)slide, 599 LoadFarString(FilenameNotMatched), G.pfnames[i])); 600 #endif 601 if (error_in_archive <= PK_WARN) 602 error_in_archive = PK_FIND; /* some files not found */ 603 } 604 free((zvoid *)fn_matched); 605 } 606 if (xn_matched) { 607 for (i = 0; i < G.xfilespecs; ++i) 608 if (!xn_matched[i]) 609 Info(slide, 0x401, ((char *)slide, 610 LoadFarString(ExclFilenameNotMatched), G.pxnames[i])); 611 free((zvoid *)xn_matched); 612 } 613 614 /*--------------------------------------------------------------------------- 615 Double-check that we're back at the end-of-central-directory record, and 616 print quick summary of results, if we were just testing the archive. We 617 send the summary to stdout so that people doing the testing in the back- 618 ground and redirecting to a file can just do a "tail" on the output file. 619 ---------------------------------------------------------------------------*/ 620 621 #ifndef SFX 622 if (no_endsig_found) { /* just to make sure */ 623 Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg))); 624 Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg))); 625 if (!error_in_archive) /* don't overwrite stronger error */ 626 error_in_archive = PK_WARN; 627 } 628 #endif /* !SFX */ 629 if (uO.tflag) { 630 ulg num = filnum - num_bad_pwd; 631 632 if (uO.qflag < 2) { /* GRR 930710: was (uO.qflag == 1) */ 633 if (error_in_archive) 634 Info(slide, 0, ((char *)slide, LoadFarString(ErrorInArchive), 635 (error_in_archive == PK_WARN)? "warning-" : "", G.zipfn)); 636 else if (num == 0L) 637 Info(slide, 0, ((char *)slide, LoadFarString(ZeroFilesTested), 638 G.zipfn)); 639 else if (G.process_all_files && (num_skipped+num_bad_pwd == 0L)) 640 Info(slide, 0, ((char *)slide, LoadFarString(NoErrInCompData), 641 G.zipfn)); 642 else 643 Info(slide, 0, ((char *)slide, LoadFarString(NoErrInTestedFiles) 644 , G.zipfn, num, (num==1L)? "":"s")); 645 if (num_skipped > 0L) 646 Info(slide, 0, ((char *)slide, LoadFarString(FilesSkipped), 647 num_skipped, (num_skipped==1L)? "":"s")); 648 #if CRYPT 649 if (num_bad_pwd > 0L) 650 Info(slide, 0, ((char *)slide, LoadFarString(FilesSkipBadPasswd) 651 , num_bad_pwd, (num_bad_pwd==1L)? "":"s")); 652 #endif /* CRYPT */ 653 } else if ((uO.qflag == 0) && !error_in_archive && (num == 0)) 654 Info(slide, 0, ((char *)slide, LoadFarString(ZeroFilesTested), 655 G.zipfn)); 656 } 657 658 /* give warning if files not tested or extracted (first condition can still 659 * happen if zipfile is empty and no files specified on command line) */ 660 661 if ((filnum == 0) && error_in_archive <= PK_WARN) { 662 if (num_skipped > 0L) 663 error_in_archive = IZ_UNSUP; /* unsupport. compression/encryption */ 664 else 665 error_in_archive = PK_FIND; /* no files found at all */ 666 } 667 #if CRYPT 668 else if ((filnum == num_bad_pwd) && error_in_archive <= PK_WARN) 669 error_in_archive = IZ_BADPWD; /* bad passwd => all files skipped */ 670 #endif 671 else if ((num_skipped > 0L) && error_in_archive <= PK_WARN) 672 error_in_archive = IZ_UNSUP; /* was PK_WARN; Jean-loup complained */ 673 #if CRYPT 674 else if ((num_bad_pwd > 0L) && !error_in_archive) 675 error_in_archive = PK_WARN; 676 #endif 677 678 return error_in_archive; 679 680 } /* end function extract_or_test_files() */ 681 682 683 684 685 686 /***************************/ 687 /* Function store_info() */ 688 /***************************/ 689 690 static int store_info(__G) /* return 0 if skipping, 1 if OK */ 691 __GDEF 692 { 693 #ifdef SFX 694 # ifdef USE_DEFLATE64 695 # define UNKN_COMPR \ 696 (G.crec.compression_method!=STORED && G.crec.compression_method<DEFLATED \ 697 && G.crec.compression_method>ENHDEFLATED) 698 # else 699 # define UNKN_COMPR \ 700 (G.crec.compression_method!=STORED && G.crec.compression_method!=DEFLATED) 701 # endif 702 #else 703 # ifdef COPYRIGHT_CLEAN /* no reduced files */ 704 # define UNKN_RED (G.crec.compression_method >= REDUCED1 && \ 705 G.crec.compression_method <= REDUCED4) 706 # else 707 # define UNKN_RED FALSE /* reducing not unknown */ 708 # endif 709 # ifdef LZW_CLEAN /* no shrunk files */ 710 # define UNKN_SHR (G.crec.compression_method == SHRUNK) 711 # else 712 # define UNKN_SHR FALSE /* unshrinking not unknown */ 713 # endif 714 # ifdef USE_DEFLATE64 715 # define UNKN_COMPR (UNKN_RED || UNKN_SHR || \ 716 G.crec.compression_method==TOKENIZED || \ 717 G.crec.compression_method>ENHDEFLATED) 718 # else 719 # define UNKN_COMPR (UNKN_RED || UNKN_SHR || \ 720 G.crec.compression_method==TOKENIZED || \ 721 G.crec.compression_method>DEFLATED) 722 # endif 723 #endif 724 725 /*--------------------------------------------------------------------------- 726 Check central directory info for version/compatibility requirements. 727 ---------------------------------------------------------------------------*/ 728 729 G.pInfo->encrypted = G.crec.general_purpose_bit_flag & 1; /* bit field */ 730 G.pInfo->ExtLocHdr = (G.crec.general_purpose_bit_flag & 8) == 8; /* bit */ 731 G.pInfo->textfile = G.crec.internal_file_attributes & 1; /* bit field */ 732 G.pInfo->crc = G.crec.crc32; 733 G.pInfo->compr_size = G.crec.csize; 734 G.pInfo->uncompr_size = G.crec.ucsize; 735 736 switch (uO.aflag) { 737 case 0: 738 G.pInfo->textmode = FALSE; /* bit field */ 739 break; 740 case 1: 741 G.pInfo->textmode = G.pInfo->textfile; /* auto-convert mode */ 742 break; 743 default: /* case 2: */ 744 G.pInfo->textmode = TRUE; 745 break; 746 } 747 748 if (G.crec.version_needed_to_extract[1] == VMS_) { 749 if (G.crec.version_needed_to_extract[0] > VMS_UNZIP_VERSION) { 750 if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) 751 Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg), 752 FnFilter1(G.filename), "VMS", 753 G.crec.version_needed_to_extract[0] / 10, 754 G.crec.version_needed_to_extract[0] % 10, 755 VMS_UNZIP_VERSION / 10, VMS_UNZIP_VERSION % 10)); 756 return 0; 757 } 758 #ifndef VMS /* won't be able to use extra field, but still have data */ 759 else if (!uO.tflag && !IS_OVERWRT_ALL) { /* if -o, extract anyway */ 760 Info(slide, 0x481, ((char *)slide, LoadFarString(VMSFormatQuery), 761 FnFilter1(G.filename))); 762 fgets(G.answerbuf, 9, stdin); 763 if ((*G.answerbuf != 'y') && (*G.answerbuf != 'Y')) 764 return 0; 765 } 766 #endif /* !VMS */ 767 /* usual file type: don't need VMS to extract */ 768 } else if (G.crec.version_needed_to_extract[0] > UNZIP_VERSION) { 769 if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) 770 Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg), 771 FnFilter1(G.filename), "PK", 772 G.crec.version_needed_to_extract[0] / 10, 773 G.crec.version_needed_to_extract[0] % 10, 774 UNZIP_VERSION / 10, UNZIP_VERSION % 10)); 775 return 0; 776 } 777 778 if UNKN_COMPR { 779 if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) { 780 #ifndef SFX 781 if (G.crec.compression_method < NUM_METHODS) 782 Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgName), 783 FnFilter1(G.filename), 784 LoadFarStringSmall(ComprNames[G.crec.compression_method]))); 785 else 786 #endif 787 Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgNum), 788 FnFilter1(G.filename), 789 G.crec.compression_method)); 790 } 791 return 0; 792 } 793 #if (!CRYPT) 794 if (G.pInfo->encrypted) { 795 if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) 796 Info(slide, 0x401, ((char *)slide, LoadFarString(SkipEncrypted), 797 FnFilter1(G.filename))); 798 return 0; 799 } 800 #endif /* !CRYPT */ 801 802 /* map whatever file attributes we have into the local format */ 803 mapattr(__G); /* GRR: worry about return value later */ 804 805 G.pInfo->diskstart = G.crec.disk_number_start; 806 G.pInfo->offset = (long)G.crec.relative_offset_local_header; 807 return 1; 808 809 } /* end function store_info() */ 810 811 812 813 814 815 /******************************************/ 816 /* Function extract_or_test_entrylist() */ 817 /******************************************/ 818 819 static int extract_or_test_entrylist(__G__ numchunk, 820 pfilnum, pnum_bad_pwd, pold_extra_bytes, 821 #ifdef SET_DIR_ATTRIB 822 pnum_dirs, pdirlist, 823 #endif 824 error_in_archive) /* return PK-type error code */ 825 __GDEF 826 unsigned numchunk; 827 ulg *pfilnum; 828 ulg *pnum_bad_pwd; 829 LONGINT *pold_extra_bytes; 830 #ifdef SET_DIR_ATTRIB 831 unsigned *pnum_dirs; 832 dirtime **pdirlist; 833 #endif 834 int error_in_archive; 835 { 836 unsigned i; 837 int renamed, query; 838 int skip_entry; 839 long bufstart, inbuf_offset, request; 840 int error, errcode; 841 842 /* possible values for local skip_entry flag: */ 843 #define SKIP_NO 0 /* do not skip this entry */ 844 #define SKIP_Y_EXISTING 1 /* skip this entry, do not overwrite file */ 845 #define SKIP_Y_NONEXIST 2 /* skip this entry, do not create new file */ 846 847 /*----------------------------------------------------------------------- 848 Second loop: process files in current block, extracting or testing 849 each one. 850 -----------------------------------------------------------------------*/ 851 852 for (i = 0; i < numchunk; ++i) { 853 (*pfilnum)++; /* *pfilnum = i + blknum*DIR_BLKSIZ + 1; */ 854 G.pInfo = &G.info[i]; 855 #ifdef NOVELL_BUG_FAILSAFE 856 G.dne = FALSE; /* assume file exists until stat() says otherwise */ 857 #endif 858 859 /* if the target position is not within the current input buffer 860 * (either haven't yet read far enough, or (maybe) skipping back- 861 * ward), skip to the target position and reset readbuf(). */ 862 863 /* seek_zipf(__G__ pInfo->offset); */ 864 request = G.pInfo->offset + G.extra_bytes; 865 inbuf_offset = request % INBUFSIZ; 866 bufstart = request - inbuf_offset; 867 868 Trace((stderr, "\ndebug: request = %ld, inbuf_offset = %ld\n", 869 request, inbuf_offset)); 870 Trace((stderr, 871 "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n", 872 bufstart, G.cur_zipfile_bufstart)); 873 if (request < 0) { 874 Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(SeekMsg), 875 G.zipfn, LoadFarString(ReportMsg))); 876 error_in_archive = PK_ERR; 877 if (*pfilnum == 1 && G.extra_bytes != 0L) { 878 Info(slide, 0x401, ((char *)slide, 879 LoadFarString(AttemptRecompensate))); 880 *pold_extra_bytes = G.extra_bytes; 881 G.extra_bytes = 0L; 882 request = G.pInfo->offset; /* could also check if != 0 */ 883 inbuf_offset = request % INBUFSIZ; 884 bufstart = request - inbuf_offset; 885 Trace((stderr, "debug: request = %ld, inbuf_offset = %ld\n", 886 request, inbuf_offset)); 887 Trace((stderr, 888 "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n", 889 bufstart, G.cur_zipfile_bufstart)); 890 /* try again */ 891 if (request < 0) { 892 Trace((stderr, 893 "debug: recompensated request still < 0\n")); 894 Info(slide, 0x401, ((char *)slide, 895 LoadFarStringSmall(SeekMsg), 896 G.zipfn, LoadFarString(ReportMsg))); 897 error_in_archive = PK_BADERR; 898 continue; 899 } 900 } else { 901 error_in_archive = PK_BADERR; 902 continue; /* this one hosed; try next */ 903 } 904 } 905 906 if (bufstart != G.cur_zipfile_bufstart) { 907 Trace((stderr, "debug: bufstart != cur_zipfile_bufstart\n")); 908 #ifdef USE_STRM_INPUT 909 fseek((FILE *)G.zipfd, (LONGINT)bufstart, SEEK_SET); 910 G.cur_zipfile_bufstart = ftell((FILE *)G.zipfd); 911 #else /* !USE_STRM_INPUT */ 912 G.cur_zipfile_bufstart = 913 lseek(G.zipfd, (LONGINT)bufstart, SEEK_SET); 914 #endif /* ?USE_STRM_INPUT */ 915 if ((G.incnt = read(G.zipfd,(char *)G.inbuf,INBUFSIZ)) <= 0) 916 { 917 Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg), 918 *pfilnum, "lseek", bufstart)); 919 error_in_archive = PK_BADERR; 920 continue; /* can still do next file */ 921 } 922 G.inptr = G.inbuf + (int)inbuf_offset; 923 G.incnt -= (int)inbuf_offset; 924 } else { 925 G.incnt += (int)(G.inptr-G.inbuf) - (int)inbuf_offset; 926 G.inptr = G.inbuf + (int)inbuf_offset; 927 } 928 929 /* should be in proper position now, so check for sig */ 930 if (readbuf(__G__ G.sig, 4) == 0) { /* bad offset */ 931 Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg), 932 *pfilnum, "EOF", request)); 933 error_in_archive = PK_BADERR; 934 continue; /* but can still try next one */ 935 } 936 if (strncmp(G.sig, local_hdr_sig, 4)) { 937 Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg), 938 *pfilnum, LoadFarStringSmall(LocalHdrSig), request)); 939 /* 940 GRRDUMP(G.sig, 4) 941 GRRDUMP(local_hdr_sig, 4) 942 */ 943 error_in_archive = PK_ERR; 944 if ((*pfilnum == 1 && G.extra_bytes != 0L) || 945 (G.extra_bytes == 0L && *pold_extra_bytes != 0L)) { 946 Info(slide, 0x401, ((char *)slide, 947 LoadFarString(AttemptRecompensate))); 948 if (G.extra_bytes) { 949 *pold_extra_bytes = G.extra_bytes; 950 G.extra_bytes = 0L; 951 } else 952 G.extra_bytes = *pold_extra_bytes; /* third attempt */ 953 if (((error = seek_zipf(__G__ G.pInfo->offset)) != PK_OK) || 954 (readbuf(__G__ G.sig, 4) == 0)) { /* bad offset */ 955 if (error != PK_BADERR) 956 Info(slide, 0x401, ((char *)slide, 957 LoadFarString(OffsetMsg), *pfilnum, "EOF", request)); 958 error_in_archive = PK_BADERR; 959 continue; /* but can still try next one */ 960 } 961 if (strncmp(G.sig, local_hdr_sig, 4)) { 962 Info(slide, 0x401, ((char *)slide, 963 LoadFarString(OffsetMsg), *pfilnum, 964 LoadFarStringSmall(LocalHdrSig), request)); 965 error_in_archive = PK_BADERR; 966 continue; 967 } 968 } else 969 continue; /* this one hosed; try next */ 970 } 971 if ((error = process_local_file_hdr(__G)) != PK_COOL) { 972 Info(slide, 0x421, ((char *)slide, LoadFarString(BadLocalHdr), 973 *pfilnum)); 974 error_in_archive = error; /* only PK_EOF defined */ 975 continue; /* can still try next one */ 976 } 977 if ((error = do_string(__G__ G.lrec.filename_length, DS_FN_L)) != 978 PK_COOL) 979 { 980 if (error > error_in_archive) 981 error_in_archive = error; 982 if (error > PK_WARN) { 983 Info(slide, 0x401, ((char *)slide, LoadFarString(FilNamMsg), 984 FnFilter1(G.filename), "local")); 985 continue; /* go on to next one */ 986 } 987 } 988 if (G.extra_field != (uch *)NULL) { 989 free(G.extra_field); 990 G.extra_field = (uch *)NULL; 991 } 992 if ((error = 993 do_string(__G__ G.lrec.extra_field_length, EXTRA_FIELD)) != 0) 994 { 995 if (error > error_in_archive) 996 error_in_archive = error; 997 if (error > PK_WARN) { 998 Info(slide, 0x401, ((char *)slide, 999 LoadFarString(ExtFieldMsg), 1000 FnFilter1(G.filename), "local")); 1001 continue; /* go on */ 1002 } 1003 } 1004 1005 #if CRYPT 1006 if (G.pInfo->encrypted && 1007 (error = decrypt(__G__ uO.pwdarg)) != PK_COOL) { 1008 if (error == PK_WARN) { 1009 if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) 1010 Info(slide, 0x401, ((char *)slide, 1011 LoadFarString(SkipIncorrectPasswd), 1012 FnFilter1(G.filename))); 1013 ++(*pnum_bad_pwd); 1014 } else { /* (error > PK_WARN) */ 1015 if (error > error_in_archive) 1016 error_in_archive = error; 1017 Info(slide, 0x401, ((char *)slide, 1018 LoadFarString(SkipCannotGetPasswd), 1019 FnFilter1(G.filename))); 1020 } 1021 continue; /* go on to next file */ 1022 } 1023 #endif /* CRYPT */ 1024 1025 /* 1026 * just about to extract file: if extracting to disk, check if 1027 * already exists, and if so, take appropriate action according to 1028 * fflag/uflag/overwrite_all/etc. (we couldn't do this in upper 1029 * loop because we don't store the possibly renamed filename[] in 1030 * info[]) 1031 */ 1032 #ifdef DLL 1033 if (!uO.tflag && !uO.cflag && !G.redirect_data) 1034 #else 1035 if (!uO.tflag && !uO.cflag) 1036 #endif 1037 { 1038 renamed = FALSE; /* user hasn't renamed output file yet */ 1039 1040 startover: 1041 query = FALSE; 1042 skip_entry = SKIP_NO; 1043 /* for files from DOS FAT, check for use of backslash instead 1044 * of slash as directory separator (bug in some zipper(s); so 1045 * far, not a problem in HPFS, NTFS or VFAT systems) 1046 */ 1047 #ifndef SFX 1048 if (G.pInfo->hostnum == FS_FAT_ && !MBSCHR(G.filename, '/')) { 1049 char *p=G.filename; 1050 1051 if (*p) do { 1052 if (*p == '\\') { 1053 if (!G.reported_backslash) { 1054 Info(slide, 0x21, ((char *)slide, 1055 LoadFarString(BackslashPathSep), G.zipfn)); 1056 G.reported_backslash = TRUE; 1057 if (!error_in_archive) 1058 error_in_archive = PK_WARN; 1059 } 1060 *p = '/'; 1061 } 1062 } while (*PREINCSTR(p)); 1063 } 1064 #endif /* !SFX */ 1065 1066 if (!renamed) { 1067 /* remove absolute path specs */ 1068 if (G.filename[0] == '/') { 1069 Info(slide, 0x401, ((char *)slide, 1070 LoadFarString(AbsolutePathWarning), 1071 FnFilter1(G.filename))); 1072 if (!error_in_archive) 1073 error_in_archive = PK_WARN; 1074 do { 1075 char *p = G.filename + 1; 1076 do { 1077 *(p-1) = *p; 1078 } while (*p++ != '\0'); 1079 } while (G.filename[0] == '/'); 1080 } 1081 } 1082 1083 /* mapname can create dirs if not freshening or if renamed */ 1084 error = mapname(__G__ renamed); 1085 if ((errcode = error & ~MPN_MASK) != PK_OK && 1086 error_in_archive < errcode) 1087 error_in_archive = errcode; 1088 if ((errcode = error & MPN_MASK) > MPN_INF_TRUNC) { 1089 if (errcode == MPN_CREATED_DIR) { 1090 #ifdef SET_DIR_ATTRIB 1091 dirtime *d_entry; 1092 1093 d_entry = (dirtime *)malloc(sizeof(dirtime)); 1094 if (d_entry == (dirtime *)NULL) { 1095 Info(slide, 0x401, ((char *)slide, 1096 LoadFarString(DirlistEntryNoMem))); 1097 } else { 1098 unsigned eb_izux_flg; 1099 1100 d_entry->next = (*pdirlist); 1101 (*pdirlist) = d_entry; 1102 (*pdirlist)->fn = 1103 (char *)malloc(strlen(G.filename) + 1); 1104 if ((*pdirlist)->fn == (char *)NULL) { 1105 Info(slide, 0x401, ((char *)slide, 1106 LoadFarString(DirlistEntryNoMem))); 1107 (*pdirlist) = d_entry->next; 1108 free(d_entry); 1109 if (!error_in_archive) 1110 error_in_archive = PK_WARN; 1111 continue; 1112 } 1113 strcpy((*pdirlist)->fn, G.filename); 1114 (*pdirlist)->perms = G.pInfo->file_attr; 1115 #ifdef USE_EF_UT_TIME 1116 eb_izux_flg = G.extra_field? ef_scan_for_izux( 1117 G.extra_field, G.lrec.extra_field_length, 0, 1118 G.lrec.last_mod_dos_datetime, 1119 #ifdef IZ_CHECK_TZ 1120 (G.tz_is_valid ? &((*pdirlist)->u.t3) : NULL), 1121 #else 1122 &((*pdirlist)->u.t3), 1123 #endif 1124 (*pdirlist)->uidgid) 1125 : 0; 1126 #else /* !USE_EF_UT_TIME */ 1127 eb_izux_flg = 0; 1128 #endif /* ?USE_EF_UT_TIME */ 1129 if (eb_izux_flg & EB_UT_FL_MTIME) { 1130 TTrace((stderr, 1131 "\nextract: Unix dir e.f. modtime = %ld\n", 1132 (*pdirlist)->u.t3.mtime)); 1133 } else { 1134 (*pdirlist)->u.t3.mtime = dos_to_unix_time( 1135 G.lrec.last_mod_dos_datetime); 1136 } 1137 if (eb_izux_flg & EB_UT_FL_ATIME) { 1138 TTrace((stderr, 1139 "\nextract: Unix dir e.f. actime = %ld\n", 1140 (*pdirlist)->u.t3.atime)); 1141 } else { 1142 (*pdirlist)->u.t3.atime = 1143 (*pdirlist)->u.t3.mtime; 1144 } 1145 (*pdirlist)->have_uidgid = 1146 #ifdef RESTORE_UIDGID 1147 (uO.X_flag && (eb_izux_flg & EB_UX2_VALID)); 1148 #else 1149 0; 1150 #endif 1151 ++(*pnum_dirs); 1152 } 1153 #endif /* SET_DIR_ATTRIB */ 1154 } else if (errcode == MPN_VOL_LABEL) { 1155 #ifdef DOS_OS2_W32 1156 Info(slide, 0x401, ((char *)slide, 1157 LoadFarString(SkipVolumeLabel), 1158 FnFilter1(G.filename), 1159 uO.volflag? "hard disk " : "")); 1160 #else 1161 Info(slide, 1, ((char *)slide, 1162 LoadFarString(SkipVolumeLabel), 1163 FnFilter1(G.filename), "")); 1164 #endif 1165 } else if (errcode > MPN_INF_SKIP && 1166 error_in_archive < PK_ERR) 1167 error_in_archive = PK_ERR; 1168 Trace((stderr, "mapname(%s) returns error code = %d\n", 1169 FnFilter1(G.filename), error)); 1170 continue; /* go on to next file */ 1171 } 1172 1173 #ifdef QDOS 1174 QFilename(__G__ G.filename); 1175 #endif 1176 switch (check_for_newer(__G__ G.filename)) { 1177 case DOES_NOT_EXIST: 1178 #ifdef NOVELL_BUG_FAILSAFE 1179 G.dne = TRUE; /* stat() says file DOES NOT EXIST */ 1180 #endif 1181 /* freshen (no new files): skip unless just renamed */ 1182 if (uO.fflag && !renamed) 1183 skip_entry = SKIP_Y_NONEXIST; 1184 break; 1185 case EXISTS_AND_OLDER: 1186 #ifdef UNIXBACKUP 1187 if (!uO.B_flag) 1188 #endif 1189 { 1190 if (IS_OVERWRT_NONE) 1191 /* never overwrite: skip file */ 1192 skip_entry = SKIP_Y_EXISTING; 1193 else if (!IS_OVERWRT_ALL) 1194 query = TRUE; 1195 } 1196 break; 1197 case EXISTS_AND_NEWER: /* (or equal) */ 1198 #ifdef UNIXBACKUP 1199 if ((!uO.B_flag && IS_OVERWRT_NONE) || 1200 #else 1201 if (IS_OVERWRT_NONE || 1202 #endif 1203 (uO.uflag && !renamed)) { 1204 /* skip if update/freshen & orig name */ 1205 skip_entry = SKIP_Y_EXISTING; 1206 } else { 1207 #ifdef UNIXBACKUP 1208 if (!IS_OVERWRT_ALL && !uO.B_flag) 1209 #else 1210 if (!IS_OVERWRT_ALL) 1211 #endif 1212 query = TRUE; 1213 } 1214 break; 1215 } 1216 if (query) { 1217 #ifdef WINDLL 1218 switch (G.lpUserFunctions->replace != NULL ? 1219 (*G.lpUserFunctions->replace)(G.filename) : 1220 IDM_REPLACE_NONE) { 1221 case IDM_REPLACE_RENAME: 1222 _ISO_INTERN(G.filename); 1223 renamed = TRUE; 1224 goto startover; 1225 case IDM_REPLACE_ALL: 1226 G.overwrite_mode = OVERWRT_ALWAYS; 1227 /* FALL THROUGH, extract */ 1228 case IDM_REPLACE_YES: 1229 break; 1230 case IDM_REPLACE_NONE: 1231 G.overwrite_mode = OVERWRT_NEVER; 1232 /* FALL THROUGH, skip */ 1233 case IDM_REPLACE_NO: 1234 skip_entry = SKIP_Y_EXISTING; 1235 break; 1236 } 1237 #else /* !WINDLL */ 1238 extent fnlen; 1239 reprompt: 1240 Info(slide, 0x81, ((char *)slide, 1241 LoadFarString(ReplaceQuery), 1242 FnFilter1(G.filename))); 1243 if (fgets(G.answerbuf, 9, stdin) == (char *)NULL) { 1244 Info(slide, 1, ((char *)slide, 1245 LoadFarString(AssumeNone))); 1246 *G.answerbuf = 'N'; 1247 if (!error_in_archive) 1248 error_in_archive = 1; /* not extracted: warning */ 1249 } 1250 switch (*G.answerbuf) { 1251 case 'r': 1252 case 'R': 1253 do { 1254 Info(slide, 0x81, ((char *)slide, 1255 LoadFarString(NewNameQuery))); 1256 fgets(G.filename, FILNAMSIZ, stdin); 1257 /* usually get \n here: better check for it */ 1258 fnlen = strlen(G.filename); 1259 if (lastchar(G.filename, fnlen) == '\n') 1260 G.filename[--fnlen] = '\0'; 1261 } while (fnlen == 0); 1262 #ifdef WIN32 /* WIN32 fgets( ... , stdin) returns OEM coded strings */ 1263 _OEM_INTERN(G.filename); 1264 #endif 1265 renamed = TRUE; 1266 goto startover; /* sorry for a goto */ 1267 case 'A': /* dangerous option: force caps */ 1268 G.overwrite_mode = OVERWRT_ALWAYS; 1269 /* FALL THROUGH, extract */ 1270 case 'y': 1271 case 'Y': 1272 break; 1273 case 'N': 1274 G.overwrite_mode = OVERWRT_NEVER; 1275 /* FALL THROUGH, skip */ 1276 case 'n': 1277 /* skip file */ 1278 skip_entry = SKIP_Y_EXISTING; 1279 break; 1280 default: 1281 Info(slide, 1, ((char *)slide, 1282 LoadFarString(InvalidResponse), *G.answerbuf)); 1283 goto reprompt; /* yet another goto? */ 1284 } /* end switch (*answerbuf) */ 1285 #endif /* ?WINDLL */ 1286 } /* end if (query) */ 1287 if (skip_entry != SKIP_NO) { 1288 #ifdef WINDLL 1289 if (skip_entry == SKIP_Y_EXISTING) { 1290 /* report skipping of an existing entry */ 1291 Info(slide, 0, ((char *)slide, 1292 ((IS_OVERWRT_NONE || !uO.uflag || renamed) ? 1293 "Target file exists.\nSkipping %s\n" : 1294 "Target file newer.\nSkipping %s\n"), 1295 FnFilter1(G.filename))); 1296 } 1297 #endif /* WINDLL */ 1298 continue; 1299 } 1300 } /* end if (extracting to disk) */ 1301 1302 #ifdef DLL 1303 if ((G.statreportcb != NULL) && 1304 (*G.statreportcb)(__G__ UZ_ST_START_EXTRACT, G.zipfn, 1305 G.filename, NULL)) { 1306 return IZ_CTRLC; /* cancel operation by user request */ 1307 } 1308 #endif 1309 #ifdef MACOS /* MacOS is no preemptive OS, thus call event-handling by hand */ 1310 UserStop(); 1311 #endif 1312 #ifdef AMIGA 1313 G.filenote_slot = i; 1314 #endif 1315 G.disk_full = 0; 1316 if ((error = extract_or_test_member(__G)) != PK_COOL) { 1317 if (error > error_in_archive) 1318 error_in_archive = error; /* ...and keep going */ 1319 #ifdef DLL 1320 if (G.disk_full > 1 || error_in_archive == IZ_CTRLC) { 1321 #else 1322 if (G.disk_full > 1) { 1323 #endif 1324 return error_in_archive; /* (unless disk full) */ 1325 } 1326 } 1327 #ifdef DLL 1328 if ((G.statreportcb != NULL) && 1329 (*G.statreportcb)(__G__ UZ_ST_FINISH_MEMBER, G.zipfn, 1330 G.filename, (zvoid *)&G.lrec.ucsize)) { 1331 return IZ_CTRLC; /* cancel operation by user request */ 1332 } 1333 #endif 1334 #ifdef MACOS /* MacOS is no preemptive OS, thus call event-handling by hand */ 1335 UserStop(); 1336 #endif 1337 } /* end for-loop (i: files in current block) */ 1338 1339 return error_in_archive; 1340 1341 } /* end function extract_or_test_entrylist() */ 1342 1343 1344 1345 1346 1347 /***************************************/ 1348 /* Function extract_or_test_member() */ 1349 /***************************************/ 1350 1351 static int extract_or_test_member(__G) /* return PK-type error code */ 1352 __GDEF 1353 { 1354 char *nul="[empty] ", *txt="[text] ", *bin="[binary]"; 1355 #ifdef CMS_MVS 1356 char *ebc="[ebcdic]"; 1357 #endif 1358 register int b; 1359 int r, error=PK_COOL; 1360 #if (defined(DLL) && !defined(NO_SLIDE_REDIR)) 1361 ulg wsize; 1362 #else 1363 # define wsize WSIZE 1364 #endif 1365 1366 1367 /*--------------------------------------------------------------------------- 1368 Initialize variables, buffers, etc. 1369 ---------------------------------------------------------------------------*/ 1370 1371 G.bits_left = 0; 1372 G.bitbuf = 0L; /* unreduce and unshrink only */ 1373 G.zipeof = 0; 1374 G.newfile = TRUE; 1375 G.crc32val = CRCVAL_INITIAL; 1376 1377 #ifdef SYMLINKS 1378 /* if file came from Unix and is a symbolic link and we are extracting 1379 * to disk, prepare to restore the link */ 1380 if (S_ISLNK(G.pInfo->file_attr) && 1381 (G.pInfo->hostnum == UNIX_ || G.pInfo->hostnum == ATARI_ || 1382 G.pInfo->hostnum == BEOS_) && 1383 !uO.tflag && !uO.cflag && (G.lrec.ucsize > 0)) 1384 G.symlnk = TRUE; 1385 else 1386 G.symlnk = FALSE; 1387 #endif /* SYMLINKS */ 1388 1389 if (uO.tflag) { 1390 if (!uO.qflag) 1391 Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), "test", 1392 FnFilter1(G.filename), "", "")); 1393 } else { 1394 #ifdef DLL 1395 if (uO.cflag && !G.redirect_data) 1396 #else 1397 if (uO.cflag) 1398 #endif 1399 { 1400 #if (defined(OS2) && defined(__IBMC__) && (__IBMC__ >= 200)) 1401 G.outfile = freopen("", "wb", stdout); /* VAC++ ignores setmode */ 1402 #else 1403 G.outfile = stdout; 1404 #endif 1405 #ifdef DOS_FLX_NLM_OS2_W32 1406 #if (defined(__HIGHC__) && !defined(FLEXOS)) 1407 setmode(G.outfile, _BINARY); 1408 #else /* !(defined(__HIGHC__) && !defined(FLEXOS)) */ 1409 setmode(fileno(G.outfile), O_BINARY); 1410 #endif /* ?(defined(__HIGHC__) && !defined(FLEXOS)) */ 1411 # define NEWLINE "\r\n" 1412 #else /* !DOS_FLX_NLM_OS2_W32 */ 1413 # define NEWLINE "\n" 1414 #endif /* ?DOS_FLX_NLM_OS2_W32 */ 1415 #ifdef VMS 1416 if (open_outfile(__G)) /* VMS: required even for stdout! */ 1417 return PK_DISK; 1418 #endif 1419 } else if (open_outfile(__G)) 1420 return PK_DISK; 1421 } 1422 1423 /*--------------------------------------------------------------------------- 1424 Unpack the file. 1425 ---------------------------------------------------------------------------*/ 1426 1427 defer_leftover_input(__G); /* so NEXTBYTE bounds check will work */ 1428 switch (G.lrec.compression_method) { 1429 case STORED: 1430 if (!uO.tflag && QCOND2) { 1431 #ifdef SYMLINKS 1432 if (G.symlnk) /* can also be deflated, but rarer... */ 1433 Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), 1434 "link", FnFilter1(G.filename), "", "")); 1435 else 1436 #endif /* SYMLINKS */ 1437 Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), 1438 "extract", FnFilter1(G.filename), 1439 (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)? 1440 "" : (G.lrec.ucsize == 0L? nul : (G.pInfo->textfile? txt : 1441 bin)), uO.cflag? NEWLINE : "")); 1442 } 1443 #if (defined(DLL) && !defined(NO_SLIDE_REDIR)) 1444 if (G.redirect_slide) { 1445 wsize = G.redirect_size; redirSlide = G.redirect_buffer; 1446 } else { 1447 wsize = WSIZE; redirSlide = slide; 1448 } 1449 #endif 1450 G.outptr = redirSlide; 1451 G.outcnt = 0L; 1452 while ((b = NEXTBYTE) != EOF) { 1453 *G.outptr++ = (uch)b; 1454 if (++G.outcnt == wsize) { 1455 error = flush(__G__ redirSlide, G.outcnt, 0); 1456 G.outptr = redirSlide; 1457 G.outcnt = 0L; 1458 if (error != PK_COOL || G.disk_full) break; 1459 } 1460 } 1461 if (G.outcnt) /* flush final (partial) buffer */ 1462 flush(__G__ redirSlide, G.outcnt, 0); 1463 break; 1464 1465 #ifndef SFX 1466 #ifndef LZW_CLEAN 1467 case SHRUNK: 1468 if (!uO.tflag && QCOND2) { 1469 Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), 1470 LoadFarStringSmall(Unshrink), FnFilter1(G.filename), 1471 (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)? 1472 "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : "")); 1473 } 1474 if ((r = unshrink(__G)) != PK_COOL) { 1475 if (r < PK_DISK) { 1476 if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)) 1477 Info(slide, 0x401, ((char *)slide, 1478 LoadFarStringSmall(ErrUnzipFile), 1479 LoadFarString(NotEnoughMem), 1480 LoadFarStringSmall2(Unshrink), 1481 FnFilter1(G.filename))); 1482 else 1483 Info(slide, 0x401, ((char *)slide, 1484 LoadFarStringSmall(ErrUnzipNoFile), 1485 LoadFarString(NotEnoughMem), 1486 LoadFarStringSmall2(Unshrink))); 1487 } 1488 error = r; 1489 } 1490 break; 1491 #endif /* !LZW_CLEAN */ 1492 1493 #ifndef COPYRIGHT_CLEAN 1494 case REDUCED1: 1495 case REDUCED2: 1496 case REDUCED3: 1497 case REDUCED4: 1498 if (!uO.tflag && QCOND2) { 1499 Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), 1500 "unreduc", FnFilter1(G.filename), 1501 (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)? 1502 "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : "")); 1503 } 1504 if ((r = unreduce(__G)) != PK_COOL) { 1505 /* unreduce() returns only PK_COOL, PK_DISK, or IZ_CTRLC */ 1506 error = r; 1507 } 1508 break; 1509 #endif /* !COPYRIGHT_CLEAN */ 1510 1511 case IMPLODED: 1512 if (!uO.tflag && QCOND2) { 1513 Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), 1514 "explod", FnFilter1(G.filename), 1515 (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)? 1516 "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : "")); 1517 } 1518 if (((r = explode(__G)) != 0) && (r != 5)) { /* treat 5 specially */ 1519 if (r < PK_DISK) { 1520 if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)) 1521 Info(slide, 0x401, ((char *)slide, 1522 LoadFarStringSmall(ErrUnzipFile), r == 3? 1523 LoadFarString(NotEnoughMem) : 1524 LoadFarString(InvalidComprData), 1525 LoadFarStringSmall2(Explode), 1526 FnFilter1(G.filename))); 1527 else 1528 Info(slide, 0x401, ((char *)slide, 1529 LoadFarStringSmall(ErrUnzipNoFile), r == 3? 1530 LoadFarString(NotEnoughMem) : 1531 LoadFarString(InvalidComprData), 1532 LoadFarStringSmall2(Explode))); 1533 error = (r == 3)? PK_MEM3 : PK_ERR; 1534 } else { 1535 error = r; 1536 } 1537 } 1538 if (r == 5) { 1539 int warning = ((ulg)G.used_csize <= G.lrec.csize); 1540 1541 if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)) 1542 Info(slide, 0x401, ((char *)slide, LoadFarString(LengthMsg), 1543 "", warning? "warning" : "error", G.used_csize, 1544 G.lrec.ucsize, warning? " " : "", G.lrec.csize, 1545 " [", FnFilter1(G.filename), "]")); 1546 else 1547 Info(slide, 0x401, ((char *)slide, LoadFarString(LengthMsg), 1548 "\n", warning? "warning" : "error", G.used_csize, 1549 G.lrec.ucsize, warning? " ":"", G.lrec.csize, 1550 "", "", ".")); 1551 error = warning? PK_WARN : PK_ERR; 1552 } 1553 break; 1554 #endif /* !SFX */ 1555 1556 case DEFLATED: 1557 #ifdef USE_DEFLATE64 1558 case ENHDEFLATED: 1559 #endif 1560 if (!uO.tflag && QCOND2) { 1561 Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), 1562 "inflat", FnFilter1(G.filename), 1563 (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)? 1564 "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : "")); 1565 } 1566 #ifndef USE_ZLIB /* zlib's function is called inflate(), too */ 1567 # define UZinflate inflate 1568 #endif 1569 if ((r = UZinflate(__G__ 1570 (G.lrec.compression_method == ENHDEFLATED))) 1571 != 0) { 1572 if (r < PK_DISK) { 1573 if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)) 1574 Info(slide, 0x401, ((char *)slide, 1575 LoadFarStringSmall(ErrUnzipFile), r == 3? 1576 LoadFarString(NotEnoughMem) : 1577 LoadFarString(InvalidComprData), 1578 LoadFarStringSmall2(Inflate), 1579 FnFilter1(G.filename))); 1580 else 1581 Info(slide, 0x401, ((char *)slide, 1582 LoadFarStringSmall(ErrUnzipNoFile), r == 3? 1583 LoadFarString(NotEnoughMem) : 1584 LoadFarString(InvalidComprData), 1585 LoadFarStringSmall2(Inflate))); 1586 error = (r == 3)? PK_MEM3 : PK_ERR; 1587 } else { 1588 error = r; 1589 } 1590 } 1591 break; 1592 1593 default: /* should never get to this point */ 1594 Info(slide, 0x401, ((char *)slide, 1595 LoadFarString(FileUnknownCompMethod), FnFilter1(G.filename))); 1596 /* close and delete file before return? */ 1597 undefer_input(__G); 1598 return PK_WARN; 1599 1600 } /* end switch (compression method) */ 1601 1602 /*--------------------------------------------------------------------------- 1603 Close the file and set its date and time (not necessarily in that order), 1604 and make sure the CRC checked out OK. Logical-AND the CRC for 64-bit 1605 machines (redundant on 32-bit machines). 1606 ---------------------------------------------------------------------------*/ 1607 1608 #ifdef VMS /* VMS: required even for stdout! (final flush) */ 1609 if (!uO.tflag) /* don't close NULL file */ 1610 close_outfile(__G); 1611 #else 1612 #ifdef DLL 1613 if (!uO.tflag && (!uO.cflag || G.redirect_data)) { 1614 if (G.redirect_data) 1615 FINISH_REDIRECT(); 1616 else 1617 close_outfile(__G); 1618 } 1619 #else 1620 if (!uO.tflag && !uO.cflag) /* don't close NULL file or stdout */ 1621 close_outfile(__G); 1622 #endif 1623 #endif /* VMS */ 1624 1625 /* GRR: CONVERT close_outfile() TO NON-VOID: CHECK FOR ERRORS! */ 1626 1627 1628 if (G.disk_full) { /* set by flush() */ 1629 if (G.disk_full > 1) { 1630 #if (defined(DELETE_IF_FULL) && defined(HAVE_UNLINK)) 1631 /* delete the incomplete file if we can */ 1632 if (unlink(G.filename) != 0) 1633 Trace((stderr, "extract.c: could not delete %s\n", 1634 FnFilter1(G.filename))); 1635 #else 1636 /* warn user about the incomplete file */ 1637 Info(slide, 0x421, ((char *)slide, LoadFarString(FileTruncated), 1638 FnFilter1(G.filename))); 1639 #endif 1640 error = PK_DISK; 1641 } else { 1642 error = PK_WARN; 1643 } 1644 } 1645 1646 if (error > PK_WARN) {/* don't print redundant CRC error if error already */ 1647 undefer_input(__G); 1648 return error; 1649 } 1650 if (G.crc32val != G.lrec.crc32) { 1651 /* if quiet enough, we haven't output the filename yet: do it */ 1652 if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)) 1653 Info(slide, 0x401, ((char *)slide, "%-22s ", 1654 FnFilter1(G.filename))); 1655 Info(slide, 0x401, ((char *)slide, LoadFarString(BadCRC), G.crc32val, 1656 G.lrec.crc32)); 1657 #if CRYPT 1658 if (G.pInfo->encrypted) 1659 Info(slide, 0x401, ((char *)slide, LoadFarString(MaybeBadPasswd))); 1660 #endif 1661 error = PK_ERR; 1662 } else if (uO.tflag) { 1663 #ifndef SFX 1664 if (G.extra_field) { 1665 if ((r = TestExtraField(__G__ G.extra_field, 1666 G.lrec.extra_field_length)) > error) 1667 error = r; 1668 } else 1669 #endif /* !SFX */ 1670 if (!uO.qflag) 1671 Info(slide, 0, ((char *)slide, " OK\n")); 1672 } else { 1673 if (QCOND2 && !error) /* GRR: is stdout reset to text mode yet? */ 1674 Info(slide, 0, ((char *)slide, "\n")); 1675 } 1676 1677 undefer_input(__G); 1678 return error; 1679 1680 } /* end function extract_or_test_member() */ 1681 1682 1683 1684 1685 1686 #ifndef SFX 1687 1688 /*******************************/ 1689 /* Function TestExtraField() */ 1690 /*******************************/ 1691 1692 static int TestExtraField(__G__ ef, ef_len) 1693 __GDEF 1694 uch *ef; 1695 unsigned ef_len; 1696 { 1697 ush ebID; 1698 unsigned ebLen; 1699 unsigned eb_cmpr_offs = 0; 1700 int r; 1701 1702 /* we know the regular compressed file data tested out OK, or else we 1703 * wouldn't be here ==> print filename if any extra-field errors found 1704 */ 1705 while (ef_len >= EB_HEADSIZE) { 1706 ebID = makeword(ef); 1707 ebLen = (unsigned)makeword(ef+EB_LEN); 1708 1709 if (ebLen > (ef_len - EB_HEADSIZE)) { 1710 /* Discovered some extra field inconsistency! */ 1711 if (uO.qflag) 1712 Info(slide, 1, ((char *)slide, "%-22s ", 1713 FnFilter1(G.filename))); 1714 Info(slide, 1, ((char *)slide, LoadFarString(InconsistEFlength), 1715 ebLen, (ef_len - EB_HEADSIZE))); 1716 return PK_ERR; 1717 } 1718 1719 switch (ebID) { 1720 case EF_OS2: 1721 case EF_ACL: 1722 case EF_MAC3: 1723 case EF_BEOS: 1724 switch (ebID) { 1725 case EF_OS2: 1726 case EF_ACL: 1727 eb_cmpr_offs = EB_OS2_HLEN; 1728 break; 1729 case EF_MAC3: 1730 if (ebLen >= EB_MAC3_HLEN && 1731 (makeword(ef+(EB_HEADSIZE+EB_FLGS_OFFS)) 1732 & EB_M3_FL_UNCMPR) && 1733 (makelong(ef+EB_HEADSIZE) == ebLen - EB_MAC3_HLEN)) 1734 eb_cmpr_offs = 0; 1735 else 1736 eb_cmpr_offs = EB_MAC3_HLEN; 1737 break; 1738 case EF_BEOS: 1739 if (ebLen >= EB_BEOS_HLEN && 1740 (*(ef+(EB_HEADSIZE+EB_FLGS_OFFS)) & EB_BE_FL_UNCMPR) && 1741 (makelong(ef+EB_HEADSIZE) == ebLen - EB_BEOS_HLEN)) 1742 eb_cmpr_offs = 0; 1743 else 1744 eb_cmpr_offs = EB_BEOS_HLEN; 1745 break; 1746 } 1747 if ((r = test_compr_eb(__G__ ef, ebLen, eb_cmpr_offs, NULL)) 1748 != PK_OK) { 1749 if (uO.qflag) 1750 Info(slide, 1, ((char *)slide, "%-22s ", 1751 FnFilter1(G.filename))); 1752 switch (r) { 1753 case IZ_EF_TRUNC: 1754 Info(slide, 1, ((char *)slide, 1755 LoadFarString(TruncEAs), 1756 ebLen-(eb_cmpr_offs+EB_CMPRHEADLEN), "\n")); 1757 break; 1758 case PK_ERR: 1759 Info(slide, 1, ((char *)slide, 1760 LoadFarString(InvalidComprDataEAs))); 1761 break; 1762 case PK_MEM3: 1763 case PK_MEM4: 1764 Info(slide, 1, ((char *)slide, 1765 LoadFarString(NotEnoughMemEAs))); 1766 break; 1767 default: 1768 if ((r & 0xff) != PK_ERR) 1769 Info(slide, 1, ((char *)slide, 1770 LoadFarString(UnknErrorEAs))); 1771 else { 1772 ush m = (ush)(r >> 8); 1773 if (m == DEFLATED) /* GRR KLUDGE! */ 1774 Info(slide, 1, ((char *)slide, 1775 LoadFarString(BadCRC_EAs))); 1776 else 1777 Info(slide, 1, ((char *)slide, 1778 LoadFarString(UnknComprMethodEAs), m)); 1779 } 1780 break; 1781 } 1782 return r; 1783 } 1784 break; 1785 1786 case EF_NTSD: 1787 Trace((stderr, "ebID: %i / ebLen: %u\n", ebID, ebLen)); 1788 r = ebLen < EB_NTSD_L_LEN ? IZ_EF_TRUNC : 1789 ((ef[EB_HEADSIZE+EB_NTSD_VERSION] > EB_NTSD_MAX_VER) ? 1790 (PK_WARN | 0x4000) : 1791 test_compr_eb(__G__ ef, ebLen, EB_NTSD_L_LEN, TEST_NTSD)); 1792 if (r != PK_OK) { 1793 if (uO.qflag) 1794 Info(slide, 1, ((char *)slide, "%-22s ", 1795 FnFilter1(G.filename))); 1796 switch (r) { 1797 case IZ_EF_TRUNC: 1798 Info(slide, 1, ((char *)slide, 1799 LoadFarString(TruncNTSD), 1800 ebLen-(EB_NTSD_L_LEN+EB_CMPRHEADLEN), "\n")); 1801 break; 1802 #if (defined(WIN32) && defined(NTSD_EAS)) 1803 case PK_WARN: 1804 Info(slide, 1, ((char *)slide, 1805 LoadFarString(InvalidSecurityEAs))); 1806 break; 1807 #endif 1808 case PK_ERR: 1809 Info(slide, 1, ((char *)slide, 1810 LoadFarString(InvalidComprDataEAs))); 1811 break; 1812 case PK_MEM3: 1813 case PK_MEM4: 1814 Info(slide, 1, ((char *)slide, 1815 LoadFarString(NotEnoughMemEAs))); 1816 break; 1817 case (PK_WARN | 0x4000): 1818 Info(slide, 1, ((char *)slide, 1819 LoadFarString(UnsuppNTSDVersEAs), 1820 (int)ef[EB_HEADSIZE+EB_NTSD_VERSION])); 1821 r = PK_WARN; 1822 break; 1823 default: 1824 if ((r & 0xff) != PK_ERR) 1825 Info(slide, 1, ((char *)slide, 1826 LoadFarString(UnknErrorEAs))); 1827 else { 1828 ush m = (ush)(r >> 8); 1829 if (m == DEFLATED) /* GRR KLUDGE! */ 1830 Info(slide, 1, ((char *)slide, 1831 LoadFarString(BadCRC_EAs))); 1832 else 1833 Info(slide, 1, ((char *)slide, 1834 LoadFarString(UnknComprMethodEAs), m)); 1835 } 1836 break; 1837 } 1838 return r; 1839 } 1840 break; 1841 case EF_PKVMS: 1842 if (makelong(ef+EB_HEADSIZE) != 1843 crc32(CRCVAL_INITIAL, ef+(EB_HEADSIZE+4), 1844 (extent)(ebLen-4))) 1845 Info(slide, 1, ((char *)slide, 1846 LoadFarString(BadCRC_EAs))); 1847 break; 1848 case EF_PKW32: 1849 case EF_PKUNIX: 1850 case EF_ASIUNIX: 1851 case EF_IZVMS: 1852 case EF_IZUNIX: 1853 case EF_VMCMS: 1854 case EF_MVS: 1855 case EF_SPARK: 1856 case EF_TANDEM: 1857 case EF_THEOS: 1858 case EF_AV: 1859 default: 1860 break; 1861 } 1862 ef_len -= (ebLen + EB_HEADSIZE); 1863 ef += (ebLen + EB_HEADSIZE); 1864 } 1865 1866 if (!uO.qflag) 1867 Info(slide, 0, ((char *)slide, " OK\n")); 1868 1869 return PK_COOL; 1870 1871 } /* end function TestExtraField() */ 1872 1873 1874 1875 1876 1877 /******************************/ 1878 /* Function test_compr_eb() */ 1879 /******************************/ 1880 1881 #ifdef PROTO 1882 static int test_compr_eb( 1883 __GPRO__ 1884 uch *eb, 1885 unsigned eb_size, 1886 unsigned compr_offset, 1887 int (*test_uc_ebdata)(__GPRO__ uch *eb, unsigned eb_size, 1888 uch *eb_ucptr, ulg eb_ucsize)) 1889 #else /* !PROTO */ 1890 static int test_compr_eb(__G__ eb, eb_size, compr_offset, test_uc_ebdata) 1891 __GDEF 1892 uch *eb; 1893 unsigned eb_size; 1894 unsigned compr_offset; 1895 int (*test_uc_ebdata)(); 1896 #endif /* ?PROTO */ 1897 { 1898 ulg eb_ucsize; 1899 uch *eb_ucptr; 1900 int r; 1901 1902 if (compr_offset < 4) /* field is not compressed: */ 1903 return PK_OK; /* do nothing and signal OK */ 1904 1905 if ((eb_size < (EB_UCSIZE_P + 4)) || 1906 ((eb_ucsize = makelong(eb+(EB_HEADSIZE+EB_UCSIZE_P))) > 0L && 1907 eb_size <= (compr_offset + EB_CMPRHEADLEN))) 1908 return IZ_EF_TRUNC; /* no compressed data! */ 1909 1910 if ((eb_ucptr = (uch *)malloc((extent)eb_ucsize)) == (uch *)NULL) 1911 return PK_MEM4; 1912 1913 r = memextract(__G__ eb_ucptr, eb_ucsize, 1914 eb + (EB_HEADSIZE + compr_offset), 1915 (ulg)(eb_size - compr_offset)); 1916 1917 if (r == PK_OK && test_uc_ebdata != NULL) 1918 r = (*test_uc_ebdata)(__G__ eb, eb_size, eb_ucptr, eb_ucsize); 1919 1920 free(eb_ucptr); 1921 return r; 1922 1923 } /* end function test_compr_eb() */ 1924 1925 #endif /* !SFX */ 1926 1927 1928 1929 1930 1931 /***************************/ 1932 /* Function memextract() */ 1933 /***************************/ 1934 1935 int memextract(__G__ tgt, tgtsize, src, srcsize) /* extract compressed */ 1936 __GDEF /* extra field block; */ 1937 uch *tgt; /* return PK-type error */ 1938 ulg tgtsize; /* level */ 1939 ZCONST uch *src; 1940 ulg srcsize; 1941 { 1942 long old_csize=G.csize; 1943 uch *old_inptr=G.inptr; 1944 int old_incnt=G.incnt; 1945 int r, error=PK_OK; 1946 ush method; 1947 ulg extra_field_crc; 1948 1949 1950 method = makeword(src); 1951 extra_field_crc = makelong(src+2); 1952 1953 /* compressed extra field exists completely in memory at this location: */ 1954 G.inptr = (uch *)src + (2 + 4); /* method and extra_field_crc */ 1955 G.incnt = (int)(G.csize = (long)(srcsize - (2 + 4))); 1956 G.mem_mode = TRUE; 1957 G.outbufptr = tgt; 1958 G.outsize = tgtsize; 1959 1960 switch (method) { 1961 case STORED: 1962 memcpy((char *)tgt, (char *)G.inptr, (extent)G.incnt); 1963 G.outcnt = G.csize; /* for CRC calculation */ 1964 break; 1965 case DEFLATED: 1966 #ifdef USE_DEFLATE64 1967 case ENHDEFLATED: 1968 #endif 1969 G.outcnt = 0L; 1970 if ((r = UZinflate(__G__ (method == ENHDEFLATED))) != 0) { 1971 if (!uO.tflag) 1972 Info(slide, 0x401, ((char *)slide, 1973 LoadFarStringSmall(ErrUnzipNoFile), r == 3? 1974 LoadFarString(NotEnoughMem) : 1975 LoadFarString(InvalidComprData), 1976 LoadFarStringSmall2(Inflate))); 1977 error = (r == 3)? PK_MEM3 : PK_ERR; 1978 } 1979 if (G.outcnt == 0L) /* inflate's final FLUSH sets outcnt */ 1980 break; 1981 break; 1982 default: 1983 if (uO.tflag) 1984 error = PK_ERR | ((int)method << 8); 1985 else { 1986 Info(slide, 0x401, ((char *)slide, 1987 LoadFarString(UnsupportedExtraField), method)); 1988 error = PK_ERR; /* GRR: should be passed on up via SetEAs() */ 1989 } 1990 break; 1991 } 1992 1993 G.inptr = old_inptr; 1994 G.incnt = old_incnt; 1995 G.csize = old_csize; 1996 G.mem_mode = FALSE; 1997 1998 if (!error) { 1999 register ulg crcval = crc32(CRCVAL_INITIAL, tgt, (extent)G.outcnt); 2000 2001 if (crcval != extra_field_crc) { 2002 if (uO.tflag) 2003 error = PK_ERR | (DEFLATED << 8); /* kludge for now */ 2004 else { 2005 Info(slide, 0x401, ((char *)slide, 2006 LoadFarString(BadExtraFieldCRC), G.zipfn, crcval, 2007 extra_field_crc)); 2008 error = PK_ERR; 2009 } 2010 } 2011 } 2012 return error; 2013 2014 } /* end function memextract() */ 2015 2016 2017 2018 2019 2020 /*************************/ 2021 /* Function memflush() */ 2022 /*************************/ 2023 2024 int memflush(__G__ rawbuf, size) 2025 __GDEF 2026 ZCONST uch *rawbuf; 2027 ulg size; 2028 { 2029 if (size > G.outsize) 2030 /* Here, PK_DISK is a bit off-topic, but in the sense of marking 2031 "overflow of output space", its use may be tolerated. */ 2032 return PK_DISK; /* more data than output buffer can hold */ 2033 2034 2035 2036 memcpy((char *)G.outbufptr, (char *)rawbuf, (extent)size); 2037 G.outbufptr += (unsigned int)size; 2038 G.outsize -= size; 2039 G.outcnt += size; 2040 2041 return 0; 2042 2043 } /* end function memflush() */ 2044 2045 2046 2047 2048 2049 #if (defined(VMS) || defined(VMS_TEXT_CONV)) 2050 2051 /************************************/ 2052 /* Function extract_izvms_block() */ 2053 /************************************/ 2054 2055 /* 2056 * Extracts block from p. If resulting length is less then needed, fill 2057 * extra space with corresponding bytes from 'init'. 2058 * Currently understands 3 formats of block compression: 2059 * - Simple storing 2060 * - Compression of zero bytes to zero bits 2061 * - Deflation (see memextract()) 2062 * The IZVMS block data is returned in malloc'd space. 2063 */ 2064 uch *extract_izvms_block(__G__ ebdata, size, retlen, init, needlen) 2065 __GDEF 2066 ZCONST uch *ebdata; 2067 unsigned size; 2068 unsigned *retlen; 2069 ZCONST uch *init; 2070 unsigned needlen; 2071 { 2072 uch *ucdata; /* Pointer to block allocated */ 2073 int cmptype; 2074 unsigned usiz, csiz; 2075 2076 cmptype = (makeword(ebdata+EB_IZVMS_FLGS) & EB_IZVMS_BCMASK); 2077 csiz = size - EB_IZVMS_HLEN; 2078 usiz = (cmptype == EB_IZVMS_BCSTOR ? 2079 csiz : makeword(ebdata+EB_IZVMS_UCSIZ)); 2080 2081 if (retlen) 2082 *retlen = usiz; 2083 2084 if ((ucdata = (uch *)malloc(MAX(needlen, usiz))) == NULL) 2085 return NULL; 2086 2087 if (init && (usiz < needlen)) 2088 memcpy((char *)ucdata, (ZCONST char *)init, needlen); 2089 2090 switch (cmptype) 2091 { 2092 case EB_IZVMS_BCSTOR: /* The simplest case */ 2093 memcpy(ucdata, ebdata+EB_IZVMS_HLEN, usiz); 2094 break; 2095 case EB_IZVMS_BC00: 2096 decompress_bits(ucdata, usiz, ebdata+EB_IZVMS_HLEN); 2097 break; 2098 case EB_IZVMS_BCDEFL: 2099 memextract(__G__ ucdata, (ulg)usiz, 2100 ebdata+EB_IZVMS_HLEN, (ulg)csiz); 2101 break; 2102 default: 2103 free(ucdata); 2104 ucdata = NULL; 2105 } 2106 return ucdata; 2107 2108 } /* end of extract_izvms_block */ 2109 2110 2111 2112 2113 2114 /********************************/ 2115 /* Function decompress_bits() */ 2116 /********************************/ 2117 /* 2118 * Simple uncompression routine. The compression uses bit stream. 2119 * Compression scheme: 2120 * 2121 * if (byte!=0) 2122 * putbit(1),putbyte(byte) 2123 * else 2124 * putbit(0) 2125 */ 2126 static void decompress_bits(outptr, needlen, bitptr) 2127 uch *outptr; /* Pointer into output block */ 2128 unsigned needlen; /* Size of uncompressed block */ 2129 ZCONST uch *bitptr; /* Pointer into compressed data */ 2130 { 2131 ulg bitbuf = 0; 2132 int bitcnt = 0; 2133 2134 #define _FILL { bitbuf |= (*bitptr++) << bitcnt;\ 2135 bitcnt += 8; \ 2136 } 2137 2138 while (needlen--) 2139 { 2140 if (bitcnt <= 0) 2141 _FILL; 2142 2143 if (bitbuf & 1) 2144 { 2145 bitbuf >>= 1; 2146 if ((bitcnt -= 1) < 8) 2147 _FILL; 2148 *outptr++ = (uch)bitbuf; 2149 bitcnt -= 8; 2150 bitbuf >>= 8; 2151 } 2152 else 2153 { 2154 *outptr++ = '\0'; 2155 bitcnt -= 1; 2156 bitbuf >>= 1; 2157 } 2158 } 2159 } /* end function decompress_bits() */ 2160 2161 #endif /* VMS || VMS_TEXT_CONV */ 2162 2163 2164 2165 2166 2167 /*************************/ 2168 /* Function fnfilter() */ /* here instead of in list.c for SFX */ 2169 /*************************/ 2170 2171 char *fnfilter(raw, space) /* convert name to safely printable form */ 2172 ZCONST char *raw; 2173 uch *space; 2174 { 2175 #ifndef NATIVE /* ASCII: filter ANSI escape codes, etc. */ 2176 ZCONST uch *r=(ZCONST uch *)raw; 2177 uch *s=space; 2178 2179 while (*r) { 2180 #ifdef QDOS 2181 if (qlflag & 2) { 2182 if (*r == '/' || *r == '.') { 2183 ++r; 2184 *s++ = '_'; 2185 continue; 2186 } 2187 } else 2188 #endif 2189 if (*r < 32) { 2190 *s++ = '^', *s++ = (uch)(64 + *r++); 2191 } else { 2192 #ifdef _MBCS 2193 unsigned i; 2194 for (i = CLEN(r); i > 0; i--) 2195 *s++ = *r++; 2196 #else 2197 *s++ = *r++; 2198 #endif 2199 } 2200 } 2201 *s = '\0'; 2202 2203 #ifdef WINDLL 2204 INTERN_TO_ISO((char *)space, (char *)space); /* translate to ANSI */ 2205 #else 2206 #ifdef WIN32 2207 /* Win9x console always uses OEM character coding, and 2208 WinNT console is set to OEM charset by default, too */ 2209 INTERN_TO_OEM((char *)space, (char *)space); 2210 #endif /* WIN32 */ 2211 #endif /* ?WINDLL */ 2212 2213 return (char *)space; 2214 2215 #else /* NATIVE: EBCDIC or whatever */ 2216 return (char *)raw; 2217 #endif 2218 2219 } /* end function fnfilter() */ 2220 2221 2222 2223 2224 2225 #ifdef SET_DIR_ATTRIB 2226 /* must sort saved directories so can set perms from bottom up */ 2227 2228 /************************/ 2229 /* Function dircomp() */ 2230 /************************/ 2231 2232 static int dircomp(a, b) /* used by qsort(); swiped from Zip */ 2233 ZCONST zvoid *a, *b; 2234 { 2235 /* order is significant: this sorts in reverse order (deepest first) */ 2236 return strcmp((*(dirtime **)b)->fn, (*(dirtime **)a)->fn); 2237 /* return namecmp((*(dirtime **)b)->fn, (*(dirtime **)a)->fn); */ 2238 } 2239 2240 2241 2242 #if 0 /* not used in Unix, but maybe for future OSes? */ 2243 2244 /************************/ 2245 /* Function namecmp() */ 2246 /************************/ 2247 2248 static int namecmp(s1, s2) /* [not] used by dircomp(); swiped from Zip */ 2249 ZCONST char *s1, *s2; 2250 { 2251 int d; 2252 2253 for (;;) { 2254 d = (int)(uch)case_map(*s1) 2255 - (int)(uch)case_map(*s2); 2256 2257 if (d || *s1 == 0 || *s2 == 0) 2258 return d; 2259 2260 s1++; 2261 s2++; 2262 } 2263 } 2264 2265 #endif /* 0 */ 2266 #endif /* SET_DIR_ATTRIB */ 2267