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 off_t
acelseek(off_t offset
, int whence
);
54 int aceread(void *buf
, size_t count
);
55 int aceopen(const char *path
, int flags
);
59 char *replacestr(char *str1
, char *str2
, char *str3
);
61 /* setup of codepage conversion for decryption passwords */
63 # if (defined(CRYP_USES_ISO2OEM) && !defined(IZ_ISO2OEM_ARRAY))
64 # define IZ_ISO2OEM_ARRAY /* pull in iso2oem[] table */
66 # if (defined(CRYP_USES_OEM2ISO) && !defined(IZ_OEM2ISO_ARRAY))
67 # define IZ_OEM2ISO_ARRAY /* pull in oem2iso[] table */
70 #include "ebcdic.h" /* definition/initialization of ebcdic[] */
74 Note: Under Windows, the maximum size of the buffer that can be used
75 with any of the *printf calls is 16,384, so win_fprintf was used to
76 feed the fprintf clone no more than 16K chunks at a time. This should
77 be valid for anything up to 64K (and probably beyond, assuming your
78 buffers are that big).
81 # define WriteError(buf,len,strm) \
82 (win_fprintf(pG, strm, (extent)len, (char far *)buf) != (int)(len))
85 # define WriteError(buf,len,strm) \
86 ((extent)fwrite((char *)(buf),1,(extent)(len),strm) != (extent)(len))
88 # define WriteError(buf,len,strm) \
89 ((extent)write(fileno(strm),(char *)(buf),(extent)(len)) != (extent)(len))
93 static int disk_error
OF((__GPRO
));
96 /****************************/
97 /* Strings used in fileio.c */
98 /****************************/
100 #if (defined(UNIX) || defined(DOS_FLX_OS2_W32) || defined(__BEOS__))
101 static ZCONST
char Far CannotDeleteOldFile
[] =
102 "error: cannot delete old %s\n";
104 static ZCONST
char Far CannotRenameOldFile
[] =
105 "error: cannot rename old %s\n";
106 static ZCONST
char Far BackupSuffix
[] = "~";
108 #endif /* UNIX || DOS_FLX_OS2_W32 || __BEOS__ */
110 static ZCONST
char Far CannotOpenZipfile
[] =
111 "error: cannot open zipfile [ %s ]\n";
112 #if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS))
113 static ZCONST
char Far CannotCreateFile
[] = "error: cannot create %s\n";
115 #ifdef NOVELL_BUG_FAILSAFE
116 static ZCONST
char Far NovellBug
[] =
117 "error: %s: stat() says does not exist, but fopen() found anyway\n";
119 static ZCONST
char Far ReadError
[] = "error: zipfile read error\n";
120 static ZCONST
char Far FilenameTooLongTrunc
[] =
121 "warning: filename too long--truncating.\n";
122 static ZCONST
char Far ExtraFieldTooLong
[] =
123 "warning: extra field too long (%d). Ignoring...\n";
126 static ZCONST
char Far DiskFullQuery
[] =
127 "%s: write error (disk full?).\n";
129 static ZCONST
char Far DiskFullQuery
[] =
130 "%s: write error (disk full?). Continue? (y/n/^C) ";
131 static ZCONST
char Far ZipfileCorrupt
[] =
132 "error: zipfile probably corrupt (%s)\n";
134 static ZCONST
char Far FileIsSymLink
[] =
135 "%s exists and is a symbolic link%s.\n";
138 static ZCONST
char Far MorePrompt
[] = "--More--(%lu)";
140 static ZCONST
char Far QuitPrompt
[] =
141 "--- Press `Q' to quit, or any other key to continue ---";
142 static ZCONST
char Far HidePrompt
[] = /* "\r \r"; */
146 /* SPC: are names on MacOS REALLY so much longer than elsewhere ??? */
147 static ZCONST
char Far PasswPrompt
[] = "[%s]\n %s password: ";
149 static ZCONST
char Far PasswPrompt
[] = "[%s] %s password: ";
151 static ZCONST
char Far PasswPrompt2
[] = "Enter password: ";
152 static ZCONST
char Far PasswRetry
[] = "password incorrect--reenter: ";
160 /******************************/
161 /* Function open_input_file() */
162 /******************************/
164 int open_input_file(__G
) /* return 1 if open failed */
168 * open the zipfile for reading and in BINARY mode to prevent cr/lf
169 * translation, which would corrupt the bitstreams
172 #if (defined(UNIX) || defined(TOPS20) || defined(AOS_VS) || defined(__BEOS__))
173 G
.zipfd
= aceopen(G
.zipfn
, O_RDONLY
);
174 #else /* !(UNIX || TOPS20 || AOS_VS || __BEOS__) */
176 G
.zipfd
= open(G
.zipfn
, O_RDONLY
, 0, "ctx=stm");
179 G
.zipfd
= aceopen(G
.zipfn
, 0);
182 G
.zipfd
= fopen(G
.zipfn
, "rb");
185 G
.zipfd
= vmmvs_open_infile(__G
);
187 G
.zipfd
= aceopen(G
.zipfn
, O_RDONLY
| O_BINARY
);
188 #endif /* ?CMS_MVS */
192 #endif /* ?(UNIX || TOPS20 || AOS_VS || __BEOS__) */
194 #ifdef USE_STRM_INPUT
197 /* if (G.zipfd < 0) */ /* no good for Windows CE port */
201 Info(slide
, 0x401, ((char *)slide
, LoadFarString(CannotOpenZipfile
),
207 } /* end function open_input_file() */
212 #if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS))
214 /***************************/
215 /* Function open_outfile() */
216 /***************************/
218 int open_outfile(__G
) /* return 1 if fail */
223 return (redirect_outfile(__G
) == FALSE
);
226 QFilename(__G__ G
.filename
);
228 #if (defined(DOS_FLX_OS2_W32) || defined(UNIX) || defined(__BEOS__))
229 #ifdef BORLAND_STAT_BUG
230 /* Borland 5.0's stat() barfs if the filename has no extension and the
231 * file doesn't exist. */
232 if (access(G
.filename
, 0) == -1) {
233 FILE *tmp
= fopen(G
.filename
, "wb+");
235 /* file doesn't exist, so create a dummy file to keep stat() from
236 * failing (will be over-written anyway) */
237 fputc('0', tmp
); /* just to have something in the file */
240 #endif /* BORLAND_STAT_BUG */
242 if (SSTAT(G
.filename
, &G
.statbuf
) == 0 || lstat(G
.filename
,&G
.statbuf
) == 0)
244 if (SSTAT(G
.filename
, &G
.statbuf
) == 0)
245 #endif /* ?SYMLINKS */
247 Trace((stderr
, "open_outfile: stat(%s) returns 0: file exists\n",
248 FnFilter1(G
.filename
)));
250 if (uO
.B_flag
) { /* do backup */
252 int blen
, flen
, tlen
;
254 blen
= strlen(BackupSuffix
);
255 flen
= strlen(G
.filename
);
256 tlen
= flen
+ blen
+ 1;
257 if (tlen
>= FILNAMSIZ
) { /* in case name is too long, truncate */
258 tname
= (char *)malloc(FILNAMSIZ
);
260 return 1; /* in case we run out of space */
261 tlen
= FILNAMSIZ
- 1 - blen
;
262 strcpy(tname
, G
.filename
); /* make backup name */
265 tname
= (char *)malloc(tlen
);
267 return 1; /* in case we run out of space */
268 strcpy(tname
, G
.filename
); /* make backup name */
270 strcpy(tname
+flen
, BackupSuffix
);
272 /* GRR: should check if backup file exists, apply -n/-o to that */
273 if (rename(G
.filename
, tname
) < 0) { /* move file */
274 Info(slide
, 0x401, ((char *)slide
,
275 LoadFarString(CannotRenameOldFile
), FnFilter1(G
.filename
)));
281 #endif /* UNIXBACKUP */
282 #ifdef DOS_FLX_OS2_W32
283 if (!(G
.statbuf
.st_mode
& S_IWRITE
)) {
284 Trace((stderr
, "open_outfile: existing file %s is read-only\n",
285 FnFilter1(G
.filename
)));
286 chmod(G
.filename
, S_IREAD
| S_IWRITE
);
287 Trace((stderr
, "open_outfile: %s now writable\n",
288 FnFilter1(G
.filename
)));
290 #endif /* DOS_FLX_OS2_W32 */
291 if (unlink(G
.filename
) != 0) {
292 Info(slide
, 0x401, ((char *)slide
,
293 LoadFarString(CannotDeleteOldFile
), FnFilter1(G
.filename
)));
296 Trace((stderr
, "open_outfile: %s now deleted\n",
297 FnFilter1(G
.filename
)));
299 #endif /* DOS_FLX_OS2_W32 || UNIX || __BEOS__ */
301 if (SWI_OS_File_7(G
.filename
,0xDEADDEAD,0xDEADDEAD,G
.lrec
.ucsize
)!=NULL
) {
302 Info(slide
, 1, ((char *)slide
, LoadFarString(CannotCreateFile
),
303 FnFilter1(G
.filename
)));
310 if ((tfilnam
= (char *)malloc(2*strlen(G
.filename
)+1)) == (char *)NULL
)
312 strcpy(tfilnam
, G
.filename
);
315 if ((G
.outfile
= fopen(tfilnam
, FOPW
)) == (FILE *)NULL
) {
316 Info(slide
, 1, ((char *)slide
, LoadFarString(CannotCreateFile
),
325 G
.outfile
= fopen(G
.filename
, FOPWT
);
327 G
.outfile
= fopen(G
.filename
, FOPW
);
328 if (G
.outfile
== (FILE *)NULL
) {
329 Info(slide
, 1, ((char *)slide
, LoadFarString(CannotCreateFile
),
330 FnFilter1(G
.filename
)));
335 if (SSTAT(G
.filename
, &G
.statbuf
) == 0) {
336 Trace((stderr
, "open_outfile: stat(%s) returns 0 (file exists)\n",
337 FnFilter1(G
.filename
)));
338 if (unlink(G
.filename
) != 0) {
339 Trace((stderr
, "open_outfile: existing file %s is read-only\n",
340 FnFilter1(G
.filename
)));
341 chmod(G
.filename
, S_IRUSR
| S_IWUSR
);
342 Trace((stderr
, "open_outfile: %s now writable\n",
343 FnFilter1(G
.filename
)));
344 if (unlink(G
.filename
) != 0)
347 Trace((stderr
, "open_outfile: %s now deleted\n",
348 FnFilter1(G
.filename
)));
350 if (G
.pInfo
->textmode
)
351 G
.outfile
= fopen(G
.filename
, FOPWT
);
353 G
.outfile
= fopen(G
.filename
, FOPW
);
354 if (G
.outfile
== (FILE *)NULL
) {
355 Info(slide
, 1, ((char *)slide
, LoadFarString(CannotCreateFile
),
356 FnFilter1(G
.filename
)));
361 Info(slide
, 1, ((char *)slide
,
362 "open_outfile: doing fopen(%s) for reading\n", FnFilter1(G
.filename
)));
363 if ((G
.outfile
= fopen(G
.filename
, FOPR
)) == (FILE *)NULL
)
364 Info(slide
, 1, ((char *)slide
,
365 "open_outfile: fopen(%s) for reading failed: does not exist\n",
366 FnFilter1(G
.filename
)));
368 Info(slide
, 1, ((char *)slide
,
369 "open_outfile: fopen(%s) for reading succeeded: file exists\n",
370 FnFilter1(G
.filename
)));
374 #ifdef NOVELL_BUG_FAILSAFE
375 if (G
.dne
&& ((G
.outfile
= fopen(G
.filename
, FOPR
)) != (FILE *)NULL
)) {
376 Info(slide
, 0x401, ((char *)slide
, LoadFarString(NovellBug
),
377 FnFilter1(G
.filename
)));
379 return 1; /* with "./" fix in checkdir(), should never reach here */
381 #endif /* NOVELL_BUG_FAILSAFE */
382 Trace((stderr
, "open_outfile: doing fopen(%s) for writing\n",
383 FnFilter1(G
.filename
)));
384 if ((G
.outfile
= fopen(G
.filename
, FOPW
)) == (FILE *)NULL
) {
385 Info(slide
, 0x401, ((char *)slide
, LoadFarString(CannotCreateFile
),
386 FnFilter1(G
.filename
)));
389 Trace((stderr
, "open_outfile: fopen(%s) for writing succeeded\n",
390 FnFilter1(G
.filename
)));
397 /* 16-bit MSC: buffer size must be strictly LESS than 32K (WSIZE): bogus */
398 setbuf(G
.outfile
, (char *)NULL
); /* make output unbuffered */
399 #else /* !DOS_OS2_W32 */
401 #ifdef _IOFBF /* make output fully buffered (works just about like write()) */
402 setvbuf(G
.outfile
, (char *)slide
, _IOFBF
, WSIZE
);
404 setbuf(G
.outfile
, (char *)slide
);
407 #endif /* ?DOS_OS2_W32 */
408 #endif /* USE_FWRITE */
411 } /* end function open_outfile() */
413 #endif /* !VMS && !AOS_VS && !CMS_MVS && !MACOS */
420 * These functions allow NEXTBYTE to function without needing two bounds
421 * checks. Call defer_leftover_input() if you ever have filled G.inbuf
422 * by some means other than readbyte(), and you then want to start using
423 * NEXTBYTE. When going back to processing bytes without NEXTBYTE, call
424 * undefer_input(). For example, extract_or_test_member brackets its
425 * central section that does the decompression with these two functions.
426 * If you need to check the number of bytes remaining in the current
427 * file while using NEXTBYTE, check (G.csize + G.incnt), not G.csize.
430 /****************************/
431 /* function undefer_input() */
432 /****************************/
434 void undefer_input(__G
)
439 if (G
.incnt_leftover
> 0) {
440 /* We know that "(G.csize < MAXINT)" so we can cast G.csize to int:
441 * This condition was checked when G.incnt_leftover was set > 0 in
442 * defer_leftover_input(), and it is NOT allowed to touch G.csize
443 * before calling undefer_input() when (G.incnt_leftover > 0)
444 * (single exception: see read_byte()'s "G.csize <= 0" handling) !!
446 G
.incnt
= G
.incnt_leftover
+ (int)G
.csize
;
447 G
.inptr
= G
.inptr_leftover
- (int)G
.csize
;
448 G
.incnt_leftover
= 0;
449 } else if (G
.incnt
< 0)
451 } /* end function undefer_input() */
457 /***********************************/
458 /* function defer_leftover_input() */
459 /***********************************/
461 void defer_leftover_input(__G
)
464 if ((long)G
.incnt
> G
.csize
) {
465 /* (G.csize < MAXINT), we can safely cast it to int !! */
468 G
.inptr_leftover
= G
.inptr
+ (int)G
.csize
;
469 G
.incnt_leftover
= G
.incnt
- (int)G
.csize
;
470 G
.incnt
= (int)G
.csize
;
472 G
.incnt_leftover
= 0;
474 } /* end function defer_leftover_input() */
480 /**********************/
481 /* Function readbuf() */
482 /**********************/
484 unsigned readbuf(__G__ buf
, size
) /* return number of bytes read into buf */
487 register unsigned size
;
489 register unsigned count
;
495 if ((G
.incnt
= aceread((char *)G
.inbuf
, INBUFSIZ
)) == 0)
497 else if (G
.incnt
< 0) {
498 /* another hack, but no real harm copying same thing twice */
499 (*G
.message
)((zvoid
*)&G
,
500 (uch
*)LoadFarString(ReadError
), /* CANNOT use slide */
501 (ulg
)strlen(LoadFarString(ReadError
)), 0x401);
502 return 0; /* discarding some data; better than lock-up */
504 /* buffer ALWAYS starts on a block boundary: */
505 G
.cur_zipfile_bufstart
+= INBUFSIZ
;
508 count
= MIN(size
, (unsigned)G
.incnt
);
509 memcpy(buf
, G
.inptr
, count
);
517 } /* end function readbuf() */
523 /***********************/
524 /* Function readbyte() */
525 /***********************/
527 int readbyte(__G
) /* refill inbuf and return a byte if available, else EOF */
533 G
.csize
--; /* for tests done after exploding */
538 if ((G
.incnt
= aceread((char *)G
.inbuf
, INBUFSIZ
)) == 0) {
539 G
.incnt
= 0; /* do not allow negative value to affect stuff */
541 } else if (G
.incnt
< 0) { /* "fail" (abort, retry, ...) returns this */
542 /* another hack, but no real harm copying same thing twice */
543 (*G
.message
)((zvoid
*)&G
,
544 (uch
*)LoadFarString(ReadError
),
545 (ulg
)strlen(LoadFarString(ReadError
)), 0x401);
548 longjmp(dll_error_return
, 1);
551 EXIT(PK_BADERR
); /* totally bailing; better than lock-up */
554 G
.cur_zipfile_bufstart
+= INBUFSIZ
; /* always starts on block bndry */
556 defer_leftover_input(__G
); /* decrements G.csize */
560 if (G
.pInfo
->encrypted
) {
564 /* This was previously set to decrypt one byte beyond G.csize, when
565 * incnt reached that far. GRR said, "but it's required: why?" This
566 * was a bug in fillinbuf() -- was it also a bug here?
568 for (n
= G
.incnt
, p
= G
.inptr
; n
--; p
++)
576 } /* end function readbyte() */
584 /************************/
585 /* Function fillinbuf() */
586 /************************/
588 int fillinbuf(__G
) /* like readbyte() except returns number of bytes in inbuf */
592 (G
.incnt
= aceread((char *)G
.inbuf
, INBUFSIZ
)) <= 0)
594 G
.cur_zipfile_bufstart
+= INBUFSIZ
; /* always starts on a block boundary */
596 defer_leftover_input(__G
); /* decrements G.csize */
599 if (G
.pInfo
->encrypted
) {
603 for (n
= G
.incnt
, p
= G
.inptr
; n
--; p
++)
610 } /* end function fillinbuf() */
612 #endif /* USE_ZLIB */
618 #ifndef VMS /* for VMS use code in vms.c */
620 /********************/
621 /* Function flush() */ /* returns PK error codes: */
622 /********************/ /* if cflag => always 0; PK_DISK if write error */
624 int flush(__G__ rawbuf
, size
, unshrink
)
632 #if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV))
635 /* static int didCRlast = FALSE; moved to globals.h */
638 /*---------------------------------------------------------------------------
639 Compute the CRC first; if testing or if disk is full, that's it.
640 ---------------------------------------------------------------------------*/
642 G
.crc32val
= crc32(G
.crc32val
, rawbuf
, (extent
)size
);
645 if ((G
.statreportcb
!= NULL
) &&
646 (*G
.statreportcb
)(__G__ UZ_ST_IN_PROGRESS
, G
.zipfn
, G
.filename
, NULL
))
647 return IZ_CTRLC
; /* cancel operation by user request */
650 if (uO
.tflag
|| size
== 0L) /* testing or nothing to write: all done */
654 return PK_DISK
; /* disk already full: ignore rest of file */
656 /*---------------------------------------------------------------------------
657 Write the bytes rawbuf[0..size-1] to the output device, first converting
658 end-of-lines and ASCII/EBCDIC as needed. If SMALL_MEM or MED_MEM are NOT
659 defined, outbuf is assumed to be at least as large as rawbuf and is not
660 necessarily checked for overflow.
661 ---------------------------------------------------------------------------*/
663 if (!G
.pInfo
->textmode
) { /* write raw binary data */
664 /* GRR: note that for standard MS-DOS compilers, size argument to
665 * fwrite() can never be more than 65534, so WriteError macro will
666 * have to be rewritten if size can ever be that large. For now,
667 * never more than 32K. Also note that write() returns an int, which
668 * doesn't necessarily limit size to 32767 bytes if write() is used
669 * on 16-bit systems but does make it more of a pain; however, because
670 * at least MSC 5.1 has a lousy implementation of fwrite() (as does
671 * DEC Ultrix cc), write() is used anyway.
675 writeToMemory(__G__ rawbuf
, size
);
678 if (!uO
.cflag
&& WriteError(rawbuf
, size
, G
.outfile
))
679 return disk_error(__G
);
680 else if (uO
.cflag
&& (*G
.message
)((zvoid
*)&G
, rawbuf
, size
, 0))
682 } else { /* textmode: aflag is true */
684 /* rawbuf = outbuf */
685 transbuf
= G
.outbuf2
;
686 #if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV))
687 transbufsiz
= TRANSBUFSIZ
;
692 #if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV))
693 transbufsiz
= OUTBUFSIZ
;
694 Trace((stderr
, "\ntransbufsiz = OUTBUFSIZ = %u\n", OUTBUFSIZ
));
699 /* GRR: really want to check if -aa (or -aaa?) was given... */
700 if (rawbuf
[1]) { /* first line is more than 255 chars long */
702 "\nfirst line of VMS `text' too long; switching to normal extraction\n"));
703 G
.VMS_line_state
= -1; /* -1: don't treat as VMS text */
705 G
.VMS_line_state
= 0; /* 0: ready to read line length */
707 G
.didCRlast
= FALSE
; /* no previous buffers written */
712 if (G
.pInfo
->hostnum
== VMS_
&& G
.extra_field
&& G
.VMS_line_state
>= 0)
714 /* GRR: really want to check for actual VMS extra field, and
715 * ideally for variable-length record format */
717 printf("\n>>>>>> GRR: file is VMS text and has an extra field\n");
722 while(p
< rawbuf
+(unsigned)size
) {
723 switch (G
.VMS_line_state
) {
725 /* 0: ready to read line length */
727 G
.VMS_line_length
= 0;
729 if (p
== rawbuf
+(unsigned)size
-1) { /* last char */
730 G
.VMS_line_length
= (int)((uch
)(*p
++));
731 G
.VMS_line_state
= 1;
733 G
.VMS_line_length
= makeword(p
);
735 G
.VMS_line_state
= 2;
737 if (G
.VMS_line_length
& 1) /* odd */
741 /* 1: read one byte of length, need second */
743 G
.VMS_line_length
+= ((int)((uch
)(*p
++)) << 8);
744 G
.VMS_line_state
= 2;
747 /* 2: ready to read VMS_line_length chars */
749 if (G
.VMS_line_length
< rawbuf
+(unsigned)size
-p
) {
750 if (G
.VMS_line_length
>=
751 transbuf
+(unsigned)transbufsiz
-q
)
753 int outroom
= transbuf
+(unsigned)transbufsiz
-q
;
755 /* GRR: need to change this to *q++ = native(*p++); loop or something */
756 memcpy(q
, p
, outroom
);
759 writeToMemory(__G__ transbuf
,
763 if (!uO
.cflag
&& WriteError(transbuf
,
764 (unsigned)outroom
, G
.outfile
))
765 return disk_error(__G
);
766 else if (uO
.cflag
&& (*G
.message
)((zvoid
*)&G
,
767 transbuf
, (ulg
)outroom
, 0))
771 G
.VMS_line_length
-= outroom
;
772 /* fall through to normal case */
774 /* GRR: need to change this to *q++ = native(*p++); loop or something */
775 memcpy(q
, p
, G
.VMS_line_length
);
776 q
+= G
.VMS_line_length
;
777 p
+= G
.VMS_line_length
;
778 G
.VMS_line_length
= 0; /* necessary?? */
779 G
.VMS_line_state
= 3;
781 } else { /* remaining input is less than full line */
782 int remaining
= rawbuf
+(unsigned)size
-p
;
785 transbuf
+(unsigned)transbufsiz
-q
)
787 int outroom
= transbuf
+(unsigned)transbufsiz
-q
;
789 /* GRR: need to change this to *q++ = native(*p++); loop or something */
790 memcpy(q
, p
, outroom
);
793 writeToMemory(__G__ transbuf
,
794 (unsigned)(outroom
));
797 if (!uO
.cflag
&& WriteError(transbuf
,
798 (unsigned)outroom
, G
.outfile
))
799 return disk_error(__G
);
800 else if (uO
.cflag
&& (*G
.message
)((zvoid
*)&G
,
801 transbuf
, (ulg
)outroom
, 0))
805 remaining
-= outroom
;
807 /* GRR: need to change this to *q++ = native(*p++); loop or something */
808 memcpy(q
, p
, remaining
);
811 G
.VMS_line_length
-= remaining
;
812 /* no change in G.VMS_line_state */
816 /* 3: ready to PutNativeEOL */
818 if (q
> transbuf
+(unsigned)transbufsiz
-lenEOL
) {
821 writeToMemory(__G__ transbuf
,
822 (unsigned)(q
-transbuf
));
826 WriteError(transbuf
, (unsigned)(q
-transbuf
),
828 return disk_error(__G
);
829 else if (uO
.cflag
&& (*G
.message
)((zvoid
*)&G
,
830 transbuf
, (ulg
)(q
-transbuf
), 0))
836 if (p
< rawbuf
+(unsigned)size
) {
838 G
.VMS_line_state
= 0;
840 G
.VMS_line_state
= 4;
842 G
.VMS_line_state
= 0;
845 /* 4: ready to read pad byte */
848 G
.VMS_line_state
= 0;
854 #endif /* VMS_TEXT_CONV */
856 /*-----------------------------------------------------------------------
857 Algorithm: CR/LF => native; lone CR => native; lone LF => native.
858 This routine is only for non-raw-VMS, non-raw-VM/CMS files (i.e.,
859 stream-oriented files, not record-oriented).
860 -----------------------------------------------------------------------*/
862 /* else not VMS text */ {
864 if (*p
== LF
&& G
.didCRlast
)
867 for (q
= transbuf
; p
< rawbuf
+(unsigned)size
; ++p
) {
868 if (*p
== CR
) { /* lone CR or CR/LF: EOL either way */
870 if (p
== rawbuf
+(unsigned)size
-1) /* last char in buffer */
872 else if (p
[1] == LF
) /* get rid of accompanying LF */
874 } else if (*p
== LF
) /* lone LF */
877 #ifndef DOS_FLX_OS2_W32
878 if (*p
!= CTRLZ
) /* lose all ^Z's */
882 #if (defined(SMALL_MEM) || defined(MED_MEM))
883 # if (lenEOL == 1) /* don't check unshrink: both buffers small but equal */
886 /* check for danger of buffer overflow and flush */
887 if (q
> transbuf
+(unsigned)transbufsiz
-lenEOL
) {
889 "p - rawbuf = %u q-transbuf = %u size = %lu\n",
890 (unsigned)(p
-rawbuf
), (unsigned)(q
-transbuf
), size
));
891 if (!uO
.cflag
&& WriteError(transbuf
,
892 (unsigned)(q
-transbuf
), G
.outfile
))
893 return disk_error(__G
);
894 else if (uO
.cflag
&& (*G
.message
)((zvoid
*)&G
,
895 transbuf
, (ulg
)(q
-transbuf
), 0))
900 #endif /* SMALL_MEM || MED_MEM */
904 /*-----------------------------------------------------------------------
905 Done translating: write whatever we've got to file (or screen).
906 -----------------------------------------------------------------------*/
908 Trace((stderr
, "p - rawbuf = %u q-transbuf = %u size = %lu\n",
909 (unsigned)(p
-rawbuf
), (unsigned)(q
-transbuf
), size
));
913 writeToMemory(__G__ transbuf
, (unsigned)(q
-transbuf
));
916 if (!uO
.cflag
&& WriteError(transbuf
, (unsigned)(q
-transbuf
),
918 return disk_error(__G
);
919 else if (uO
.cflag
&& (*G
.message
)((zvoid
*)&G
, transbuf
,
920 (ulg
)(q
-transbuf
), 0))
927 } /* end function flush() */
933 /*************************/
934 /* Function disk_error() */
935 /*************************/
937 static int disk_error(__G
)
940 /* OK to use slide[] here because this file is finished regardless */
941 Info(slide
, 0x4a1, ((char *)slide
, LoadFarString(DiskFullQuery
),
942 FnFilter1(G
.filename
)));
945 fgets(G
.answerbuf
, 9, stdin
);
946 if (*G
.answerbuf
== 'y') /* stop writing to this file */
947 G
.disk_full
= 1; /* (outfile bad?), but new OK */
950 G
.disk_full
= 2; /* no: exit program */
954 } /* end function disk_error() */
962 /*****************************/
963 /* Function UzpMessagePrnt() */
964 /*****************************/
966 int UZ_EXP
UzpMessagePrnt(pG
, buf
, size
, flag
)
967 zvoid
*pG
; /* globals struct: always passed */
968 uch
*buf
; /* preformatted string to be printed */
969 ulg size
; /* length of string (may include nulls) */
970 int flag
; /* flag bits */
973 * The name of the first parameter of UzpMessagePrnt(), which passes
974 * the "Uz_Globs" address, >>> MUST <<< be identical to the string
975 * expansion of the __G__ macro in the REENTRANT case (see globals.h).
976 * This name identity is mandatory for the LoadFarString() macro
977 * (in the SMALL_MEM case) !!!
980 uch
*q
=buf
, *endbuf
=buf
+(unsigned)size
;
987 /*---------------------------------------------------------------------------
988 These tests are here to allow fine-tuning of UnZip's output messages,
989 but none of them will do anything without setting the appropriate bit
990 in the flag argument of every Info() statement which is to be turned
991 *off*. That is, all messages are currently turned on for all ports.
992 To turn off *all* messages, use the UzpMessageNull() function instead
994 ---------------------------------------------------------------------------*/
996 #if (defined(OS2) && defined(DLL))
997 if (MSG_NO_DLL2(flag
)) /* if OS/2 DLL bit is set, do NOT print this msg */
1001 if (MSG_NO_WDLL(flag
))
1005 if (MSG_NO_WGUI(flag
))
1010 if (MSG_NO_AGUI(flag))
1014 #ifdef DLL /* don't display message if data is redirected */
1015 if (((Uz_Globs
*)pG
)->redirect_data
&&
1016 !((Uz_Globs
*)pG
)->redirect_text
)
1020 if (MSG_STDERR(flag
) && !((Uz_Globs
*)pG
)->UzO
.tflag
)
1021 outfp
= (FILE *)stderr
;
1023 outfp
= (FILE *)stdout
;
1025 #ifdef QUERY_TRNEWLN
1026 /* some systems require termination of query prompts with '\n' to force
1027 * immediate display */
1028 if (MSG_MNEWLN(flag
)) { /* assumes writable buffer (e.g., slide[]) */
1029 *endbuf
++ = '\n'; /* with room for one more char at end of buf */
1030 ++size
; /* (safe assumption: only used for four */
1031 } /* short queries in extract.c and fileio.c) */
1034 if (MSG_TNEWLN(flag
)) { /* again assumes writable buffer: fragile... */
1035 if ((!size
&& !((Uz_Globs
*)pG
)->sol
) ||
1036 (size
&& (endbuf
[-1] != '\n')))
1044 /* room for --More-- and one line of overlap: */
1045 ((Uz_Globs
*)pG
)->height
= SCREENLINES
- 2;
1048 if (MSG_LNEWLN(flag
) && !((Uz_Globs
*)pG
)->sol
) {
1049 /* not at start of line: want newline */
1051 if (!((Uz_Globs
*)pG
)->redirect_text
) {
1056 if (((Uz_Globs
*)pG
)->M_flag
)
1058 ++((Uz_Globs
*)pG
)->numlines
;
1059 if (((Uz_Globs
*)pG
)->numlines
%
1060 ((Uz_Globs
*)pG
)->height
== 0L) /* GRR: fix */
1061 (*((Uz_Globs
*)pG
)->mpause
)((zvoid
*)pG
,
1062 LoadFarString(MorePrompt
), 1);
1065 if (MSG_STDERR(flag
) && ((Uz_Globs
*)pG
)->UzO
.tflag
&&
1066 !isatty(1) && isatty(2))
1068 /* error output from testing redirected: also send to stderr */
1076 ((Uz_Globs
*)pG
)->sol
= TRUE
;
1079 /* put zipfile name, filename and/or error/warning keywords here */
1082 if (((Uz_Globs
*)pG
)->M_flag
1084 && !((Uz_Globs
*)pG
)->redirect_text
1088 while (++p
< endbuf
) {
1090 ++((Uz_Globs
*)pG
)->numlines
;
1091 if (((Uz_Globs
*)pG
)->numlines
%
1092 ((Uz_Globs
*)pG
)->height
== 0L) /* GRR: fix */
1094 if ((error
= WriteError(q
, p
-q
+1, outfp
)) != 0)
1097 ((Uz_Globs
*)pG
)->sol
= TRUE
;
1099 (*((Uz_Globs
*)pG
)->mpause
)((zvoid
*)pG
,
1100 LoadFarString(MorePrompt
), 1);
1104 size
= (ulg
)(p
- q
); /* remaining text */
1110 if (!((Uz_Globs
*)pG
)->redirect_text
) {
1112 if ((error
= WriteError(q
, size
, outfp
)) != 0)
1115 if (MSG_STDERR(flag
) && ((Uz_Globs
*)pG
)->UzO
.tflag
&&
1116 !isatty(1) && isatty(2))
1118 /* error output from testing redirected: also send to stderr */
1119 if ((error
= WriteError(q
, size
, stderr
)) != 0)
1124 } else { /* GRR: this is ugly: hide with macro */
1125 if ((error
= REDIRECTPRINT(q
, size
)) != 0)
1129 ((Uz_Globs
*)pG
)->sol
= (endbuf
[-1] == '\n');
1133 } /* end function UzpMessagePrnt() */
1141 /*****************************/
1142 /* Function UzpMessageNull() */ /* convenience routine for no output at all */
1143 /*****************************/
1145 int UZ_EXP
UzpMessageNull(pG
, buf
, size
, flag
)
1146 zvoid
*pG
; /* globals struct: always passed */
1147 uch
*buf
; /* preformatted string to be printed */
1148 ulg size
; /* length of string (may include nulls) */
1149 int flag
; /* flag bits */
1153 } /* end function UzpMessageNull() */
1161 /***********************/
1162 /* Function UzpInput() */ /* GRR: this is a placeholder for now */
1163 /***********************/
1165 int UZ_EXP
UzpInput(pG
, buf
, size
, flag
)
1166 zvoid
*pG
; /* globals struct: always passed */
1167 uch
*buf
; /* preformatted string to be printed */
1168 int *size
; /* (address of) size of buf and of returned string */
1169 int flag
; /* flag bits (bit 0: no echo) */
1171 /* tell picky compilers to shut up about "unused variable" warnings */
1172 pG
= pG
; buf
= buf
; flag
= flag
;
1177 } /* end function UzpInput() */
1183 #if (!defined(WINDLL) && !defined(MACOS))
1185 /***************************/
1186 /* Function UzpMorePause() */
1187 /***************************/
1189 void UZ_EXP
UzpMorePause(pG
, prompt
, flag
)
1190 zvoid
*pG
; /* globals struct: always passed */
1191 ZCONST
char *prompt
; /* "--More--" prompt */
1192 int flag
; /* 0 = any char OK; 1 = accept only '\n', ' ', q */
1197 /*---------------------------------------------------------------------------
1198 Print a prompt and wait for the user to press a key, then erase prompt
1200 ---------------------------------------------------------------------------*/
1202 if (!((Uz_Globs
*)pG
)->sol
)
1203 fprintf(stderr
, "\n");
1204 /* numlines may or may not be used: */
1205 fprintf(stderr
, prompt
, ((Uz_Globs
*)pG
)->numlines
);
1210 } while (c
!= '\r' && c
!= '\n' && c
!= ' ' && c
!= 'q' && c
!= 'Q');
1214 /* newline was not echoed, so cover up prompt line */
1215 fprintf(stderr
, LoadFarString(HidePrompt
));
1218 if (ToLower(c
) == 'q') {
1223 ((Uz_Globs
*)pG
)->sol
= TRUE
;
1226 } /* end function UzpMorePause() */
1228 #endif /* !WINDLL && !MACOS */
1235 /**************************/
1236 /* Function UzpPassword() */
1237 /**************************/
1239 int UZ_EXP
UzpPassword (pG
, rcnt
, pwbuf
, size
, zfn
, efn
)
1240 zvoid
*pG
; /* pointer to UnZip's internal global vars */
1241 int *rcnt
; /* retry counter */
1242 char *pwbuf
; /* buffer for password */
1243 int size
; /* size of password buffer */
1244 ZCONST
char *zfn
; /* name of zip archive */
1245 ZCONST
char *efn
; /* name of archive entry being processed */
1248 int r
= IZ_PW_ENTERED
;
1253 /* tell picky compilers to shut up about "unused variable" warnings */
1257 if (*rcnt
== 0) { /* First call for current entry */
1259 if ((prompt
= (char *)malloc(2*FILNAMSIZ
+ 15)) != (char *)NULL
) {
1260 sprintf(prompt
, LoadFarString(PasswPrompt
),
1261 FnFilter1(zfn
), FnFilter2(efn
));
1264 m
= (char *)LoadFarString(PasswPrompt2
);
1265 } else { /* Retry call, previous password was wrong */
1268 m
= (char *)LoadFarString(PasswRetry
);
1271 m
= getp(__G__ m
, pwbuf
, size
);
1272 if (prompt
!= (char *)NULL
) {
1275 if (m
== (char *)NULL
) {
1278 else if (*pwbuf
== '\0') {
1279 r
= IZ_PW_CANCELALL
;
1284 /* tell picky compilers to shut up about "unused variable" warnings */
1285 pG
= pG
; rcnt
= rcnt
; pwbuf
= pwbuf
; size
= size
; zfn
= zfn
; efn
= efn
;
1287 return IZ_PW_ERROR
; /* internal error; function should never get called */
1290 } /* end function UzpPassword() */
1296 /**********************/
1297 /* Function handler() */
1298 /**********************/
1300 void handler(signal
) /* upon interrupt, turn on echo and exit cleanly */
1305 #if !(defined(SIGBUS) || defined(SIGSEGV)) /* add a newline if not at */
1306 (*G
.message
)((zvoid
*)&G
, slide
, 0L, 0x41); /* start of line (to stderr; */
1307 #endif /* slide[] should be safe) */
1312 if (signal
== SIGBUS
) {
1313 Info(slide
, 0x421, ((char *)slide
, LoadFarString(ZipfileCorrupt
),
1321 if (signal
== SIGSEGV
) {
1322 Info(slide
, 0x421, ((char *)slide
, LoadFarString(ZipfileCorrupt
),
1323 "segmentation violation"));
1327 #endif /* SIGSEGV */
1329 /* probably ctrl-C */
1331 #if defined(AMIGA) && defined(__SASC)
1334 EXIT(IZ_CTRLC
); /* was EXIT(0), then EXIT(PK_ERR) */
1337 #endif /* !WINDLL */
1342 #if (!defined(VMS) && !defined(CMS_MVS))
1343 #if (!defined(OS2) || defined(TIMESTAMP))
1345 #if (!defined(HAVE_MKTIME) || defined(AMIGA) || defined(WIN32))
1346 /* also used in amiga/filedate.c and win32/win32.c */
1347 ZCONST ush ydays
[] =
1348 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
1351 /*******************************/
1352 /* Function dos_to_unix_time() */ /* used for freshening/updating/timestamps */
1353 /*******************************/
1355 time_t dos_to_unix_time(dosdatetime
)
1362 ZCONST
time_t now
= time(NULL
);
1364 # define YRBASE 1900
1366 tm
= localtime(&now
);
1367 tm
->tm_isdst
= -1; /* let mktime determine if DST is in effect */
1370 tm
->tm_year
= ((int)(dosdatetime
>> 25) & 0x7f) + (1980 - YRBASE
);
1371 tm
->tm_mon
= ((int)(dosdatetime
>> 21) & 0x0f) - 1;
1372 tm
->tm_mday
= ((int)(dosdatetime
>> 16) & 0x1f);
1375 tm
->tm_hour
= (int)((unsigned)dosdatetime
>> 11) & 0x1f;
1376 tm
->tm_min
= (int)((unsigned)dosdatetime
>> 5) & 0x3f;
1377 tm
->tm_sec
= (int)((unsigned)dosdatetime
<< 1) & 0x3e;
1379 m_time
= mktime(tm
);
1380 NATIVE_TO_TIMET(m_time
) /* NOP unless MSC 7.0 or Macintosh */
1381 TTrace((stderr
, " final m_time = %lu\n", (ulg
)m_time
));
1383 #else /* !HAVE_MKTIME */
1385 int yr
, mo
, dy
, hh
, mm
, ss
;
1387 # define YRBASE 1900
1391 # define YRBASE 1970
1395 #if (!defined(MACOS) && !defined(RISCOS) && !defined(QDOS) && !defined(TANDEM))
1397 TIME_ZONE_INFORMATION tzinfo
;
1400 #ifndef BSD4_4 /* GRR: change to !defined(MODERN) ? */
1401 #if (defined(BSD) || defined(MTS) || defined(__GO32__))
1403 #else /* !(BSD || MTS || __GO32__) */
1404 #ifdef DECLARE_TIMEZONE
1405 extern time_t timezone
;
1407 #endif /* ?(BSD || MTS || __GO32__) */
1408 #endif /* !BSD4_4 */
1410 #endif /* !MACOS && !RISCOS && !QDOS && !TANDEM */
1411 #endif /* ?TOPS20 */
1415 yr
= ((int)(dosdatetime
>> 25) & 0x7f) + (1980 - YRBASE
);
1416 mo
= ((int)(dosdatetime
>> 21) & 0x0f) - 1;
1417 dy
= ((int)(dosdatetime
>> 16) & 0x1f) - 1;
1420 hh
= (int)((unsigned)dosdatetime
>> 11) & 0x1f;
1421 mm
= (int)((unsigned)dosdatetime
>> 5) & 0x3f;
1422 ss
= (int)((unsigned)dosdatetime
& 0x1f) * 2;
1425 tmx
= (struct tmx
*)malloc(sizeof(struct tmx
));
1426 sprintf (temp
, "%02d/%02d/%02d %02d:%02d:%02d", mo
+1, dy
+1, yr
, hh
, mm
, ss
);
1427 time_parse(temp
, tmx
, (char *)0);
1428 m_time
= time_make(tmx
);
1433 /*---------------------------------------------------------------------------
1434 Calculate the number of seconds since the epoch, usually 1 January 1970.
1435 ---------------------------------------------------------------------------*/
1437 /* leap = # of leap yrs from YRBASE up to but not including current year */
1438 leap
= ((yr
+ YRBASE
- 1) / 4); /* leap year base factor */
1440 /* calculate days from BASE to this year and add expired days this year */
1441 days
= (yr
* 365) + (leap
- 492) + ydays
[mo
];
1443 /* if year is a leap year and month is after February, add another day */
1444 if ((mo
> 1) && ((yr
+YRBASE
)%4
== 0) && ((yr
+YRBASE
) != 2100))
1445 ++days
; /* OK through 2199 */
1447 /* convert date & time to seconds relative to 00:00:00, 01/01/YRBASE */
1448 m_time
= (time_t)((unsigned long)(days
+ dy
) * 86400L +
1449 (unsigned long)hh
* 3600L +
1450 (unsigned long)(mm
* 60 + ss
));
1451 /* - 1; MS-DOS times always rounded up to nearest even second */
1452 TTrace((stderr
, "dos_to_unix_time:\n"));
1453 TTrace((stderr
, " m_time before timezone = %lu\n", (ulg
)m_time
));
1455 /*---------------------------------------------------------------------------
1456 Adjust for local standard timezone offset.
1457 ---------------------------------------------------------------------------*/
1459 #if (!defined(MACOS) && !defined(RISCOS) && !defined(QDOS) && !defined(TANDEM))
1461 /* account for timezone differences */
1462 res
= GetTimeZoneInformation(&tzinfo
);
1463 if (res
!= TIME_ZONE_ID_UNKNOWN
)
1465 m_time
+= 60*(tzinfo
.Bias
);
1467 #if (defined(BSD) || defined(MTS) || defined(__GO32__))
1469 if ( (dosdatetime
>= DOSTIME_2038_01_18
) &&
1470 (m_time
< (time_t)0x70000000L
) )
1471 m_time
= U_TIME_T_MAX
; /* saturate in case of (unsigned) overflow */
1472 if (m_time
< (time_t)0L) /* a converted DOS time cannot be negative */
1473 m_time
= S_TIME_T_MAX
; /* -> saturate at max signed time_t value */
1474 if ((tm
= localtime(&m_time
)) != (struct tm
*)NULL
)
1475 m_time
-= tm
->tm_gmtoff
; /* sec. EAST of GMT: subtr. */
1476 #else /* !(BSD4_4 */
1477 ftime(&tbp
); /* get `timezone' */
1478 m_time
+= tbp
.timezone
* 60L; /* seconds WEST of GMT: add */
1479 #endif /* ?(BSD4_4 || __EMX__) */
1480 #else /* !(BSD || MTS || __GO32__) */
1481 /* tzset was already called at start of process_zipfiles() */
1482 /* tzset(); */ /* set `timezone' variable */
1483 #ifndef __BEOS__ /* BeOS DR8 has no timezones... */
1484 m_time
+= timezone
; /* seconds WEST of GMT: add */
1486 #endif /* ?(BSD || MTS || __GO32__) */
1488 TTrace((stderr
, " m_time after timezone = %lu\n", (ulg
)m_time
));
1490 /*---------------------------------------------------------------------------
1491 Adjust for local daylight savings (summer) time.
1492 ---------------------------------------------------------------------------*/
1494 #ifndef BSD4_4 /* (DST already added to tm_gmtoff, so skip tm_isdst) */
1495 if ( (dosdatetime
>= DOSTIME_2038_01_18
) &&
1496 (m_time
< (time_t)0x70000000L
) )
1497 m_time
= U_TIME_T_MAX
; /* saturate in case of (unsigned) overflow */
1498 if (m_time
< (time_t)0L) /* a converted DOS time cannot be negative */
1499 m_time
= S_TIME_T_MAX
; /* -> saturate at max signed time_t value */
1500 TIMET_TO_NATIVE(m_time
) /* NOP unless MSC 7.0 or Macintosh */
1501 if (((tm
= localtime((time_t *)&m_time
)) != NULL
) && tm
->tm_isdst
)
1503 m_time
+= 60L * tzinfo
.DaylightBias
; /* adjust with DST bias */
1505 m_time
+= 60L * tzinfo
.StandardBias
; /* add StdBias (normally 0) */
1507 m_time
-= 60L * 60L; /* adjust for daylight savings time */
1509 NATIVE_TO_TIMET(m_time
) /* NOP unless MSC 7.0 or Macintosh */
1510 TTrace((stderr
, " m_time after DST = %lu\n", (ulg
)m_time
));
1511 #endif /* !BSD4_4 */
1515 #endif /* !MACOS && !RISCOS && !QDOS && !TANDEM */
1516 #endif /* ?TOPS20 */
1518 #endif /* ?HAVE_MKTIME */
1520 if ( (dosdatetime
>= DOSTIME_2038_01_18
) &&
1521 (m_time
< (time_t)0x70000000L
) )
1522 m_time
= U_TIME_T_MAX
; /* saturate in case of (unsigned) overflow */
1523 if (m_time
< (time_t)0L) /* a converted DOS time cannot be negative */
1524 m_time
= S_TIME_T_MAX
; /* -> saturate at max signed time_t value */
1528 } /* end function dos_to_unix_time() */
1530 #endif /* !OS2 || TIMESTAMP */
1531 #endif /* !VMS && !CMS_MVS */
1535 #if (!defined(VMS) && !defined(OS2) && !defined(CMS_MVS))
1537 /******************************/
1538 /* Function check_for_newer() */ /* used for overwriting/freshening/updating */
1539 /******************************/
1541 int check_for_newer(__G__ filename
) /* return 1 if existing file is newer */
1542 __GDEF
/* or equal; 0 if older; -1 if doesn't */
1543 char *filename
; /* exist yet */
1545 time_t existing
, archive
;
1546 #ifdef USE_EF_UT_TIME
1550 long dyy
, dmm
, ddd
, dhh
, dmin
, dss
;
1553 dyy
= (lrec
.last_mod_dos_datetime
>> 25) + 1980;
1554 dmm
= (lrec
.last_mod_dos_datetime
>> 21) & 0x0f;
1555 ddd
= (lrec
.last_mod_dos_datetime
>> 16) & 0x1f;
1556 dhh
= (lrec
.last_mod_dos_datetime
>> 11) & 0x1f;
1557 dmin
= (lrec
.last_mod_dos_datetime
>> 5) & 0x3f;
1558 dss
= (lrec
.last_mod_dos_datetime
& 0x1f) * 2;
1560 /* under AOS/VS, file times can only be set at creation time,
1561 * with the info in a special DG format. Make sure we can create
1562 * it here - we delete it later & re-create it, whether or not
1565 if (!zvs_create(filename
, (((ulg
)dgdate(dmm
, ddd
, dyy
)) << 16) |
1566 (dhh
*1800L + dmin
*30L + dss
/2L), -1L, -1L, (char *) -1, -1, -1, -1))
1567 return DOES_NOT_EXIST
;
1570 Trace((stderr
, "check_for_newer: doing stat(%s)\n", FnFilter1(filename
)));
1571 if (SSTAT(filename
, &G
.statbuf
)) {
1573 "check_for_newer: stat(%s) returns %d: file does not exist\n",
1574 FnFilter1(filename
), SSTAT(filename
, &G
.statbuf
)));
1576 Trace((stderr
, "check_for_newer: doing lstat(%s)\n",
1577 FnFilter1(filename
)));
1578 /* GRR OPTION: could instead do this test ONLY if G.symlnk is true */
1579 if (lstat(filename
, &G
.statbuf
) == 0) {
1581 "check_for_newer: lstat(%s) returns 0: symlink does exist\n",
1582 FnFilter1(filename
)));
1583 if (QCOND2
&& !uO
.overwrite_all
)
1584 Info(slide
, 0, ((char *)slide
, LoadFarString(FileIsSymLink
),
1585 FnFilter1(filename
), " with no real file"));
1586 return EXISTS_AND_OLDER
; /* symlink dates are meaningless */
1588 #endif /* SYMLINKS */
1589 return DOES_NOT_EXIST
;
1591 Trace((stderr
, "check_for_newer: stat(%s) returns 0: file exists\n",
1592 FnFilter1(filename
)));
1595 /* GRR OPTION: could instead do this test ONLY if G.symlnk is true */
1596 if (lstat(filename
, &G
.statbuf
) == 0 && S_ISLNK(G
.statbuf
.st_mode
)) {
1597 Trace((stderr
, "check_for_newer: %s is a symbolic link\n",
1598 FnFilter1(filename
)));
1599 if (QCOND2
&& !uO
.overwrite_all
)
1600 Info(slide
, 0, ((char *)slide
, LoadFarString(FileIsSymLink
),
1601 FnFilter1(filename
), ""));
1602 return EXISTS_AND_OLDER
; /* symlink dates are meaningless */
1604 #endif /* SYMLINKS */
1606 NATIVE_TO_TIMET(G
.statbuf
.st_mtime
) /* NOP unless MSC 7.0 or Macintosh */
1608 #ifdef USE_EF_UT_TIME
1609 /* The `Unix extra field mtime' should be used for comparison with the
1610 * time stamp of the existing file >>>ONLY<<< when the EF info is also
1611 * used to set the modification time of the extracted file.
1613 if (G
.extra_field
&&
1617 (ef_scan_for_izux(G
.extra_field
, G
.lrec
.extra_field_length
, 0,
1618 G
.lrec
.last_mod_dos_datetime
, &z_utime
, NULL
)
1621 TTrace((stderr
, "check_for_newer: using Unix extra field mtime\n"));
1622 existing
= G
.statbuf
.st_mtime
;
1623 archive
= z_utime
.mtime
;
1625 /* round up existing filetime to nearest 2 seconds for comparison,
1626 * but saturate in case of arithmetic overflow
1628 existing
= ((G
.statbuf
.st_mtime
& 1) &&
1629 (G
.statbuf
.st_mtime
+ 1 > G
.statbuf
.st_mtime
)) ?
1630 G
.statbuf
.st_mtime
+ 1 : G
.statbuf
.st_mtime
;
1631 archive
= dos_to_unix_time(G
.lrec
.last_mod_dos_datetime
);
1633 #else /* !USE_EF_UT_TIME */
1634 /* round up existing filetime to nearest 2 seconds for comparison,
1635 * but saturate in case of arithmetic overflow
1637 existing
= ((G
.statbuf
.st_mtime
& 1) &&
1638 (G
.statbuf
.st_mtime
+ 1 > G
.statbuf
.st_mtime
)) ?
1639 G
.statbuf
.st_mtime
+ 1 : G
.statbuf
.st_mtime
;
1640 archive
= dos_to_unix_time(G
.lrec
.last_mod_dos_datetime
);
1641 #endif /* ?USE_EF_UT_TIME */
1643 TTrace((stderr
, "check_for_newer: existing %lu, archive %lu, e-a %ld\n",
1644 (ulg
)existing
, (ulg
)archive
, (long)(existing
-archive
)));
1646 return (existing
>= archive
);
1648 } /* end function check_for_newer() */
1650 #endif /* !VMS && !OS2 && !CMS_MVS */
1656 /************************/
1657 /* Function do_string() */
1658 /************************/
1660 int do_string(__G__ len
, option
) /* return PK-type error code */
1662 unsigned int len
; /* without prototype, ush converted to this */
1665 long comment_bytes_left
, block_length
;
1669 char tmp_fnote
[2 * AMIGA_FILENOTELEN
]; /* extra room for squozen chars */
1673 /*---------------------------------------------------------------------------
1674 This function processes arbitrary-length (well, usually) strings. Four
1675 options are allowed: SKIP, wherein the string is skipped (pretty logical,
1676 eh?); DISPLAY, wherein the string is printed to standard output after un-
1677 dergoing any necessary or unnecessary character conversions; DS_FN,
1678 wherein the string is put into the filename[] array after undergoing ap-
1679 propriate conversions (including case-conversion, if that is indicated:
1680 see the global variable pInfo->lcflag); and EXTRA_FIELD, wherein the
1681 `string' is assumed to be an extra field and is copied to the (freshly
1682 malloced) buffer G.extra_field. The third option should be OK since
1683 filename is dimensioned at 1025, but we check anyway.
1685 The string, by the way, is assumed to start at the current file-pointer
1686 position; its length is given by len. So start off by checking length
1687 of string: if zero, we're already done.
1688 ---------------------------------------------------------------------------*/
1696 * First case: print string on standard output. First set loop vari-
1697 * ables, then loop through the comment in chunks of OUTBUFSIZ bytes,
1698 * converting formats and printing as we go. The second half of the
1699 * loop conditional was added because the file might be truncated, in
1700 * which case comment_bytes_left will remain at some non-zero value for
1701 * all time. outbuf and slide are used as scratch buffers because they
1702 * are available (we should be either before or in between any file pro-
1708 comment_bytes_left
= len
;
1709 block_length
= OUTBUFSIZ
; /* for the while statement, first time */
1710 while (comment_bytes_left
> 0 && block_length
> 0) {
1711 register uch
*p
= G
.outbuf
;
1712 register uch
*q
= G
.outbuf
;
1714 if ((block_length
= readbuf(__G__ (char *)G
.outbuf
,
1715 (unsigned) MIN((long)OUTBUFSIZ
, comment_bytes_left
))) == 0)
1717 comment_bytes_left
-= block_length
;
1719 /* this is why we allocated an extra byte for outbuf: terminate
1720 * with zero (ASCIIZ) */
1721 G
.outbuf
[(unsigned)block_length
] = '\0';
1723 /* remove all ASCII carriage returns from comment before printing
1724 * (since used before A_TO_N(), check for CR instead of '\r')
1731 /* could check whether (p - outbuf) == block_length here */
1734 if (option
== DISPL_8
) {
1735 /* translate the text coded in the entry's host-dependent
1736 "extended ASCII" charset into the compiler's (system's)
1737 internal text code page */
1738 Ext_ASCII_TO_Native((char *)G
.outbuf
, G
.pInfo
->hostnum
,
1739 G
.crec
.version_made_by
[0]);
1741 /* translate to ANSI (RTL internal codepage may be OEM) */
1742 INTERN_TO_ISO((char *)G
.outbuf
, (char *)G
.outbuf
);
1745 /* Win9x console always uses OEM character coding, and
1746 WinNT console is set to OEM charset by default, too */
1747 INTERN_TO_OEM((char *)G
.outbuf
, (char *)G
.outbuf
);
1749 #endif /* ?WINDLL */
1751 A_TO_N(G
.outbuf
); /* translate string to native */
1755 /* ran out of local mem -- had to cheat */
1756 win_fprintf((zvoid
*)&G
, stdout
, len
, (char *)G
.outbuf
);
1757 win_fprintf((zvoid
*)&G
, stdout
, 2, (char *)"\n\n");
1759 #ifdef NOANSIFILT /* GRR: can ANSI be used with EBCDIC? */
1760 (*G
.message
)((zvoid
*)&G
, G
.outbuf
, (ulg
)(q
-G
.outbuf
), 0);
1761 #else /* ASCII, filter out ANSI escape sequences and handle ^S (pause) */
1767 if (*p
== 0x1B) { /* ASCII escape char */
1770 } else if (*p
== 0x13) { /* ASCII ^S (pause) */
1772 if (p
[1] == LF
) /* ASCII LF */
1774 else if (p
[1] == CR
&& p
[2] == LF
) { /* ASCII CR LF */
1780 if ((unsigned)(q
-slide
) > WSIZE
-3 || pause
) { /* flush */
1781 (*G
.message
)((zvoid
*)&G
, slide
, (ulg
)(q
-slide
), 0);
1783 if (pause
&& G
.extract_flag
) /* don't pause for list/test */
1784 (*G
.mpause
)((zvoid
*)&G
, LoadFarString(QuitPrompt
), 0);
1787 (*G
.message
)((zvoid
*)&G
, slide
, (ulg
)(q
-slide
), 0);
1788 #endif /* ?NOANSIFILT */
1789 #endif /* ?WINDLL */
1791 /* add '\n' if not at start of line */
1792 (*G
.message
)((zvoid
*)&G
, slide
, 0L, 0x40);
1796 * Second case: read string into filename[] array. The filename should
1797 * never ever be longer than FILNAMSIZ-1 (1024), but for now we'll check,
1803 if (len
>= FILNAMSIZ
) {
1804 Info(slide
, 0x401, ((char *)slide
,
1805 LoadFarString(FilenameTooLongTrunc
)));
1807 extra_len
= (ush
)(len
- FILNAMSIZ
+ 1);
1808 len
= FILNAMSIZ
- 1;
1810 if (readbuf(__G__ G
.filename
, len
) == 0)
1812 G
.filename
[len
] = '\0'; /* terminate w/zero: ASCIIZ */
1814 /* translate the Zip entry filename coded in host-dependent "extended
1815 ASCII" into the compiler's (system's) internal text code page */
1816 Ext_ASCII_TO_Native(G
.filename
, G
.pInfo
->hostnum
,
1817 G
.crec
.version_made_by
[0]);
1819 if (G
.pInfo
->lcflag
) /* replace with lowercase filename */
1820 TOLOWER(G
.filename
, G
.filename
);
1822 if (G
.pInfo
->vollabel
&& len
> 8 && G
.filename
[8] == '.') {
1823 char *p
= G
.filename
+8;
1825 p
[-1] = *p
; /* disk label, and 8th char is dot: remove dot */
1828 if (!extra_len
) /* we're done here */
1832 * We truncated the filename, so print what's left and then fall
1833 * through to the SKIP routine.
1835 Info(slide
, 0x401, ((char *)slide
, "[ %s ]\n", FnFilter1(G
.filename
)));
1837 /* FALL THROUGH... */
1840 * Third case: skip string, adjusting readbuf's internal variables
1841 * as necessary (and possibly skipping to and reading a new block of
1846 /* cur_zipfile_bufstart already takes account of extra_bytes, so don't
1847 * correct for it twice: */
1848 ZLSEEK(G
.cur_zipfile_bufstart
- G
.extra_bytes
+
1849 (G
.inptr
-G
.inbuf
) + len
)
1853 * Fourth case: assume we're at the start of an "extra field"; malloc
1854 * storage for it and read data into the allocated space.
1858 if (G
.extra_field
!= (uch
*)NULL
)
1859 free(G
.extra_field
);
1860 if ((G
.extra_field
= (uch
*)malloc(len
)) == (uch
*)NULL
) {
1861 Info(slide
, 0x401, ((char *)slide
, LoadFarString(ExtraFieldTooLong
),
1863 /* cur_zipfile_bufstart already takes account of extra_bytes,
1864 * so don't correct for it twice: */
1865 ZLSEEK(G
.cur_zipfile_bufstart
- G
.extra_bytes
+
1866 (G
.inptr
-G
.inbuf
) + len
)
1868 if (readbuf(__G__ (char *)G
.extra_field
, len
) == 0)
1874 * Fifth case, for the Amiga only: take the comment that would ordinarily
1875 * be skipped over, and turn it into a 79 character string that will be
1876 * attached to the file as a "filenote" after it is extracted.
1880 if ((extra_len
= readbuf(__G__ tmp_fnote
, (unsigned)
1881 MIN(len
, 2 * AMIGA_FILENOTELEN
- 1))) == 0)
1883 if ((len
-= extra_len
) > 0) /* treat remainder as in case SKIP: */
1884 ZLSEEK(G
.cur_zipfile_bufstart
- G
.extra_bytes
1885 + (G
.inptr
- G
.inbuf
) + len
)
1886 /* convert multi-line text into single line with no ctl-chars: */
1887 tmp_fnote
[extra_len
] = '\0';
1888 while ((short int) --extra_len
>= 0)
1889 if ((unsigned) tmp_fnote
[extra_len
] < ' ')
1890 if (tmp_fnote
[extra_len
+1] == ' ') /* no excess */
1891 strcpy(tmp_fnote
+extra_len
, tmp_fnote
+extra_len
+1);
1893 tmp_fnote
[extra_len
] = ' ';
1894 tmp_fnote
[AMIGA_FILENOTELEN
- 1] = '\0';
1895 if (G
.filenotes
[G
.filenote_slot
])
1896 free(G
.filenotes
[G
.filenote_slot
]); /* should not happen */
1897 G
.filenotes
[G
.filenote_slot
] = NULL
;
1899 if (!(G
.filenotes
[G
.filenote_slot
] = malloc(strlen(tmp_fnote
)+1)))
1901 strcpy(G
.filenotes
[G
.filenote_slot
], tmp_fnote
);
1906 } /* end switch (option) */
1910 } /* end function do_string() */
1916 /***********************/
1917 /* Function makeword() */
1918 /***********************/
1924 * Convert Intel style 'short' integer to non-Intel non-16-bit
1925 * host format. This routine also takes care of byte-ordering.
1927 return (ush
)((b
[1] << 8) | b
[0]);
1934 /***********************/
1935 /* Function makelong() */
1936 /***********************/
1942 * Convert intel style 'long' variable to non-Intel non-16-bit
1943 * host format. This routine also takes care of byte-ordering.
1945 return (((ulg
)sig
[3]) << 24)
1946 + (((ulg
)sig
[2]) << 16)
1947 + (((ulg
)sig
[1]) << 8)
1956 /**********************/
1957 /* Function str2iso() */
1958 /**********************/
1960 char *str2iso(dst
, src
)
1961 char *dst
; /* destination buffer */
1962 register ZCONST
char *src
; /* source string */
1964 #ifdef INTERN_TO_ISO
1965 INTERN_TO_ISO(src
, dst
);
1968 register char *dstp
= dst
;
1971 c
= (uch
)foreign(*src
++);
1972 *dstp
++ = (char)ASCII2ISO(c
);
1973 } while (c
!= '\0');
1978 #endif /* NEED_STR2ISO */
1982 /**********************/
1983 /* Function str2oem() */
1984 /**********************/
1986 char *str2oem(dst
, src
)
1987 char *dst
; /* destination buffer */
1988 register ZCONST
char *src
; /* source string */
1990 #ifdef INTERN_TO_OEM
1991 INTERN_TO_OEM(src
, dst
);
1994 register char *dstp
= dst
;
1997 c
= (uch
)foreign(*src
++);
1998 *dstp
++ = (char)ASCII2OEM(c
);
1999 } while (c
!= '\0');
2004 #endif /* NEED_STR2OEM */
2009 #ifdef ZMEM /* memset/memcmp/memcpy for systems without either them or */
2010 /* bzero/bcmp/bcopy */
2011 /* (no known systems as of 960211) */
2013 /*********************/
2014 /* Function memset() */
2015 /*********************/
2017 zvoid
*memset(buf
, init
, len
)
2018 register zvoid
*buf
; /* buffer location */
2019 register int init
; /* initializer character */
2020 register unsigned int len
; /* length of the buffer */
2026 *((char *)buf
++) = (char)init
;
2032 /*********************/
2033 /* Function memcmp() */
2034 /*********************/
2036 int memcmp(b1
, b2
, len
)
2037 register ZCONST zvoid
*b1
;
2038 register ZCONST zvoid
*b2
;
2039 register unsigned int len
;
2044 if ((c
= (int)(*((ZCONST
unsigned char *)b1
)++) -
2045 (int)(*((ZCONST
unsigned char *)b2
)++)) != 0)
2053 /*********************/
2054 /* Function memcpy() */
2055 /*********************/
2057 zvoid
*memcpy(dst
, src
, len
)
2058 register zvoid
*dst
;
2059 register ZCONST zvoid
*src
;
2060 register unsigned int len
;
2066 *((char *)dst
)++ = *((ZCONST
char *)src
)++;
2076 /************************/
2077 /* Function zstrnicmp() */
2078 /************************/
2080 int zstrnicmp(s1
, s2
, n
)
2081 register ZCONST
char *s1
, *s2
;
2082 register unsigned n
;
2084 for (; n
> 0; --n
, ++s1
, ++s2
) {
2086 if (ToLower(*s1
) != ToLower(*s2
))
2087 /* test includes early termination of one string */
2088 return (ToLower(*s1
) < ToLower(*s2
))? -1 : 1;
2090 if (*s1
== '\0') /* both strings terminate early */
2100 #ifdef REGULUS /* returns the inode number on success(!)...argh argh argh */
2103 /********************/
2104 /* Function zstat() */
2105 /********************/
2111 return (stat(p
,s
) >= 0? 0 : (-1));
2114 #endif /* REGULUS */
2122 /*******************************/
2123 /* Function fLoadFarString() */ /* (and friends...) */
2124 /*******************************/
2126 char *fLoadFarString(__GPRO__
const char Far
*sz
)
2128 (void)zfstrcpy(G
.rgchBigBuffer
, sz
);
2129 return G
.rgchBigBuffer
;
2132 char *fLoadFarStringSmall(__GPRO__
const char Far
*sz
)
2134 (void)zfstrcpy(G
.rgchSmallBuffer
, sz
);
2135 return G
.rgchSmallBuffer
;
2138 char *fLoadFarStringSmall2(__GPRO__
const char Far
*sz
)
2140 (void)zfstrcpy(G
.rgchSmallBuffer2
, sz
);
2141 return G
.rgchSmallBuffer2
;
2147 #if (!defined(_MSC_VER) || (_MSC_VER < 600))
2148 /*************************/
2149 /* Function zfstrcpy() */ /* portable clone of _fstrcpy() */
2150 /*************************/
2152 char Far
* Far
zfstrcpy(char Far
*s1
, const char Far
*s2
)
2156 while ((*s1
++ = *s2
++) != '\0');
2159 #endif /* !_MSC_VER || (_MSC_VER < 600) */
2161 #endif /* SMALL_MEM */