1 /*---------------------------------------------------------------------------
5 This file contains routines for doing direct but relatively generic input/
6 output, file-related sorts of things, plus some miscellaneous stuff. Most
7 of the stuff has to do with opening, closing, reading and/or writing files.
9 Contains: open_input_file()
10 open_outfile() (non-VMS, non-AOS/VS, non-CMS_MVS)
12 defer_leftover_input()
17 disk_error() (non-VMS)
19 UzpMessageNull() (DLL only)
22 UzpPassword() (non-WINDLL)
24 dos_to_unix_time() (non-VMS, non-VM/CMS, non-MVS)
25 check_for_newer() (non-VMS, non-OS/2, non-VM/CMS, non-MVS)
29 str2iso() (CRYPT && NEED_STR2ISO, only)
30 str2oem() (CRYPT && NEED_STR2OEM, only)
34 zstat() (REGULUS only)
35 fLoadFarString() (SMALL_MEM only)
36 fLoadFarStringSmall() (SMALL_MEM only)
37 fLoadFarStringSmall2() (SMALL_MEM only)
38 zfstrcpy() (SMALL_MEM only)
40 ---------------------------------------------------------------------------*/
44 #define UNZIP_INTERNAL
47 # include "windll/windll.h"
53 /* setup of codepage conversion for decryption passwords */
55 # if (defined(CRYP_USES_ISO2OEM) && !defined(IZ_ISO2OEM_ARRAY))
56 # define IZ_ISO2OEM_ARRAY /* pull in iso2oem[] table */
58 # if (defined(CRYP_USES_OEM2ISO) && !defined(IZ_OEM2ISO_ARRAY))
59 # define IZ_OEM2ISO_ARRAY /* pull in oem2iso[] table */
62 #include "ebcdic.h" /* definition/initialization of ebcdic[] */
66 Note: Under Windows, the maximum size of the buffer that can be used
67 with any of the *printf calls is 16,384, so win_fprintf was used to
68 feed the fprintf clone no more than 16K chunks at a time. This should
69 be valid for anything up to 64K (and probably beyond, assuming your
70 buffers are that big).
73 # define WriteError(buf,len,strm) \
74 (win_fprintf(pG, strm, (extent)len, (char far *)buf) != (int)(len))
77 # define WriteError(buf,len,strm) \
78 ((extent)fwrite((char *)(buf),1,(extent)(len),strm) != (extent)(len))
80 # define WriteError(buf,len,strm) \
81 ((extent)write(fileno(strm),(char *)(buf),(extent)(len)) != (extent)(len))
85 static int disk_error
OF((__GPRO
));
88 /****************************/
89 /* Strings used in fileio.c */
90 /****************************/
92 #if (defined(UNIX) || defined(DOS_FLX_OS2_W32) || defined(__BEOS__))
93 static ZCONST
char Far CannotDeleteOldFile
[] =
94 "error: cannot delete old %s\n";
96 static ZCONST
char Far CannotRenameOldFile
[] =
97 "error: cannot rename old %s\n";
98 static ZCONST
char Far BackupSuffix
[] = "~";
100 #endif /* UNIX || DOS_FLX_OS2_W32 || __BEOS__ */
102 static ZCONST
char Far CannotOpenZipfile
[] =
103 "error: cannot open zipfile [ %s ]\n";
104 #if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS))
105 static ZCONST
char Far CannotCreateFile
[] = "error: cannot create %s\n";
107 #ifdef NOVELL_BUG_FAILSAFE
108 static ZCONST
char Far NovellBug
[] =
109 "error: %s: stat() says does not exist, but fopen() found anyway\n";
111 static ZCONST
char Far ReadError
[] = "error: zipfile read error\n";
112 static ZCONST
char Far FilenameTooLongTrunc
[] =
113 "warning: filename too long--truncating.\n";
114 static ZCONST
char Far ExtraFieldTooLong
[] =
115 "warning: extra field too long (%d). Ignoring...\n";
118 static ZCONST
char Far DiskFullQuery
[] =
119 "%s: write error (disk full?).\n";
121 static ZCONST
char Far DiskFullQuery
[] =
122 "%s: write error (disk full?). Continue? (y/n/^C) ";
123 static ZCONST
char Far ZipfileCorrupt
[] =
124 "error: zipfile probably corrupt (%s)\n";
126 static ZCONST
char Far FileIsSymLink
[] =
127 "%s exists and is a symbolic link%s.\n";
130 static ZCONST
char Far MorePrompt
[] = "--More--(%lu)";
132 static ZCONST
char Far QuitPrompt
[] =
133 "--- Press `Q' to quit, or any other key to continue ---";
134 static ZCONST
char Far HidePrompt
[] = /* "\r \r"; */
138 /* SPC: are names on MacOS REALLY so much longer than elsewhere ??? */
139 static ZCONST
char Far PasswPrompt
[] = "[%s]\n %s password: ";
141 static ZCONST
char Far PasswPrompt
[] = "[%s] %s password: ";
143 static ZCONST
char Far PasswPrompt2
[] = "Enter password: ";
144 static ZCONST
char Far PasswRetry
[] = "password incorrect--reenter: ";
152 /******************************/
153 /* Function open_input_file() */
154 /******************************/
156 int open_input_file(__G
) /* return 1 if open failed */
160 * open the zipfile for reading and in BINARY mode to prevent cr/lf
161 * translation, which would corrupt the bitstreams
164 #if (defined(UNIX) || defined(TOPS20) || defined(AOS_VS) || defined(__BEOS__))
165 G
.zipfd
= open(G
.zipfn
, O_RDONLY
);
166 #else /* !(UNIX || TOPS20 || AOS_VS || __BEOS__) */
168 G
.zipfd
= open(G
.zipfn
, O_RDONLY
, 0, "ctx=stm");
171 G
.zipfd
= open(G
.zipfn
, 0);
174 G
.zipfd
= fopen(G
.zipfn
, "rb");
177 G
.zipfd
= vmmvs_open_infile(__G
);
179 G
.zipfd
= open(G
.zipfn
, O_RDONLY
| O_BINARY
);
180 #endif /* ?CMS_MVS */
184 #endif /* ?(UNIX || TOPS20 || AOS_VS || __BEOS__) */
186 #ifdef USE_STRM_INPUT
189 /* if (G.zipfd < 0) */ /* no good for Windows CE port */
193 Info(slide
, 0x401, ((char *)slide
, LoadFarString(CannotOpenZipfile
),
199 } /* end function open_input_file() */
204 #if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS))
206 /***************************/
207 /* Function open_outfile() */
208 /***************************/
210 int open_outfile(__G
) /* return 1 if fail */
215 return (redirect_outfile(__G
) == FALSE
);
218 QFilename(__G__ G
.filename
);
220 #if (defined(DOS_FLX_OS2_W32) || defined(UNIX) || defined(__BEOS__))
221 #ifdef BORLAND_STAT_BUG
222 /* Borland 5.0's stat() barfs if the filename has no extension and the
223 * file doesn't exist. */
224 if (access(G
.filename
, 0) == -1) {
225 FILE *tmp
= fopen(G
.filename
, "wb+");
227 /* file doesn't exist, so create a dummy file to keep stat() from
228 * failing (will be over-written anyway) */
229 fputc('0', tmp
); /* just to have something in the file */
232 #endif /* BORLAND_STAT_BUG */
234 if (SSTAT(G
.filename
, &G
.statbuf
) == 0 || lstat(G
.filename
,&G
.statbuf
) == 0)
236 if (SSTAT(G
.filename
, &G
.statbuf
) == 0)
237 #endif /* ?SYMLINKS */
239 Trace((stderr
, "open_outfile: stat(%s) returns 0: file exists\n",
240 FnFilter1(G
.filename
)));
242 if (uO
.B_flag
) { /* do backup */
244 int blen
, flen
, tlen
;
246 blen
= strlen(BackupSuffix
);
247 flen
= strlen(G
.filename
);
248 tlen
= flen
+ blen
+ 1;
249 if (tlen
>= FILNAMSIZ
) { /* in case name is too long, truncate */
250 tname
= (char *)malloc(FILNAMSIZ
);
252 return 1; /* in case we run out of space */
253 tlen
= FILNAMSIZ
- 1 - blen
;
254 strcpy(tname
, G
.filename
); /* make backup name */
257 tname
= (char *)malloc(tlen
);
259 return 1; /* in case we run out of space */
260 strcpy(tname
, G
.filename
); /* make backup name */
262 strcpy(tname
+flen
, BackupSuffix
);
264 /* GRR: should check if backup file exists, apply -n/-o to that */
265 if (rename(G
.filename
, tname
) < 0) { /* move file */
266 Info(slide
, 0x401, ((char *)slide
,
267 LoadFarString(CannotRenameOldFile
), FnFilter1(G
.filename
)));
273 #endif /* UNIXBACKUP */
274 #ifdef DOS_FLX_OS2_W32
275 if (!(G
.statbuf
.st_mode
& S_IWRITE
)) {
276 Trace((stderr
, "open_outfile: existing file %s is read-only\n",
277 FnFilter1(G
.filename
)));
278 chmod(G
.filename
, S_IREAD
| S_IWRITE
);
279 Trace((stderr
, "open_outfile: %s now writable\n",
280 FnFilter1(G
.filename
)));
282 #endif /* DOS_FLX_OS2_W32 */
283 if (unlink(G
.filename
) != 0) {
284 Info(slide
, 0x401, ((char *)slide
,
285 LoadFarString(CannotDeleteOldFile
), FnFilter1(G
.filename
)));
288 Trace((stderr
, "open_outfile: %s now deleted\n",
289 FnFilter1(G
.filename
)));
291 #endif /* DOS_FLX_OS2_W32 || UNIX || __BEOS__ */
293 if (SWI_OS_File_7(G
.filename
,0xDEADDEAD,0xDEADDEAD,G
.lrec
.ucsize
)!=NULL
) {
294 Info(slide
, 1, ((char *)slide
, LoadFarString(CannotCreateFile
),
295 FnFilter1(G
.filename
)));
302 if ((tfilnam
= (char *)malloc(2*strlen(G
.filename
)+1)) == (char *)NULL
)
304 strcpy(tfilnam
, G
.filename
);
307 if ((G
.outfile
= fopen(tfilnam
, FOPW
)) == (FILE *)NULL
) {
308 Info(slide
, 1, ((char *)slide
, LoadFarString(CannotCreateFile
),
317 G
.outfile
= fopen(G
.filename
, FOPWT
);
319 G
.outfile
= fopen(G
.filename
, FOPW
);
320 if (G
.outfile
== (FILE *)NULL
) {
321 Info(slide
, 1, ((char *)slide
, LoadFarString(CannotCreateFile
),
322 FnFilter1(G
.filename
)));
327 if (SSTAT(G
.filename
, &G
.statbuf
) == 0) {
328 Trace((stderr
, "open_outfile: stat(%s) returns 0 (file exists)\n",
329 FnFilter1(G
.filename
)));
330 if (unlink(G
.filename
) != 0) {
331 Trace((stderr
, "open_outfile: existing file %s is read-only\n",
332 FnFilter1(G
.filename
)));
333 chmod(G
.filename
, S_IRUSR
| S_IWUSR
);
334 Trace((stderr
, "open_outfile: %s now writable\n",
335 FnFilter1(G
.filename
)));
336 if (unlink(G
.filename
) != 0)
339 Trace((stderr
, "open_outfile: %s now deleted\n",
340 FnFilter1(G
.filename
)));
342 if (G
.pInfo
->textmode
)
343 G
.outfile
= fopen(G
.filename
, FOPWT
);
345 G
.outfile
= fopen(G
.filename
, FOPW
);
346 if (G
.outfile
== (FILE *)NULL
) {
347 Info(slide
, 1, ((char *)slide
, LoadFarString(CannotCreateFile
),
348 FnFilter1(G
.filename
)));
353 Info(slide
, 1, ((char *)slide
,
354 "open_outfile: doing fopen(%s) for reading\n", FnFilter1(G
.filename
)));
355 if ((G
.outfile
= fopen(G
.filename
, FOPR
)) == (FILE *)NULL
)
356 Info(slide
, 1, ((char *)slide
,
357 "open_outfile: fopen(%s) for reading failed: does not exist\n",
358 FnFilter1(G
.filename
)));
360 Info(slide
, 1, ((char *)slide
,
361 "open_outfile: fopen(%s) for reading succeeded: file exists\n",
362 FnFilter1(G
.filename
)));
366 #ifdef NOVELL_BUG_FAILSAFE
367 if (G
.dne
&& ((G
.outfile
= fopen(G
.filename
, FOPR
)) != (FILE *)NULL
)) {
368 Info(slide
, 0x401, ((char *)slide
, LoadFarString(NovellBug
),
369 FnFilter1(G
.filename
)));
371 return 1; /* with "./" fix in checkdir(), should never reach here */
373 #endif /* NOVELL_BUG_FAILSAFE */
374 Trace((stderr
, "open_outfile: doing fopen(%s) for writing\n",
375 FnFilter1(G
.filename
)));
376 if ((G
.outfile
= fopen(G
.filename
, FOPW
)) == (FILE *)NULL
) {
377 Info(slide
, 0x401, ((char *)slide
, LoadFarString(CannotCreateFile
),
378 FnFilter1(G
.filename
)));
381 Trace((stderr
, "open_outfile: fopen(%s) for writing succeeded\n",
382 FnFilter1(G
.filename
)));
389 /* 16-bit MSC: buffer size must be strictly LESS than 32K (WSIZE): bogus */
390 setbuf(G
.outfile
, (char *)NULL
); /* make output unbuffered */
391 #else /* !DOS_OS2_W32 */
393 #ifdef _IOFBF /* make output fully buffered (works just about like write()) */
394 setvbuf(G
.outfile
, (char *)slide
, _IOFBF
, WSIZE
);
396 setbuf(G
.outfile
, (char *)slide
);
399 #endif /* ?DOS_OS2_W32 */
400 #endif /* USE_FWRITE */
403 } /* end function open_outfile() */
405 #endif /* !VMS && !AOS_VS && !CMS_MVS && !MACOS */
412 * These functions allow NEXTBYTE to function without needing two bounds
413 * checks. Call defer_leftover_input() if you ever have filled G.inbuf
414 * by some means other than readbyte(), and you then want to start using
415 * NEXTBYTE. When going back to processing bytes without NEXTBYTE, call
416 * undefer_input(). For example, extract_or_test_member brackets its
417 * central section that does the decompression with these two functions.
418 * If you need to check the number of bytes remaining in the current
419 * file while using NEXTBYTE, check (G.csize + G.incnt), not G.csize.
422 /****************************/
423 /* function undefer_input() */
424 /****************************/
426 void undefer_input(__G
)
431 if (G
.incnt_leftover
> 0) {
432 /* We know that "(G.csize < MAXINT)" so we can cast G.csize to int:
433 * This condition was checked when G.incnt_leftover was set > 0 in
434 * defer_leftover_input(), and it is NOT allowed to touch G.csize
435 * before calling undefer_input() when (G.incnt_leftover > 0)
436 * (single exception: see read_byte()'s "G.csize <= 0" handling) !!
438 G
.incnt
= G
.incnt_leftover
+ (int)G
.csize
;
439 G
.inptr
= G
.inptr_leftover
- (int)G
.csize
;
440 G
.incnt_leftover
= 0;
441 } else if (G
.incnt
< 0)
443 } /* end function undefer_input() */
449 /***********************************/
450 /* function defer_leftover_input() */
451 /***********************************/
453 void defer_leftover_input(__G
)
456 if ((long)G
.incnt
> G
.csize
) {
457 /* (G.csize < MAXINT), we can safely cast it to int !! */
460 G
.inptr_leftover
= G
.inptr
+ (int)G
.csize
;
461 G
.incnt_leftover
= G
.incnt
- (int)G
.csize
;
462 G
.incnt
= (int)G
.csize
;
464 G
.incnt_leftover
= 0;
466 } /* end function defer_leftover_input() */
472 /**********************/
473 /* Function readbuf() */
474 /**********************/
476 unsigned readbuf(__G__ buf
, size
) /* return number of bytes read into buf */
479 register unsigned size
;
481 register unsigned count
;
487 if ((G
.incnt
= read(G
.zipfd
, (char *)G
.inbuf
, INBUFSIZ
)) == 0)
489 else if (G
.incnt
< 0) {
490 /* another hack, but no real harm copying same thing twice */
491 (*G
.message
)((zvoid
*)&G
,
492 (uch
*)LoadFarString(ReadError
), /* CANNOT use slide */
493 (ulg
)strlen(LoadFarString(ReadError
)), 0x401);
494 return 0; /* discarding some data; better than lock-up */
496 /* buffer ALWAYS starts on a block boundary: */
497 G
.cur_zipfile_bufstart
+= INBUFSIZ
;
500 count
= MIN(size
, (unsigned)G
.incnt
);
501 memcpy(buf
, G
.inptr
, count
);
509 } /* end function readbuf() */
515 /***********************/
516 /* Function readbyte() */
517 /***********************/
519 int readbyte(__G
) /* refill inbuf and return a byte if available, else EOF */
525 G
.csize
--; /* for tests done after exploding */
530 if ((G
.incnt
= read(G
.zipfd
, (char *)G
.inbuf
, INBUFSIZ
)) == 0) {
531 G
.incnt
= 0; /* do not allow negative value to affect stuff */
533 } else if (G
.incnt
< 0) { /* "fail" (abort, retry, ...) returns this */
534 /* another hack, but no real harm copying same thing twice */
535 (*G
.message
)((zvoid
*)&G
,
536 (uch
*)LoadFarString(ReadError
),
537 (ulg
)strlen(LoadFarString(ReadError
)), 0x401);
540 longjmp(dll_error_return
, 1);
543 EXIT(PK_BADERR
); /* totally bailing; better than lock-up */
546 G
.cur_zipfile_bufstart
+= INBUFSIZ
; /* always starts on block bndry */
548 defer_leftover_input(__G
); /* decrements G.csize */
552 if (G
.pInfo
->encrypted
) {
556 /* This was previously set to decrypt one byte beyond G.csize, when
557 * incnt reached that far. GRR said, "but it's required: why?" This
558 * was a bug in fillinbuf() -- was it also a bug here?
560 for (n
= G
.incnt
, p
= G
.inptr
; n
--; p
++)
568 } /* end function readbyte() */
576 /************************/
577 /* Function fillinbuf() */
578 /************************/
580 int fillinbuf(__G
) /* like readbyte() except returns number of bytes in inbuf */
584 (G
.incnt
= read(G
.zipfd
, (char *)G
.inbuf
, INBUFSIZ
)) <= 0)
586 G
.cur_zipfile_bufstart
+= INBUFSIZ
; /* always starts on a block boundary */
588 defer_leftover_input(__G
); /* decrements G.csize */
591 if (G
.pInfo
->encrypted
) {
595 for (n
= G
.incnt
, p
= G
.inptr
; n
--; p
++)
602 } /* end function fillinbuf() */
604 #endif /* USE_ZLIB */
610 #ifndef VMS /* for VMS use code in vms.c */
612 /********************/
613 /* Function flush() */ /* returns PK error codes: */
614 /********************/ /* if cflag => always 0; PK_DISK if write error */
616 int flush(__G__ rawbuf
, size
, unshrink
)
624 #if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV))
627 /* static int didCRlast = FALSE; moved to globals.h */
630 /*---------------------------------------------------------------------------
631 Compute the CRC first; if testing or if disk is full, that's it.
632 ---------------------------------------------------------------------------*/
634 G
.crc32val
= crc32(G
.crc32val
, rawbuf
, (extent
)size
);
637 if ((G
.statreportcb
!= NULL
) &&
638 (*G
.statreportcb
)(__G__ UZ_ST_IN_PROGRESS
, G
.zipfn
, G
.filename
, NULL
))
639 return IZ_CTRLC
; /* cancel operation by user request */
642 if (uO
.tflag
|| size
== 0L) /* testing or nothing to write: all done */
646 return PK_DISK
; /* disk already full: ignore rest of file */
648 /*---------------------------------------------------------------------------
649 Write the bytes rawbuf[0..size-1] to the output device, first converting
650 end-of-lines and ASCII/EBCDIC as needed. If SMALL_MEM or MED_MEM are NOT
651 defined, outbuf is assumed to be at least as large as rawbuf and is not
652 necessarily checked for overflow.
653 ---------------------------------------------------------------------------*/
655 if (!G
.pInfo
->textmode
) { /* write raw binary data */
656 /* GRR: note that for standard MS-DOS compilers, size argument to
657 * fwrite() can never be more than 65534, so WriteError macro will
658 * have to be rewritten if size can ever be that large. For now,
659 * never more than 32K. Also note that write() returns an int, which
660 * doesn't necessarily limit size to 32767 bytes if write() is used
661 * on 16-bit systems but does make it more of a pain; however, because
662 * at least MSC 5.1 has a lousy implementation of fwrite() (as does
663 * DEC Ultrix cc), write() is used anyway.
667 writeToMemory(__G__ rawbuf
, size
);
670 if (!uO
.cflag
&& WriteError(rawbuf
, size
, G
.outfile
))
671 return disk_error(__G
);
672 else if (uO
.cflag
&& (*G
.message
)((zvoid
*)&G
, rawbuf
, size
, 0))
674 } else { /* textmode: aflag is true */
676 /* rawbuf = outbuf */
677 transbuf
= G
.outbuf2
;
678 #if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV))
679 transbufsiz
= TRANSBUFSIZ
;
684 #if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV))
685 transbufsiz
= OUTBUFSIZ
;
686 Trace((stderr
, "\ntransbufsiz = OUTBUFSIZ = %u\n", OUTBUFSIZ
));
691 /* GRR: really want to check if -aa (or -aaa?) was given... */
692 if (rawbuf
[1]) { /* first line is more than 255 chars long */
694 "\nfirst line of VMS `text' too long; switching to normal extraction\n"));
695 G
.VMS_line_state
= -1; /* -1: don't treat as VMS text */
697 G
.VMS_line_state
= 0; /* 0: ready to read line length */
699 G
.didCRlast
= FALSE
; /* no previous buffers written */
704 if (G
.pInfo
->hostnum
== VMS_
&& G
.extra_field
&& G
.VMS_line_state
>= 0)
706 /* GRR: really want to check for actual VMS extra field, and
707 * ideally for variable-length record format */
709 printf("\n>>>>>> GRR: file is VMS text and has an extra field\n");
714 while(p
< rawbuf
+(unsigned)size
) {
715 switch (G
.VMS_line_state
) {
717 /* 0: ready to read line length */
719 G
.VMS_line_length
= 0;
721 if (p
== rawbuf
+(unsigned)size
-1) { /* last char */
722 G
.VMS_line_length
= (int)((uch
)(*p
++));
723 G
.VMS_line_state
= 1;
725 G
.VMS_line_length
= makeword(p
);
727 G
.VMS_line_state
= 2;
729 if (G
.VMS_line_length
& 1) /* odd */
733 /* 1: read one byte of length, need second */
735 G
.VMS_line_length
+= ((int)((uch
)(*p
++)) << 8);
736 G
.VMS_line_state
= 2;
739 /* 2: ready to read VMS_line_length chars */
741 if (G
.VMS_line_length
< rawbuf
+(unsigned)size
-p
) {
742 if (G
.VMS_line_length
>=
743 transbuf
+(unsigned)transbufsiz
-q
)
745 int outroom
= transbuf
+(unsigned)transbufsiz
-q
;
747 /* GRR: need to change this to *q++ = native(*p++); loop or something */
748 memcpy(q
, p
, outroom
);
751 writeToMemory(__G__ transbuf
,
755 if (!uO
.cflag
&& WriteError(transbuf
,
756 (unsigned)outroom
, G
.outfile
))
757 return disk_error(__G
);
758 else if (uO
.cflag
&& (*G
.message
)((zvoid
*)&G
,
759 transbuf
, (ulg
)outroom
, 0))
763 G
.VMS_line_length
-= outroom
;
764 /* fall through to normal case */
766 /* GRR: need to change this to *q++ = native(*p++); loop or something */
767 memcpy(q
, p
, G
.VMS_line_length
);
768 q
+= G
.VMS_line_length
;
769 p
+= G
.VMS_line_length
;
770 G
.VMS_line_length
= 0; /* necessary?? */
771 G
.VMS_line_state
= 3;
773 } else { /* remaining input is less than full line */
774 int remaining
= rawbuf
+(unsigned)size
-p
;
777 transbuf
+(unsigned)transbufsiz
-q
)
779 int outroom
= transbuf
+(unsigned)transbufsiz
-q
;
781 /* GRR: need to change this to *q++ = native(*p++); loop or something */
782 memcpy(q
, p
, outroom
);
785 writeToMemory(__G__ transbuf
,
786 (unsigned)(outroom
));
789 if (!uO
.cflag
&& WriteError(transbuf
,
790 (unsigned)outroom
, G
.outfile
))
791 return disk_error(__G
);
792 else if (uO
.cflag
&& (*G
.message
)((zvoid
*)&G
,
793 transbuf
, (ulg
)outroom
, 0))
797 remaining
-= outroom
;
799 /* GRR: need to change this to *q++ = native(*p++); loop or something */
800 memcpy(q
, p
, remaining
);
803 G
.VMS_line_length
-= remaining
;
804 /* no change in G.VMS_line_state */
808 /* 3: ready to PutNativeEOL */
810 if (q
> transbuf
+(unsigned)transbufsiz
-lenEOL
) {
813 writeToMemory(__G__ transbuf
,
814 (unsigned)(q
-transbuf
));
818 WriteError(transbuf
, (unsigned)(q
-transbuf
),
820 return disk_error(__G
);
821 else if (uO
.cflag
&& (*G
.message
)((zvoid
*)&G
,
822 transbuf
, (ulg
)(q
-transbuf
), 0))
828 if (p
< rawbuf
+(unsigned)size
) {
830 G
.VMS_line_state
= 0;
832 G
.VMS_line_state
= 4;
834 G
.VMS_line_state
= 0;
837 /* 4: ready to read pad byte */
840 G
.VMS_line_state
= 0;
846 #endif /* VMS_TEXT_CONV */
848 /*-----------------------------------------------------------------------
849 Algorithm: CR/LF => native; lone CR => native; lone LF => native.
850 This routine is only for non-raw-VMS, non-raw-VM/CMS files (i.e.,
851 stream-oriented files, not record-oriented).
852 -----------------------------------------------------------------------*/
854 /* else not VMS text */ {
856 if (*p
== LF
&& G
.didCRlast
)
859 for (q
= transbuf
; p
< rawbuf
+(unsigned)size
; ++p
) {
860 if (*p
== CR
) { /* lone CR or CR/LF: EOL either way */
862 if (p
== rawbuf
+(unsigned)size
-1) /* last char in buffer */
864 else if (p
[1] == LF
) /* get rid of accompanying LF */
866 } else if (*p
== LF
) /* lone LF */
869 #ifndef DOS_FLX_OS2_W32
870 if (*p
!= CTRLZ
) /* lose all ^Z's */
874 #if (defined(SMALL_MEM) || defined(MED_MEM))
875 # if (lenEOL == 1) /* don't check unshrink: both buffers small but equal */
878 /* check for danger of buffer overflow and flush */
879 if (q
> transbuf
+(unsigned)transbufsiz
-lenEOL
) {
881 "p - rawbuf = %u q-transbuf = %u size = %lu\n",
882 (unsigned)(p
-rawbuf
), (unsigned)(q
-transbuf
), size
));
883 if (!uO
.cflag
&& WriteError(transbuf
,
884 (unsigned)(q
-transbuf
), G
.outfile
))
885 return disk_error(__G
);
886 else if (uO
.cflag
&& (*G
.message
)((zvoid
*)&G
,
887 transbuf
, (ulg
)(q
-transbuf
), 0))
892 #endif /* SMALL_MEM || MED_MEM */
896 /*-----------------------------------------------------------------------
897 Done translating: write whatever we've got to file (or screen).
898 -----------------------------------------------------------------------*/
900 Trace((stderr
, "p - rawbuf = %u q-transbuf = %u size = %lu\n",
901 (unsigned)(p
-rawbuf
), (unsigned)(q
-transbuf
), size
));
905 writeToMemory(__G__ transbuf
, (unsigned)(q
-transbuf
));
908 if (!uO
.cflag
&& WriteError(transbuf
, (unsigned)(q
-transbuf
),
910 return disk_error(__G
);
911 else if (uO
.cflag
&& (*G
.message
)((zvoid
*)&G
, transbuf
,
912 (ulg
)(q
-transbuf
), 0))
919 } /* end function flush() */
925 /*************************/
926 /* Function disk_error() */
927 /*************************/
929 static int disk_error(__G
)
932 /* OK to use slide[] here because this file is finished regardless */
933 Info(slide
, 0x4a1, ((char *)slide
, LoadFarString(DiskFullQuery
),
934 FnFilter1(G
.filename
)));
937 fgets(G
.answerbuf
, 9, stdin
);
938 if (*G
.answerbuf
== 'y') /* stop writing to this file */
939 G
.disk_full
= 1; /* (outfile bad?), but new OK */
942 G
.disk_full
= 2; /* no: exit program */
946 } /* end function disk_error() */
954 /*****************************/
955 /* Function UzpMessagePrnt() */
956 /*****************************/
958 int UZ_EXP
UzpMessagePrnt(pG
, buf
, size
, flag
)
959 zvoid
*pG
; /* globals struct: always passed */
960 uch
*buf
; /* preformatted string to be printed */
961 ulg size
; /* length of string (may include nulls) */
962 int flag
; /* flag bits */
965 * The name of the first parameter of UzpMessagePrnt(), which passes
966 * the "Uz_Globs" address, >>> MUST <<< be identical to the string
967 * expansion of the __G__ macro in the REENTRANT case (see globals.h).
968 * This name identity is mandatory for the LoadFarString() macro
969 * (in the SMALL_MEM case) !!!
972 uch
*q
=buf
, *endbuf
=buf
+(unsigned)size
;
979 /*---------------------------------------------------------------------------
980 These tests are here to allow fine-tuning of UnZip's output messages,
981 but none of them will do anything without setting the appropriate bit
982 in the flag argument of every Info() statement which is to be turned
983 *off*. That is, all messages are currently turned on for all ports.
984 To turn off *all* messages, use the UzpMessageNull() function instead
986 ---------------------------------------------------------------------------*/
988 #if (defined(OS2) && defined(DLL))
989 if (MSG_NO_DLL2(flag
)) /* if OS/2 DLL bit is set, do NOT print this msg */
993 if (MSG_NO_WDLL(flag
))
997 if (MSG_NO_WGUI(flag
))
1002 if (MSG_NO_AGUI(flag))
1006 #ifdef DLL /* don't display message if data is redirected */
1007 if (((Uz_Globs
*)pG
)->redirect_data
&&
1008 !((Uz_Globs
*)pG
)->redirect_text
)
1012 if (MSG_STDERR(flag
) && !((Uz_Globs
*)pG
)->UzO
.tflag
)
1013 outfp
= (FILE *)stderr
;
1015 outfp
= (FILE *)stdout
;
1017 #ifdef QUERY_TRNEWLN
1018 /* some systems require termination of query prompts with '\n' to force
1019 * immediate display */
1020 if (MSG_MNEWLN(flag
)) { /* assumes writable buffer (e.g., slide[]) */
1021 *endbuf
++ = '\n'; /* with room for one more char at end of buf */
1022 ++size
; /* (safe assumption: only used for four */
1023 } /* short queries in extract.c and fileio.c) */
1026 if (MSG_TNEWLN(flag
)) { /* again assumes writable buffer: fragile... */
1027 if ((!size
&& !((Uz_Globs
*)pG
)->sol
) ||
1028 (size
&& (endbuf
[-1] != '\n')))
1036 /* room for --More-- and one line of overlap: */
1037 ((Uz_Globs
*)pG
)->height
= SCREENLINES
- 2;
1040 if (MSG_LNEWLN(flag
) && !((Uz_Globs
*)pG
)->sol
) {
1041 /* not at start of line: want newline */
1043 if (!((Uz_Globs
*)pG
)->redirect_text
) {
1048 if (((Uz_Globs
*)pG
)->M_flag
)
1050 ++((Uz_Globs
*)pG
)->numlines
;
1051 if (((Uz_Globs
*)pG
)->numlines
%
1052 ((Uz_Globs
*)pG
)->height
== 0L) /* GRR: fix */
1053 (*((Uz_Globs
*)pG
)->mpause
)((zvoid
*)pG
,
1054 LoadFarString(MorePrompt
), 1);
1057 if (MSG_STDERR(flag
) && ((Uz_Globs
*)pG
)->UzO
.tflag
&&
1058 !isatty(1) && isatty(2))
1060 /* error output from testing redirected: also send to stderr */
1068 ((Uz_Globs
*)pG
)->sol
= TRUE
;
1071 /* put zipfile name, filename and/or error/warning keywords here */
1074 if (((Uz_Globs
*)pG
)->M_flag
1076 && !((Uz_Globs
*)pG
)->redirect_text
1080 while (++p
< endbuf
) {
1082 ++((Uz_Globs
*)pG
)->numlines
;
1083 if (((Uz_Globs
*)pG
)->numlines
%
1084 ((Uz_Globs
*)pG
)->height
== 0L) /* GRR: fix */
1086 if ((error
= WriteError(q
, p
-q
+1, outfp
)) != 0)
1089 ((Uz_Globs
*)pG
)->sol
= TRUE
;
1091 (*((Uz_Globs
*)pG
)->mpause
)((zvoid
*)pG
,
1092 LoadFarString(MorePrompt
), 1);
1096 size
= (ulg
)(p
- q
); /* remaining text */
1102 if (!((Uz_Globs
*)pG
)->redirect_text
) {
1104 if ((error
= WriteError(q
, size
, outfp
)) != 0)
1107 if (MSG_STDERR(flag
) && ((Uz_Globs
*)pG
)->UzO
.tflag
&&
1108 !isatty(1) && isatty(2))
1110 /* error output from testing redirected: also send to stderr */
1111 if ((error
= WriteError(q
, size
, stderr
)) != 0)
1116 } else { /* GRR: this is ugly: hide with macro */
1117 if ((error
= REDIRECTPRINT(q
, size
)) != 0)
1121 ((Uz_Globs
*)pG
)->sol
= (endbuf
[-1] == '\n');
1125 } /* end function UzpMessagePrnt() */
1133 /*****************************/
1134 /* Function UzpMessageNull() */ /* convenience routine for no output at all */
1135 /*****************************/
1137 int UZ_EXP
UzpMessageNull(pG
, buf
, size
, flag
)
1138 zvoid
*pG
; /* globals struct: always passed */
1139 uch
*buf
; /* preformatted string to be printed */
1140 ulg size
; /* length of string (may include nulls) */
1141 int flag
; /* flag bits */
1145 } /* end function UzpMessageNull() */
1153 /***********************/
1154 /* Function UzpInput() */ /* GRR: this is a placeholder for now */
1155 /***********************/
1157 int UZ_EXP
UzpInput(pG
, buf
, size
, flag
)
1158 zvoid
*pG
; /* globals struct: always passed */
1159 uch
*buf
; /* preformatted string to be printed */
1160 int *size
; /* (address of) size of buf and of returned string */
1161 int flag
; /* flag bits (bit 0: no echo) */
1163 /* tell picky compilers to shut up about "unused variable" warnings */
1164 pG
= pG
; buf
= buf
; flag
= flag
;
1169 } /* end function UzpInput() */
1175 #if (!defined(WINDLL) && !defined(MACOS))
1177 /***************************/
1178 /* Function UzpMorePause() */
1179 /***************************/
1181 void UZ_EXP
UzpMorePause(pG
, prompt
, flag
)
1182 zvoid
*pG
; /* globals struct: always passed */
1183 ZCONST
char *prompt
; /* "--More--" prompt */
1184 int flag
; /* 0 = any char OK; 1 = accept only '\n', ' ', q */
1189 /*---------------------------------------------------------------------------
1190 Print a prompt and wait for the user to press a key, then erase prompt
1192 ---------------------------------------------------------------------------*/
1194 if (!((Uz_Globs
*)pG
)->sol
)
1195 fprintf(stderr
, "\n");
1196 /* numlines may or may not be used: */
1197 fprintf(stderr
, prompt
, ((Uz_Globs
*)pG
)->numlines
);
1202 } while (c
!= '\r' && c
!= '\n' && c
!= ' ' && c
!= 'q' && c
!= 'Q');
1206 /* newline was not echoed, so cover up prompt line */
1207 fprintf(stderr
, LoadFarString(HidePrompt
));
1210 if (ToLower(c
) == 'q') {
1215 ((Uz_Globs
*)pG
)->sol
= TRUE
;
1218 } /* end function UzpMorePause() */
1220 #endif /* !WINDLL && !MACOS */
1227 /**************************/
1228 /* Function UzpPassword() */
1229 /**************************/
1231 int UZ_EXP
UzpPassword (pG
, rcnt
, pwbuf
, size
, zfn
, efn
)
1232 zvoid
*pG
; /* pointer to UnZip's internal global vars */
1233 int *rcnt
; /* retry counter */
1234 char *pwbuf
; /* buffer for password */
1235 int size
; /* size of password buffer */
1236 ZCONST
char *zfn
; /* name of zip archive */
1237 ZCONST
char *efn
; /* name of archive entry being processed */
1240 int r
= IZ_PW_ENTERED
;
1245 /* tell picky compilers to shut up about "unused variable" warnings */
1249 if (*rcnt
== 0) { /* First call for current entry */
1251 if ((prompt
= (char *)malloc(2*FILNAMSIZ
+ 15)) != (char *)NULL
) {
1252 sprintf(prompt
, LoadFarString(PasswPrompt
),
1253 FnFilter1(zfn
), FnFilter2(efn
));
1256 m
= (char *)LoadFarString(PasswPrompt2
);
1257 } else { /* Retry call, previous password was wrong */
1260 m
= (char *)LoadFarString(PasswRetry
);
1263 m
= getp(__G__ m
, pwbuf
, size
);
1264 if (prompt
!= (char *)NULL
) {
1267 if (m
== (char *)NULL
) {
1270 else if (*pwbuf
== '\0') {
1271 r
= IZ_PW_CANCELALL
;
1276 /* tell picky compilers to shut up about "unused variable" warnings */
1277 pG
= pG
; rcnt
= rcnt
; pwbuf
= pwbuf
; size
= size
; zfn
= zfn
; efn
= efn
;
1279 return IZ_PW_ERROR
; /* internal error; function should never get called */
1282 } /* end function UzpPassword() */
1288 /**********************/
1289 /* Function handler() */
1290 /**********************/
1292 void handler(signal
) /* upon interrupt, turn on echo and exit cleanly */
1297 #if !(defined(SIGBUS) || defined(SIGSEGV)) /* add a newline if not at */
1298 (*G
.message
)((zvoid
*)&G
, slide
, 0L, 0x41); /* start of line (to stderr; */
1299 #endif /* slide[] should be safe) */
1304 if (signal
== SIGBUS
) {
1305 Info(slide
, 0x421, ((char *)slide
, LoadFarString(ZipfileCorrupt
),
1313 if (signal
== SIGSEGV
) {
1314 Info(slide
, 0x421, ((char *)slide
, LoadFarString(ZipfileCorrupt
),
1315 "segmentation violation"));
1319 #endif /* SIGSEGV */
1321 /* probably ctrl-C */
1323 #if defined(AMIGA) && defined(__SASC)
1326 EXIT(IZ_CTRLC
); /* was EXIT(0), then EXIT(PK_ERR) */
1329 #endif /* !WINDLL */
1334 #if (!defined(VMS) && !defined(CMS_MVS))
1335 #if (!defined(OS2) || defined(TIMESTAMP))
1337 #if (!defined(HAVE_MKTIME) || defined(AMIGA) || defined(WIN32))
1338 /* also used in amiga/filedate.c and win32/win32.c */
1339 ZCONST ush ydays
[] =
1340 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
1343 /*******************************/
1344 /* Function dos_to_unix_time() */ /* used for freshening/updating/timestamps */
1345 /*******************************/
1347 time_t dos_to_unix_time(dosdatetime
)
1354 ZCONST
time_t now
= time(NULL
);
1356 # define YRBASE 1900
1358 tm
= localtime(&now
);
1359 tm
->tm_isdst
= -1; /* let mktime determine if DST is in effect */
1362 tm
->tm_year
= ((int)(dosdatetime
>> 25) & 0x7f) + (1980 - YRBASE
);
1363 tm
->tm_mon
= ((int)(dosdatetime
>> 21) & 0x0f) - 1;
1364 tm
->tm_mday
= ((int)(dosdatetime
>> 16) & 0x1f);
1367 tm
->tm_hour
= (int)((unsigned)dosdatetime
>> 11) & 0x1f;
1368 tm
->tm_min
= (int)((unsigned)dosdatetime
>> 5) & 0x3f;
1369 tm
->tm_sec
= (int)((unsigned)dosdatetime
<< 1) & 0x3e;
1371 m_time
= mktime(tm
);
1372 NATIVE_TO_TIMET(m_time
) /* NOP unless MSC 7.0 or Macintosh */
1373 TTrace((stderr
, " final m_time = %lu\n", (ulg
)m_time
));
1375 #else /* !HAVE_MKTIME */
1377 int yr
, mo
, dy
, hh
, mm
, ss
;
1379 # define YRBASE 1900
1383 # define YRBASE 1970
1387 #if (!defined(MACOS) && !defined(RISCOS) && !defined(QDOS) && !defined(TANDEM))
1389 TIME_ZONE_INFORMATION tzinfo
;
1392 #ifndef BSD4_4 /* GRR: change to !defined(MODERN) ? */
1393 #if (defined(BSD) || defined(MTS) || defined(__GO32__))
1395 #else /* !(BSD || MTS || __GO32__) */
1396 #ifdef DECLARE_TIMEZONE
1397 extern time_t timezone
;
1399 #endif /* ?(BSD || MTS || __GO32__) */
1400 #endif /* !BSD4_4 */
1402 #endif /* !MACOS && !RISCOS && !QDOS && !TANDEM */
1403 #endif /* ?TOPS20 */
1407 yr
= ((int)(dosdatetime
>> 25) & 0x7f) + (1980 - YRBASE
);
1408 mo
= ((int)(dosdatetime
>> 21) & 0x0f) - 1;
1409 dy
= ((int)(dosdatetime
>> 16) & 0x1f) - 1;
1412 hh
= (int)((unsigned)dosdatetime
>> 11) & 0x1f;
1413 mm
= (int)((unsigned)dosdatetime
>> 5) & 0x3f;
1414 ss
= (int)((unsigned)dosdatetime
& 0x1f) * 2;
1417 tmx
= (struct tmx
*)malloc(sizeof(struct tmx
));
1418 sprintf (temp
, "%02d/%02d/%02d %02d:%02d:%02d", mo
+1, dy
+1, yr
, hh
, mm
, ss
);
1419 time_parse(temp
, tmx
, (char *)0);
1420 m_time
= time_make(tmx
);
1425 /*---------------------------------------------------------------------------
1426 Calculate the number of seconds since the epoch, usually 1 January 1970.
1427 ---------------------------------------------------------------------------*/
1429 /* leap = # of leap yrs from YRBASE up to but not including current year */
1430 leap
= ((yr
+ YRBASE
- 1) / 4); /* leap year base factor */
1432 /* calculate days from BASE to this year and add expired days this year */
1433 days
= (yr
* 365) + (leap
- 492) + ydays
[mo
];
1435 /* if year is a leap year and month is after February, add another day */
1436 if ((mo
> 1) && ((yr
+YRBASE
)%4
== 0) && ((yr
+YRBASE
) != 2100))
1437 ++days
; /* OK through 2199 */
1439 /* convert date & time to seconds relative to 00:00:00, 01/01/YRBASE */
1440 m_time
= (time_t)((unsigned long)(days
+ dy
) * 86400L +
1441 (unsigned long)hh
* 3600L +
1442 (unsigned long)(mm
* 60 + ss
));
1443 /* - 1; MS-DOS times always rounded up to nearest even second */
1444 TTrace((stderr
, "dos_to_unix_time:\n"));
1445 TTrace((stderr
, " m_time before timezone = %lu\n", (ulg
)m_time
));
1447 /*---------------------------------------------------------------------------
1448 Adjust for local standard timezone offset.
1449 ---------------------------------------------------------------------------*/
1451 #if (!defined(MACOS) && !defined(RISCOS) && !defined(QDOS) && !defined(TANDEM))
1453 /* account for timezone differences */
1454 res
= GetTimeZoneInformation(&tzinfo
);
1455 if (res
!= TIME_ZONE_ID_UNKNOWN
)
1457 m_time
+= 60*(tzinfo
.Bias
);
1459 #if (defined(BSD) || defined(MTS) || defined(__GO32__))
1461 if ( (dosdatetime
>= DOSTIME_2038_01_18
) &&
1462 (m_time
< (time_t)0x70000000L
) )
1463 m_time
= U_TIME_T_MAX
; /* saturate in case of (unsigned) overflow */
1464 if (m_time
< (time_t)0L) /* a converted DOS time cannot be negative */
1465 m_time
= S_TIME_T_MAX
; /* -> saturate at max signed time_t value */
1466 if ((tm
= localtime(&m_time
)) != (struct tm
*)NULL
)
1467 m_time
-= tm
->tm_gmtoff
; /* sec. EAST of GMT: subtr. */
1468 #else /* !(BSD4_4 */
1469 ftime(&tbp
); /* get `timezone' */
1470 m_time
+= tbp
.timezone
* 60L; /* seconds WEST of GMT: add */
1471 #endif /* ?(BSD4_4 || __EMX__) */
1472 #else /* !(BSD || MTS || __GO32__) */
1473 /* tzset was already called at start of process_zipfiles() */
1474 /* tzset(); */ /* set `timezone' variable */
1475 #ifndef __BEOS__ /* BeOS DR8 has no timezones... */
1476 m_time
+= timezone
; /* seconds WEST of GMT: add */
1478 #endif /* ?(BSD || MTS || __GO32__) */
1480 TTrace((stderr
, " m_time after timezone = %lu\n", (ulg
)m_time
));
1482 /*---------------------------------------------------------------------------
1483 Adjust for local daylight savings (summer) time.
1484 ---------------------------------------------------------------------------*/
1486 #ifndef BSD4_4 /* (DST already added to tm_gmtoff, so skip tm_isdst) */
1487 if ( (dosdatetime
>= DOSTIME_2038_01_18
) &&
1488 (m_time
< (time_t)0x70000000L
) )
1489 m_time
= U_TIME_T_MAX
; /* saturate in case of (unsigned) overflow */
1490 if (m_time
< (time_t)0L) /* a converted DOS time cannot be negative */
1491 m_time
= S_TIME_T_MAX
; /* -> saturate at max signed time_t value */
1492 TIMET_TO_NATIVE(m_time
) /* NOP unless MSC 7.0 or Macintosh */
1493 if (((tm
= localtime((time_t *)&m_time
)) != NULL
) && tm
->tm_isdst
)
1495 m_time
+= 60L * tzinfo
.DaylightBias
; /* adjust with DST bias */
1497 m_time
+= 60L * tzinfo
.StandardBias
; /* add StdBias (normally 0) */
1499 m_time
-= 60L * 60L; /* adjust for daylight savings time */
1501 NATIVE_TO_TIMET(m_time
) /* NOP unless MSC 7.0 or Macintosh */
1502 TTrace((stderr
, " m_time after DST = %lu\n", (ulg
)m_time
));
1503 #endif /* !BSD4_4 */
1507 #endif /* !MACOS && !RISCOS && !QDOS && !TANDEM */
1508 #endif /* ?TOPS20 */
1510 #endif /* ?HAVE_MKTIME */
1512 if ( (dosdatetime
>= DOSTIME_2038_01_18
) &&
1513 (m_time
< (time_t)0x70000000L
) )
1514 m_time
= U_TIME_T_MAX
; /* saturate in case of (unsigned) overflow */
1515 if (m_time
< (time_t)0L) /* a converted DOS time cannot be negative */
1516 m_time
= S_TIME_T_MAX
; /* -> saturate at max signed time_t value */
1520 } /* end function dos_to_unix_time() */
1522 #endif /* !OS2 || TIMESTAMP */
1523 #endif /* !VMS && !CMS_MVS */
1527 #if (!defined(VMS) && !defined(OS2) && !defined(CMS_MVS))
1529 /******************************/
1530 /* Function check_for_newer() */ /* used for overwriting/freshening/updating */
1531 /******************************/
1533 int check_for_newer(__G__ filename
) /* return 1 if existing file is newer */
1534 __GDEF
/* or equal; 0 if older; -1 if doesn't */
1535 char *filename
; /* exist yet */
1537 time_t existing
, archive
;
1538 #ifdef USE_EF_UT_TIME
1542 long dyy
, dmm
, ddd
, dhh
, dmin
, dss
;
1545 dyy
= (lrec
.last_mod_dos_datetime
>> 25) + 1980;
1546 dmm
= (lrec
.last_mod_dos_datetime
>> 21) & 0x0f;
1547 ddd
= (lrec
.last_mod_dos_datetime
>> 16) & 0x1f;
1548 dhh
= (lrec
.last_mod_dos_datetime
>> 11) & 0x1f;
1549 dmin
= (lrec
.last_mod_dos_datetime
>> 5) & 0x3f;
1550 dss
= (lrec
.last_mod_dos_datetime
& 0x1f) * 2;
1552 /* under AOS/VS, file times can only be set at creation time,
1553 * with the info in a special DG format. Make sure we can create
1554 * it here - we delete it later & re-create it, whether or not
1557 if (!zvs_create(filename
, (((ulg
)dgdate(dmm
, ddd
, dyy
)) << 16) |
1558 (dhh
*1800L + dmin
*30L + dss
/2L), -1L, -1L, (char *) -1, -1, -1, -1))
1559 return DOES_NOT_EXIST
;
1562 Trace((stderr
, "check_for_newer: doing stat(%s)\n", FnFilter1(filename
)));
1563 if (SSTAT(filename
, &G
.statbuf
)) {
1565 "check_for_newer: stat(%s) returns %d: file does not exist\n",
1566 FnFilter1(filename
), SSTAT(filename
, &G
.statbuf
)));
1568 Trace((stderr
, "check_for_newer: doing lstat(%s)\n",
1569 FnFilter1(filename
)));
1570 /* GRR OPTION: could instead do this test ONLY if G.symlnk is true */
1571 if (lstat(filename
, &G
.statbuf
) == 0) {
1573 "check_for_newer: lstat(%s) returns 0: symlink does exist\n",
1574 FnFilter1(filename
)));
1575 if (QCOND2
&& !uO
.overwrite_all
)
1576 Info(slide
, 0, ((char *)slide
, LoadFarString(FileIsSymLink
),
1577 FnFilter1(filename
), " with no real file"));
1578 return EXISTS_AND_OLDER
; /* symlink dates are meaningless */
1580 #endif /* SYMLINKS */
1581 return DOES_NOT_EXIST
;
1583 Trace((stderr
, "check_for_newer: stat(%s) returns 0: file exists\n",
1584 FnFilter1(filename
)));
1587 /* GRR OPTION: could instead do this test ONLY if G.symlnk is true */
1588 if (lstat(filename
, &G
.statbuf
) == 0 && S_ISLNK(G
.statbuf
.st_mode
)) {
1589 Trace((stderr
, "check_for_newer: %s is a symbolic link\n",
1590 FnFilter1(filename
)));
1591 if (QCOND2
&& !uO
.overwrite_all
)
1592 Info(slide
, 0, ((char *)slide
, LoadFarString(FileIsSymLink
),
1593 FnFilter1(filename
), ""));
1594 return EXISTS_AND_OLDER
; /* symlink dates are meaningless */
1596 #endif /* SYMLINKS */
1598 NATIVE_TO_TIMET(G
.statbuf
.st_mtime
) /* NOP unless MSC 7.0 or Macintosh */
1600 #ifdef USE_EF_UT_TIME
1601 /* The `Unix extra field mtime' should be used for comparison with the
1602 * time stamp of the existing file >>>ONLY<<< when the EF info is also
1603 * used to set the modification time of the extracted file.
1605 if (G
.extra_field
&&
1609 (ef_scan_for_izux(G
.extra_field
, G
.lrec
.extra_field_length
, 0,
1610 G
.lrec
.last_mod_dos_datetime
, &z_utime
, NULL
)
1613 TTrace((stderr
, "check_for_newer: using Unix extra field mtime\n"));
1614 existing
= G
.statbuf
.st_mtime
;
1615 archive
= z_utime
.mtime
;
1617 /* round up existing filetime to nearest 2 seconds for comparison,
1618 * but saturate in case of arithmetic overflow
1620 existing
= ((G
.statbuf
.st_mtime
& 1) &&
1621 (G
.statbuf
.st_mtime
+ 1 > G
.statbuf
.st_mtime
)) ?
1622 G
.statbuf
.st_mtime
+ 1 : G
.statbuf
.st_mtime
;
1623 archive
= dos_to_unix_time(G
.lrec
.last_mod_dos_datetime
);
1625 #else /* !USE_EF_UT_TIME */
1626 /* round up existing filetime to nearest 2 seconds for comparison,
1627 * but saturate in case of arithmetic overflow
1629 existing
= ((G
.statbuf
.st_mtime
& 1) &&
1630 (G
.statbuf
.st_mtime
+ 1 > G
.statbuf
.st_mtime
)) ?
1631 G
.statbuf
.st_mtime
+ 1 : G
.statbuf
.st_mtime
;
1632 archive
= dos_to_unix_time(G
.lrec
.last_mod_dos_datetime
);
1633 #endif /* ?USE_EF_UT_TIME */
1635 TTrace((stderr
, "check_for_newer: existing %lu, archive %lu, e-a %ld\n",
1636 (ulg
)existing
, (ulg
)archive
, (long)(existing
-archive
)));
1638 return (existing
>= archive
);
1640 } /* end function check_for_newer() */
1642 #endif /* !VMS && !OS2 && !CMS_MVS */
1648 /************************/
1649 /* Function do_string() */
1650 /************************/
1652 int do_string(__G__ len
, option
) /* return PK-type error code */
1654 unsigned int len
; /* without prototype, ush converted to this */
1657 long comment_bytes_left
, block_length
;
1661 char tmp_fnote
[2 * AMIGA_FILENOTELEN
]; /* extra room for squozen chars */
1665 /*---------------------------------------------------------------------------
1666 This function processes arbitrary-length (well, usually) strings. Four
1667 options are allowed: SKIP, wherein the string is skipped (pretty logical,
1668 eh?); DISPLAY, wherein the string is printed to standard output after un-
1669 dergoing any necessary or unnecessary character conversions; DS_FN,
1670 wherein the string is put into the filename[] array after undergoing ap-
1671 propriate conversions (including case-conversion, if that is indicated:
1672 see the global variable pInfo->lcflag); and EXTRA_FIELD, wherein the
1673 `string' is assumed to be an extra field and is copied to the (freshly
1674 malloced) buffer G.extra_field. The third option should be OK since
1675 filename is dimensioned at 1025, but we check anyway.
1677 The string, by the way, is assumed to start at the current file-pointer
1678 position; its length is given by len. So start off by checking length
1679 of string: if zero, we're already done.
1680 ---------------------------------------------------------------------------*/
1688 * First case: print string on standard output. First set loop vari-
1689 * ables, then loop through the comment in chunks of OUTBUFSIZ bytes,
1690 * converting formats and printing as we go. The second half of the
1691 * loop conditional was added because the file might be truncated, in
1692 * which case comment_bytes_left will remain at some non-zero value for
1693 * all time. outbuf and slide are used as scratch buffers because they
1694 * are available (we should be either before or in between any file pro-
1700 comment_bytes_left
= len
;
1701 block_length
= OUTBUFSIZ
; /* for the while statement, first time */
1702 while (comment_bytes_left
> 0 && block_length
> 0) {
1703 register uch
*p
= G
.outbuf
;
1704 register uch
*q
= G
.outbuf
;
1706 if ((block_length
= readbuf(__G__ (char *)G
.outbuf
,
1707 (unsigned) MIN((long)OUTBUFSIZ
, comment_bytes_left
))) == 0)
1709 comment_bytes_left
-= block_length
;
1711 /* this is why we allocated an extra byte for outbuf: terminate
1712 * with zero (ASCIIZ) */
1713 G
.outbuf
[(unsigned)block_length
] = '\0';
1715 /* remove all ASCII carriage returns from comment before printing
1716 * (since used before A_TO_N(), check for CR instead of '\r')
1723 /* could check whether (p - outbuf) == block_length here */
1726 if (option
== DISPL_8
) {
1727 /* translate the text coded in the entry's host-dependent
1728 "extended ASCII" charset into the compiler's (system's)
1729 internal text code page */
1730 Ext_ASCII_TO_Native((char *)G
.outbuf
, G
.pInfo
->hostnum
,
1731 G
.crec
.version_made_by
[0]);
1733 /* translate to ANSI (RTL internal codepage may be OEM) */
1734 INTERN_TO_ISO((char *)G
.outbuf
, (char *)G
.outbuf
);
1737 /* Win9x console always uses OEM character coding, and
1738 WinNT console is set to OEM charset by default, too */
1739 INTERN_TO_OEM((char *)G
.outbuf
, (char *)G
.outbuf
);
1741 #endif /* ?WINDLL */
1743 A_TO_N(G
.outbuf
); /* translate string to native */
1747 /* ran out of local mem -- had to cheat */
1748 win_fprintf((zvoid
*)&G
, stdout
, len
, (char *)G
.outbuf
);
1749 win_fprintf((zvoid
*)&G
, stdout
, 2, (char *)"\n\n");
1751 #ifdef NOANSIFILT /* GRR: can ANSI be used with EBCDIC? */
1752 (*G
.message
)((zvoid
*)&G
, G
.outbuf
, (ulg
)(q
-G
.outbuf
), 0);
1753 #else /* ASCII, filter out ANSI escape sequences and handle ^S (pause) */
1759 if (*p
== 0x1B) { /* ASCII escape char */
1762 } else if (*p
== 0x13) { /* ASCII ^S (pause) */
1764 if (p
[1] == LF
) /* ASCII LF */
1766 else if (p
[1] == CR
&& p
[2] == LF
) { /* ASCII CR LF */
1772 if ((unsigned)(q
-slide
) > WSIZE
-3 || pause
) { /* flush */
1773 (*G
.message
)((zvoid
*)&G
, slide
, (ulg
)(q
-slide
), 0);
1775 if (pause
&& G
.extract_flag
) /* don't pause for list/test */
1776 (*G
.mpause
)((zvoid
*)&G
, LoadFarString(QuitPrompt
), 0);
1779 (*G
.message
)((zvoid
*)&G
, slide
, (ulg
)(q
-slide
), 0);
1780 #endif /* ?NOANSIFILT */
1781 #endif /* ?WINDLL */
1783 /* add '\n' if not at start of line */
1784 (*G
.message
)((zvoid
*)&G
, slide
, 0L, 0x40);
1788 * Second case: read string into filename[] array. The filename should
1789 * never ever be longer than FILNAMSIZ-1 (1024), but for now we'll check,
1795 if (len
>= FILNAMSIZ
) {
1796 Info(slide
, 0x401, ((char *)slide
,
1797 LoadFarString(FilenameTooLongTrunc
)));
1799 extra_len
= (ush
)(len
- FILNAMSIZ
+ 1);
1800 len
= FILNAMSIZ
- 1;
1802 if (readbuf(__G__ G
.filename
, len
) == 0)
1804 G
.filename
[len
] = '\0'; /* terminate w/zero: ASCIIZ */
1806 /* translate the Zip entry filename coded in host-dependent "extended
1807 ASCII" into the compiler's (system's) internal text code page */
1808 Ext_ASCII_TO_Native(G
.filename
, G
.pInfo
->hostnum
,
1809 G
.crec
.version_made_by
[0]);
1811 if (G
.pInfo
->lcflag
) /* replace with lowercase filename */
1812 TOLOWER(G
.filename
, G
.filename
);
1814 if (G
.pInfo
->vollabel
&& len
> 8 && G
.filename
[8] == '.') {
1815 char *p
= G
.filename
+8;
1817 p
[-1] = *p
; /* disk label, and 8th char is dot: remove dot */
1820 if (!extra_len
) /* we're done here */
1824 * We truncated the filename, so print what's left and then fall
1825 * through to the SKIP routine.
1827 Info(slide
, 0x401, ((char *)slide
, "[ %s ]\n", FnFilter1(G
.filename
)));
1829 /* FALL THROUGH... */
1832 * Third case: skip string, adjusting readbuf's internal variables
1833 * as necessary (and possibly skipping to and reading a new block of
1838 /* cur_zipfile_bufstart already takes account of extra_bytes, so don't
1839 * correct for it twice: */
1840 ZLSEEK(G
.cur_zipfile_bufstart
- G
.extra_bytes
+
1841 (G
.inptr
-G
.inbuf
) + len
)
1845 * Fourth case: assume we're at the start of an "extra field"; malloc
1846 * storage for it and read data into the allocated space.
1850 if (G
.extra_field
!= (uch
*)NULL
)
1851 free(G
.extra_field
);
1852 if ((G
.extra_field
= (uch
*)malloc(len
)) == (uch
*)NULL
) {
1853 Info(slide
, 0x401, ((char *)slide
, LoadFarString(ExtraFieldTooLong
),
1855 /* cur_zipfile_bufstart already takes account of extra_bytes,
1856 * so don't correct for it twice: */
1857 ZLSEEK(G
.cur_zipfile_bufstart
- G
.extra_bytes
+
1858 (G
.inptr
-G
.inbuf
) + len
)
1860 if (readbuf(__G__ (char *)G
.extra_field
, len
) == 0)
1866 * Fifth case, for the Amiga only: take the comment that would ordinarily
1867 * be skipped over, and turn it into a 79 character string that will be
1868 * attached to the file as a "filenote" after it is extracted.
1872 if ((extra_len
= readbuf(__G__ tmp_fnote
, (unsigned)
1873 MIN(len
, 2 * AMIGA_FILENOTELEN
- 1))) == 0)
1875 if ((len
-= extra_len
) > 0) /* treat remainder as in case SKIP: */
1876 ZLSEEK(G
.cur_zipfile_bufstart
- G
.extra_bytes
1877 + (G
.inptr
- G
.inbuf
) + len
)
1878 /* convert multi-line text into single line with no ctl-chars: */
1879 tmp_fnote
[extra_len
] = '\0';
1880 while ((short int) --extra_len
>= 0)
1881 if ((unsigned) tmp_fnote
[extra_len
] < ' ')
1882 if (tmp_fnote
[extra_len
+1] == ' ') /* no excess */
1883 strcpy(tmp_fnote
+extra_len
, tmp_fnote
+extra_len
+1);
1885 tmp_fnote
[extra_len
] = ' ';
1886 tmp_fnote
[AMIGA_FILENOTELEN
- 1] = '\0';
1887 if (G
.filenotes
[G
.filenote_slot
])
1888 free(G
.filenotes
[G
.filenote_slot
]); /* should not happen */
1889 G
.filenotes
[G
.filenote_slot
] = NULL
;
1891 if (!(G
.filenotes
[G
.filenote_slot
] = malloc(strlen(tmp_fnote
)+1)))
1893 strcpy(G
.filenotes
[G
.filenote_slot
], tmp_fnote
);
1898 } /* end switch (option) */
1902 } /* end function do_string() */
1908 /***********************/
1909 /* Function makeword() */
1910 /***********************/
1916 * Convert Intel style 'short' integer to non-Intel non-16-bit
1917 * host format. This routine also takes care of byte-ordering.
1919 return (ush
)((b
[1] << 8) | b
[0]);
1926 /***********************/
1927 /* Function makelong() */
1928 /***********************/
1934 * Convert intel style 'long' variable to non-Intel non-16-bit
1935 * host format. This routine also takes care of byte-ordering.
1937 return (((ulg
)sig
[3]) << 24)
1938 + (((ulg
)sig
[2]) << 16)
1939 + (((ulg
)sig
[1]) << 8)
1948 /**********************/
1949 /* Function str2iso() */
1950 /**********************/
1952 char *str2iso(dst
, src
)
1953 char *dst
; /* destination buffer */
1954 register ZCONST
char *src
; /* source string */
1956 #ifdef INTERN_TO_ISO
1957 INTERN_TO_ISO(src
, dst
);
1960 register char *dstp
= dst
;
1963 c
= (uch
)foreign(*src
++);
1964 *dstp
++ = (char)ASCII2ISO(c
);
1965 } while (c
!= '\0');
1970 #endif /* NEED_STR2ISO */
1974 /**********************/
1975 /* Function str2oem() */
1976 /**********************/
1978 char *str2oem(dst
, src
)
1979 char *dst
; /* destination buffer */
1980 register ZCONST
char *src
; /* source string */
1982 #ifdef INTERN_TO_OEM
1983 INTERN_TO_OEM(src
, dst
);
1986 register char *dstp
= dst
;
1989 c
= (uch
)foreign(*src
++);
1990 *dstp
++ = (char)ASCII2OEM(c
);
1991 } while (c
!= '\0');
1996 #endif /* NEED_STR2OEM */
2001 #ifdef ZMEM /* memset/memcmp/memcpy for systems without either them or */
2002 /* bzero/bcmp/bcopy */
2003 /* (no known systems as of 960211) */
2005 /*********************/
2006 /* Function memset() */
2007 /*********************/
2009 zvoid
*memset(buf
, init
, len
)
2010 register zvoid
*buf
; /* buffer location */
2011 register int init
; /* initializer character */
2012 register unsigned int len
; /* length of the buffer */
2018 *((char *)buf
++) = (char)init
;
2024 /*********************/
2025 /* Function memcmp() */
2026 /*********************/
2028 int memcmp(b1
, b2
, len
)
2029 register ZCONST zvoid
*b1
;
2030 register ZCONST zvoid
*b2
;
2031 register unsigned int len
;
2036 if ((c
= (int)(*((ZCONST
unsigned char *)b1
)++) -
2037 (int)(*((ZCONST
unsigned char *)b2
)++)) != 0)
2045 /*********************/
2046 /* Function memcpy() */
2047 /*********************/
2049 zvoid
*memcpy(dst
, src
, len
)
2050 register zvoid
*dst
;
2051 register ZCONST zvoid
*src
;
2052 register unsigned int len
;
2058 *((char *)dst
)++ = *((ZCONST
char *)src
)++;
2068 /************************/
2069 /* Function zstrnicmp() */
2070 /************************/
2072 int zstrnicmp(s1
, s2
, n
)
2073 register ZCONST
char *s1
, *s2
;
2074 register unsigned n
;
2076 for (; n
> 0; --n
, ++s1
, ++s2
) {
2078 if (ToLower(*s1
) != ToLower(*s2
))
2079 /* test includes early termination of one string */
2080 return (ToLower(*s1
) < ToLower(*s2
))? -1 : 1;
2082 if (*s1
== '\0') /* both strings terminate early */
2092 #ifdef REGULUS /* returns the inode number on success(!)...argh argh argh */
2095 /********************/
2096 /* Function zstat() */
2097 /********************/
2103 return (stat(p
,s
) >= 0? 0 : (-1));
2106 #endif /* REGULUS */
2114 /*******************************/
2115 /* Function fLoadFarString() */ /* (and friends...) */
2116 /*******************************/
2118 char *fLoadFarString(__GPRO__
const char Far
*sz
)
2120 (void)zfstrcpy(G
.rgchBigBuffer
, sz
);
2121 return G
.rgchBigBuffer
;
2124 char *fLoadFarStringSmall(__GPRO__
const char Far
*sz
)
2126 (void)zfstrcpy(G
.rgchSmallBuffer
, sz
);
2127 return G
.rgchSmallBuffer
;
2130 char *fLoadFarStringSmall2(__GPRO__
const char Far
*sz
)
2132 (void)zfstrcpy(G
.rgchSmallBuffer2
, sz
);
2133 return G
.rgchSmallBuffer2
;
2139 #if (!defined(_MSC_VER) || (_MSC_VER < 600))
2140 /*************************/
2141 /* Function zfstrcpy() */ /* portable clone of _fstrcpy() */
2142 /*************************/
2144 char Far
* Far
zfstrcpy(char Far
*s1
, const char Far
*s2
)
2148 while ((*s1
++ = *s2
++) != '\0');
2151 #endif /* !_MSC_VER || (_MSC_VER < 600) */
2153 #endif /* SMALL_MEM */