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 fileio.c 12 13 This file contains routines for doing direct but relatively generic input/ 14 output, file-related sorts of things, plus some miscellaneous stuff. Most 15 of the stuff has to do with opening, closing, reading and/or writing files. 16 17 Contains: open_input_file() 18 open_outfile() (not: VMS, AOS/VS, CMSMVS, MACOS, TANDEM) 19 undefer_input() 20 defer_leftover_input() 21 readbuf() 22 readbyte() 23 fillinbuf() 24 seek_zipf() 25 flush() (non-VMS) 26 is_vms_varlen_txt() (non-VMS, VMS_TEXT_CONV only) 27 disk_error() (non-VMS) 28 UzpMessagePrnt() 29 UzpMessageNull() (DLL only) 30 UzpInput() 31 UzpMorePause() 32 UzpPassword() (non-WINDLL) 33 handler() 34 dos_to_unix_time() (non-VMS, non-VM/CMS, non-MVS) 35 check_for_newer() (non-VMS, non-OS/2, non-VM/CMS, non-MVS) 36 do_string() 37 makeword() 38 makelong() 39 str2iso() (CRYPT && NEED_STR2ISO, only) 40 str2oem() (CRYPT && NEED_STR2OEM, only) 41 memset() (ZMEM only) 42 memcpy() (ZMEM only) 43 zstrnicmp() (NO_STRNICMP only) 44 zstat() (REGULUS only) 45 plastchar() (_MBCS only) 46 uzmbschr() (_MBCS && NEED_UZMBSCHR, only) 47 uzmbsrchr() (_MBCS && NEED_UZMBSRCHR, only) 48 fLoadFarString() (SMALL_MEM only) 49 fLoadFarStringSmall() (SMALL_MEM only) 50 fLoadFarStringSmall2() (SMALL_MEM only) 51 zfstrcpy() (SMALL_MEM only) 52 53 ---------------------------------------------------------------------------*/ 54 55 56 #define __FILEIO_C /* identifies this source module */ 57 #define UNZIP_INTERNAL 58 #include "unzip.h" 59 #ifdef WINDLL 60 # include "windll/windll.h" 61 # include <setjmp.h> 62 #endif 63 #include "crypt.h" 64 #include "ttyio.h" 65 66 /* setup of codepage conversion for decryption passwords */ 67 #if CRYPT 68 # if (defined(CRYP_USES_ISO2OEM) && !defined(IZ_ISO2OEM_ARRAY)) 69 # define IZ_ISO2OEM_ARRAY /* pull in iso2oem[] table */ 70 # endif 71 # if (defined(CRYP_USES_OEM2ISO) && !defined(IZ_OEM2ISO_ARRAY)) 72 # define IZ_OEM2ISO_ARRAY /* pull in oem2iso[] table */ 73 # endif 74 #endif 75 #include "ebcdic.h" /* definition/initialization of ebcdic[] */ 76 77 78 /* 79 Note: Under Windows, the maximum size of the buffer that can be used 80 with any of the *printf calls is 16,384, so win_fprintf was used to 81 feed the fprintf clone no more than 16K chunks at a time. This should 82 be valid for anything up to 64K (and probably beyond, assuming your 83 buffers are that big). 84 */ 85 #ifdef WINDLL 86 # define WriteError(buf,len,strm) \ 87 (win_fprintf(pG, strm, (extent)len, (char far *)buf) != (int)(len)) 88 #else /* !WINDLL */ 89 # ifdef USE_FWRITE 90 # define WriteError(buf,len,strm) \ 91 ((extent)fwrite((char *)(buf),1,(extent)(len),strm) != (extent)(len)) 92 # else 93 # define WriteError(buf,len,strm) \ 94 ((extent)write(fileno(strm),(char *)(buf),(extent)(len)) != (extent)(len)) 95 # endif 96 #endif /* ?WINDLL */ 97 98 #if (defined(USE_DEFLATE64) && defined(__16BIT__)) 99 static int partflush OF((__GPRO__ uch *rawbuf, ulg size, int unshrink)); 100 #endif 101 #ifdef VMS_TEXT_CONV 102 static int is_vms_varlen_txt OF((__GPRO__ uch *ef_buf, unsigned ef_len)); 103 #endif 104 static int disk_error OF((__GPRO)); 105 106 107 /****************************/ 108 /* Strings used in fileio.c */ 109 /****************************/ 110 111 static ZCONST char Far CannotOpenZipfile[] = 112 "error: cannot open zipfile [ %s ]\n"; 113 114 #if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS)) 115 #if (!defined(TANDEM)) 116 #if (defined(BEO_THS_UNX) || defined(DOS_FLX_NLM_OS2_W32)) 117 static ZCONST char Far CannotDeleteOldFile[] = 118 "error: cannot delete old %s\n"; 119 #ifdef UNIXBACKUP 120 static ZCONST char Far CannotRenameOldFile[] = 121 "error: cannot rename old %s\n"; 122 static ZCONST char Far BackupSuffix[] = "~"; 123 #endif 124 #endif /* BEO_THS_UNX || DOS_FLX_NLM_OS2_W32 */ 125 #ifdef NOVELL_BUG_FAILSAFE 126 static ZCONST char Far NovellBug[] = 127 "error: %s: stat() says does not exist, but fopen() found anyway\n"; 128 #endif 129 static ZCONST char Far CannotCreateFile[] = "error: cannot create %s\n"; 130 #endif /* !TANDEM */ 131 #endif /* !VMS && !AOS_VS && !CMS_MVS && !MACOS */ 132 133 static ZCONST char Far ReadError[] = "error: zipfile read error\n"; 134 static ZCONST char Far FilenameTooLongTrunc[] = 135 "warning: filename too long--truncating.\n"; 136 static ZCONST char Far ExtraFieldTooLong[] = 137 "warning: extra field too long (%d). Ignoring...\n"; 138 139 #ifdef WINDLL 140 static ZCONST char Far DiskFullQuery[] = 141 "%s: write error (disk full?).\n"; 142 #else 143 static ZCONST char Far DiskFullQuery[] = 144 "%s: write error (disk full?). Continue? (y/n/^C) "; 145 static ZCONST char Far ZipfileCorrupt[] = 146 "error: zipfile probably corrupt (%s)\n"; 147 # ifdef SYMLINKS 148 static ZCONST char Far FileIsSymLink[] = 149 "%s exists and is a symbolic link%s.\n"; 150 # endif 151 # ifdef MORE 152 static ZCONST char Far MorePrompt[] = "--More--(%lu)"; 153 # endif 154 static ZCONST char Far QuitPrompt[] = 155 "--- Press `Q' to quit, or any other key to continue ---"; 156 static ZCONST char Far HidePrompt[] = /* "\r \r"; */ 157 "\r \r"; 158 # if CRYPT 159 # ifdef MACOS 160 /* SPC: are names on MacOS REALLY so much longer than elsewhere ??? */ 161 static ZCONST char Far PasswPrompt[] = "[%s]\n %s password: "; 162 # else 163 static ZCONST char Far PasswPrompt[] = "[%s] %s password: "; 164 # endif 165 static ZCONST char Far PasswPrompt2[] = "Enter password: "; 166 static ZCONST char Far PasswRetry[] = "password incorrect--reenter: "; 167 # endif /* CRYPT */ 168 #endif /* !WINDLL */ 169 170 171 172 173 174 /******************************/ 175 /* Function open_input_file() */ 176 /******************************/ 177 178 int open_input_file(__G) /* return 1 if open failed */ 179 __GDEF 180 { 181 /* 182 * open the zipfile for reading and in BINARY mode to prevent cr/lf 183 * translation, which would corrupt the bitstreams 184 */ 185 186 #ifdef VMS 187 G.zipfd = open(G.zipfn, O_RDONLY, 0, "ctx=stm"); 188 #else /* !VMS */ 189 #ifdef MACOS 190 G.zipfd = open(G.zipfn, 0); 191 #else /* !MACOS */ 192 #ifdef CMS_MVS 193 G.zipfd = vmmvs_open_infile(__G); 194 #else /* !CMS_MVS */ 195 #ifdef USE_STRM_INPUT 196 G.zipfd = fopen(G.zipfn, FOPR); 197 #else /* !USE_STRM_INPUT */ 198 # ifdef O_BINARY 199 G.zipfd = open(G.zipfn, O_RDONLY | O_BINARY); 200 # else 201 G.zipfd = open(G.zipfn, O_RDONLY); 202 # endif 203 #endif /* ?USE_STRM_INPUT */ 204 #endif /* ?CMS_MVS */ 205 #endif /* ?MACOS */ 206 #endif /* ?VMS */ 207 208 #ifdef USE_STRM_INPUT 209 if (G.zipfd == NULL) 210 #else 211 /* if (G.zipfd < 0) */ /* no good for Windows CE port */ 212 if (G.zipfd == -1) 213 #endif 214 { 215 Info(slide, 0x401, ((char *)slide, LoadFarString(CannotOpenZipfile), 216 G.zipfn)); 217 return 1; 218 } 219 return 0; 220 221 } /* end function open_input_file() */ 222 223 224 225 226 #if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS)) 227 #if (!defined(TANDEM)) 228 229 /***************************/ 230 /* Function open_outfile() */ 231 /***************************/ 232 233 int open_outfile(__G) /* return 1 if fail */ 234 __GDEF 235 { 236 #ifdef DLL 237 if (G.redirect_data) 238 return (redirect_outfile(__G) == FALSE); 239 #endif 240 #ifdef QDOS 241 QFilename(__G__ G.filename); 242 #endif 243 #if (defined(DOS_FLX_NLM_OS2_W32) || defined(BEO_THS_UNX)) 244 #ifdef BORLAND_STAT_BUG 245 /* Borland 5.0's stat() barfs if the filename has no extension and the 246 * file doesn't exist. */ 247 if (access(G.filename, 0) == -1) { 248 FILE *tmp = fopen(G.filename, "wb+"); 249 250 /* file doesn't exist, so create a dummy file to keep stat() from 251 * failing (will be over-written anyway) */ 252 fputc('0', tmp); /* just to have something in the file */ 253 fclose(tmp); 254 } 255 #endif /* BORLAND_STAT_BUG */ 256 #ifdef SYMLINKS 257 if (SSTAT(G.filename, &G.statbuf) == 0 || lstat(G.filename,&G.statbuf) == 0) 258 #else 259 if (SSTAT(G.filename, &G.statbuf) == 0) 260 #endif /* ?SYMLINKS */ 261 { 262 Trace((stderr, "open_outfile: stat(%s) returns 0: file exists\n", 263 FnFilter1(G.filename))); 264 #ifdef UNIXBACKUP 265 if (uO.B_flag) { /* do backup */ 266 char *tname; 267 struct stat tmpstat; 268 int blen, flen, tlen; 269 270 blen = strlen(BackupSuffix); 271 flen = strlen(G.filename); 272 tlen = flen + blen + 6; /* includes space for 5 digits */ 273 if (tlen >= FILNAMSIZ) { /* in case name is too long, truncate */ 274 tname = (char *)malloc(FILNAMSIZ); 275 if (tname == NULL) 276 return 1; /* in case we run out of space */ 277 tlen = FILNAMSIZ - 1 - blen; 278 strcpy(tname, G.filename); /* make backup name */ 279 tname[tlen] = '\0'; 280 if (flen > tlen) flen = tlen; 281 tlen = FILNAMSIZ; 282 } else { 283 tname = (char *)malloc(tlen); 284 if (tname == NULL) 285 return 1; /* in case we run out of space */ 286 strcpy(tname, G.filename); /* make backup name */ 287 } 288 strcpy(tname+flen, BackupSuffix); 289 290 if (IS_OVERWRT_ALL) { 291 /* If there is a previous backup file, delete it, 292 * otherwise the following rename operation may fail. 293 */ 294 if (SSTAT(tname, &tmpstat) == 0) 295 unlink(tname); 296 } else { 297 /* Check if backupname exists, and, if it's true, try 298 * appending numbers of up to 5 digits to the BackupSuffix, 299 * until an unused name is found. 300 */ 301 unsigned maxtail, i; 302 char *numtail = tname + flen + blen; 303 304 maxtail = 65535; 305 switch (tlen - flen - blen - 1) { 306 case 4: maxtail = 9999; break; 307 case 3: maxtail = 999; break; 308 case 2: maxtail = 99; break; 309 case 1: maxtail = 9; break; 310 case 0: maxtail = 0; break; 311 } 312 /* while filename exists */ 313 for (i = 0; (i <= maxtail) && (SSTAT(tname, &tmpstat) == 0);) 314 sprintf(numtail,"%u", ++i); 315 } 316 317 if (rename(G.filename, tname) != 0) { /* move file */ 318 Info(slide, 0x401, ((char *)slide, 319 LoadFarString(CannotRenameOldFile), FnFilter1(G.filename))); 320 free(tname); 321 return 1; 322 } 323 Trace((stderr, "open_outfile: %s now renamed into %s\n", 324 FnFilter1(G.filename), FnFilter2(tname))); 325 free(tname); 326 } else 327 #endif /* UNIXBACKUP */ 328 { 329 #ifdef DOS_FLX_OS2_W32 330 if (!(G.statbuf.st_mode & S_IWRITE)) { 331 Trace((stderr, 332 "open_outfile: existing file %s is read-only\n", 333 FnFilter1(G.filename))); 334 chmod(G.filename, S_IREAD | S_IWRITE); 335 Trace((stderr, "open_outfile: %s now writable\n", 336 FnFilter1(G.filename))); 337 } 338 #endif /* DOS_FLX_OS2_W32 */ 339 #ifdef NLM 340 /* Give the file read/write permission (non-POSIX shortcut) */ 341 chmod(G.filename, 0); 342 #endif /* NLM */ 343 if (unlink(G.filename) != 0) { 344 Info(slide, 0x401, ((char *)slide, 345 LoadFarString(CannotDeleteOldFile), FnFilter1(G.filename))); 346 return 1; 347 } 348 Trace((stderr, "open_outfile: %s now deleted\n", 349 FnFilter1(G.filename))); 350 } 351 } 352 #endif /* DOS_FLX_NLM_OS2_W32 || BEO_THS_UNX */ 353 #ifdef RISCOS 354 if (SWI_OS_File_7(G.filename,0xDEADDEAD,0xDEADDEAD,G.lrec.ucsize)!=NULL) { 355 Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile), 356 FnFilter1(G.filename))); 357 return 1; 358 } 359 #endif /* RISCOS */ 360 #ifdef TOPS20 361 char *tfilnam; 362 363 if ((tfilnam = (char *)malloc(2*strlen(G.filename)+1)) == (char *)NULL) 364 return 1; 365 strcpy(tfilnam, G.filename); 366 upper(tfilnam); 367 enquote(tfilnam); 368 if ((G.outfile = fopen(tfilnam, FOPW)) == (FILE *)NULL) { 369 Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile), 370 tfilnam)); 371 free(tfilnam); 372 return 1; 373 } 374 free(tfilnam); 375 #else /* !TOPS20 */ 376 #ifdef MTS 377 if (uO.aflag) 378 G.outfile = fopen(G.filename, FOPWT); 379 else 380 G.outfile = fopen(G.filename, FOPW); 381 if (G.outfile == (FILE *)NULL) { 382 Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile), 383 FnFilter1(G.filename))); 384 return 1; 385 } 386 #else /* !MTS */ 387 #ifdef DEBUG 388 Info(slide, 1, ((char *)slide, 389 "open_outfile: doing fopen(%s) for reading\n", FnFilter1(G.filename))); 390 if ((G.outfile = fopen(G.filename, FOPR)) == (FILE *)NULL) 391 Info(slide, 1, ((char *)slide, 392 "open_outfile: fopen(%s) for reading failed: does not exist\n", 393 FnFilter1(G.filename))); 394 else { 395 Info(slide, 1, ((char *)slide, 396 "open_outfile: fopen(%s) for reading succeeded: file exists\n", 397 FnFilter1(G.filename))); 398 fclose(G.outfile); 399 } 400 #endif /* DEBUG */ 401 #ifdef NOVELL_BUG_FAILSAFE 402 if (G.dne && ((G.outfile = fopen(G.filename, FOPR)) != (FILE *)NULL)) { 403 Info(slide, 0x401, ((char *)slide, LoadFarString(NovellBug), 404 FnFilter1(G.filename))); 405 fclose(G.outfile); 406 return 1; /* with "./" fix in checkdir(), should never reach here */ 407 } 408 #endif /* NOVELL_BUG_FAILSAFE */ 409 Trace((stderr, "open_outfile: doing fopen(%s) for writing\n", 410 FnFilter1(G.filename))); 411 if ((G.outfile = fopen(G.filename, FOPW)) == (FILE *)NULL) { 412 Info(slide, 0x401, ((char *)slide, LoadFarString(CannotCreateFile), 413 FnFilter1(G.filename))); 414 return 1; 415 } 416 Trace((stderr, "open_outfile: fopen(%s) for writing succeeded\n", 417 FnFilter1(G.filename))); 418 #endif /* !MTS */ 419 #endif /* !TOPS20 */ 420 421 #ifdef USE_FWRITE 422 #ifdef DOS_NLM_OS2_W32 423 /* 16-bit MSC: buffer size must be strictly LESS than 32K (WSIZE): bogus */ 424 setbuf(G.outfile, (char *)NULL); /* make output unbuffered */ 425 #else /* !DOS_NLM_OS2_W32 */ 426 #ifndef RISCOS 427 #ifdef _IOFBF /* make output fully buffered (works just about like write()) */ 428 setvbuf(G.outfile, (char *)slide, _IOFBF, WSIZE); 429 #else 430 setbuf(G.outfile, (char *)slide); 431 #endif 432 #endif /* !RISCOS */ 433 #endif /* ?DOS_NLM_OS2_W32 */ 434 #endif /* USE_FWRITE */ 435 #ifdef OS2_W32 436 /* preallocate the final file size to prevent file fragmentation */ 437 SetFileSize(G.outfile, G.pInfo->uncompr_size); 438 #endif 439 return 0; 440 441 } /* end function open_outfile() */ 442 443 #endif /* !TANDEM */ 444 #endif /* !VMS && !AOS_VS && !CMS_MVS && !MACOS */ 445 446 447 448 449 450 /* 451 * These functions allow NEXTBYTE to function without needing two bounds 452 * checks. Call defer_leftover_input() if you ever have filled G.inbuf 453 * by some means other than readbyte(), and you then want to start using 454 * NEXTBYTE. When going back to processing bytes without NEXTBYTE, call 455 * undefer_input(). For example, extract_or_test_member brackets its 456 * central section that does the decompression with these two functions. 457 * If you need to check the number of bytes remaining in the current 458 * file while using NEXTBYTE, check (G.csize + G.incnt), not G.csize. 459 */ 460 461 /****************************/ 462 /* function undefer_input() */ 463 /****************************/ 464 465 void undefer_input(__G) 466 __GDEF 467 { 468 if (G.incnt > 0) 469 G.csize += G.incnt; 470 if (G.incnt_leftover > 0) { 471 /* We know that "(G.csize < MAXINT)" so we can cast G.csize to int: 472 * This condition was checked when G.incnt_leftover was set > 0 in 473 * defer_leftover_input(), and it is NOT allowed to touch G.csize 474 * before calling undefer_input() when (G.incnt_leftover > 0) 475 * (single exception: see read_byte()'s "G.csize <= 0" handling) !! 476 */ 477 G.incnt = G.incnt_leftover + (int)G.csize; 478 G.inptr = G.inptr_leftover - (int)G.csize; 479 G.incnt_leftover = 0; 480 } else if (G.incnt < 0) 481 G.incnt = 0; 482 } /* end function undefer_input() */ 483 484 485 486 487 488 /***********************************/ 489 /* function defer_leftover_input() */ 490 /***********************************/ 491 492 void defer_leftover_input(__G) 493 __GDEF 494 { 495 if ((long)G.incnt > G.csize) { 496 /* (G.csize < MAXINT), we can safely cast it to int !! */ 497 if (G.csize < 0L) 498 G.csize = 0L; 499 G.inptr_leftover = G.inptr + (int)G.csize; 500 G.incnt_leftover = G.incnt - (int)G.csize; 501 G.incnt = (int)G.csize; 502 } else 503 G.incnt_leftover = 0; 504 G.csize -= G.incnt; 505 } /* end function defer_leftover_input() */ 506 507 508 509 510 511 /**********************/ 512 /* Function readbuf() */ 513 /**********************/ 514 515 unsigned readbuf(__G__ buf, size) /* return number of bytes read into buf */ 516 __GDEF 517 char *buf; 518 register unsigned size; 519 { 520 register unsigned count; 521 unsigned n; 522 523 n = size; 524 while (size) { 525 if (G.incnt <= 0) { 526 if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) == 0) 527 return (n-size); 528 else if (G.incnt < 0) { 529 /* another hack, but no real harm copying same thing twice */ 530 (*G.message)((zvoid *)&G, 531 (uch *)LoadFarString(ReadError), /* CANNOT use slide */ 532 (ulg)strlen(LoadFarString(ReadError)), 0x401); 533 return 0; /* discarding some data; better than lock-up */ 534 } 535 /* buffer ALWAYS starts on a block boundary: */ 536 G.cur_zipfile_bufstart += INBUFSIZ; 537 G.inptr = G.inbuf; 538 } 539 count = MIN(size, (unsigned)G.incnt); 540 memcpy(buf, G.inptr, count); 541 buf += count; 542 G.inptr += count; 543 G.incnt -= count; 544 size -= count; 545 } 546 return n; 547 548 } /* end function readbuf() */ 549 550 551 552 553 554 /***********************/ 555 /* Function readbyte() */ 556 /***********************/ 557 558 int readbyte(__G) /* refill inbuf and return a byte if available, else EOF */ 559 __GDEF 560 { 561 if (G.mem_mode) 562 return EOF; 563 if (G.csize <= 0) { 564 G.csize--; /* for tests done after exploding */ 565 G.incnt = 0; 566 return EOF; 567 } 568 if (G.incnt <= 0) { 569 if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) == 0) { 570 G.incnt = 0; /* do not allow negative value to affect stuff */ 571 return EOF; 572 } else if (G.incnt < 0) { /* "fail" (abort, retry, ...) returns this */ 573 /* another hack, but no real harm copying same thing twice */ 574 (*G.message)((zvoid *)&G, 575 (uch *)LoadFarString(ReadError), 576 (ulg)strlen(LoadFarString(ReadError)), 0x401); 577 echon(); 578 #ifdef WINDLL 579 longjmp(dll_error_return, 1); 580 #else 581 DESTROYGLOBALS(); 582 EXIT(PK_BADERR); /* totally bailing; better than lock-up */ 583 #endif 584 } 585 G.cur_zipfile_bufstart += INBUFSIZ; /* always starts on block bndry */ 586 G.inptr = G.inbuf; 587 defer_leftover_input(__G); /* decrements G.csize */ 588 } 589 590 #if CRYPT 591 if (G.pInfo->encrypted) { 592 uch *p; 593 int n; 594 595 /* This was previously set to decrypt one byte beyond G.csize, when 596 * incnt reached that far. GRR said, "but it's required: why?" This 597 * was a bug in fillinbuf() -- was it also a bug here? 598 */ 599 for (n = G.incnt, p = G.inptr; n--; p++) 600 zdecode(*p); 601 } 602 #endif /* CRYPT */ 603 604 --G.incnt; 605 return *G.inptr++; 606 607 } /* end function readbyte() */ 608 609 610 611 612 613 #ifdef USE_ZLIB 614 615 /************************/ 616 /* Function fillinbuf() */ 617 /************************/ 618 619 int fillinbuf(__G) /* like readbyte() except returns number of bytes in inbuf */ 620 __GDEF 621 { 622 if (G.mem_mode || 623 (G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) <= 0) 624 return 0; 625 G.cur_zipfile_bufstart += INBUFSIZ; /* always starts on a block boundary */ 626 G.inptr = G.inbuf; 627 defer_leftover_input(__G); /* decrements G.csize */ 628 629 #if CRYPT 630 if (G.pInfo->encrypted) { 631 uch *p; 632 int n; 633 634 for (n = G.incnt, p = G.inptr; n--; p++) 635 zdecode(*p); 636 } 637 #endif /* CRYPT */ 638 639 return G.incnt; 640 641 } /* end function fillinbuf() */ 642 643 #endif /* USE_ZLIB */ 644 645 646 647 648 649 /************************/ 650 /* Function seek_zipf() */ 651 /************************/ 652 653 int seek_zipf(__G__ abs_offset) 654 __GDEF 655 LONGINT abs_offset; 656 { 657 /* 658 * Seek to the block boundary of the block which includes abs_offset, 659 * then read block into input buffer and set pointers appropriately. 660 * If block is already in the buffer, just set the pointers. This function 661 * is used by do_seekable (process.c), extract_or_test_entrylist (extract.c) 662 * and do_string (fileio.c). Also, a slightly modified version is embedded 663 * within extract_or_test_entrylist (extract.c). readbyte() and readbuf() 664 * (fileio.c) are compatible. NOTE THAT abs_offset is intended to be the 665 * "proper offset" (i.e., if there were no extra bytes prepended); 666 * cur_zipfile_bufstart contains the corrected offset. 667 * 668 * Since seek_zipf() is never used during decompression, it is safe to 669 * use the slide[] buffer for the error message. 670 * 671 * returns PK error codes: 672 * PK_BADERR if effective offset in zipfile is negative 673 * PK_EOF if seeking past end of zipfile 674 * PK_OK when seek was successful 675 */ 676 LONGINT request = abs_offset + G.extra_bytes; 677 LONGINT inbuf_offset = request % INBUFSIZ; 678 LONGINT bufstart = request - inbuf_offset; 679 680 if (request < 0) { 681 Info(slide, 1, ((char *)slide, LoadFarStringSmall(SeekMsg), 682 G.zipfn, LoadFarString(ReportMsg))); 683 return(PK_BADERR); 684 } else if (bufstart != G.cur_zipfile_bufstart) { 685 Trace((stderr, 686 "fpos_zip: abs_offset = %ld, G.extra_bytes = %ld\n", 687 abs_offset, G.extra_bytes)); 688 #ifdef USE_STRM_INPUT 689 fseek(G.zipfd, (LONGINT)bufstart, SEEK_SET); 690 G.cur_zipfile_bufstart = ftell(G.zipfd); 691 #else /* !USE_STRM_INPUT */ 692 G.cur_zipfile_bufstart = lseek(G.zipfd, (LONGINT)bufstart, SEEK_SET); 693 #endif /* ?USE_STRM_INPUT */ 694 Trace((stderr, 695 " request = %ld, (abs+extra) = %ld, inbuf_offset = %ld\n", 696 request, (abs_offset+G.extra_bytes), inbuf_offset)); 697 Trace((stderr, " bufstart = %ld, cur_zipfile_bufstart = %ld\n", 698 bufstart, G.cur_zipfile_bufstart)); 699 if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) <= 0) 700 return(PK_EOF); 701 G.incnt -= (int)inbuf_offset; 702 G.inptr = G.inbuf + (int)inbuf_offset; 703 } else { 704 G.incnt += (G.inptr-G.inbuf) - (int)inbuf_offset; 705 G.inptr = G.inbuf + (int)inbuf_offset; 706 } 707 return(PK_OK); 708 } /* end function seek_zipf() */ 709 710 711 712 713 714 #ifndef VMS /* for VMS use code in vms.c */ 715 716 /********************/ 717 /* Function flush() */ /* returns PK error codes: */ 718 /********************/ /* if cflag => always 0; PK_DISK if write error */ 719 720 int flush(__G__ rawbuf, size, unshrink) 721 __GDEF 722 uch *rawbuf; 723 ulg size; 724 int unshrink; 725 #if (defined(USE_DEFLATE64) && defined(__16BIT__)) 726 { 727 int ret; 728 729 /* On 16-bit systems (MSDOS, OS/2 1.x), the standard C library functions 730 * cannot handle writes of 64k blocks at once. For these systems, the 731 * blocks to flush are split into pieces of 32k or less. 732 */ 733 while (size > 0x8000L) { 734 ret = partflush(__G__ rawbuf, 0x8000L, unshrink); 735 if (ret != PK_OK) 736 return ret; 737 size -= 0x8000L; 738 rawbuf += (unsigned)0x8000; 739 } 740 return partflush(__G__ rawbuf, size, unshrink); 741 } /* end function flush() */ 742 743 744 /************************/ 745 /* Function partflush() */ /* returns PK error codes: */ 746 /************************/ /* if cflag => always 0; PK_DISK if write error */ 747 748 static int partflush(__G__ rawbuf, size, unshrink) 749 __GDEF 750 uch *rawbuf; /* cannot be ZCONST, gets passed to (*G.message)() */ 751 ulg size; 752 int unshrink; 753 #endif /* USE_DEFLATE64 && __16BIT__ */ 754 { 755 register uch *p; 756 register uch *q; 757 uch *transbuf; 758 #if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV)) 759 ulg transbufsiz; 760 #endif 761 /* static int didCRlast = FALSE; moved to globals.h */ 762 763 764 /*--------------------------------------------------------------------------- 765 Compute the CRC first; if testing or if disk is full, that's it. 766 ---------------------------------------------------------------------------*/ 767 768 G.crc32val = crc32(G.crc32val, rawbuf, (extent)size); 769 770 #ifdef DLL 771 if ((G.statreportcb != NULL) && 772 (*G.statreportcb)(__G__ UZ_ST_IN_PROGRESS, G.zipfn, G.filename, NULL)) 773 return IZ_CTRLC; /* cancel operation by user request */ 774 #endif 775 776 if (uO.tflag || size == 0L) /* testing or nothing to write: all done */ 777 return PK_OK; 778 779 if (G.disk_full) 780 return PK_DISK; /* disk already full: ignore rest of file */ 781 782 /*--------------------------------------------------------------------------- 783 Write the bytes rawbuf[0..size-1] to the output device, first converting 784 end-of-lines and ASCII/EBCDIC as needed. If SMALL_MEM or MED_MEM are NOT 785 defined, outbuf is assumed to be at least as large as rawbuf and is not 786 necessarily checked for overflow. 787 ---------------------------------------------------------------------------*/ 788 789 if (!G.pInfo->textmode) { /* write raw binary data */ 790 /* GRR: note that for standard MS-DOS compilers, size argument to 791 * fwrite() can never be more than 65534, so WriteError macro will 792 * have to be rewritten if size can ever be that large. For now, 793 * never more than 32K. Also note that write() returns an int, which 794 * doesn't necessarily limit size to 32767 bytes if write() is used 795 * on 16-bit systems but does make it more of a pain; however, because 796 * at least MSC 5.1 has a lousy implementation of fwrite() (as does 797 * DEC Ultrix cc), write() is used anyway. 798 */ 799 #ifdef DLL 800 if (G.redirect_data) 801 writeToMemory(__G__ rawbuf, (extent)size); 802 else 803 #endif 804 if (!uO.cflag && WriteError(rawbuf, size, G.outfile)) 805 return disk_error(__G); 806 else if (uO.cflag && (*G.message)((zvoid *)&G, rawbuf, size, 0)) 807 return PK_OK; 808 } else { /* textmode: aflag is true */ 809 if (unshrink) { 810 /* rawbuf = outbuf */ 811 transbuf = G.outbuf2; 812 #if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV)) 813 transbufsiz = TRANSBUFSIZ; 814 #endif 815 } else { 816 /* rawbuf = slide */ 817 transbuf = G.outbuf; 818 #if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV)) 819 transbufsiz = OUTBUFSIZ; 820 Trace((stderr, "\ntransbufsiz = OUTBUFSIZ = %u\n", 821 (unsigned)OUTBUFSIZ)); 822 #endif 823 } 824 if (G.newfile) { 825 #ifdef VMS_TEXT_CONV 826 if (G.pInfo->hostnum == VMS_ && G.extra_field && 827 is_vms_varlen_txt(__G__ G.extra_field, 828 G.lrec.extra_field_length)) 829 G.VMS_line_state = 0; /* 0: ready to read line length */ 830 else 831 G.VMS_line_state = -1; /* -1: don't treat as VMS text */ 832 #endif 833 G.didCRlast = FALSE; /* no previous buffers written */ 834 G.newfile = FALSE; 835 } 836 837 #ifdef VMS_TEXT_CONV 838 if (G.VMS_line_state >= 0) 839 { 840 /* GRR: really want to check for actual VMS extra field, and 841 * ideally for variable-length record format */ 842 /* 843 printf("\n>>>>>> GRR: file is VMS text and has an extra field\n"); 844 */ 845 846 p = rawbuf; 847 q = transbuf; 848 while (p < rawbuf+(unsigned)size) { 849 switch (G.VMS_line_state) { 850 851 /* 0: ready to read line length */ 852 case 0: 853 G.VMS_line_length = 0; 854 if (p == rawbuf+(unsigned)size-1) { /* last char */ 855 G.VMS_line_length = (unsigned)(*p++); 856 G.VMS_line_state = 1; 857 } else { 858 G.VMS_line_length = makeword(p); 859 p += 2; 860 G.VMS_line_state = 2; 861 } 862 G.VMS_line_pad = 863 ((G.VMS_line_length & 1) != 0); /* odd */ 864 break; 865 866 /* 1: read one byte of length, need second */ 867 case 1: 868 G.VMS_line_length += ((unsigned)(*p++) << 8); 869 G.VMS_line_state = 2; 870 break; 871 872 /* 2: ready to read VMS_line_length chars */ 873 case 2: 874 { 875 extent remaining = rawbuf+(unsigned)size-p; 876 extent outroom; 877 878 if (G.VMS_line_length < remaining) { 879 remaining = G.VMS_line_length; 880 G.VMS_line_state = 3; 881 } 882 883 outroom = transbuf+(unsigned)transbufsiz-q; 884 if (remaining >= outroom) { 885 remaining -= outroom; 886 for (;outroom > 0; p++, outroom--) 887 *q++ = native(*p); 888 #ifdef DLL 889 if (G.redirect_data) 890 writeToMemory(__G__ transbuf, 891 (extent)(q-transbuf)); 892 else 893 #endif 894 if (!uO.cflag && WriteError(transbuf, 895 (extent)(q-transbuf), G.outfile)) 896 return disk_error(__G); 897 else if (uO.cflag && (*G.message)((zvoid *)&G, 898 transbuf, (ulg)(q-transbuf), 0)) 899 return PK_OK; 900 q = transbuf; 901 /* fall through to normal case */ 902 } 903 G.VMS_line_length -= remaining; 904 for (;remaining > 0; p++, remaining--) 905 *q++ = native(*p); 906 } 907 break; 908 909 /* 3: ready to PutNativeEOL */ 910 case 3: 911 if (q > transbuf+(unsigned)transbufsiz-lenEOL) { 912 #ifdef DLL 913 if (G.redirect_data) 914 writeToMemory(__G__ transbuf, 915 (extent)(q-transbuf)); 916 else 917 #endif 918 if (!uO.cflag && 919 WriteError(transbuf, (extent)(q-transbuf), 920 G.outfile)) 921 return disk_error(__G); 922 else if (uO.cflag && (*G.message)((zvoid *)&G, 923 transbuf, (ulg)(q-transbuf), 0)) 924 return PK_OK; 925 q = transbuf; 926 } 927 PutNativeEOL 928 G.VMS_line_state = G.VMS_line_pad ? 4 : 0; 929 break; 930 931 /* 4: ready to read pad byte */ 932 case 4: 933 ++p; 934 G.VMS_line_state = 0; 935 break; 936 } 937 } /* end while */ 938 939 } else 940 #endif /* VMS_TEXT_CONV */ 941 942 /*----------------------------------------------------------------------- 943 Algorithm: CR/LF => native; lone CR => native; lone LF => native. 944 This routine is only for non-raw-VMS, non-raw-VM/CMS files (i.e., 945 stream-oriented files, not record-oriented). 946 -----------------------------------------------------------------------*/ 947 948 /* else not VMS text */ { 949 p = rawbuf; 950 if (*p == LF && G.didCRlast) 951 ++p; 952 G.didCRlast = FALSE; 953 for (q = transbuf; p < rawbuf+(unsigned)size; ++p) { 954 if (*p == CR) { /* lone CR or CR/LF: treat as EOL */ 955 PutNativeEOL 956 if (p == rawbuf+(unsigned)size-1) /* last char in buffer */ 957 G.didCRlast = TRUE; 958 else if (p[1] == LF) /* get rid of accompanying LF */ 959 ++p; 960 } else if (*p == LF) /* lone LF */ 961 PutNativeEOL 962 else 963 #ifndef DOS_FLX_OS2_W32 964 if (*p != CTRLZ) /* lose all ^Z's */ 965 #endif 966 *q++ = native(*p); 967 968 #if (defined(SMALL_MEM) || defined(MED_MEM)) 969 # if (lenEOL == 1) /* don't check unshrink: both buffers small but equal */ 970 if (!unshrink) 971 # endif 972 /* check for danger of buffer overflow and flush */ 973 if (q > transbuf+(unsigned)transbufsiz-lenEOL) { 974 Trace((stderr, 975 "p - rawbuf = %u q-transbuf = %u size = %lu\n", 976 (unsigned)(p-rawbuf), (unsigned)(q-transbuf), size)); 977 if (!uO.cflag && WriteError(transbuf, 978 (extent)(q-transbuf), G.outfile)) 979 return disk_error(__G); 980 else if (uO.cflag && (*G.message)((zvoid *)&G, 981 transbuf, (ulg)(q-transbuf), 0)) 982 return PK_OK; 983 q = transbuf; 984 continue; 985 } 986 #endif /* SMALL_MEM || MED_MEM */ 987 } 988 } 989 990 /*----------------------------------------------------------------------- 991 Done translating: write whatever we've got to file (or screen). 992 -----------------------------------------------------------------------*/ 993 994 Trace((stderr, "p - rawbuf = %u q-transbuf = %u size = %lu\n", 995 (unsigned)(p-rawbuf), (unsigned)(q-transbuf), size)); 996 if (q > transbuf) { 997 #ifdef DLL 998 if (G.redirect_data) 999 writeToMemory(__G__ transbuf, (extent)(q-transbuf)); 1000 else 1001 #endif 1002 if (!uO.cflag && WriteError(transbuf, (extent)(q-transbuf), 1003 G.outfile)) 1004 return disk_error(__G); 1005 else if (uO.cflag && (*G.message)((zvoid *)&G, transbuf, 1006 (ulg)(q-transbuf), 0)) 1007 return PK_OK; 1008 } 1009 } 1010 1011 return PK_OK; 1012 1013 } /* end function flush() [resp. partflush() for 16-bit Deflate64 support] */ 1014 1015 1016 1017 1018 1019 #ifdef VMS_TEXT_CONV 1020 1021 /********************************/ 1022 /* Function is_vms_varlen_txt() */ 1023 /********************************/ 1024 1025 static int is_vms_varlen_txt(__G__ ef_buf, ef_len) 1026 __GDEF 1027 uch *ef_buf; /* buffer containing extra field */ 1028 unsigned ef_len; /* total length of extra field */ 1029 { 1030 unsigned eb_id; 1031 unsigned eb_len; 1032 uch *eb_data; 1033 unsigned eb_datlen; 1034 #define VMSREC_C_UNDEF 0 1035 #define VMSREC_C_VAR 2 1036 uch vms_rectype = VMSREC_C_UNDEF; 1037 uch vms_fileorg = 0; 1038 1039 #define VMSPK_ITEMID 0 1040 #define VMSPK_ITEMLEN 2 1041 #define VMSPK_ITEMHEADSZ 4 1042 1043 #define VMSATR_C_RECATTR 4 1044 #define VMS_FABSIG 0x42414656 /* "VFAB" */ 1045 /* offsets of interesting fields in VMS fabdef structure */ 1046 #define VMSFAB_B_RFM 31 /* record format byte */ 1047 #define VMSFAB_B_ORG 29 /* file organization byte */ 1048 1049 if (ef_len == 0 || ef_buf == NULL) 1050 return FALSE; 1051 1052 while (ef_len >= EB_HEADSIZE) { 1053 eb_id = makeword(EB_ID + ef_buf); 1054 eb_len = makeword(EB_LEN + ef_buf); 1055 1056 if (eb_len > (ef_len - EB_HEADSIZE)) { 1057 /* discovered some extra field inconsistency! */ 1058 Trace((stderr, 1059 "is_vms_varlen_txt: block length %u > rest ef_size %u\n", eb_len, 1060 ef_len - EB_HEADSIZE)); 1061 break; 1062 } 1063 1064 switch (eb_id) { 1065 case EF_PKVMS: 1066 /* The PKVMS e.f. raw data part consists of: 1067 * a) 4 bytes CRC checksum 1068 * b) list of uncompressed variable-length data items 1069 * Each data item is introduced by a fixed header 1070 * - 2 bytes data type ID 1071 * - 2 bytes <size> of data 1072 * - <size> bytes of actual attribute data 1073 */ 1074 1075 /* get pointer to start of data and its total length */ 1076 eb_data = ef_buf+(EB_HEADSIZE+4); 1077 eb_datlen = eb_len-4; 1078 1079 /* test the CRC checksum */ 1080 if (makelong(ef_buf+EB_HEADSIZE) != 1081 crc32(CRCVAL_INITIAL, eb_data, (extent)eb_datlen)) 1082 { 1083 Info(slide, 1, ((char *)slide, 1084 "[Warning: CRC error, discarding PKWARE extra field]\n")); 1085 /* skip over the data analysis code */ 1086 break; 1087 } 1088 1089 /* scan through the attribute data items */ 1090 while (eb_datlen > 4) 1091 { 1092 unsigned fldsize = makeword(&eb_data[VMSPK_ITEMLEN]); 1093 1094 /* check the item type word */ 1095 switch (makeword(&eb_data[VMSPK_ITEMID])) { 1096 case VMSATR_C_RECATTR: 1097 /* we have found the (currently only) interesting 1098 * data item */ 1099 if (fldsize >= 1) { 1100 vms_rectype = eb_data[VMSPK_ITEMHEADSZ] & 15; 1101 vms_fileorg = eb_data[VMSPK_ITEMHEADSZ] >> 4; 1102 } 1103 break; 1104 default: 1105 break; 1106 } 1107 /* skip to next data item */ 1108 eb_datlen -= fldsize + VMSPK_ITEMHEADSZ; 1109 eb_data += fldsize + VMSPK_ITEMHEADSZ; 1110 } 1111 break; 1112 1113 case EF_IZVMS: 1114 if (makelong(ef_buf+EB_HEADSIZE) == VMS_FABSIG) { 1115 if ((eb_data = extract_izvms_block(__G__ 1116 ef_buf+EB_HEADSIZE, eb_len, 1117 &eb_datlen, NULL, 0)) 1118 != NULL) 1119 { 1120 if (eb_datlen >= VMSFAB_B_RFM+1) { 1121 vms_rectype = eb_data[VMSFAB_B_RFM] & 15; 1122 vms_fileorg = eb_data[VMSFAB_B_ORG] >> 4; 1123 } 1124 free(eb_data); 1125 } 1126 } 1127 break; 1128 1129 default: 1130 break; 1131 } 1132 1133 /* Skip this extra field block */ 1134 ef_buf += (eb_len + EB_HEADSIZE); 1135 ef_len -= (eb_len + EB_HEADSIZE); 1136 } 1137 1138 return (vms_rectype == VMSREC_C_VAR); 1139 1140 } /* end function is_vms_varlen_txtfile() */ 1141 1142 #endif /* VMS_TEXT_CONV */ 1143 1144 1145 1146 1147 /*************************/ 1148 /* Function disk_error() */ 1149 /*************************/ 1150 1151 static int disk_error(__G) 1152 __GDEF 1153 { 1154 /* OK to use slide[] here because this file is finished regardless */ 1155 Info(slide, 0x4a1, ((char *)slide, LoadFarString(DiskFullQuery), 1156 FnFilter1(G.filename))); 1157 1158 #ifndef WINDLL 1159 fgets(G.answerbuf, 9, stdin); 1160 if (*G.answerbuf == 'y') /* stop writing to this file */ 1161 G.disk_full = 1; /* (outfile bad?), but new OK */ 1162 else 1163 #endif 1164 G.disk_full = 2; /* no: exit program */ 1165 1166 return PK_DISK; 1167 1168 } /* end function disk_error() */ 1169 1170 #endif /* !VMS */ 1171 1172 1173 1174 1175 1176 /*****************************/ 1177 /* Function UzpMessagePrnt() */ 1178 /*****************************/ 1179 1180 int UZ_EXP UzpMessagePrnt(pG, buf, size, flag) 1181 zvoid *pG; /* globals struct: always passed */ 1182 uch *buf; /* preformatted string to be printed */ 1183 ulg size; /* length of string (may include nulls) */ 1184 int flag; /* flag bits */ 1185 { 1186 /* IMPORTANT NOTE: 1187 * The name of the first parameter of UzpMessagePrnt(), which passes 1188 * the "Uz_Globs" address, >>> MUST <<< be identical to the string 1189 * expansion of the __G__ macro in the REENTRANT case (see globals.h). 1190 * This name identity is mandatory for the LoadFarString() macro 1191 * (in the SMALL_MEM case) !!! 1192 */ 1193 int error; 1194 uch *q=buf, *endbuf=buf+(unsigned)size; 1195 #ifdef MORE 1196 uch *p=buf; 1197 #if (defined(SCREENWIDTH) && defined(SCREENLWRAP)) 1198 int islinefeed = FALSE; 1199 #endif 1200 #endif 1201 FILE *outfp; 1202 1203 1204 /*--------------------------------------------------------------------------- 1205 These tests are here to allow fine-tuning of UnZip's output messages, 1206 but none of them will do anything without setting the appropriate bit 1207 in the flag argument of every Info() statement which is to be turned 1208 *off*. That is, all messages are currently turned on for all ports. 1209 To turn off *all* messages, use the UzpMessageNull() function instead 1210 of this one. 1211 ---------------------------------------------------------------------------*/ 1212 1213 #if (defined(OS2) && defined(DLL)) 1214 if (MSG_NO_DLL2(flag)) /* if OS/2 DLL bit is set, do NOT print this msg */ 1215 return 0; 1216 #endif 1217 #ifdef WINDLL 1218 if (MSG_NO_WDLL(flag)) 1219 return 0; 1220 #endif 1221 #ifdef WINDLL 1222 if (MSG_NO_WGUI(flag)) 1223 return 0; 1224 #endif 1225 /* 1226 #ifdef ACORN_GUI 1227 if (MSG_NO_AGUI(flag)) 1228 return 0; 1229 #endif 1230 */ 1231 #ifdef DLL /* don't display message if data is redirected */ 1232 if (((Uz_Globs *)pG)->redirect_data && 1233 !((Uz_Globs *)pG)->redirect_text) 1234 return 0; 1235 #endif 1236 1237 if (MSG_STDERR(flag) && !((Uz_Globs *)pG)->UzO.tflag) 1238 outfp = (FILE *)stderr; 1239 else 1240 outfp = (FILE *)stdout; 1241 1242 #ifdef QUERY_TRNEWLN 1243 /* some systems require termination of query prompts with '\n' to force 1244 * immediate display */ 1245 if (MSG_MNEWLN(flag)) { /* assumes writable buffer (e.g., slide[]) */ 1246 *endbuf++ = '\n'; /* with room for one more char at end of buf */ 1247 ++size; /* (safe assumption: only used for four */ 1248 } /* short queries in extract.c and fileio.c) */ 1249 #endif 1250 1251 if (MSG_TNEWLN(flag)) { /* again assumes writable buffer: fragile... */ 1252 if ((!size && !((Uz_Globs *)pG)->sol) || 1253 (size && (endbuf[-1] != '\n'))) 1254 { 1255 *endbuf++ = '\n'; 1256 ++size; 1257 } 1258 } 1259 1260 #ifdef MORE 1261 # ifdef SCREENSIZE 1262 /* room for --More-- and one line of overlap: */ 1263 # if (defined(SCREENWIDTH) && defined(SCREENLWRAP)) 1264 SCREENSIZE(&((Uz_Globs *)pG)->height, &((Uz_Globs *)pG)->width); 1265 # else 1266 SCREENSIZE(&((Uz_Globs *)pG)->height, (int *)NULL); 1267 # endif 1268 ((Uz_Globs *)pG)->height -= 2; 1269 # else 1270 /* room for --More-- and one line of overlap: */ 1271 ((Uz_Globs *)pG)->height = SCREENLINES - 2; 1272 # if (defined(SCREENWIDTH) && defined(SCREENLWRAP)) 1273 ((Uz_Globs *)pG)->width = SCREENWIDTH; 1274 # endif 1275 # endif 1276 #endif /* MORE */ 1277 1278 if (MSG_LNEWLN(flag) && !((Uz_Globs *)pG)->sol) { 1279 /* not at start of line: want newline */ 1280 #ifdef OS2DLL 1281 if (!((Uz_Globs *)pG)->redirect_text) { 1282 #endif 1283 putc('\n', outfp); 1284 fflush(outfp); 1285 #ifdef MORE 1286 if (((Uz_Globs *)pG)->M_flag) 1287 { 1288 #if (defined(SCREENWIDTH) && defined(SCREENLWRAP)) 1289 ((Uz_Globs *)pG)->chars = 0; 1290 #endif 1291 ++((Uz_Globs *)pG)->numlines; 1292 ++((Uz_Globs *)pG)->lines; 1293 if (((Uz_Globs *)pG)->lines >= ((Uz_Globs *)pG)->height) 1294 (*((Uz_Globs *)pG)->mpause)((zvoid *)pG, 1295 LoadFarString(MorePrompt), 1); 1296 } 1297 #endif /* MORE */ 1298 if (MSG_STDERR(flag) && ((Uz_Globs *)pG)->UzO.tflag && 1299 !isatty(1) && isatty(2)) 1300 { 1301 /* error output from testing redirected: also send to stderr */ 1302 putc('\n', stderr); 1303 fflush(stderr); 1304 } 1305 #ifdef OS2DLL 1306 } else 1307 REDIRECTC('\n'); 1308 #endif 1309 ((Uz_Globs *)pG)->sol = TRUE; 1310 } 1311 1312 /* put zipfile name, filename and/or error/warning keywords here */ 1313 1314 #ifdef MORE 1315 if (((Uz_Globs *)pG)->M_flag 1316 #ifdef OS2DLL 1317 && !((Uz_Globs *)pG)->redirect_text 1318 #endif 1319 ) 1320 { 1321 while (p < endbuf) { 1322 if (*p == '\n') { 1323 #if (defined(SCREENWIDTH) && defined(SCREENLWRAP)) 1324 islinefeed = TRUE; 1325 } else if (SCREENLWRAP) { 1326 if (*p == '\r') { 1327 ((Uz_Globs *)pG)->chars = 0; 1328 } else { 1329 # ifdef TABSIZE 1330 if (*p == '\t') 1331 ((Uz_Globs *)pG)->chars += 1332 (TABSIZE - (((Uz_Globs *)pG)->chars % TABSIZE)); 1333 else 1334 # endif 1335 ++((Uz_Globs *)pG)->chars; 1336 1337 if (((Uz_Globs *)pG)->chars >= ((Uz_Globs *)pG)->width) 1338 islinefeed = TRUE; 1339 } 1340 } 1341 if (islinefeed) { 1342 islinefeed = FALSE; 1343 ((Uz_Globs *)pG)->chars = 0; 1344 #endif /* (SCREENWIDTH && SCREEN_LWRAP) */ 1345 ++((Uz_Globs *)pG)->numlines; 1346 ++((Uz_Globs *)pG)->lines; 1347 if (((Uz_Globs *)pG)->lines >= ((Uz_Globs *)pG)->height) 1348 { 1349 if ((error = WriteError(q, p-q+1, outfp)) != 0) 1350 return error; 1351 fflush(outfp); 1352 ((Uz_Globs *)pG)->sol = TRUE; 1353 q = p + 1; 1354 (*((Uz_Globs *)pG)->mpause)((zvoid *)pG, 1355 LoadFarString(MorePrompt), 1); 1356 } 1357 } 1358 INCSTR(p); 1359 } /* end while */ 1360 size = (ulg)(p - q); /* remaining text */ 1361 } 1362 #endif /* MORE */ 1363 1364 if (size) { 1365 #ifdef OS2DLL 1366 if (!((Uz_Globs *)pG)->redirect_text) { 1367 #endif 1368 if ((error = WriteError(q, size, outfp)) != 0) 1369 return error; 1370 fflush(outfp); 1371 if (MSG_STDERR(flag) && ((Uz_Globs *)pG)->UzO.tflag && 1372 !isatty(1) && isatty(2)) 1373 { 1374 /* error output from testing redirected: also send to stderr */ 1375 if ((error = WriteError(q, size, stderr)) != 0) 1376 return error; 1377 fflush(stderr); 1378 } 1379 #ifdef OS2DLL 1380 } else { /* GRR: this is ugly: hide with macro */ 1381 if ((error = REDIRECTPRINT(q, size)) != 0) 1382 return error; 1383 } 1384 #endif /* OS2DLL */ 1385 ((Uz_Globs *)pG)->sol = (endbuf[-1] == '\n'); 1386 } 1387 return 0; 1388 1389 } /* end function UzpMessagePrnt() */ 1390 1391 1392 1393 1394 1395 #ifdef DLL 1396 1397 /*****************************/ 1398 /* Function UzpMessageNull() */ /* convenience routine for no output at all */ 1399 /*****************************/ 1400 1401 int UZ_EXP UzpMessageNull(pG, buf, size, flag) 1402 zvoid *pG; /* globals struct: always passed */ 1403 uch *buf; /* preformatted string to be printed */ 1404 ulg size; /* length of string (may include nulls) */ 1405 int flag; /* flag bits */ 1406 { 1407 return 0; 1408 1409 } /* end function UzpMessageNull() */ 1410 1411 #endif /* DLL */ 1412 1413 1414 1415 1416 1417 /***********************/ 1418 /* Function UzpInput() */ /* GRR: this is a placeholder for now */ 1419 /***********************/ 1420 1421 int UZ_EXP UzpInput(pG, buf, size, flag) 1422 zvoid *pG; /* globals struct: always passed */ 1423 uch *buf; /* preformatted string to be printed */ 1424 int *size; /* (address of) size of buf and of returned string */ 1425 int flag; /* flag bits (bit 0: no echo) */ 1426 { 1427 /* tell picky compilers to shut up about "unused variable" warnings */ 1428 pG = pG; buf = buf; flag = flag; 1429 1430 *size = 0; 1431 return 0; 1432 1433 } /* end function UzpInput() */ 1434 1435 1436 1437 1438 1439 #if (!defined(WINDLL) && !defined(MACOS)) 1440 1441 /***************************/ 1442 /* Function UzpMorePause() */ 1443 /***************************/ 1444 1445 void UZ_EXP UzpMorePause(pG, prompt, flag) 1446 zvoid *pG; /* globals struct: always passed */ 1447 ZCONST char *prompt; /* "--More--" prompt */ 1448 int flag; /* 0 = any char OK; 1 = accept only '\n', ' ', q */ 1449 { 1450 uch c; 1451 1452 /*--------------------------------------------------------------------------- 1453 Print a prompt and wait for the user to press a key, then erase prompt 1454 if possible. 1455 ---------------------------------------------------------------------------*/ 1456 1457 if (!((Uz_Globs *)pG)->sol) 1458 fprintf(stderr, "\n"); 1459 /* numlines may or may not be used: */ 1460 fprintf(stderr, prompt, ((Uz_Globs *)pG)->numlines); 1461 fflush(stderr); 1462 if (flag & 1) { 1463 do { 1464 c = (uch)FGETCH(0); 1465 } while ( 1466 #ifdef THEOS 1467 c != 17 && /* standard QUIT key */ 1468 #endif 1469 c != '\r' && c != '\n' && c != ' ' && c != 'q' && c != 'Q'); 1470 } else 1471 c = (uch)FGETCH(0); 1472 1473 /* newline was not echoed, so cover up prompt line */ 1474 fprintf(stderr, LoadFarString(HidePrompt)); 1475 fflush(stderr); 1476 1477 if ( 1478 #ifdef THEOS 1479 (c == 17) || /* standard QUIT key */ 1480 #endif 1481 (ToLower(c) == 'q')) { 1482 DESTROYGLOBALS(); 1483 EXIT(PK_COOL); 1484 } 1485 1486 ((Uz_Globs *)pG)->sol = TRUE; 1487 1488 #ifdef MORE 1489 /* space for another screen, enter for another line. */ 1490 if ((flag & 1) && c == ' ') 1491 ((Uz_Globs *)pG)->lines = 0; 1492 #endif /* MORE */ 1493 1494 } /* end function UzpMorePause() */ 1495 1496 #endif /* !WINDLL && !MACOS */ 1497 1498 1499 1500 1501 #ifndef WINDLL 1502 1503 /**************************/ 1504 /* Function UzpPassword() */ 1505 /**************************/ 1506 1507 int UZ_EXP UzpPassword (pG, rcnt, pwbuf, size, zfn, efn) 1508 zvoid *pG; /* pointer to UnZip's internal global vars */ 1509 int *rcnt; /* retry counter */ 1510 char *pwbuf; /* buffer for password */ 1511 int size; /* size of password buffer */ 1512 ZCONST char *zfn; /* name of zip archive */ 1513 ZCONST char *efn; /* name of archive entry being processed */ 1514 { 1515 #if CRYPT 1516 int r = IZ_PW_ENTERED; 1517 char *m; 1518 char *prompt; 1519 1520 #ifndef REENTRANT 1521 /* tell picky compilers to shut up about "unused variable" warnings */ 1522 pG = pG; 1523 #endif 1524 1525 if (*rcnt == 0) { /* First call for current entry */ 1526 *rcnt = 2; 1527 if ((prompt = (char *)malloc(2*FILNAMSIZ + 15)) != (char *)NULL) { 1528 sprintf(prompt, LoadFarString(PasswPrompt), 1529 FnFilter1(zfn), FnFilter2(efn)); 1530 m = prompt; 1531 } else 1532 m = (char *)LoadFarString(PasswPrompt2); 1533 } else { /* Retry call, previous password was wrong */ 1534 (*rcnt)--; 1535 prompt = NULL; 1536 m = (char *)LoadFarString(PasswRetry); 1537 } 1538 1539 m = getp(__G__ m, pwbuf, size); 1540 if (prompt != (char *)NULL) { 1541 free(prompt); 1542 } 1543 if (m == (char *)NULL) { 1544 r = IZ_PW_ERROR; 1545 } 1546 else if (*pwbuf == '\0') { 1547 r = IZ_PW_CANCELALL; 1548 } 1549 return r; 1550 1551 #else /* !CRYPT */ 1552 /* tell picky compilers to shut up about "unused variable" warnings */ 1553 pG = pG; rcnt = rcnt; pwbuf = pwbuf; size = size; zfn = zfn; efn = efn; 1554 1555 return IZ_PW_ERROR; /* internal error; function should never get called */ 1556 #endif /* ?CRYPT */ 1557 1558 } /* end function UzpPassword() */ 1559 1560 1561 1562 1563 1564 /**********************/ 1565 /* Function handler() */ 1566 /**********************/ 1567 1568 void handler(signal) /* upon interrupt, turn on echo and exit cleanly */ 1569 int signal; 1570 { 1571 GETGLOBALS(); 1572 1573 #if !(defined(SIGBUS) || defined(SIGSEGV)) /* add a newline if not at */ 1574 (*G.message)((zvoid *)&G, slide, 0L, 0x41); /* start of line (to stderr; */ 1575 #endif /* slide[] should be safe) */ 1576 1577 echon(); 1578 1579 #ifdef SIGBUS 1580 if (signal == SIGBUS) { 1581 Info(slide, 0x421, ((char *)slide, LoadFarString(ZipfileCorrupt), 1582 "bus error")); 1583 DESTROYGLOBALS(); 1584 EXIT(PK_BADERR); 1585 } 1586 #endif /* SIGBUS */ 1587 1588 #ifdef SIGSEGV 1589 if (signal == SIGSEGV) { 1590 Info(slide, 0x421, ((char *)slide, LoadFarString(ZipfileCorrupt), 1591 "segmentation violation")); 1592 DESTROYGLOBALS(); 1593 EXIT(PK_BADERR); 1594 } 1595 #endif /* SIGSEGV */ 1596 1597 /* probably ctrl-C */ 1598 DESTROYGLOBALS(); 1599 #if defined(AMIGA) && defined(__SASC) 1600 _abort(); 1601 #endif 1602 EXIT(IZ_CTRLC); /* was EXIT(0), then EXIT(PK_ERR) */ 1603 } 1604 1605 #endif /* !WINDLL */ 1606 1607 1608 1609 1610 #if (!defined(VMS) && !defined(CMS_MVS)) 1611 #if (!defined(OS2) || defined(TIMESTAMP)) 1612 1613 #if (!defined(HAVE_MKTIME) || defined(WIN32)) 1614 /* also used in amiga/filedate.c and win32/win32.c */ 1615 ZCONST ush ydays[] = 1616 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; 1617 #endif 1618 1619 /*******************************/ 1620 /* Function dos_to_unix_time() */ /* used for freshening/updating/timestamps */ 1621 /*******************************/ 1622 1623 time_t dos_to_unix_time(dosdatetime) 1624 ulg dosdatetime; 1625 { 1626 time_t m_time; 1627 1628 #ifdef HAVE_MKTIME 1629 1630 ZCONST time_t now = time(NULL); 1631 struct tm *tm; 1632 # define YRBASE 1900 1633 1634 tm = localtime(&now); 1635 tm->tm_isdst = -1; /* let mktime determine if DST is in effect */ 1636 1637 /* dissect date */ 1638 tm->tm_year = ((int)(dosdatetime >> 25) & 0x7f) + (1980 - YRBASE); 1639 tm->tm_mon = ((int)(dosdatetime >> 21) & 0x0f) - 1; 1640 tm->tm_mday = ((int)(dosdatetime >> 16) & 0x1f); 1641 1642 /* dissect time */ 1643 tm->tm_hour = (int)((unsigned)dosdatetime >> 11) & 0x1f; 1644 tm->tm_min = (int)((unsigned)dosdatetime >> 5) & 0x3f; 1645 tm->tm_sec = (int)((unsigned)dosdatetime << 1) & 0x3e; 1646 1647 m_time = mktime(tm); 1648 NATIVE_TO_TIMET(m_time) /* NOP unless MSC 7.0 or Macintosh */ 1649 TTrace((stderr, " final m_time = %lu\n", (ulg)m_time)); 1650 1651 #else /* !HAVE_MKTIME */ 1652 1653 int yr, mo, dy, hh, mm, ss; 1654 #ifdef TOPS20 1655 # define YRBASE 1900 1656 struct tmx *tmx; 1657 char temp[20]; 1658 #else /* !TOPS20 */ 1659 # define YRBASE 1970 1660 int leap; 1661 unsigned days; 1662 struct tm *tm; 1663 #if (!defined(MACOS) && !defined(RISCOS) && !defined(QDOS) && !defined(TANDEM)) 1664 #ifdef WIN32 1665 TIME_ZONE_INFORMATION tzinfo; 1666 DWORD res; 1667 #else /* ! WIN32 */ 1668 #ifndef BSD4_4 /* GRR: change to !defined(MODERN) ? */ 1669 #if (defined(BSD) || defined(MTS) || defined(__GO32__)) 1670 struct timeb tbp; 1671 #else /* !(BSD || MTS || __GO32__) */ 1672 #ifdef DECLARE_TIMEZONE 1673 extern time_t timezone; 1674 #endif 1675 #endif /* ?(BSD || MTS || __GO32__) */ 1676 #endif /* !BSD4_4 */ 1677 #endif /* ?WIN32 */ 1678 #endif /* !MACOS && !RISCOS && !QDOS && !TANDEM */ 1679 #endif /* ?TOPS20 */ 1680 1681 1682 /* dissect date */ 1683 yr = ((int)(dosdatetime >> 25) & 0x7f) + (1980 - YRBASE); 1684 mo = ((int)(dosdatetime >> 21) & 0x0f) - 1; 1685 dy = ((int)(dosdatetime >> 16) & 0x1f) - 1; 1686 1687 /* dissect time */ 1688 hh = (int)((unsigned)dosdatetime >> 11) & 0x1f; 1689 mm = (int)((unsigned)dosdatetime >> 5) & 0x3f; 1690 ss = (int)((unsigned)dosdatetime & 0x1f) * 2; 1691 1692 #ifdef TOPS20 1693 tmx = (struct tmx *)malloc(sizeof(struct tmx)); 1694 sprintf (temp, "%02d/%02d/%02d %02d:%02d:%02d", mo+1, dy+1, yr, hh, mm, ss); 1695 time_parse(temp, tmx, (char *)0); 1696 m_time = time_make(tmx); 1697 free(tmx); 1698 1699 #else /* !TOPS20 */ 1700 1701 /*--------------------------------------------------------------------------- 1702 Calculate the number of seconds since the epoch, usually 1 January 1970. 1703 ---------------------------------------------------------------------------*/ 1704 1705 /* leap = # of leap yrs from YRBASE up to but not including current year */ 1706 leap = ((yr + YRBASE - 1) / 4); /* leap year base factor */ 1707 1708 /* calculate days from BASE to this year and add expired days this year */ 1709 days = (yr * 365) + (leap - 492) + ydays[mo]; 1710 1711 /* if year is a leap year and month is after February, add another day */ 1712 if ((mo > 1) && ((yr+YRBASE)%4 == 0) && ((yr+YRBASE) != 2100)) 1713 ++days; /* OK through 2199 */ 1714 1715 /* convert date & time to seconds relative to 00:00:00, 01/01/YRBASE */ 1716 m_time = (time_t)(((unsigned long)days + dy) * 86400L + 1717 (unsigned long)hh * 3600L + 1718 (unsigned long)(mm * 60 + ss)); 1719 /* - 1; MS-DOS times always rounded up to nearest even second */ 1720 TTrace((stderr, "dos_to_unix_time:\n")); 1721 TTrace((stderr, " m_time before timezone = %lu\n", (ulg)m_time)); 1722 1723 /*--------------------------------------------------------------------------- 1724 Adjust for local standard timezone offset. 1725 ---------------------------------------------------------------------------*/ 1726 1727 #if (!defined(MACOS) && !defined(RISCOS) && !defined(QDOS) && !defined(TANDEM)) 1728 #ifdef WIN32 1729 /* account for timezone differences */ 1730 res = GetTimeZoneInformation(&tzinfo); 1731 if (res != TIME_ZONE_ID_INVALID) 1732 { 1733 m_time += 60*(tzinfo.Bias); 1734 #else /* !WIN32 */ 1735 #if (defined(BSD) || defined(MTS) || defined(__GO32__)) 1736 #ifdef BSD4_4 1737 if ( (dosdatetime >= DOSTIME_2038_01_18) && 1738 (m_time < (time_t)0x70000000L) ) 1739 m_time = U_TIME_T_MAX; /* saturate in case of (unsigned) overflow */ 1740 if (m_time < (time_t)0L) /* a converted DOS time cannot be negative */ 1741 m_time = S_TIME_T_MAX; /* -> saturate at max signed time_t value */ 1742 if ((tm = localtime(&m_time)) != (struct tm *)NULL) 1743 m_time -= tm->tm_gmtoff; /* sec. EAST of GMT: subtr. */ 1744 #else /* !(BSD4_4 */ 1745 ftime(&tbp); /* get `timezone' */ 1746 m_time += tbp.timezone * 60L; /* seconds WEST of GMT: add */ 1747 #endif /* ?(BSD4_4 || __EMX__) */ 1748 #else /* !(BSD || MTS || __GO32__) */ 1749 /* tzset was already called at start of process_zipfiles() */ 1750 /* tzset(); */ /* set `timezone' variable */ 1751 #if (!defined(__BEOS__) && !defined(__HAIKU__)) /* BeOS DR8 has no timezones... */ 1752 m_time += timezone; /* seconds WEST of GMT: add */ 1753 #endif 1754 #endif /* ?(BSD || MTS || __GO32__) */ 1755 #endif /* ?WIN32 */ 1756 TTrace((stderr, " m_time after timezone = %lu\n", (ulg)m_time)); 1757 1758 /*--------------------------------------------------------------------------- 1759 Adjust for local daylight savings (summer) time. 1760 ---------------------------------------------------------------------------*/ 1761 1762 #ifndef BSD4_4 /* (DST already added to tm_gmtoff, so skip tm_isdst) */ 1763 if ( (dosdatetime >= DOSTIME_2038_01_18) && 1764 (m_time < (time_t)0x70000000L) ) 1765 m_time = U_TIME_T_MAX; /* saturate in case of (unsigned) overflow */ 1766 if (m_time < (time_t)0L) /* a converted DOS time cannot be negative */ 1767 m_time = S_TIME_T_MAX; /* -> saturate at max signed time_t value */ 1768 TIMET_TO_NATIVE(m_time) /* NOP unless MSC 7.0 or Macintosh */ 1769 if (((tm = localtime((time_t *)&m_time)) != NULL) && tm->tm_isdst) 1770 #ifdef WIN32 1771 m_time += 60L * tzinfo.DaylightBias; /* adjust with DST bias */ 1772 else 1773 m_time += 60L * tzinfo.StandardBias; /* add StdBias (normally 0) */ 1774 #else 1775 m_time -= 60L * 60L; /* adjust for daylight savings time */ 1776 #endif 1777 NATIVE_TO_TIMET(m_time) /* NOP unless MSC 7.0 or Macintosh */ 1778 TTrace((stderr, " m_time after DST = %lu\n", (ulg)m_time)); 1779 #endif /* !BSD4_4 */ 1780 #ifdef WIN32 1781 } 1782 #endif 1783 #endif /* !MACOS && !RISCOS && !QDOS && !TANDEM */ 1784 #endif /* ?TOPS20 */ 1785 1786 #endif /* ?HAVE_MKTIME */ 1787 1788 if ( (dosdatetime >= DOSTIME_2038_01_18) && 1789 (m_time < (time_t)0x70000000L) ) 1790 m_time = U_TIME_T_MAX; /* saturate in case of (unsigned) overflow */ 1791 if (m_time < (time_t)0L) /* a converted DOS time cannot be negative */ 1792 m_time = S_TIME_T_MAX; /* -> saturate at max signed time_t value */ 1793 1794 return m_time; 1795 1796 } /* end function dos_to_unix_time() */ 1797 1798 #endif /* !OS2 || TIMESTAMP */ 1799 #endif /* !VMS && !CMS_MVS */ 1800 1801 1802 1803 #if (!defined(VMS) && !defined(OS2) && !defined(CMS_MVS)) 1804 1805 /******************************/ 1806 /* Function check_for_newer() */ /* used for overwriting/freshening/updating */ 1807 /******************************/ 1808 1809 int check_for_newer(__G__ filename) /* return 1 if existing file is newer */ 1810 __GDEF /* or equal; 0 if older; -1 if doesn't */ 1811 char *filename; /* exist yet */ 1812 { 1813 time_t existing, archive; 1814 #ifdef USE_EF_UT_TIME 1815 iztimes z_utime; 1816 #endif 1817 #ifdef AOS_VS 1818 long dyy, dmm, ddd, dhh, dmin, dss; 1819 1820 1821 dyy = (lrec.last_mod_dos_datetime >> 25) + 1980; 1822 dmm = (lrec.last_mod_dos_datetime >> 21) & 0x0f; 1823 ddd = (lrec.last_mod_dos_datetime >> 16) & 0x1f; 1824 dhh = (lrec.last_mod_dos_datetime >> 11) & 0x1f; 1825 dmin = (lrec.last_mod_dos_datetime >> 5) & 0x3f; 1826 dss = (lrec.last_mod_dos_datetime & 0x1f) * 2; 1827 1828 /* under AOS/VS, file times can only be set at creation time, 1829 * with the info in a special DG format. Make sure we can create 1830 * it here - we delete it later & re-create it, whether or not 1831 * it exists now. 1832 */ 1833 if (!zvs_create(filename, (((ulg)dgdate(dmm, ddd, dyy)) << 16) | 1834 (dhh*1800L + dmin*30L + dss/2L), -1L, -1L, (char *) -1, -1, -1, -1)) 1835 return DOES_NOT_EXIST; 1836 #endif /* AOS_VS */ 1837 1838 Trace((stderr, "check_for_newer: doing stat(%s)\n", FnFilter1(filename))); 1839 if (SSTAT(filename, &G.statbuf)) { 1840 Trace((stderr, 1841 "check_for_newer: stat(%s) returns %d: file does not exist\n", 1842 FnFilter1(filename), SSTAT(filename, &G.statbuf))); 1843 #ifdef SYMLINKS 1844 Trace((stderr, "check_for_newer: doing lstat(%s)\n", 1845 FnFilter1(filename))); 1846 /* GRR OPTION: could instead do this test ONLY if G.symlnk is true */ 1847 if (lstat(filename, &G.statbuf) == 0) { 1848 Trace((stderr, 1849 "check_for_newer: lstat(%s) returns 0: symlink does exist\n", 1850 FnFilter1(filename))); 1851 if (QCOND2 && !IS_OVERWRT_ALL) 1852 Info(slide, 0, ((char *)slide, LoadFarString(FileIsSymLink), 1853 FnFilter1(filename), " with no real file")); 1854 return EXISTS_AND_OLDER; /* symlink dates are meaningless */ 1855 } 1856 #endif /* SYMLINKS */ 1857 return DOES_NOT_EXIST; 1858 } 1859 Trace((stderr, "check_for_newer: stat(%s) returns 0: file exists\n", 1860 FnFilter1(filename))); 1861 1862 #ifdef SYMLINKS 1863 /* GRR OPTION: could instead do this test ONLY if G.symlnk is true */ 1864 if (lstat(filename, &G.statbuf) == 0 && S_ISLNK(G.statbuf.st_mode)) { 1865 Trace((stderr, "check_for_newer: %s is a symbolic link\n", 1866 FnFilter1(filename))); 1867 if (QCOND2 && !IS_OVERWRT_ALL) 1868 Info(slide, 0, ((char *)slide, LoadFarString(FileIsSymLink), 1869 FnFilter1(filename), "")); 1870 return EXISTS_AND_OLDER; /* symlink dates are meaningless */ 1871 } 1872 #endif /* SYMLINKS */ 1873 1874 NATIVE_TO_TIMET(G.statbuf.st_mtime) /* NOP unless MSC 7.0 or Macintosh */ 1875 1876 #ifdef USE_EF_UT_TIME 1877 /* The `Unix extra field mtime' should be used for comparison with the 1878 * time stamp of the existing file >>>ONLY<<< when the EF info is also 1879 * used to set the modification time of the extracted file. 1880 */ 1881 if (G.extra_field && 1882 #ifdef IZ_CHECK_TZ 1883 G.tz_is_valid && 1884 #endif 1885 (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0, 1886 G.lrec.last_mod_dos_datetime, &z_utime, NULL) 1887 & EB_UT_FL_MTIME)) 1888 { 1889 TTrace((stderr, "check_for_newer: using Unix extra field mtime\n")); 1890 existing = G.statbuf.st_mtime; 1891 archive = z_utime.mtime; 1892 } else { 1893 /* round up existing filetime to nearest 2 seconds for comparison, 1894 * but saturate in case of arithmetic overflow 1895 */ 1896 existing = ((G.statbuf.st_mtime & 1) && 1897 (G.statbuf.st_mtime + 1 > G.statbuf.st_mtime)) ? 1898 G.statbuf.st_mtime + 1 : G.statbuf.st_mtime; 1899 archive = dos_to_unix_time(G.lrec.last_mod_dos_datetime); 1900 } 1901 #else /* !USE_EF_UT_TIME */ 1902 /* round up existing filetime to nearest 2 seconds for comparison, 1903 * but saturate in case of arithmetic overflow 1904 */ 1905 existing = ((G.statbuf.st_mtime & 1) && 1906 (G.statbuf.st_mtime + 1 > G.statbuf.st_mtime)) ? 1907 G.statbuf.st_mtime + 1 : G.statbuf.st_mtime; 1908 archive = dos_to_unix_time(G.lrec.last_mod_dos_datetime); 1909 #endif /* ?USE_EF_UT_TIME */ 1910 1911 TTrace((stderr, "check_for_newer: existing %lu, archive %lu, e-a %ld\n", 1912 (ulg)existing, (ulg)archive, (long)(existing-archive))); 1913 1914 return (existing >= archive); 1915 1916 } /* end function check_for_newer() */ 1917 1918 #endif /* !VMS && !OS2 && !CMS_MVS */ 1919 1920 1921 1922 1923 1924 /************************/ 1925 /* Function do_string() */ 1926 /************************/ 1927 1928 int do_string(__G__ length, option) /* return PK-type error code */ 1929 __GDEF 1930 unsigned int length; /* without prototype, ush converted to this */ 1931 int option; 1932 { 1933 unsigned comment_bytes_left; 1934 unsigned int block_len; 1935 int error=PK_OK; 1936 #ifdef AMIGA 1937 char tmp_fnote[2 * AMIGA_FILENOTELEN]; /* extra room for squozen chars */ 1938 #endif 1939 1940 1941 /*--------------------------------------------------------------------------- 1942 This function processes arbitrary-length (well, usually) strings. Four 1943 major options are allowed: SKIP, wherein the string is skipped (pretty 1944 logical, eh?); DISPLAY, wherein the string is printed to standard output 1945 after undergoing any necessary or unnecessary character conversions; 1946 DS_FN, wherein the string is put into the filename[] array after under- 1947 going appropriate conversions (including case-conversion, if that is 1948 indicated: see the global variable pInfo->lcflag); and EXTRA_FIELD, 1949 wherein the `string' is assumed to be an extra field and is copied to 1950 the (freshly malloced) buffer G.extra_field. The third option should 1951 be OK since filename is dimensioned at 1025, but we check anyway. 1952 1953 The string, by the way, is assumed to start at the current file-pointer 1954 position; its length is given by 'length'. So start off by checking the 1955 length of the string: if zero, we're already done. 1956 ---------------------------------------------------------------------------*/ 1957 1958 if (!length) 1959 return PK_COOL; 1960 1961 switch (option) { 1962 1963 #if (defined(SFX) && defined(CHEAP_SFX_AUTORUN)) 1964 /* 1965 * Special case: See if the comment begins with an autorun command line. 1966 * Save that and display (or skip) the remainder. 1967 */ 1968 1969 case CHECK_AUTORUN: 1970 case CHECK_AUTORUN_Q: 1971 comment_bytes_left = length; 1972 if (length >= 10) 1973 { 1974 block_len = readbuf(__G__ (char *)G.outbuf, 10); 1975 if (block_len == 0) 1976 return PK_EOF; 1977 comment_bytes_left -= block_len; 1978 G.outbuf[block_len] = '\0'; 1979 if (!strcmp((char *)G.outbuf, "$AUTORUN$>")) { 1980 char *eol; 1981 length -= 10; 1982 block_len = readbuf(__G__ G.autorun_command, 1983 MIN(length, sizeof(G.autorun_command)-1)); 1984 if (block_len == 0) 1985 return PK_EOF; 1986 comment_bytes_left -= block_len; 1987 G.autorun_command[block_len] = '\0'; 1988 A_TO_N(G.autorun_command); 1989 eol = strchr(G.autorun_command, '\n'); 1990 if (!eol) 1991 eol = G.autorun_command + strlen(G.autorun_command) - 1; 1992 length -= eol + 1 - G.autorun_command; 1993 while (eol >= G.autorun_command && isspace(*eol)) 1994 *eol-- = '\0'; 1995 #ifdef WIN32 1996 /* Win9x console always uses OEM character coding, and 1997 WinNT console is set to OEM charset by default, too */ 1998 INTERN_TO_OEM(G.autorun_command, G.autorun_command); 1999 #endif /* WIN32 */ 2000 } 2001 } 2002 if (option == CHECK_AUTORUN_Q) /* don't display the remainder */ 2003 length = 0; 2004 /* seek to beginning of remaining part of comment -- rewind if */ 2005 /* displaying entire comment, or skip to end if discarding it */ 2006 seek_zipf(__G__ G.cur_zipfile_bufstart - G.extra_bytes + 2007 (G.inptr - G.inbuf) + comment_bytes_left - length); 2008 if (!length) 2009 break; 2010 /* FALL THROUGH... */ 2011 #endif /* SFX && CHEAP_SFX_AUTORUN */ 2012 2013 /* 2014 * First normal case: print string on standard output. First set loop 2015 * variables, then loop through the comment in chunks of OUTBUFSIZ bytes, 2016 * converting formats and printing as we go. The second half of the 2017 * loop conditional was added because the file might be truncated, in 2018 * which case comment_bytes_left will remain at some non-zero value for 2019 * all time. outbuf and slide are used as scratch buffers because they 2020 * are available (we should be either before or in between any file pro- 2021 * cessing). 2022 */ 2023 2024 case DISPLAY: 2025 case DISPL_8: 2026 comment_bytes_left = length; 2027 block_len = OUTBUFSIZ; /* for the while statement, first time */ 2028 while (comment_bytes_left > 0 && block_len > 0) { 2029 register uch *p = G.outbuf; 2030 register uch *q = G.outbuf; 2031 2032 if ((block_len = readbuf(__G__ (char *)G.outbuf, 2033 MIN((unsigned)OUTBUFSIZ, comment_bytes_left))) == 0) 2034 return PK_EOF; 2035 comment_bytes_left -= block_len; 2036 2037 /* this is why we allocated an extra byte for outbuf: terminate 2038 * with zero (ASCIIZ) */ 2039 G.outbuf[block_len] = '\0'; 2040 2041 /* remove all ASCII carriage returns from comment before printing 2042 * (since used before A_TO_N(), check for CR instead of '\r') 2043 */ 2044 while (*p) { 2045 while (*p == CR) 2046 ++p; 2047 *q++ = *p++; 2048 } 2049 /* could check whether (p - outbuf) == block_len here */ 2050 *q = '\0'; 2051 2052 if (option == DISPL_8) { 2053 /* translate the text coded in the entry's host-dependent 2054 "extended ASCII" charset into the compiler's (system's) 2055 internal text code page */ 2056 Ext_ASCII_TO_Native((char *)G.outbuf, G.pInfo->hostnum, 2057 G.pInfo->hostver, G.pInfo->HasUxAtt, 2058 FALSE); 2059 #ifdef WINDLL 2060 /* translate to ANSI (RTL internal codepage may be OEM) */ 2061 INTERN_TO_ISO((char *)G.outbuf, (char *)G.outbuf); 2062 #else /* !WINDLL */ 2063 #ifdef WIN32 2064 /* Win9x console always uses OEM character coding, and 2065 WinNT console is set to OEM charset by default, too */ 2066 INTERN_TO_OEM((char *)G.outbuf, (char *)G.outbuf); 2067 #endif /* WIN32 */ 2068 #endif /* ?WINDLL */ 2069 } else { 2070 A_TO_N(G.outbuf); /* translate string to native */ 2071 } 2072 2073 #ifdef WINDLL 2074 /* ran out of local mem -- had to cheat */ 2075 win_fprintf((zvoid *)&G, stdout, length, (char *)G.outbuf); 2076 win_fprintf((zvoid *)&G, stdout, 2, (char *)"\n\n"); 2077 #else /* !WINDLL */ 2078 #ifdef NOANSIFILT /* GRR: can ANSI be used with EBCDIC? */ 2079 (*G.message)((zvoid *)&G, G.outbuf, (ulg)(q-G.outbuf), 0); 2080 #else /* ASCII, filter out ANSI escape sequences and handle ^S (pause) */ 2081 p = G.outbuf - 1; 2082 q = slide; 2083 while (*++p) { 2084 int pause = FALSE; 2085 2086 if (*p == 0x1B) { /* ASCII escape char */ 2087 *q++ = '^'; 2088 *q++ = '['; 2089 } else if (*p == 0x13) { /* ASCII ^S (pause) */ 2090 pause = TRUE; 2091 if (p[1] == LF) /* ASCII LF */ 2092 *q++ = *++p; 2093 else if (p[1] == CR && p[2] == LF) { /* ASCII CR LF */ 2094 *q++ = *++p; 2095 *q++ = *++p; 2096 } 2097 } else 2098 *q++ = *p; 2099 if ((unsigned)(q-slide) > WSIZE-3 || pause) { /* flush */ 2100 (*G.message)((zvoid *)&G, slide, (ulg)(q-slide), 0); 2101 q = slide; 2102 if (pause && G.extract_flag) /* don't pause for list/test */ 2103 (*G.mpause)((zvoid *)&G, LoadFarString(QuitPrompt), 0); 2104 } 2105 } 2106 (*G.message)((zvoid *)&G, slide, (ulg)(q-slide), 0); 2107 #endif /* ?NOANSIFILT */ 2108 #endif /* ?WINDLL */ 2109 } 2110 /* add '\n' if not at start of line */ 2111 (*G.message)((zvoid *)&G, slide, 0L, 0x40); 2112 break; 2113 2114 /* 2115 * Second case: read string into filename[] array. The filename should 2116 * never ever be longer than FILNAMSIZ-1 (1024), but for now we'll check, 2117 * just to be sure. 2118 */ 2119 2120 case DS_FN: 2121 case DS_FN_L: 2122 if (length >= FILNAMSIZ) { 2123 Info(slide, 0x401, ((char *)slide, 2124 LoadFarString(FilenameTooLongTrunc))); 2125 error = PK_WARN; 2126 /* remember excess length in block_len */ 2127 block_len = length - (FILNAMSIZ - 1); 2128 length = FILNAMSIZ - 1; 2129 } else 2130 /* no excess size */ 2131 block_len = 0; 2132 if (readbuf(__G__ G.filename, length) == 0) 2133 return PK_EOF; 2134 G.filename[length] = '\0'; /* terminate w/zero: ASCIIZ */ 2135 2136 /* translate the Zip entry filename coded in host-dependent "extended 2137 ASCII" into the compiler's (system's) internal text code page */ 2138 Ext_ASCII_TO_Native(G.filename, G.pInfo->hostnum, G.pInfo->hostver, 2139 G.pInfo->HasUxAtt, (option == DS_FN_L)); 2140 2141 if (G.pInfo->lcflag) /* replace with lowercase filename */ 2142 STRLOWER(G.filename, G.filename); 2143 2144 if (G.pInfo->vollabel && length > 8 && G.filename[8] == '.') { 2145 char *p = G.filename+8; 2146 while (*p++) 2147 p[-1] = *p; /* disk label, and 8th char is dot: remove dot */ 2148 } 2149 2150 if (!block_len) /* no overflow, we're done here */ 2151 break; 2152 2153 /* 2154 * We truncated the filename, so print what's left and then fall 2155 * through to the SKIP routine. 2156 */ 2157 Info(slide, 0x401, ((char *)slide, "[ %s ]\n", FnFilter1(G.filename))); 2158 length = block_len; /* SKIP the excess bytes... */ 2159 /* FALL THROUGH... */ 2160 2161 /* 2162 * Third case: skip string, adjusting readbuf's internal variables 2163 * as necessary (and possibly skipping to and reading a new block of 2164 * data). 2165 */ 2166 2167 case SKIP: 2168 /* cur_zipfile_bufstart already takes account of extra_bytes, so don't 2169 * correct for it twice: */ 2170 seek_zipf(__G__ G.cur_zipfile_bufstart - G.extra_bytes + 2171 (G.inptr-G.inbuf) + length); 2172 break; 2173 2174 /* 2175 * Fourth case: assume we're at the start of an "extra field"; malloc 2176 * storage for it and read data into the allocated space. 2177 */ 2178 2179 case EXTRA_FIELD: 2180 if (G.extra_field != (uch *)NULL) 2181 free(G.extra_field); 2182 if ((G.extra_field = (uch *)malloc(length)) == (uch *)NULL) { 2183 Info(slide, 0x401, ((char *)slide, LoadFarString(ExtraFieldTooLong), 2184 length)); 2185 /* cur_zipfile_bufstart already takes account of extra_bytes, 2186 * so don't correct for it twice: */ 2187 seek_zipf(__G__ G.cur_zipfile_bufstart - G.extra_bytes + 2188 (G.inptr-G.inbuf) + length); 2189 } else 2190 if (readbuf(__G__ (char *)G.extra_field, length) == 0) 2191 return PK_EOF; 2192 break; 2193 2194 #ifdef AMIGA 2195 /* 2196 * Fifth case, for the Amiga only: take the comment that would ordinarily 2197 * be skipped over, and turn it into a 79 character string that will be 2198 * attached to the file as a "filenote" after it is extracted. 2199 */ 2200 2201 case FILENOTE: 2202 if ((block_len = readbuf(__G__ tmp_fnote, (unsigned) 2203 MIN(length, 2 * AMIGA_FILENOTELEN - 1))) == 0) 2204 return PK_EOF; 2205 if ((length -= block_len) > 0) /* treat remainder as in case SKIP: */ 2206 seek_zipf(__G__ G.cur_zipfile_bufstart - G.extra_bytes 2207 + (G.inptr - G.inbuf) + length); 2208 /* convert multi-line text into single line with no ctl-chars: */ 2209 tmp_fnote[block_len] = '\0'; 2210 while ((short int) --block_len >= 0) 2211 if ((unsigned) tmp_fnote[block_len] < ' ') 2212 if (tmp_fnote[block_len+1] == ' ') /* no excess */ 2213 strcpy(tmp_fnote+block_len, tmp_fnote+block_len+1); 2214 else 2215 tmp_fnote[block_len] = ' '; 2216 tmp_fnote[AMIGA_FILENOTELEN - 1] = '\0'; 2217 if (G.filenotes[G.filenote_slot]) 2218 free(G.filenotes[G.filenote_slot]); /* should not happen */ 2219 G.filenotes[G.filenote_slot] = NULL; 2220 if (tmp_fnote[0]) { 2221 if (!(G.filenotes[G.filenote_slot] = malloc(strlen(tmp_fnote)+1))) 2222 return PK_MEM; 2223 strcpy(G.filenotes[G.filenote_slot], tmp_fnote); 2224 } 2225 break; 2226 #endif /* AMIGA */ 2227 2228 } /* end switch (option) */ 2229 2230 return error; 2231 2232 } /* end function do_string() */ 2233 2234 2235 2236 2237 2238 /***********************/ 2239 /* Function makeword() */ 2240 /***********************/ 2241 2242 ush makeword(b) 2243 ZCONST uch *b; 2244 { 2245 /* 2246 * Convert Intel style 'short' integer to non-Intel non-16-bit 2247 * host format. This routine also takes care of byte-ordering. 2248 */ 2249 return (ush)((b[1] << 8) | b[0]); 2250 } 2251 2252 2253 2254 2255 2256 /***********************/ 2257 /* Function makelong() */ 2258 /***********************/ 2259 2260 ulg makelong(sig) 2261 ZCONST uch *sig; 2262 { 2263 /* 2264 * Convert intel style 'long' variable to non-Intel non-16-bit 2265 * host format. This routine also takes care of byte-ordering. 2266 */ 2267 return (((ulg)sig[3]) << 24) 2268 + (((ulg)sig[2]) << 16) 2269 + (((ulg)sig[1]) << 8) 2270 + ((ulg)sig[0]); 2271 } 2272 2273 2274 2275 #if CRYPT 2276 2277 #ifdef NEED_STR2ISO 2278 /**********************/ 2279 /* Function str2iso() */ 2280 /**********************/ 2281 2282 char *str2iso(dst, src) 2283 char *dst; /* destination buffer */ 2284 register ZCONST char *src; /* source string */ 2285 { 2286 #ifdef INTERN_TO_ISO 2287 INTERN_TO_ISO(src, dst); 2288 #else 2289 register uch c; 2290 register char *dstp = dst; 2291 2292 do { 2293 c = (uch)foreign(*src++); 2294 *dstp++ = (char)ASCII2ISO(c); 2295 } while (c != '\0'); 2296 #endif 2297 2298 return dst; 2299 } 2300 #endif /* NEED_STR2ISO */ 2301 2302 2303 #ifdef NEED_STR2OEM 2304 /**********************/ 2305 /* Function str2oem() */ 2306 /**********************/ 2307 2308 char *str2oem(dst, src) 2309 char *dst; /* destination buffer */ 2310 register ZCONST char *src; /* source string */ 2311 { 2312 #ifdef INTERN_TO_OEM 2313 INTERN_TO_OEM(src, dst); 2314 #else 2315 register uch c; 2316 register char *dstp = dst; 2317 2318 do { 2319 c = (uch)foreign(*src++); 2320 *dstp++ = (char)ASCII2OEM(c); 2321 } while (c != '\0'); 2322 #endif 2323 2324 return dst; 2325 } 2326 #endif /* NEED_STR2OEM */ 2327 2328 #endif /* CRYPT */ 2329 2330 2331 #ifdef ZMEM /* memset/memcmp/memcpy for systems without either them or */ 2332 /* bzero/bcmp/bcopy */ 2333 /* (no known systems as of 960211) */ 2334 2335 /*********************/ 2336 /* Function memset() */ 2337 /*********************/ 2338 2339 zvoid *memset(buf, init, len) 2340 register zvoid *buf; /* buffer location */ 2341 register int init; /* initializer character */ 2342 register unsigned int len; /* length of the buffer */ 2343 { 2344 zvoid *start; 2345 2346 start = buf; 2347 while (len--) 2348 *((char *)buf++) = (char)init; 2349 return start; 2350 } 2351 2352 2353 2354 /*********************/ 2355 /* Function memcmp() */ 2356 /*********************/ 2357 2358 int memcmp(b1, b2, len) 2359 register ZCONST zvoid *b1; 2360 register ZCONST zvoid *b2; 2361 register unsigned int len; 2362 { 2363 register int c; 2364 2365 if (len > 0) do { 2366 if ((c = (int)(*((ZCONST unsigned char *)b1)++) - 2367 (int)(*((ZCONST unsigned char *)b2)++)) != 0) 2368 return c; 2369 } while (--len > 0) 2370 return 0; 2371 } 2372 2373 2374 2375 /*********************/ 2376 /* Function memcpy() */ 2377 /*********************/ 2378 2379 zvoid *memcpy(dst, src, len) 2380 register zvoid *dst; 2381 register ZCONST zvoid *src; 2382 register unsigned int len; 2383 { 2384 zvoid *start; 2385 2386 start = dst; 2387 while (len-- > 0) 2388 *((char *)dst)++ = *((ZCONST char *)src)++; 2389 return start; 2390 } 2391 2392 #endif /* ZMEM */ 2393 2394 2395 2396 2397 #ifdef NO_STRNICMP 2398 2399 /************************/ 2400 /* Function zstrnicmp() */ 2401 /************************/ 2402 2403 int zstrnicmp(s1, s2, n) 2404 register ZCONST char *s1, *s2; 2405 register unsigned n; 2406 { 2407 for (; n > 0; --n, ++s1, ++s2) { 2408 2409 if (ToLower(*s1) != ToLower(*s2)) 2410 /* test includes early termination of one string */ 2411 return (ToLower(*s1) < ToLower(*s2))? -1 : 1; 2412 2413 if (*s1 == '\0') /* both strings terminate early */ 2414 return 0; 2415 } 2416 return 0; 2417 } 2418 2419 #endif /* NO_STRNICMP */ 2420 2421 2422 2423 2424 #ifdef REGULUS /* returns the inode number on success(!)...argh argh argh */ 2425 # undef stat 2426 2427 /********************/ 2428 /* Function zstat() */ 2429 /********************/ 2430 2431 int zstat(p, s) 2432 ZCONST char *p; 2433 struct stat *s; 2434 { 2435 return (stat((char *)p,s) >= 0? 0 : (-1)); 2436 } 2437 2438 #endif /* REGULUS */ 2439 2440 2441 2442 2443 #ifdef _MBCS 2444 2445 /* DBCS support for Info-ZIP's zip (mainly for japanese (-: ) 2446 * by Yoshioka Tsuneo (QWF00133@nifty.ne.jp,tsuneo-y@is.aist-nara.ac.jp) 2447 * This code is public domain! Date: 1998/12/20 2448 */ 2449 2450 /************************/ 2451 /* Function plastchar() */ 2452 /************************/ 2453 2454 char *plastchar(ptr, len) 2455 ZCONST char *ptr; 2456 extent len; 2457 { 2458 unsigned clen; 2459 ZCONST char *oldptr = ptr; 2460 while(*ptr != '\0' && len > 0){ 2461 oldptr = ptr; 2462 clen = CLEN(ptr); 2463 ptr += clen; 2464 len -= clen; 2465 } 2466 return (char *)oldptr; 2467 } 2468 2469 2470 #ifdef NEED_UZMBSCHR 2471 /***********************/ 2472 /* Function uzmbschr() */ 2473 /***********************/ 2474 2475 unsigned char *uzmbschr(str, c) 2476 ZCONST unsigned char *str; 2477 unsigned int c; 2478 { 2479 while(*str != '\0'){ 2480 if (*str == c) {return (unsigned char *)str;} 2481 INCSTR(str); 2482 } 2483 return NULL; 2484 } 2485 #endif /* NEED_UZMBSCHR */ 2486 2487 2488 #ifdef NEED_UZMBSRCHR 2489 /************************/ 2490 /* Function uzmbsrchr() */ 2491 /************************/ 2492 2493 unsigned char *uzmbsrchr(str, c) 2494 ZCONST unsigned char *str; 2495 unsigned int c; 2496 { 2497 unsigned char *match = NULL; 2498 while(*str != '\0'){ 2499 if (*str == c) {match = (unsigned char *)str;} 2500 INCSTR(str); 2501 } 2502 return match; 2503 } 2504 #endif /* NEED_UZMBSRCHR */ 2505 #endif /* _MBCS */ 2506 2507 2508 2509 2510 2511 #ifdef SMALL_MEM 2512 2513 /*******************************/ 2514 /* Function fLoadFarString() */ /* (and friends...) */ 2515 /*******************************/ 2516 2517 char *fLoadFarString(__GPRO__ const char Far *sz) 2518 { 2519 (void)zfstrcpy(G.rgchBigBuffer, sz); 2520 return G.rgchBigBuffer; 2521 } 2522 2523 char *fLoadFarStringSmall(__GPRO__ const char Far *sz) 2524 { 2525 (void)zfstrcpy(G.rgchSmallBuffer, sz); 2526 return G.rgchSmallBuffer; 2527 } 2528 2529 char *fLoadFarStringSmall2(__GPRO__ const char Far *sz) 2530 { 2531 (void)zfstrcpy(G.rgchSmallBuffer2, sz); 2532 return G.rgchSmallBuffer2; 2533 } 2534 2535 2536 2537 2538 #if (!defined(_MSC_VER) || (_MSC_VER < 600)) 2539 /*************************/ 2540 /* Function zfstrcpy() */ /* portable clone of _fstrcpy() */ 2541 /*************************/ 2542 2543 char Far * Far zfstrcpy(char Far *s1, const char Far *s2) 2544 { 2545 char Far *p = s1; 2546 2547 while ((*s1++ = *s2++) != '\0'); 2548 return p; 2549 } 2550 #endif /* !_MSC_VER || (_MSC_VER < 600) */ 2551 2552 #endif /* SMALL_MEM */ 2553