|
|
1.1 ! root 1: /*--------------------------------------------------------------------------- ! 2: ! 3: file_io.c ! 4: ! 5: This file contains routines for doing direct input/output, file-related ! 6: sorts of things. Most of the system-specific code for unzip is contained ! 7: here, including the non-echoing password code for decryption (bottom). ! 8: ! 9: ---------------------------------------------------------------------------*/ ! 10: ! 11: ! 12: #if (!defined(__GO32__) && !defined(NeXT)) ! 13: # define const ! 14: #endif ! 15: ! 16: #define FILE_IO_C ! 17: #include "unzip.h" ! 18: ! 19: #ifdef MSWIN ! 20: # include "wizunzip.h" ! 21: #endif ! 22: ! 23: ! 24: /************************************/ ! 25: /* File_IO Local Prototypes, etc. */ ! 26: /************************************/ ! 27: ! 28: #if (!defined(DOS_OS2) || defined(MSWIN)) ! 29: static int dos2unix __((unsigned char *buf, int len)); ! 30: int CR_flag = 0; /* when last char of buffer == CR (for dos2unix()) */ ! 31: #endif ! 32: ! 33: #ifdef OS2 ! 34: extern int longname; /* set in mapname.c */ ! 35: extern char longfilename[]; ! 36: #endif ! 37: ! 38: #ifdef CRYPT ! 39: # if (defined(DOS_OS2) || defined(VMS)) ! 40: # define MSVMS ! 41: # ifdef DOS_OS2 ! 42: # ifdef __EMX__ ! 43: # define getch() _read_kbd(0, 1, 0) ! 44: # else ! 45: # ifdef __GO32__ ! 46: # include <pc.h> ! 47: # define getch() getkey() ! 48: # else /* !__GO32__ */ ! 49: # include <conio.h> ! 50: # endif /* ?__GO32__ */ ! 51: # endif ! 52: # else /* !DOS_OS2 */ ! 53: # define getch() getc(stderr) ! 54: # define OFF 0 /* for echo control */ ! 55: # define ON 1 ! 56: # define echoff(f) echo(OFF) ! 57: # define echon() echo(ON) ! 58: # include <descrip.h> ! 59: # include <iodef.h> ! 60: # include <ttdef.h> ! 61: # if !defined(SS$_NORMAL) ! 62: # define SS$_NORMAL 1 /* only thing we need from <ssdef.h> */ ! 63: # endif ! 64: # endif /* ?DOS_OS2 */ ! 65: # else /* !(DOS_OS2 || VMS) */ ! 66: # ifdef TERMIO /* Amdahl, Cray, all SysV? */ ! 67: # ifdef CONVEX ! 68: # include <sys/termios.h> ! 69: # include <sgtty.h> ! 70: # else /* !CONVEX */ ! 71: # ifdef LINUX ! 72: # include <termios.h> ! 73: # else /* !LINUX */ ! 74: # include <termio.h> ! 75: # endif /* ?LINUX */ ! 76: # define sgttyb termio ! 77: # define sg_flags c_lflag ! 78: # endif /* ?CONVEX */ ! 79: int ioctl OF((int, int, voidp *)); ! 80: # define GTTY(f,s) ioctl(f,TCGETA,(voidp *)s) ! 81: # define STTY(f,s) ioctl(f,TCSETAW,(voidp *)s) ! 82: # else /* !TERMIO */ ! 83: # if (!defined(MINIX) && !defined(__386BSD__)) ! 84: # include <sys/ioctl.h> ! 85: # endif /* !MINIX && !__386BSD__ */ ! 86: # include <sgtty.h> ! 87: # ifdef __386BSD__ ! 88: # define GTTY(f, s) ioctl(f, TIOCGETP, (voidp *) s) ! 89: # define STTY(f, s) ioctl(f, TIOCSETP, (voidp *) s) ! 90: # else /* !__386BSD__ */ ! 91: # define GTTY gtty ! 92: # define STTY stty ! 93: int gtty OF((int, struct sgttyb *)); ! 94: int stty OF((int, struct sgttyb *)); ! 95: # endif /* ?__386BSD__ */ ! 96: # endif /* ?TERMIO */ ! 97: int isatty OF((int)); ! 98: char *ttyname OF((int)); ! 99: # if (defined(PROTO) && !defined(__GNUC__) && !defined(_AIX)) ! 100: int open (char *, int, ...); ! 101: # endif ! 102: int close OF((int)); ! 103: int read OF((int, voidp *, int)); ! 104: # endif /* ?(DOS_OS2 || VMS) */ ! 105: #endif /* CRYPT */ ! 106: ! 107: ! 108: ! 109: ! 110: ! 111: /******************************/ ! 112: /* Function open_input_file() */ ! 113: /******************************/ ! 114: ! 115: int open_input_file() /* return non-zero if open failed */ ! 116: { ! 117: /* ! 118: * open the zipfile for reading and in BINARY mode to prevent cr/lf ! 119: * translation, which would corrupt the bitstreams ! 120: */ ! 121: ! 122: #ifdef VMS ! 123: zipfd = open(zipfn, O_RDONLY, 0, "ctx=stm"); ! 124: #else /* !VMS */ ! 125: #ifdef UNIX ! 126: zipfd = open(zipfn, O_RDONLY); ! 127: #else /* !UNIX */ ! 128: #ifdef MACOS ! 129: zipfd = open(zipfn, 0); ! 130: #else /* !MACOS */ ! 131: zipfd = open(zipfn, O_RDONLY | O_BINARY); ! 132: #endif /* ?MACOS */ ! 133: #endif /* ?UNIX */ ! 134: #endif /* ?VMS */ ! 135: if (zipfd < 1) { ! 136: fprintf(stderr, "error: can't open zipfile [ %s ]\n", zipfn); ! 137: return (1); ! 138: } ! 139: return 0; ! 140: } ! 141: ! 142: ! 143: ! 144: ! 145: ! 146: /**********************/ ! 147: /* Function readbuf() */ ! 148: /**********************/ ! 149: ! 150: int readbuf(buf, size) ! 151: char *buf; ! 152: register unsigned size; ! 153: { /* return number of bytes read into buf */ ! 154: register int count; ! 155: int n; ! 156: ! 157: n = size; ! 158: while (size) { ! 159: if (incnt == 0) { ! 160: if ((incnt = read(zipfd, (char *)inbuf, INBUFSIZ)) <= 0) ! 161: return (n-size); ! 162: /* buffer ALWAYS starts on a block boundary: */ ! 163: cur_zipfile_bufstart += INBUFSIZ; ! 164: inptr = inbuf; ! 165: } ! 166: count = MIN(size, (unsigned)incnt); ! 167: memcpy(buf, inptr, count); ! 168: buf += count; ! 169: inptr += count; ! 170: incnt -= count; ! 171: size -= count; ! 172: } ! 173: return (n); ! 174: } ! 175: ! 176: ! 177: ! 178: ! 179: ! 180: #ifndef VMS /* for VMS use code in vms.c (old VMS code below is retained ! 181: * in case of problems...will be removed in a later release) */ ! 182: ! 183: /*********************************/ ! 184: /* Function create_output_file() */ ! 185: /*********************************/ ! 186: ! 187: int create_output_file() /* return non-0 if creat failed */ ! 188: { ! 189: /*--------------------------------------------------------------------------- ! 190: Create the output file with appropriate permissions. If we've gotten to ! 191: this point and the file still exists, we have permission to blow it away. ! 192: ---------------------------------------------------------------------------*/ ! 193: ! 194: #if (!defined(DOS_OS2) || defined(MSWIN)) ! 195: CR_flag = 0; /* hack to get CR at end of buffer working */ ! 196: #endif ! 197: ! 198: #if (defined(UNIX) && !defined(AMIGA)) ! 199: { ! 200: int mask; ! 201: ! 202: #ifndef VMS ! 203: if (!stat(filename, &statbuf) && (unlink(filename) < 0)) { ! 204: fprintf(stderr, "\n%s: cannot delete old copy\n", filename); ! 205: return 1; ! 206: } ! 207: # define EXTRA_ARGS ! 208: #else /* VMS */ ! 209: # define EXTRA_ARGS ,"rfm=stmlf","rat=cr" ! 210: #endif /* ?VMS */ ! 211: ! 212: mask = umask(0); /* now know that we own it */ ! 213: outfd = creat(filename, 0xffff & pInfo->unix_attr EXTRA_ARGS); ! 214: umask(mask); /* VMS, Unix */ ! 215: } ! 216: #else /* !UNIX || AMIGA */ /* file permissions set after file closed */ ! 217: #ifndef MACOS ! 218: outfd = creat(filename, S_IWRITE | S_IREAD); /* DOS, OS2, Mac, Amiga */ ! 219: #else /* MACOS */ ! 220: { ! 221: short fDataFork=TRUE; ! 222: MACINFO mi; ! 223: OSErr err; ! 224: ! 225: fMacZipped = FALSE; ! 226: CtoPstr(filename); ! 227: if (extra_field && ! 228: (lrec.extra_field_length > sizeof(MACINFOMIN)) && ! 229: (lrec.extra_field_length <= sizeof(MACINFO))) { ! 230: BlockMove(extra_field, &mi, lrec.extra_field_length); ! 231: if ((makeword((byte *)&mi.header) == 1992) && ! 232: (makeword((byte *)&mi.data) == ! 233: lrec.extra_field_length-sizeof(ZIP_EXTRA_HEADER)) && ! 234: (mi.signature == 'JLEE')) { ! 235: gostCreator = mi.finfo.fdCreator; ! 236: gostType = mi.finfo.fdType; ! 237: fDataFork = (mi.flags & 1) ? TRUE : FALSE; ! 238: fMacZipped = true; ! 239: /* If it was Zipped w/Mac version, the filename has either */ ! 240: /* a 'd' or 'r' appended. Remove the d/r when unzipping */ ! 241: filename[0]-=1; ! 242: } ! 243: } ! 244: if (!fMacZipped) { ! 245: if (!aflag) ! 246: gostType = gostCreator = '\?\?\?\?'; ! 247: else { ! 248: #ifdef THINK_C ! 249: gostCreator = 'KAHL'; ! 250: #else ! 251: #ifdef MCH_MACINTOSH ! 252: gostCreator = 'Manx'; ! 253: #else ! 254: gostCreator = 'MPS '; ! 255: #endif ! 256: #endif ! 257: gostType = 'TEXT'; ! 258: } ! 259: } ! 260: PtoCstr(filename); ! 261: ! 262: outfd = creat(filename, 0); ! 263: if (fMacZipped) { ! 264: CtoPstr(filename); ! 265: if (hfsflag) { ! 266: HParamBlockRec hpbr; ! 267: ! 268: hpbr.fileParam.ioNamePtr = (StringPtr)filename; ! 269: hpbr.fileParam.ioVRefNum = gnVRefNum; ! 270: hpbr.fileParam.ioDirID = glDirID; ! 271: hpbr.fileParam.ioFlFndrInfo = mi.finfo; ! 272: hpbr.fileParam.ioFlCrDat = mi.lCrDat; ! 273: hpbr.fileParam.ioFlMdDat = mi.lMdDat; ! 274: err = PBHSetFInfo(&hpbr, 0); ! 275: } else { ! 276: err = SetFInfo((StringPtr)filename , 0, &mi.finfo); ! 277: } ! 278: PtoCstr(filename); ! 279: } ! 280: if (outfd != -1) ! 281: outfd = open(filename, (fDataFork)? 1 : 2); ! 282: } ! 283: #endif /* ?MACOS */ ! 284: #endif /* ?(UNIX && !AMIGA) */ ! 285: ! 286: if (outfd < 1) { ! 287: fprintf(stderr, "\n%s: cannot create\n", filename); ! 288: return 1; ! 289: } ! 290: ! 291: /*--------------------------------------------------------------------------- ! 292: If newly created file is in text mode and should be binary (to disable ! 293: automatic CR/LF translations), either close it and reopen as binary or ! 294: else change the mode to binary (DOS, OS/2). ! 295: ---------------------------------------------------------------------------*/ ! 296: ! 297: #if (!defined(UNIX) && !defined(MACOS)) ! 298: if (!aflag) { ! 299: #ifdef DOS_OS2 ! 300: if (setmode(outfd, O_BINARY) == -1) { ! 301: #else /* !DOS_OS2 */ ! 302: close(outfd); ! 303: if ((outfd = open(filename, O_RDWR | O_BINARY)) < 1) { ! 304: #endif /* ?DOS_OS2 */ ! 305: fprintf(stderr, "Can't make output file binary: %s\n", filename); ! 306: return 1; ! 307: } ! 308: } ! 309: #endif /* !UNIX && !MACOS */ ! 310: ! 311: return 0; ! 312: } ! 313: ! 314: #endif /* !VMS */ ! 315: ! 316: ! 317: ! 318: ! 319: ! 320: /****************************/ ! 321: /* Function FillBitBuffer() */ ! 322: /****************************/ ! 323: ! 324: int FillBitBuffer() ! 325: { ! 326: /* ! 327: * Fill bitbuf, which is 32 bits. This function is only used by the ! 328: * READBIT and PEEKBIT macros (which are used by all of the uncompression ! 329: * routines). ! 330: */ ! 331: UWORD temp; ! 332: ! 333: zipeof = 1; ! 334: while (bits_left < 25 && ReadByte(&temp) == 8) ! 335: { ! 336: bitbuf |= (ULONG)temp << bits_left; ! 337: bits_left += 8; ! 338: zipeof = 0; ! 339: } ! 340: return 0; ! 341: } ! 342: ! 343: ! 344: ! 345: ! 346: ! 347: /***********************/ ! 348: /* Function ReadByte() */ ! 349: /***********************/ ! 350: ! 351: int ReadByte(x) ! 352: UWORD *x; ! 353: { ! 354: /* ! 355: * read a byte; return 8 if byte available, 0 if not ! 356: */ ! 357: ! 358: if (mem_mode) ! 359: return ReadMemoryByte(x); ! 360: ! 361: if (csize-- <= 0) ! 362: return 0; ! 363: ! 364: if (incnt == 0) { ! 365: if ((incnt = read(zipfd, (char *)inbuf, INBUFSIZ)) <= 0) ! 366: return 0; ! 367: /* buffer ALWAYS starts on a block boundary: */ ! 368: cur_zipfile_bufstart += INBUFSIZ; ! 369: inptr = inbuf; ! 370: #ifdef CRYPT ! 371: if (pInfo->encrypted) { ! 372: byte *p; ! 373: int n, t; ! 374: ! 375: for (n = (longint)incnt > csize + 1 ? (int)csize + 1 : incnt, ! 376: p = inptr; n--; p++) ! 377: *p = (byte) DECRYPT(*p); ! 378: } ! 379: #endif /* CRYPT */ ! 380: } ! 381: *x = *inptr++; ! 382: --incnt; ! 383: return 8; ! 384: } ! 385: ! 386: ! 387: ! 388: ! 389: ! 390: #ifndef VMS /* for VMS use code in vms.c */ ! 391: ! 392: /**************************/ ! 393: /* Function FlushOutput() */ ! 394: /**************************/ ! 395: ! 396: int FlushOutput() ! 397: { ! 398: /* ! 399: * flush contents of output buffer; return PK-type error code ! 400: */ ! 401: #if (!defined(DOS_OS2) || defined(MSWIN)) ! 402: int saved_ctrlZ = FALSE; ! 403: #endif ! 404: int len; ! 405: ! 406: ! 407: if (mem_mode) { ! 408: int rc = FlushMemory(); ! 409: outpos += outcnt; ! 410: outcnt = 0; ! 411: outptr = outbuf; ! 412: return rc; ! 413: } ! 414: ! 415: if (disk_full) { ! 416: outpos += outcnt; /* fake emptied buffer */ ! 417: outcnt = 0; ! 418: outptr = outbuf; ! 419: return 50; /* ignore rest of this file */ ! 420: } ! 421: ! 422: if (outcnt) { ! 423: UpdateCRC(outbuf, outcnt); ! 424: ! 425: if (!tflag) { ! 426: #if (!defined(DOS_OS2) || defined(MSWIN)) ! 427: if (aflag) { ! 428: if (outbuf[outcnt-1] == CTRLZ) { ! 429: --outcnt; ! 430: saved_ctrlZ = TRUE; ! 431: } ! 432: len = dos2unix(outbuf, outcnt); ! 433: } else ! 434: #endif /* !DOS_OS2 || MSWIN */ ! 435: len = outcnt; ! 436: #ifdef MACOS ! 437: if ((giCursor+1) >> 2 != (giCursor>>2)) ! 438: SetCursor( *rghCursor[((giCursor+1)>>2)&0x03] ); ! 439: giCursor = (giCursor+1) & 15; ! 440: #endif /* MACOS */ ! 441: #ifdef MSWIN ! 442: /* if writing to console vs. actual file, write to Msg Window */ ! 443: if (cflag) ! 444: WriteBufferToMsgWin(outout, len, FALSE); ! 445: else if (_lwrite(outfd, outout, len) != (UINT)len) ! 446: #else /* !MSWIN */ ! 447: if (write(outfd, (char *)outout, len) != len) ! 448: #endif /* ?MSWIN */ ! 449: #ifdef DOS_OS2 ! 450: if (!cflag) /* ^Z treated as EOF, removed with -c */ ! 451: #else /* !DOS_OS2 */ ! 452: #ifdef MINIX ! 453: if (errno == EFBIG) ! 454: if (write(fd, outout, len/2) != len/2 || ! 455: write(fd, outout+len/2, len/2) != len/2) ! 456: #endif /* MINIX */ ! 457: #endif /* ?DOS_OS2 */ ! 458: { ! 459: /* GRR: add test for force_flag when has its own switch */ ! 460: fprintf(stderr, ! 461: "\n%s: write error (disk full?). Continue? (y/n/^C) ", ! 462: filename); ! 463: FFLUSH /* for Amiga and Mac MPW */ ! 464: #ifdef MSWIN ! 465: disk_full = 2; ! 466: #else /* !MSWIN */ ! 467: fgets(answerbuf, 9, stdin); ! 468: if (*answerbuf == 'y') /* stop writing to this file */ ! 469: disk_full = 1; /* (outfd bad?), but new OK */ ! 470: else ! 471: disk_full = 2; /* no: exit program */ ! 472: #endif /* ?MSWIN */ ! 473: return 50; /* 50: disk full */ ! 474: } ! 475: } ! 476: outpos += outcnt; ! 477: outcnt = 0; ! 478: outptr = outbuf; ! 479: #if (!defined(DOS_OS2) || defined(MSWIN)) ! 480: if (saved_ctrlZ) { ! 481: *outptr++ = CTRLZ; ! 482: ++outcnt; ! 483: } ! 484: #endif /* !DOS_OS2 || MSWIN */ ! 485: } ! 486: return 0; /* 0: no error */ ! 487: } ! 488: ! 489: #endif /* !VMS */ ! 490: ! 491: ! 492: ! 493: ! 494: ! 495: #if (!defined(DOS_OS2) || defined(MSWIN)) ! 496: ! 497: /***********************/ ! 498: /* Function dos2unix() */ ! 499: /***********************/ ! 500: ! 501: static int dos2unix(buf, len) /* GRR: rewrite for generic text conversions */ ! 502: unsigned char *buf; ! 503: int len; ! 504: { ! 505: int new_len; ! 506: int i; ! 507: #ifdef MSWIN ! 508: unsigned char __far *walker; ! 509: #else /* !MSWIN */ ! 510: unsigned char *walker; ! 511: #endif /* ?MSWIN */ ! 512: ! 513: new_len = len; ! 514: walker = outout; ! 515: #ifdef MACOS ! 516: /* ! 517: * Mac wants to strip LFs instead CRs from CRLF pairs ! 518: */ ! 519: if (CR_flag && *buf == LF) { ! 520: buf++; ! 521: new_len--; ! 522: len--; ! 523: CR_flag = buf[len] == CR; ! 524: } ! 525: else ! 526: CR_flag = buf[len - 1] == CR; ! 527: for (i = 0; i < len; i += 1) { ! 528: *walker++ = ascii_to_native(*buf); ! 529: if (*buf == LF) walker[-1] = CR; ! 530: if (*buf++ == CR && *buf == LF) { ! 531: new_len--; ! 532: buf++; ! 533: i++; ! 534: } ! 535: } ! 536: #else /* !MACOS */ ! 537: if (CR_flag && *buf != LF) ! 538: *walker++ = ascii_to_native(CR); ! 539: CR_flag = buf[len - 1] == CR; ! 540: for (i = 0; i < len; i += 1) { ! 541: *walker++ = ascii_to_native(*buf); ! 542: if (*buf++ == CR && *buf == LF) { ! 543: new_len--; ! 544: walker[-1] = ascii_to_native(*buf++); ! 545: i++; ! 546: } ! 547: } ! 548: /* ! 549: * If the last character is a CR, then "ignore it" for now... ! 550: */ ! 551: if (walker[-1] == ascii_to_native(CR)) ! 552: new_len--; ! 553: #endif /* ?MACOS */ ! 554: return new_len; ! 555: } ! 556: ! 557: #endif /* !DOS_OS2 || MSWIN */ ! 558: ! 559: ! 560: ! 561: ! 562: ! 563: #ifdef __GO32__ ! 564: ! 565: void _dos_setftime(int fd, UWORD dosdate, UWORD dostime) ! 566: { ! 567: asm("pushl %ebx"); ! 568: asm("movl %0, %%ebx": : "g" (fd)); ! 569: asm("movl %0, %%ecx": : "g" (dostime)); ! 570: asm("movl %0, %%edx": : "g" (dosdate)); ! 571: asm("movl $0x5701, %eax"); ! 572: asm("int $0x21"); ! 573: asm("popl %ebx"); ! 574: } ! 575: ! 576: void _dos_setfileattr(char *name, int attr) ! 577: { ! 578: asm("movl %0, %%edx": : "g" (name)); ! 579: asm("movl %0, %%ecx": : "g" (attr)); ! 580: asm("movl $0x4301, %eax"); ! 581: asm("int $0x21"); ! 582: } ! 583: ! 584: #endif /* __GO32__ */ ! 585: ! 586: ! 587: ! 588: ! 589: ! 590: #ifdef DOS_OS2 ! 591: ! 592: /**************************************/ ! 593: /* Function set_file_time_and_close() */ ! 594: /**************************************/ ! 595: ! 596: void set_file_time_and_close() ! 597: /* ! 598: * MS-DOS AND OS/2 VERSION (Mac, Unix/VMS versions are below) ! 599: * ! 600: * Set the output file date/time stamp according to information from the ! 601: * zipfile directory record for this member, then close the file and set ! 602: * its permissions (archive, hidden, read-only, system). Aside from closing ! 603: * the file, this routine is optional (but most compilers support it). ! 604: */ ! 605: { ! 606: /*--------------------------------------------------------------------------- ! 607: Allocate local variables needed by OS/2 and Turbo C. ! 608: ---------------------------------------------------------------------------*/ ! 609: ! 610: #ifdef __TURBOC__ ! 611: ! 612: union { ! 613: struct ftime ft; /* system file time record */ ! 614: struct { ! 615: UWORD ztime; /* date and time words */ ! 616: UWORD zdate; /* .. same format as in .ZIP file */ ! 617: } zt; ! 618: } td; ! 619: ! 620: #endif /* __TURBOC__ */ ! 621: ! 622: /*--------------------------------------------------------------------------- ! 623: Do not attempt to set the time stamp on standard output. ! 624: ---------------------------------------------------------------------------*/ ! 625: ! 626: if (cflag) { ! 627: close(outfd); ! 628: return; ! 629: } ! 630: ! 631: /*--------------------------------------------------------------------------- ! 632: Copy and/or convert time and date variables, if necessary; then set the ! 633: file time/date. ! 634: ---------------------------------------------------------------------------*/ ! 635: ! 636: #ifndef OS2 ! 637: #ifdef __TURBOC__ ! 638: td.zt.ztime = lrec.last_mod_file_time; ! 639: td.zt.zdate = lrec.last_mod_file_date; ! 640: setftime(outfd, &td.ft); ! 641: #else /* !__TURBOC__ */ ! 642: #ifdef WIN32 ! 643: { ! 644: FILETIME ft; /* 64-bit value made up of two 32 bit [low & high] */ ! 645: WORD wDOSDate; /* for vconvertin from DOS date to Windows NT */ ! 646: WORD wDOSTime; ! 647: HANDLE hFile; /* file handle (defined in Windows NT) */ ! 648: ! 649: wDOSTime = (WORD) lrec.last_mod_file_time; ! 650: wDOSDate = (WORD) lrec.last_mod_file_date; ! 651: ! 652: /* The DosDateTimeToFileTime() function converts a DOS date/time ! 653: * into a 64 bit Windows NT file time */ ! 654: DosDateTimeToFileTime(wDOSDate, wDOSTime, &ft); ! 655: ! 656: /* Close the file and then re-open it using the Win32 ! 657: * CreateFile call, so that the file can be created ! 658: * with GENERIC_WRITE access, otherwise the SetFileTime ! 659: * call will fail. */ ! 660: close(outfd); ! 661: ! 662: hFile = CreateFile(filename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, ! 663: FILE_ATTRIBUTE_NORMAL, NULL); ! 664: ! 665: if (!SetFileTime(hFile, NULL, NULL, &ft)) ! 666: printf("\nSetFileTime failed: %d\n", GetLastError()); ! 667: CloseHandle(hFile); ! 668: return; ! 669: } ! 670: #else /* !WIN32 */ ! 671: _dos_setftime(outfd, lrec.last_mod_file_date, lrec.last_mod_file_time); ! 672: #endif /* ?WIN32 */ ! 673: #endif /* ?__TURBOC__ */ ! 674: #endif /* ?OS2 */ ! 675: ! 676: /*--------------------------------------------------------------------------- ! 677: And finally we can close the file...at least everybody agrees on how to ! 678: do *this*. I think... Oh yeah, also change the mode according to the ! 679: stored file attributes, since we didn't do that when we opened the dude. ! 680: ---------------------------------------------------------------------------*/ ! 681: ! 682: close(outfd); ! 683: ! 684: #ifdef OS2 ! 685: SetPathInfo(filename, lrec.last_mod_file_date, ! 686: lrec.last_mod_file_time, pInfo->dos_attr); ! 687: if (extra_field) ! 688: SetEAs(filename, extra_field); ! 689: if (longname) ! 690: SetLongNameEA(filename, longfilename); ! 691: #else /* !OS2 */ ! 692: #ifdef __TURBOC__ ! 693: if (_chmod(filename, 1, pInfo->dos_attr) != pInfo->dos_attr) ! 694: fprintf(stderr, "\nwarning: file attributes may not be correct\n"); ! 695: #else /* !__TURBOC__ */ ! 696: #ifdef WIN32 ! 697: /* Attempt to set the file attributes. SetFileAttributes returns ! 698: * FALSE (0) if unsucessful, in which case print an error message, ! 699: * with error value returned from GetLastError call. */ ! 700: pInfo->dos_attr = pInfo->dos_attr & 0x7F; ! 701: ! 702: if (!(SetFileAttributes(filename, pInfo->dos_attr))) ! 703: fprintf(stderr, "\nwarning (%d): could not set file attributes\n", ! 704: GetLastError()); ! 705: #else /* !WIN32 */ ! 706: _dos_setfileattr(filename, pInfo->dos_attr); ! 707: #endif /* ?WIN32 */ ! 708: #endif /* ?__TURBOC__ */ ! 709: #endif /* ?OS2 */ ! 710: ! 711: } /* end function set_file_time_and_close() (DOS, OS/2) */ ! 712: ! 713: ! 714: ! 715: ! 716: ! 717: #else /* !DOS_OS2 */ ! 718: #ifdef MACOS /* Mac */ ! 719: ! 720: /**************************************/ ! 721: /* Function set_file_time_and_close() */ ! 722: /**************************************/ ! 723: ! 724: void set_file_time_and_close() ! 725: /* ! 726: * MAC VERSION ! 727: */ ! 728: { ! 729: long m_time; ! 730: DateTimeRec dtr; ! 731: ParamBlockRec pbr; ! 732: HParamBlockRec hpbr; ! 733: OSErr err; ! 734: ! 735: if (outfd != 1) { ! 736: close(outfd); ! 737: ! 738: /* ! 739: * Macintosh bases all file modification times on the number of seconds ! 740: * elapsed since Jan 1, 1904, 00:00:00. Therefore, to maintain ! 741: * compatibility with MS-DOS archives, which date from Jan 1, 1980, ! 742: * with NO relation to GMT, the following conversions must be made: ! 743: * the Year (yr) must be incremented by 1980; ! 744: * and converted to seconds using the Mac routine Date2Secs(), ! 745: * almost similar in complexity to the Unix version :-) ! 746: * J. Lee ! 747: */ ! 748: ! 749: dtr.year = (((lrec.last_mod_file_date >> 9) & 0x7f) + 1980); ! 750: dtr.month = ((lrec.last_mod_file_date >> 5) & 0x0f); ! 751: dtr.day = (lrec.last_mod_file_date & 0x1f); ! 752: ! 753: dtr.hour = ((lrec.last_mod_file_time >> 11) & 0x1f); ! 754: dtr.minute = ((lrec.last_mod_file_time >> 5) & 0x3f); ! 755: dtr.second = ((lrec.last_mod_file_time & 0x1f) * 2); ! 756: ! 757: Date2Secs(&dtr, (unsigned long *)&m_time); ! 758: CtoPstr(filename); ! 759: if (hfsflag) { ! 760: hpbr.fileParam.ioNamePtr = (StringPtr)filename; ! 761: hpbr.fileParam.ioVRefNum = gnVRefNum; ! 762: hpbr.fileParam.ioDirID = glDirID; ! 763: hpbr.fileParam.ioFDirIndex = 0; ! 764: err = PBHGetFInfo(&hpbr, 0L); ! 765: hpbr.fileParam.ioFlMdDat = m_time; ! 766: if ( !fMacZipped ) ! 767: hpbr.fileParam.ioFlCrDat = m_time; ! 768: hpbr.fileParam.ioDirID = glDirID; ! 769: if (err == noErr) ! 770: err = PBHSetFInfo(&hpbr, 0L); ! 771: if (err != noErr) ! 772: printf("error: can't set the time for %s\n", filename); ! 773: } else { ! 774: pbr.fileParam.ioNamePtr = (StringPtr)filename; ! 775: pbr.fileParam.ioVRefNum = pbr.fileParam.ioFVersNum = ! 776: pbr.fileParam.ioFDirIndex = 0; ! 777: err = PBGetFInfo(&pbr, 0L); ! 778: pbr.fileParam.ioFlMdDat = pbr.fileParam.ioFlCrDat = m_time; ! 779: if (err == noErr) ! 780: err = PBSetFInfo(&pbr, 0L); ! 781: if (err != noErr) ! 782: printf("error: can't set the time for %s\n", filename); ! 783: } ! 784: ! 785: /* set read-only perms if needed */ ! 786: if ((err == noErr) && !(pInfo->unix_attr & S_IWRITE)) { ! 787: if (hfsflag) { ! 788: hpbr.fileParam.ioNamePtr = (StringPtr)filename; ! 789: hpbr.fileParam.ioVRefNum = gnVRefNum; ! 790: hpbr.fileParam.ioDirID = glDirID; ! 791: err = PBHSetFLock(&hpbr, 0); ! 792: } else ! 793: err = SetFLock((ConstStr255Param)filename, 0); ! 794: } ! 795: PtoCstr(filename); ! 796: } ! 797: } ! 798: ! 799: ! 800: ! 801: ! 802: ! 803: #else /* !MACOS... */ ! 804: #if (!defined(MTS) && !defined(VMS)) /* && !MTS (can't do) && !VMS: only one ! 805: * left is UNIX (for VMS use code in vms.c) */ ! 806: ! 807: /**************************************/ ! 808: /* Function set_file_time_and_close() */ ! 809: /**************************************/ ! 810: ! 811: void set_file_time_and_close() ! 812: /* ! 813: * UNIX VERSION (MS-DOS & OS/2, Mac versions are above) ! 814: */ ! 815: { ! 816: static short yday[]={0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; ! 817: long m_time; ! 818: int yr, mo, dy, hh, mm, ss, leap, days=0; ! 819: struct utimbuf { ! 820: time_t actime; /* new access time */ ! 821: time_t modtime; /* new modification time */ ! 822: } tp; ! 823: #ifdef AMIGA ! 824: # define YRBASE 1978 /* in AmigaDos, counting begins 01-Jan-1978 */ ! 825: struct DateStamp myadate; ! 826: /* extern char *_TZ; no longer used? */ ! 827: #else /* !AMIGA */ ! 828: # define YRBASE 1970 ! 829: #ifdef BSD ! 830: #ifndef __386BSD__ ! 831: static struct timeb tbp; ! 832: #endif /* !__386BSD__ */ ! 833: #else /* !BSD */ ! 834: extern long timezone; ! 835: #endif /* ?BSD */ ! 836: #endif /* ?AMIGA */ ! 837: ! 838: ! 839: /* ! 840: * Close the file *before* setting its time under Unix and AmigaDos. ! 841: */ ! 842: #ifdef AMIGA ! 843: if (cflag) /* can't set time on stdout */ ! 844: return; ! 845: close(outfd); ! 846: #else /* !AMIGA */ ! 847: close(outfd); ! 848: if (cflag) /* can't set time on stdout */ ! 849: return; ! 850: #endif /* ?AMIGA */ ! 851: ! 852: /* ! 853: * These date conversions look a little weird, so I'll explain. ! 854: * UNIX bases all file modification times on the number of seconds ! 855: * elapsed since Jan 1, 1970, 00:00:00 GMT. Therefore, to maintain ! 856: * compatibility with MS-DOS archives, which date from Jan 1, 1980, ! 857: * with NO relation to GMT, the following conversions must be made: ! 858: * the Year (yr) must be incremented by 10; ! 859: * the Date (dy) must be decremented by 1; ! 860: * and the whole mess must be adjusted by TWO factors: ! 861: * relationship to GMT (ie.,Pacific Time adds 8 hrs.), ! 862: * and whether or not it is Daylight Savings Time. ! 863: * Also, the usual conversions must take place to account for leap years, ! 864: * etc. ! 865: * C. Seaman ! 866: */ ! 867: ! 868: /* dissect date */ ! 869: yr = ((lrec.last_mod_file_date >> 9) & 0x7f) + (1980 - YRBASE); ! 870: mo = ((lrec.last_mod_file_date >> 5) & 0x0f) - 1; ! 871: dy = (lrec.last_mod_file_date & 0x1f) - 1; ! 872: ! 873: /* dissect time */ ! 874: hh = (lrec.last_mod_file_time >> 11) & 0x1f; ! 875: mm = (lrec.last_mod_file_time >> 5) & 0x3f; ! 876: ss = (lrec.last_mod_file_time & 0x1f) * 2; ! 877: ! 878: /* leap = # of leap years from BASE up to but not including current year */ ! 879: leap = ((yr + YRBASE - 1) / 4); /* leap year base factor */ ! 880: ! 881: /* How many days from BASE to this year? (& add expired days this year) */ ! 882: days = (yr * 365) + (leap - 492) + yday[mo]; ! 883: ! 884: /* if year is a leap year and month is after February, add another day */ ! 885: if ((mo > 1) && ((yr+YRBASE)%4 == 0) && ((yr+YRBASE) != 2100)) ! 886: ++days; /* OK through 2199 */ ! 887: ! 888: #ifdef AMIGA ! 889: /* _TZ = getenv("TZ"); does Amiga not have TZ and tzset() after all? */ ! 890: myadate.ds_Days = days+dy-2; /* off by one? */ ! 891: myadate.ds_Minute = hh*60+mm; ! 892: myadate.ds_Tick = ss*TICKS_PER_SECOND; ! 893: ! 894: if (!(SetFileDate(filename, &myadate))) ! 895: fprintf(stderr, "error: can't set the time for %s\n", filename); ! 896: ! 897: #else /* !AMIGA */ ! 898: /* convert date & time to seconds relative to 00:00:00, 01/01/YRBASE */ ! 899: m_time = ((days + dy) * 86400) + (hh * 3600) + (mm * 60) + ss; ! 900: ! 901: #ifdef BSD ! 902: #ifndef __386BSD__ ! 903: ftime(&tbp); ! 904: m_time += tbp.timezone * 60L; ! 905: #endif ! 906: /* #elif WIN32 ! 907: * don't do anything right now (esp. since "elif" is not legal for old cc's */ ! 908: #else /* !BSD */ ! 909: tzset(); /* set `timezone' */ ! 910: m_time += timezone; /* account for timezone differences */ ! 911: #endif /* ?BSD */ ! 912: ! 913: #ifdef __386BSD__ ! 914: m_time += localtime(&m_time)->tm_gmtoff; ! 915: #else ! 916: if (localtime(&m_time)->tm_isdst) ! 917: m_time -= 60L * 60L; /* adjust for daylight savings time */ ! 918: #endif ! 919: ! 920: tp.actime = m_time; /* set access time */ ! 921: tp.modtime = m_time; /* set modification time */ ! 922: ! 923: /* set the time stamp on the file */ ! 924: if (utime(filename, &tp)) ! 925: fprintf(stderr, "error: can't set the time for %s\n", filename); ! 926: #endif /* ?AMIGA */ ! 927: } ! 928: ! 929: #endif /* !MTS && !VMS */ ! 930: #endif /* ?MACOS */ ! 931: #endif /* ?DOS_OS2 */ ! 932: ! 933: ! 934: ! 935: ! 936: ! 937: /************************/ ! 938: /* Function handler() */ ! 939: /************************/ ! 940: ! 941: void handler(signal) /* upon interrupt, turn on echo and exit cleanly */ ! 942: int signal; ! 943: { ! 944: #if (defined(SIGBUS) || defined(SIGSEGV)) ! 945: static char *corrupt = "error: zipfile probably corrupt\n"; ! 946: #endif ! 947: ! 948: #ifndef DOS_OS2 ! 949: #ifdef CRYPT ! 950: echon(); ! 951: #endif /* CRYPT */ ! 952: putc('\n', stderr); ! 953: #endif /* !DOS_OS2 */ ! 954: #ifdef SIGBUS ! 955: if (signal == SIGBUS) { ! 956: fprintf(stderr, corrupt); ! 957: exit(3); ! 958: } ! 959: #endif /* SIGBUS */ ! 960: #ifdef SIGSEGV ! 961: if (signal == SIGSEGV) { ! 962: fprintf(stderr, corrupt); ! 963: exit(3); ! 964: } ! 965: #endif /* SIGSEGV */ ! 966: exit(0); ! 967: } ! 968: ! 969: ! 970: ! 971: ! 972: ! 973: /*******************************/ ! 974: /* Non-echoing password code */ ! 975: /*******************************/ ! 976: ! 977: #ifdef CRYPT ! 978: #ifndef DOS_OS2 ! 979: #ifdef VMS ! 980: ! 981: int echo(opt) ! 982: int opt; ! 983: { ! 984: /*--------------------------------------------------------------------------- ! 985: Based on VMSmunch.c, which in turn was based on Joe Meadows' file.c code. ! 986: --------------------------------------------------------------------------- ! 987: * For VMS v5.x: ! 988: * IO$_SENSEMODE/SETMODE info: Programming, Vol. 7A, System Programming, ! 989: * I/O User's: Part I, sec. 8.4.1.1, 8.4.3, 8.4.5, 8.6 ! 990: * sys$assign(), sys$qio() info: Programming, Vol. 4B, System Services, ! 991: * System Services Reference Manual, pp. sys-23, sys-379 ! 992: * fixed-length descriptor info: Programming, Vol. 3, System Services, ! 993: * Intro to System Routines, sec. 2.9.2 ! 994: * GRR, 15 Aug 91 ! 995: ---------------------------------------------------------------------------*/ ! 996: static struct dsc$descriptor_s DevDesc = ! 997: {9, DSC$K_DTYPE_T, DSC$K_CLASS_S, "SYS$INPUT"}; ! 998: /* {dsc$w_length, dsc$b_dtype, dsc$b_class, dsc$a_pointer}; */ ! 999: static short DevChan, iosb[4]; ! 1000: static long i, status; ! 1001: static unsigned long oldmode[2], newmode[2]; /* each = 8 bytes */ ! 1002: ! 1003: ! 1004: /*--------------------------------------------------------------------------- ! 1005: Assign a channel to standard input. ! 1006: ---------------------------------------------------------------------------*/ ! 1007: ! 1008: status = sys$assign(&DevDesc, &DevChan, 0, 0); ! 1009: if (!(status & 1)) ! 1010: return status; ! 1011: ! 1012: /*--------------------------------------------------------------------------- ! 1013: Use sys$qio and the IO$_SENSEMODE function to determine the current tty ! 1014: status (for password reading, could use IO$_READVBLK function instead, ! 1015: but echo on/off will be more general). ! 1016: ---------------------------------------------------------------------------*/ ! 1017: ! 1018: status = sys$qio(0, DevChan, IO$_SENSEMODE, &iosb, 0, 0, ! 1019: oldmode, 8, 0, 0, 0, 0); ! 1020: if (!(status & 1)) ! 1021: return status; ! 1022: status = iosb[0]; ! 1023: if (!(status & 1)) ! 1024: return status; ! 1025: ! 1026: /*--------------------------------------------------------------------------- ! 1027: Copy old mode into new-mode buffer, then modify to be either NOECHO or ! 1028: ECHO (depending on function argument opt). ! 1029: ---------------------------------------------------------------------------*/ ! 1030: ! 1031: newmode[0] = oldmode[0]; ! 1032: newmode[1] = oldmode[1]; ! 1033: if (opt == OFF) ! 1034: newmode[1] |= TT$M_NOECHO; /* set NOECHO bit */ ! 1035: else ! 1036: newmode[1] &= ~((unsigned long) TT$M_NOECHO); /* clear NOECHO bit */ ! 1037: ! 1038: /*--------------------------------------------------------------------------- ! 1039: Use the IO$_SETMODE function to change the tty status. ! 1040: ---------------------------------------------------------------------------*/ ! 1041: ! 1042: status = sys$qio(0, DevChan, IO$_SETMODE, &iosb, 0, 0, ! 1043: newmode, 8, 0, 0, 0, 0); ! 1044: if (!(status & 1)) ! 1045: return status; ! 1046: status = iosb[0]; ! 1047: if (!(status & 1)) ! 1048: return status; ! 1049: ! 1050: /*--------------------------------------------------------------------------- ! 1051: Deassign the sys$input channel by way of clean-up, then exit happily. ! 1052: ---------------------------------------------------------------------------*/ ! 1053: ! 1054: status = sys$dassgn(DevChan); ! 1055: if (!(status & 1)) ! 1056: return status; ! 1057: ! 1058: return SS$_NORMAL; /* we be happy */ ! 1059: ! 1060: } /* end function echo() */ ! 1061: ! 1062: ! 1063: ! 1064: ! 1065: ! 1066: #else /* !VMS */ ! 1067: ! 1068: static int echofd=(-1); /* file descriptor whose echo is off */ ! 1069: ! 1070: void echoff(f) ! 1071: int f; /* file descriptor for which to turn echo off */ ! 1072: /* Turn echo off for file descriptor f. Assumes that f is a tty device. */ ! 1073: { ! 1074: struct sgttyb sg; /* tty device structure */ ! 1075: ! 1076: echofd = f; ! 1077: GTTY(f, &sg); /* get settings */ ! 1078: sg.sg_flags &= ~ECHO; /* turn echo off */ ! 1079: STTY(f, &sg); ! 1080: } ! 1081: ! 1082: ! 1083: ! 1084: void echon() ! 1085: /* Turn echo back on for file descriptor echofd. */ ! 1086: { ! 1087: struct sgttyb sg; /* tty device structure */ ! 1088: ! 1089: if (echofd != -1) { ! 1090: GTTY(echofd, &sg); /* get settings */ ! 1091: sg.sg_flags |= ECHO; /* turn echo on */ ! 1092: STTY(echofd, &sg); ! 1093: echofd = -1; ! 1094: } ! 1095: } ! 1096: ! 1097: #endif /* ?VMS */ ! 1098: #endif /* !DOS_OS2 */ ! 1099: ! 1100: ! 1101: ! 1102: ! 1103: ! 1104: char *getp(m, p, n) ! 1105: char *m; /* prompt for password */ ! 1106: char *p; /* return value: line input */ ! 1107: int n; /* bytes available in p[] */ ! 1108: /* Get a password of length n-1 or less into *p using the prompt *m. ! 1109: The entered password is not echoed. Return p on success, NULL on ! 1110: failure (can't get controlling tty). */ ! 1111: { ! 1112: char c; /* one-byte buffer for read() to use */ ! 1113: int i; /* number of characters input */ ! 1114: char *w; /* warning on retry */ ! 1115: ! 1116: #ifndef DOS_OS2 ! 1117: #ifndef VMS ! 1118: int f; /* file decsriptor for tty device */ ! 1119: ! 1120: /* turn off echo on tty */ ! 1121: if (!isatty(2)) ! 1122: return NULL; /* error if not tty */ ! 1123: if ((f = open(ttyname(2), 0, 0)) == -1) ! 1124: return NULL; ! 1125: #endif /* !VMS */ ! 1126: echoff(f); /* turn echo off */ ! 1127: #endif /* !DOS_OS2 */ ! 1128: ! 1129: /* get password */ ! 1130: w = ""; ! 1131: do { ! 1132: #ifdef VMS /* bug: VMS adds '\n' to NULL fputs (apparently) */ ! 1133: if (*w) ! 1134: #endif /* VMS */ ! 1135: fputs(w, stderr); /* warning if back again */ ! 1136: fputs(m, stderr); /* prompt */ ! 1137: fflush(stderr); ! 1138: i = 0; ! 1139: do { /* read line, keeping n */ ! 1140: #ifdef MSVMS ! 1141: if ((c = (char)getch()) == '\r') ! 1142: c = '\n'; ! 1143: #else /* !MSVMS */ ! 1144: read(f, &c, 1); ! 1145: #endif /* ?MSVMS */ ! 1146: if (i < n) ! 1147: p[i++] = c; ! 1148: } while (c != '\n'); ! 1149: putc('\n', stderr); fflush(stderr); ! 1150: w = "(line too long--try again)\n"; ! 1151: } while (p[i-1] != '\n'); ! 1152: p[i-1] = 0; /* terminate at newline */ ! 1153: ! 1154: #ifndef DOS_OS2 ! 1155: echon(); /* turn echo back on */ ! 1156: #ifndef VMS ! 1157: close(f); ! 1158: #endif /* !VMS */ ! 1159: #endif /* !DOS_OS2 */ ! 1160: ! 1161: /* return pointer to password */ ! 1162: return p; ! 1163: } ! 1164: ! 1165: #endif /* CRYPT */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.