|
|
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.