2 Copyright (c) 1990-2002 Info-ZIP. All rights reserved.
4 See the accompanying file LICENSE, version 2000-Apr-09 or later
5 (the contents of which are also included in unzip.h) for terms of use.
6 If, for some reason, all these files are missing, the Info-ZIP license
7 also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
9 /*---------------------------------------------------------------------------
13 This file contains routines for doing direct but relatively generic input/
14 output, file-related sorts of things, plus some miscellaneous stuff. Most
15 of the stuff has to do with opening, closing, reading and/or writing files.
17 Contains: open_input_file()
18 open_outfile() (not: VMS, AOS/VS, CMSMVS, MACOS, TANDEM)
20 defer_leftover_input()
26 is_vms_varlen_txt() (non-VMS, VMS_TEXT_CONV only)
27 disk_error() (non-VMS)
29 UzpMessageNull() (DLL only)
32 UzpPassword() (non-WINDLL)
34 dos_to_unix_time() (non-VMS, non-VM/CMS, non-MVS)
35 check_for_newer() (non-VMS, non-OS/2, non-VM/CMS, non-MVS)
39 str2iso() (CRYPT && NEED_STR2ISO, only)
40 str2oem() (CRYPT && NEED_STR2OEM, only)
43 zstrnicmp() (NO_STRNICMP only)
44 zstat() (REGULUS only)
45 plastchar() (_MBCS only)
46 uzmbschr() (_MBCS && NEED_UZMBSCHR, only)
47 uzmbsrchr() (_MBCS && NEED_UZMBSRCHR, only)
48 fLoadFarString() (SMALL_MEM only)
49 fLoadFarStringSmall() (SMALL_MEM only)
50 fLoadFarStringSmall2() (SMALL_MEM only)
51 zfstrcpy() (SMALL_MEM only)
53 ---------------------------------------------------------------------------*/
56 #define __FILEIO_C /* identifies this source module */
57 #define UNZIP_INTERNAL
60 # include "windll/windll.h"
66 /* setup of codepage conversion for decryption passwords */
68 # if (defined(CRYP_USES_ISO2OEM) && !defined(IZ_ISO2OEM_ARRAY))
69 # define IZ_ISO2OEM_ARRAY /* pull in iso2oem[] table */
71 # if (defined(CRYP_USES_OEM2ISO) && !defined(IZ_OEM2ISO_ARRAY))
72 # define IZ_OEM2ISO_ARRAY /* pull in oem2iso[] table */
75 #include "ebcdic.h" /* definition/initialization of ebcdic[] */
79 Note: Under Windows, the maximum size of the buffer that can be used
80 with any of the *printf calls is 16,384, so win_fprintf was used to
81 feed the fprintf clone no more than 16K chunks at a time. This should
82 be valid for anything up to 64K (and probably beyond, assuming your
83 buffers are that big).
86 # define WriteError(buf,len,strm) \
87 (win_fprintf(pG, strm, (extent)len, (char far *)buf) != (int)(len))
90 # define WriteError(buf,len,strm) \
91 ((extent)fwrite((char *)(buf),1,(extent)(len),strm) != (extent)(len))
93 # define WriteError(buf,len,strm) \
94 ((extent)write(fileno(strm),(char *)(buf),(extent)(len)) != (extent)(len))
98 #if (defined(USE_DEFLATE64) && defined(__16BIT__))
99 static int partflush
OF((__GPRO__ uch
*rawbuf
, ulg size
, int unshrink
));
102 static int is_vms_varlen_txt
OF((__GPRO__ uch
*ef_buf
, unsigned ef_len
));
104 static int disk_error
OF((__GPRO
));
107 /****************************/
108 /* Strings used in fileio.c */
109 /****************************/
111 static ZCONST
char Far CannotOpenZipfile
[] =
112 "error: cannot open zipfile [ %s ]\n";
114 #if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS))
115 #if (!defined(TANDEM))
116 #if (defined(BEO_THS_UNX) || defined(DOS_FLX_NLM_OS2_W32))
117 static ZCONST
char Far CannotDeleteOldFile
[] =
118 "error: cannot delete old %s\n";
120 static ZCONST
char Far CannotRenameOldFile
[] =
121 "error: cannot rename old %s\n";
122 static ZCONST
char Far BackupSuffix
[] = "~";
124 #endif /* BEO_THS_UNX || DOS_FLX_NLM_OS2_W32 */
125 #ifdef NOVELL_BUG_FAILSAFE
126 static ZCONST
char Far NovellBug
[] =
127 "error: %s: stat() says does not exist, but fopen() found anyway\n";
129 static ZCONST
char Far CannotCreateFile
[] = "error: cannot create %s\n";
131 #endif /* !VMS && !AOS_VS && !CMS_MVS && !MACOS */
133 static ZCONST
char Far ReadError
[] = "error: zipfile read error\n";
134 static ZCONST
char Far FilenameTooLongTrunc
[] =
135 "warning: filename too long--truncating.\n";
136 static ZCONST
char Far ExtraFieldTooLong
[] =
137 "warning: extra field too long (%d). Ignoring...\n";
140 static ZCONST
char Far DiskFullQuery
[] =
141 "%s: write error (disk full?).\n";
143 static ZCONST
char Far DiskFullQuery
[] =
144 "%s: write error (disk full?). Continue? (y/n/^C) ";
145 static ZCONST
char Far ZipfileCorrupt
[] =
146 "error: zipfile probably corrupt (%s)\n";
148 static ZCONST
char Far FileIsSymLink
[] =
149 "%s exists and is a symbolic link%s.\n";
152 static ZCONST
char Far MorePrompt
[] = "--More--(%lu)";
154 static ZCONST
char Far QuitPrompt
[] =
155 "--- Press `Q' to quit, or any other key to continue ---";
156 static ZCONST
char Far HidePrompt
[] = /* "\r \r"; */
160 /* SPC: are names on MacOS REALLY so much longer than elsewhere ??? */
161 static ZCONST
char Far PasswPrompt
[] = "[%s]\n %s password: ";
163 static ZCONST
char Far PasswPrompt
[] = "[%s] %s password: ";
165 static ZCONST
char Far PasswPrompt2
[] = "Enter password: ";
166 static ZCONST
char Far PasswRetry
[] = "password incorrect--reenter: ";
174 /******************************/
175 /* Function open_input_file() */
176 /******************************/
178 int open_input_file(__G
) /* return 1 if open failed */
182 * open the zipfile for reading and in BINARY mode to prevent cr/lf
183 * translation, which would corrupt the bitstreams
187 G
.zipfd
= open(G
.zipfn
, O_RDONLY
, 0, "ctx=stm");
190 G
.zipfd
= open(G
.zipfn
, 0);
193 G
.zipfd
= vmmvs_open_infile(__G
);
195 #ifdef USE_STRM_INPUT
196 G
.zipfd
= fopen(G
.zipfn
, FOPR
);
197 #else /* !USE_STRM_INPUT */
199 G
.zipfd
= open(G
.zipfn
, O_RDONLY
| O_BINARY
);
201 G
.zipfd
= open(G
.zipfn
, O_RDONLY
);
203 #endif /* ?USE_STRM_INPUT */
204 #endif /* ?CMS_MVS */
208 #ifdef USE_STRM_INPUT
211 /* if (G.zipfd < 0) */ /* no good for Windows CE port */
215 Info(slide
, 0x401, ((char *)slide
, LoadFarString(CannotOpenZipfile
),
221 } /* end function open_input_file() */
226 #if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS))
227 #if (!defined(TANDEM))
229 /***************************/
230 /* Function open_outfile() */
231 /***************************/
233 int open_outfile(__G
) /* return 1 if fail */
238 return (redirect_outfile(__G
) == FALSE
);
241 QFilename(__G__ G
.filename
);
243 #if (defined(DOS_FLX_NLM_OS2_W32) || defined(BEO_THS_UNX))
244 #ifdef BORLAND_STAT_BUG
245 /* Borland 5.0's stat() barfs if the filename has no extension and the
246 * file doesn't exist. */
247 if (access(G
.filename
, 0) == -1) {
248 FILE *tmp
= fopen(G
.filename
, "wb+");
250 /* file doesn't exist, so create a dummy file to keep stat() from
251 * failing (will be over-written anyway) */
252 fputc('0', tmp
); /* just to have something in the file */
255 #endif /* BORLAND_STAT_BUG */
257 if (SSTAT(G
.filename
, &G
.statbuf
) == 0 || lstat(G
.filename
,&G
.statbuf
) == 0)
259 if (SSTAT(G
.filename
, &G
.statbuf
) == 0)
260 #endif /* ?SYMLINKS */
262 Trace((stderr
, "open_outfile: stat(%s) returns 0: file exists\n",
263 FnFilter1(G
.filename
)));
265 if (uO
.B_flag
) { /* do backup */
268 int blen
, flen
, tlen
;
270 blen
= strlen(BackupSuffix
);
271 flen
= strlen(G
.filename
);
272 tlen
= flen
+ blen
+ 6; /* includes space for 5 digits */
273 if (tlen
>= FILNAMSIZ
) { /* in case name is too long, truncate */
274 tname
= (char *)malloc(FILNAMSIZ
);
276 return 1; /* in case we run out of space */
277 tlen
= FILNAMSIZ
- 1 - blen
;
278 strcpy(tname
, G
.filename
); /* make backup name */
280 if (flen
> tlen
) flen
= tlen
;
283 tname
= (char *)malloc(tlen
);
285 return 1; /* in case we run out of space */
286 strcpy(tname
, G
.filename
); /* make backup name */
288 strcpy(tname
+flen
, BackupSuffix
);
290 if (IS_OVERWRT_ALL
) {
291 /* If there is a previous backup file, delete it,
292 * otherwise the following rename operation may fail.
294 if (SSTAT(tname
, &tmpstat
) == 0)
297 /* Check if backupname exists, and, if it's true, try
298 * appending numbers of up to 5 digits to the BackupSuffix,
299 * until an unused name is found.
302 char *numtail
= tname
+ flen
+ blen
;
305 switch (tlen
- flen
- blen
- 1) {
306 case 4: maxtail
= 9999; break;
307 case 3: maxtail
= 999; break;
308 case 2: maxtail
= 99; break;
309 case 1: maxtail
= 9; break;
310 case 0: maxtail
= 0; break;
312 /* while filename exists */
313 for (i
= 0; (i
<= maxtail
) && (SSTAT(tname
, &tmpstat
) == 0);)
314 sprintf(numtail
,"%u", ++i
);
317 if (rename(G
.filename
, tname
) != 0) { /* move file */
318 Info(slide
, 0x401, ((char *)slide
,
319 LoadFarString(CannotRenameOldFile
), FnFilter1(G
.filename
)));
323 Trace((stderr
, "open_outfile: %s now renamed into %s\n",
324 FnFilter1(G
.filename
), FnFilter2(tname
)));
327 #endif /* UNIXBACKUP */
329 #ifdef DOS_FLX_OS2_W32
330 if (!(G
.statbuf
.st_mode
& S_IWRITE
)) {
332 "open_outfile: existing file %s is read-only\n",
333 FnFilter1(G
.filename
)));
334 chmod(G
.filename
, S_IREAD
| S_IWRITE
);
335 Trace((stderr
, "open_outfile: %s now writable\n",
336 FnFilter1(G
.filename
)));
338 #endif /* DOS_FLX_OS2_W32 */
340 /* Give the file read/write permission (non-POSIX shortcut) */
341 chmod(G
.filename
, 0);
343 if (unlink(G
.filename
) != 0) {
344 Info(slide
, 0x401, ((char *)slide
,
345 LoadFarString(CannotDeleteOldFile
), FnFilter1(G
.filename
)));
348 Trace((stderr
, "open_outfile: %s now deleted\n",
349 FnFilter1(G
.filename
)));
352 #endif /* DOS_FLX_NLM_OS2_W32 || BEO_THS_UNX */
354 if (SWI_OS_File_7(G
.filename
,0xDEADDEAD,0xDEADDEAD,G
.lrec
.ucsize
)!=NULL
) {
355 Info(slide
, 1, ((char *)slide
, LoadFarString(CannotCreateFile
),
356 FnFilter1(G
.filename
)));
363 if ((tfilnam
= (char *)malloc(2*strlen(G
.filename
)+1)) == (char *)NULL
)
365 strcpy(tfilnam
, G
.filename
);
368 if ((G
.outfile
= fopen(tfilnam
, FOPW
)) == (FILE *)NULL
) {
369 Info(slide
, 1, ((char *)slide
, LoadFarString(CannotCreateFile
),
378 G
.outfile
= fopen(G
.filename
, FOPWT
);
380 G
.outfile
= fopen(G
.filename
, FOPW
);
381 if (G
.outfile
== (FILE *)NULL
) {
382 Info(slide
, 1, ((char *)slide
, LoadFarString(CannotCreateFile
),
383 FnFilter1(G
.filename
)));
388 Info(slide
, 1, ((char *)slide
,
389 "open_outfile: doing fopen(%s) for reading\n", FnFilter1(G
.filename
)));
390 if ((G
.outfile
= fopen(G
.filename
, FOPR
)) == (FILE *)NULL
)
391 Info(slide
, 1, ((char *)slide
,
392 "open_outfile: fopen(%s) for reading failed: does not exist\n",
393 FnFilter1(G
.filename
)));
395 Info(slide
, 1, ((char *)slide
,
396 "open_outfile: fopen(%s) for reading succeeded: file exists\n",
397 FnFilter1(G
.filename
)));
401 #ifdef NOVELL_BUG_FAILSAFE
402 if (G
.dne
&& ((G
.outfile
= fopen(G
.filename
, FOPR
)) != (FILE *)NULL
)) {
403 Info(slide
, 0x401, ((char *)slide
, LoadFarString(NovellBug
),
404 FnFilter1(G
.filename
)));
406 return 1; /* with "./" fix in checkdir(), should never reach here */
408 #endif /* NOVELL_BUG_FAILSAFE */
409 Trace((stderr
, "open_outfile: doing fopen(%s) for writing\n",
410 FnFilter1(G
.filename
)));
411 if ((G
.outfile
= fopen(G
.filename
, FOPW
)) == (FILE *)NULL
) {
412 Info(slide
, 0x401, ((char *)slide
, LoadFarString(CannotCreateFile
),
413 FnFilter1(G
.filename
)));
416 Trace((stderr
, "open_outfile: fopen(%s) for writing succeeded\n",
417 FnFilter1(G
.filename
)));
422 #ifdef DOS_NLM_OS2_W32
423 /* 16-bit MSC: buffer size must be strictly LESS than 32K (WSIZE): bogus */
424 setbuf(G
.outfile
, (char *)NULL
); /* make output unbuffered */
425 #else /* !DOS_NLM_OS2_W32 */
427 #ifdef _IOFBF /* make output fully buffered (works just about like write()) */
428 setvbuf(G
.outfile
, (char *)slide
, _IOFBF
, WSIZE
);
430 setbuf(G
.outfile
, (char *)slide
);
433 #endif /* ?DOS_NLM_OS2_W32 */
434 #endif /* USE_FWRITE */
436 /* preallocate the final file size to prevent file fragmentation */
437 SetFileSize(G
.outfile
, G
.pInfo
->uncompr_size
);
441 } /* end function open_outfile() */
444 #endif /* !VMS && !AOS_VS && !CMS_MVS && !MACOS */
451 * These functions allow NEXTBYTE to function without needing two bounds
452 * checks. Call defer_leftover_input() if you ever have filled G.inbuf
453 * by some means other than readbyte(), and you then want to start using
454 * NEXTBYTE. When going back to processing bytes without NEXTBYTE, call
455 * undefer_input(). For example, extract_or_test_member brackets its
456 * central section that does the decompression with these two functions.
457 * If you need to check the number of bytes remaining in the current
458 * file while using NEXTBYTE, check (G.csize + G.incnt), not G.csize.
461 /****************************/
462 /* function undefer_input() */
463 /****************************/
465 void undefer_input(__G
)
470 if (G
.incnt_leftover
> 0) {
471 /* We know that "(G.csize < MAXINT)" so we can cast G.csize to int:
472 * This condition was checked when G.incnt_leftover was set > 0 in
473 * defer_leftover_input(), and it is NOT allowed to touch G.csize
474 * before calling undefer_input() when (G.incnt_leftover > 0)
475 * (single exception: see read_byte()'s "G.csize <= 0" handling) !!
477 G
.incnt
= G
.incnt_leftover
+ (int)G
.csize
;
478 G
.inptr
= G
.inptr_leftover
- (int)G
.csize
;
479 G
.incnt_leftover
= 0;
480 } else if (G
.incnt
< 0)
482 } /* end function undefer_input() */
488 /***********************************/
489 /* function defer_leftover_input() */
490 /***********************************/
492 void defer_leftover_input(__G
)
495 if ((long)G
.incnt
> G
.csize
) {
496 /* (G.csize < MAXINT), we can safely cast it to int !! */
499 G
.inptr_leftover
= G
.inptr
+ (int)G
.csize
;
500 G
.incnt_leftover
= G
.incnt
- (int)G
.csize
;
501 G
.incnt
= (int)G
.csize
;
503 G
.incnt_leftover
= 0;
505 } /* end function defer_leftover_input() */
511 /**********************/
512 /* Function readbuf() */
513 /**********************/
515 unsigned readbuf(__G__ buf
, size
) /* return number of bytes read into buf */
518 register unsigned size
;
520 register unsigned count
;
526 if ((G
.incnt
= read(G
.zipfd
, (char *)G
.inbuf
, INBUFSIZ
)) == 0)
528 else if (G
.incnt
< 0) {
529 /* another hack, but no real harm copying same thing twice */
530 (*G
.message
)((zvoid
*)&G
,
531 (uch
*)LoadFarString(ReadError
), /* CANNOT use slide */
532 (ulg
)strlen(LoadFarString(ReadError
)), 0x401);
533 return 0; /* discarding some data; better than lock-up */
535 /* buffer ALWAYS starts on a block boundary: */
536 G
.cur_zipfile_bufstart
+= INBUFSIZ
;
539 count
= MIN(size
, (unsigned)G
.incnt
);
540 memcpy(buf
, G
.inptr
, count
);
548 } /* end function readbuf() */
554 /***********************/
555 /* Function readbyte() */
556 /***********************/
558 int readbyte(__G
) /* refill inbuf and return a byte if available, else EOF */
564 G
.csize
--; /* for tests done after exploding */
569 if ((G
.incnt
= read(G
.zipfd
, (char *)G
.inbuf
, INBUFSIZ
)) == 0) {
570 G
.incnt
= 0; /* do not allow negative value to affect stuff */
572 } else if (G
.incnt
< 0) { /* "fail" (abort, retry, ...) returns this */
573 /* another hack, but no real harm copying same thing twice */
574 (*G
.message
)((zvoid
*)&G
,
575 (uch
*)LoadFarString(ReadError
),
576 (ulg
)strlen(LoadFarString(ReadError
)), 0x401);
579 longjmp(dll_error_return
, 1);
582 EXIT(PK_BADERR
); /* totally bailing; better than lock-up */
585 G
.cur_zipfile_bufstart
+= INBUFSIZ
; /* always starts on block bndry */
587 defer_leftover_input(__G
); /* decrements G.csize */
591 if (G
.pInfo
->encrypted
) {
595 /* This was previously set to decrypt one byte beyond G.csize, when
596 * incnt reached that far. GRR said, "but it's required: why?" This
597 * was a bug in fillinbuf() -- was it also a bug here?
599 for (n
= G
.incnt
, p
= G
.inptr
; n
--; p
++)
607 } /* end function readbyte() */
615 /************************/
616 /* Function fillinbuf() */
617 /************************/
619 int fillinbuf(__G
) /* like readbyte() except returns number of bytes in inbuf */
623 (G
.incnt
= read(G
.zipfd
, (char *)G
.inbuf
, INBUFSIZ
)) <= 0)
625 G
.cur_zipfile_bufstart
+= INBUFSIZ
; /* always starts on a block boundary */
627 defer_leftover_input(__G
); /* decrements G.csize */
630 if (G
.pInfo
->encrypted
) {
634 for (n
= G
.incnt
, p
= G
.inptr
; n
--; p
++)
641 } /* end function fillinbuf() */
643 #endif /* USE_ZLIB */
649 /************************/
650 /* Function seek_zipf() */
651 /************************/
653 int seek_zipf(__G__ abs_offset
)
658 * Seek to the block boundary of the block which includes abs_offset,
659 * then read block into input buffer and set pointers appropriately.
660 * If block is already in the buffer, just set the pointers. This function
661 * is used by do_seekable (process.c), extract_or_test_entrylist (extract.c)
662 * and do_string (fileio.c). Also, a slightly modified version is embedded
663 * within extract_or_test_entrylist (extract.c). readbyte() and readbuf()
664 * (fileio.c) are compatible. NOTE THAT abs_offset is intended to be the
665 * "proper offset" (i.e., if there were no extra bytes prepended);
666 * cur_zipfile_bufstart contains the corrected offset.
668 * Since seek_zipf() is never used during decompression, it is safe to
669 * use the slide[] buffer for the error message.
671 * returns PK error codes:
672 * PK_BADERR if effective offset in zipfile is negative
673 * PK_EOF if seeking past end of zipfile
674 * PK_OK when seek was successful
676 LONGINT request
= abs_offset
+ G
.extra_bytes
;
677 LONGINT inbuf_offset
= request
% INBUFSIZ
;
678 LONGINT bufstart
= request
- inbuf_offset
;
681 Info(slide
, 1, ((char *)slide
, LoadFarStringSmall(SeekMsg
),
682 G
.zipfn
, LoadFarString(ReportMsg
)));
684 } else if (bufstart
!= G
.cur_zipfile_bufstart
) {
686 "fpos_zip: abs_offset = %ld, G.extra_bytes = %ld\n",
687 abs_offset
, G
.extra_bytes
));
688 #ifdef USE_STRM_INPUT
689 fseek(G
.zipfd
, (LONGINT
)bufstart
, SEEK_SET
);
690 G
.cur_zipfile_bufstart
= ftell(G
.zipfd
);
691 #else /* !USE_STRM_INPUT */
692 G
.cur_zipfile_bufstart
= lseek(G
.zipfd
, (LONGINT
)bufstart
, SEEK_SET
);
693 #endif /* ?USE_STRM_INPUT */
695 " request = %ld, (abs+extra) = %ld, inbuf_offset = %ld\n",
696 request
, (abs_offset
+G
.extra_bytes
), inbuf_offset
));
697 Trace((stderr
, " bufstart = %ld, cur_zipfile_bufstart = %ld\n",
698 bufstart
, G
.cur_zipfile_bufstart
));
699 if ((G
.incnt
= read(G
.zipfd
, (char *)G
.inbuf
, INBUFSIZ
)) <= 0)
701 G
.incnt
-= (int)inbuf_offset
;
702 G
.inptr
= G
.inbuf
+ (int)inbuf_offset
;
704 G
.incnt
+= (G
.inptr
-G
.inbuf
) - (int)inbuf_offset
;
705 G
.inptr
= G
.inbuf
+ (int)inbuf_offset
;
708 } /* end function seek_zipf() */
714 #ifndef VMS /* for VMS use code in vms.c */
716 /********************/
717 /* Function flush() */ /* returns PK error codes: */
718 /********************/ /* if cflag => always 0; PK_DISK if write error */
720 int flush(__G__ rawbuf
, size
, unshrink
)
725 #if (defined(USE_DEFLATE64) && defined(__16BIT__))
729 /* On 16-bit systems (MSDOS, OS/2 1.x), the standard C library functions
730 * cannot handle writes of 64k blocks at once. For these systems, the
731 * blocks to flush are split into pieces of 32k or less.
733 while (size
> 0x8000L
) {
734 ret
= partflush(__G__ rawbuf
, 0x8000L
, unshrink
);
738 rawbuf
+= (unsigned)0x8000;
740 return partflush(__G__ rawbuf
, size
, unshrink
);
741 } /* end function flush() */
744 /************************/
745 /* Function partflush() */ /* returns PK error codes: */
746 /************************/ /* if cflag => always 0; PK_DISK if write error */
748 static int partflush(__G__ rawbuf
, size
, unshrink
)
750 uch
*rawbuf
; /* cannot be ZCONST, gets passed to (*G.message)() */
753 #endif /* USE_DEFLATE64 && __16BIT__ */
758 #if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV))
761 /* static int didCRlast = FALSE; moved to globals.h */
764 /*---------------------------------------------------------------------------
765 Compute the CRC first; if testing or if disk is full, that's it.
766 ---------------------------------------------------------------------------*/
768 G
.crc32val
= crc32(G
.crc32val
, rawbuf
, (extent
)size
);
771 if ((G
.statreportcb
!= NULL
) &&
772 (*G
.statreportcb
)(__G__ UZ_ST_IN_PROGRESS
, G
.zipfn
, G
.filename
, NULL
))
773 return IZ_CTRLC
; /* cancel operation by user request */
776 if (uO
.tflag
|| size
== 0L) /* testing or nothing to write: all done */
780 return PK_DISK
; /* disk already full: ignore rest of file */
782 /*---------------------------------------------------------------------------
783 Write the bytes rawbuf[0..size-1] to the output device, first converting
784 end-of-lines and ASCII/EBCDIC as needed. If SMALL_MEM or MED_MEM are NOT
785 defined, outbuf is assumed to be at least as large as rawbuf and is not
786 necessarily checked for overflow.
787 ---------------------------------------------------------------------------*/
789 if (!G
.pInfo
->textmode
) { /* write raw binary data */
790 /* GRR: note that for standard MS-DOS compilers, size argument to
791 * fwrite() can never be more than 65534, so WriteError macro will
792 * have to be rewritten if size can ever be that large. For now,
793 * never more than 32K. Also note that write() returns an int, which
794 * doesn't necessarily limit size to 32767 bytes if write() is used
795 * on 16-bit systems but does make it more of a pain; however, because
796 * at least MSC 5.1 has a lousy implementation of fwrite() (as does
797 * DEC Ultrix cc), write() is used anyway.
801 writeToMemory(__G__ rawbuf
, (extent
)size
);
804 if (!uO
.cflag
&& WriteError(rawbuf
, size
, G
.outfile
))
805 return disk_error(__G
);
806 else if (uO
.cflag
&& (*G
.message
)((zvoid
*)&G
, rawbuf
, size
, 0))
808 } else { /* textmode: aflag is true */
810 /* rawbuf = outbuf */
811 transbuf
= G
.outbuf2
;
812 #if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV))
813 transbufsiz
= TRANSBUFSIZ
;
818 #if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV))
819 transbufsiz
= OUTBUFSIZ
;
820 Trace((stderr
, "\ntransbufsiz = OUTBUFSIZ = %u\n",
821 (unsigned)OUTBUFSIZ
));
826 if (G
.pInfo
->hostnum
== VMS_
&& G
.extra_field
&&
827 is_vms_varlen_txt(__G__ G
.extra_field
,
828 G
.lrec
.extra_field_length
))
829 G
.VMS_line_state
= 0; /* 0: ready to read line length */
831 G
.VMS_line_state
= -1; /* -1: don't treat as VMS text */
833 G
.didCRlast
= FALSE
; /* no previous buffers written */
838 if (G
.VMS_line_state
>= 0)
840 /* GRR: really want to check for actual VMS extra field, and
841 * ideally for variable-length record format */
843 printf("\n>>>>>> GRR: file is VMS text and has an extra field\n");
848 while (p
< rawbuf
+(unsigned)size
) {
849 switch (G
.VMS_line_state
) {
851 /* 0: ready to read line length */
853 G
.VMS_line_length
= 0;
854 if (p
== rawbuf
+(unsigned)size
-1) { /* last char */
855 G
.VMS_line_length
= (unsigned)(*p
++);
856 G
.VMS_line_state
= 1;
858 G
.VMS_line_length
= makeword(p
);
860 G
.VMS_line_state
= 2;
863 ((G
.VMS_line_length
& 1) != 0); /* odd */
866 /* 1: read one byte of length, need second */
868 G
.VMS_line_length
+= ((unsigned)(*p
++) << 8);
869 G
.VMS_line_state
= 2;
872 /* 2: ready to read VMS_line_length chars */
875 extent remaining
= rawbuf
+(unsigned)size
-p
;
878 if (G
.VMS_line_length
< remaining
) {
879 remaining
= G
.VMS_line_length
;
880 G
.VMS_line_state
= 3;
883 outroom
= transbuf
+(unsigned)transbufsiz
-q
;
884 if (remaining
>= outroom
) {
885 remaining
-= outroom
;
886 for (;outroom
> 0; p
++, outroom
--)
890 writeToMemory(__G__ transbuf
,
891 (extent
)(q
-transbuf
));
894 if (!uO
.cflag
&& WriteError(transbuf
,
895 (extent
)(q
-transbuf
), G
.outfile
))
896 return disk_error(__G
);
897 else if (uO
.cflag
&& (*G
.message
)((zvoid
*)&G
,
898 transbuf
, (ulg
)(q
-transbuf
), 0))
901 /* fall through to normal case */
903 G
.VMS_line_length
-= remaining
;
904 for (;remaining
> 0; p
++, remaining
--)
909 /* 3: ready to PutNativeEOL */
911 if (q
> transbuf
+(unsigned)transbufsiz
-lenEOL
) {
914 writeToMemory(__G__ transbuf
,
915 (extent
)(q
-transbuf
));
919 WriteError(transbuf
, (extent
)(q
-transbuf
),
921 return disk_error(__G
);
922 else if (uO
.cflag
&& (*G
.message
)((zvoid
*)&G
,
923 transbuf
, (ulg
)(q
-transbuf
), 0))
928 G
.VMS_line_state
= G
.VMS_line_pad
? 4 : 0;
931 /* 4: ready to read pad byte */
934 G
.VMS_line_state
= 0;
940 #endif /* VMS_TEXT_CONV */
942 /*-----------------------------------------------------------------------
943 Algorithm: CR/LF => native; lone CR => native; lone LF => native.
944 This routine is only for non-raw-VMS, non-raw-VM/CMS files (i.e.,
945 stream-oriented files, not record-oriented).
946 -----------------------------------------------------------------------*/
948 /* else not VMS text */ {
950 if (*p
== LF
&& G
.didCRlast
)
953 for (q
= transbuf
; p
< rawbuf
+(unsigned)size
; ++p
) {
954 if (*p
== CR
) { /* lone CR or CR/LF: treat as EOL */
956 if (p
== rawbuf
+(unsigned)size
-1) /* last char in buffer */
958 else if (p
[1] == LF
) /* get rid of accompanying LF */
960 } else if (*p
== LF
) /* lone LF */
963 #ifndef DOS_FLX_OS2_W32
964 if (*p
!= CTRLZ
) /* lose all ^Z's */
968 #if (defined(SMALL_MEM) || defined(MED_MEM))
969 # if (lenEOL == 1) /* don't check unshrink: both buffers small but equal */
972 /* check for danger of buffer overflow and flush */
973 if (q
> transbuf
+(unsigned)transbufsiz
-lenEOL
) {
975 "p - rawbuf = %u q-transbuf = %u size = %lu\n",
976 (unsigned)(p
-rawbuf
), (unsigned)(q
-transbuf
), size
));
977 if (!uO
.cflag
&& WriteError(transbuf
,
978 (extent
)(q
-transbuf
), G
.outfile
))
979 return disk_error(__G
);
980 else if (uO
.cflag
&& (*G
.message
)((zvoid
*)&G
,
981 transbuf
, (ulg
)(q
-transbuf
), 0))
986 #endif /* SMALL_MEM || MED_MEM */
990 /*-----------------------------------------------------------------------
991 Done translating: write whatever we've got to file (or screen).
992 -----------------------------------------------------------------------*/
994 Trace((stderr
, "p - rawbuf = %u q-transbuf = %u size = %lu\n",
995 (unsigned)(p
-rawbuf
), (unsigned)(q
-transbuf
), size
));
999 writeToMemory(__G__ transbuf
, (extent
)(q
-transbuf
));
1002 if (!uO
.cflag
&& WriteError(transbuf
, (extent
)(q
-transbuf
),
1004 return disk_error(__G
);
1005 else if (uO
.cflag
&& (*G
.message
)((zvoid
*)&G
, transbuf
,
1006 (ulg
)(q
-transbuf
), 0))
1013 } /* end function flush() [resp. partflush() for 16-bit Deflate64 support] */
1019 #ifdef VMS_TEXT_CONV
1021 /********************************/
1022 /* Function is_vms_varlen_txt() */
1023 /********************************/
1025 static int is_vms_varlen_txt(__G__ ef_buf
, ef_len
)
1027 uch
*ef_buf
; /* buffer containing extra field */
1028 unsigned ef_len
; /* total length of extra field */
1034 #define VMSREC_C_UNDEF 0
1035 #define VMSREC_C_VAR 2
1036 uch vms_rectype
= VMSREC_C_UNDEF
;
1037 uch vms_fileorg
= 0;
1039 #define VMSPK_ITEMID 0
1040 #define VMSPK_ITEMLEN 2
1041 #define VMSPK_ITEMHEADSZ 4
1043 #define VMSATR_C_RECATTR 4
1044 #define VMS_FABSIG 0x42414656 /* "VFAB" */
1045 /* offsets of interesting fields in VMS fabdef structure */
1046 #define VMSFAB_B_RFM 31 /* record format byte */
1047 #define VMSFAB_B_ORG 29 /* file organization byte */
1049 if (ef_len
== 0 || ef_buf
== NULL
)
1052 while (ef_len
>= EB_HEADSIZE
) {
1053 eb_id
= makeword(EB_ID
+ ef_buf
);
1054 eb_len
= makeword(EB_LEN
+ ef_buf
);
1056 if (eb_len
> (ef_len
- EB_HEADSIZE
)) {
1057 /* discovered some extra field inconsistency! */
1059 "is_vms_varlen_txt: block length %u > rest ef_size %u\n", eb_len
,
1060 ef_len
- EB_HEADSIZE
));
1066 /* The PKVMS e.f. raw data part consists of:
1067 * a) 4 bytes CRC checksum
1068 * b) list of uncompressed variable-length data items
1069 * Each data item is introduced by a fixed header
1070 * - 2 bytes data type ID
1071 * - 2 bytes <size> of data
1072 * - <size> bytes of actual attribute data
1075 /* get pointer to start of data and its total length */
1076 eb_data
= ef_buf
+(EB_HEADSIZE
+4);
1077 eb_datlen
= eb_len
-4;
1079 /* test the CRC checksum */
1080 if (makelong(ef_buf
+EB_HEADSIZE
) !=
1081 crc32(CRCVAL_INITIAL
, eb_data
, (extent
)eb_datlen
))
1083 Info(slide
, 1, ((char *)slide
,
1084 "[Warning: CRC error, discarding PKWARE extra field]\n"));
1085 /* skip over the data analysis code */
1089 /* scan through the attribute data items */
1090 while (eb_datlen
> 4)
1092 unsigned fldsize
= makeword(&eb_data
[VMSPK_ITEMLEN
]);
1094 /* check the item type word */
1095 switch (makeword(&eb_data
[VMSPK_ITEMID
])) {
1096 case VMSATR_C_RECATTR
:
1097 /* we have found the (currently only) interesting
1100 vms_rectype
= eb_data
[VMSPK_ITEMHEADSZ
] & 15;
1101 vms_fileorg
= eb_data
[VMSPK_ITEMHEADSZ
] >> 4;
1107 /* skip to next data item */
1108 eb_datlen
-= fldsize
+ VMSPK_ITEMHEADSZ
;
1109 eb_data
+= fldsize
+ VMSPK_ITEMHEADSZ
;
1114 if (makelong(ef_buf
+EB_HEADSIZE
) == VMS_FABSIG
) {
1115 if ((eb_data
= extract_izvms_block(__G__
1116 ef_buf
+EB_HEADSIZE
, eb_len
,
1117 &eb_datlen
, NULL
, 0))
1120 if (eb_datlen
>= VMSFAB_B_RFM
+1) {
1121 vms_rectype
= eb_data
[VMSFAB_B_RFM
] & 15;
1122 vms_fileorg
= eb_data
[VMSFAB_B_ORG
] >> 4;
1133 /* Skip this extra field block */
1134 ef_buf
+= (eb_len
+ EB_HEADSIZE
);
1135 ef_len
-= (eb_len
+ EB_HEADSIZE
);
1138 return (vms_rectype
== VMSREC_C_VAR
);
1140 } /* end function is_vms_varlen_txtfile() */
1142 #endif /* VMS_TEXT_CONV */
1147 /*************************/
1148 /* Function disk_error() */
1149 /*************************/
1151 static int disk_error(__G
)
1154 /* OK to use slide[] here because this file is finished regardless */
1155 Info(slide
, 0x4a1, ((char *)slide
, LoadFarString(DiskFullQuery
),
1156 FnFilter1(G
.filename
)));
1159 fgets(G
.answerbuf
, 9, stdin
);
1160 if (*G
.answerbuf
== 'y') /* stop writing to this file */
1161 G
.disk_full
= 1; /* (outfile bad?), but new OK */
1164 G
.disk_full
= 2; /* no: exit program */
1168 } /* end function disk_error() */
1176 /*****************************/
1177 /* Function UzpMessagePrnt() */
1178 /*****************************/
1180 int UZ_EXP
UzpMessagePrnt(pG
, buf
, size
, flag
)
1181 zvoid
*pG
; /* globals struct: always passed */
1182 uch
*buf
; /* preformatted string to be printed */
1183 ulg size
; /* length of string (may include nulls) */
1184 int flag
; /* flag bits */
1187 * The name of the first parameter of UzpMessagePrnt(), which passes
1188 * the "Uz_Globs" address, >>> MUST <<< be identical to the string
1189 * expansion of the __G__ macro in the REENTRANT case (see globals.h).
1190 * This name identity is mandatory for the LoadFarString() macro
1191 * (in the SMALL_MEM case) !!!
1194 uch
*q
=buf
, *endbuf
=buf
+(unsigned)size
;
1197 #if (defined(SCREENWIDTH) && defined(SCREENLWRAP))
1198 int islinefeed
= FALSE
;
1204 /*---------------------------------------------------------------------------
1205 These tests are here to allow fine-tuning of UnZip's output messages,
1206 but none of them will do anything without setting the appropriate bit
1207 in the flag argument of every Info() statement which is to be turned
1208 *off*. That is, all messages are currently turned on for all ports.
1209 To turn off *all* messages, use the UzpMessageNull() function instead
1211 ---------------------------------------------------------------------------*/
1213 #if (defined(OS2) && defined(DLL))
1214 if (MSG_NO_DLL2(flag
)) /* if OS/2 DLL bit is set, do NOT print this msg */
1218 if (MSG_NO_WDLL(flag
))
1222 if (MSG_NO_WGUI(flag
))
1227 if (MSG_NO_AGUI(flag))
1231 #ifdef DLL /* don't display message if data is redirected */
1232 if (((Uz_Globs
*)pG
)->redirect_data
&&
1233 !((Uz_Globs
*)pG
)->redirect_text
)
1237 if (MSG_STDERR(flag
) && !((Uz_Globs
*)pG
)->UzO
.tflag
)
1238 outfp
= (FILE *)stderr
;
1240 outfp
= (FILE *)stdout
;
1242 #ifdef QUERY_TRNEWLN
1243 /* some systems require termination of query prompts with '\n' to force
1244 * immediate display */
1245 if (MSG_MNEWLN(flag
)) { /* assumes writable buffer (e.g., slide[]) */
1246 *endbuf
++ = '\n'; /* with room for one more char at end of buf */
1247 ++size
; /* (safe assumption: only used for four */
1248 } /* short queries in extract.c and fileio.c) */
1251 if (MSG_TNEWLN(flag
)) { /* again assumes writable buffer: fragile... */
1252 if ((!size
&& !((Uz_Globs
*)pG
)->sol
) ||
1253 (size
&& (endbuf
[-1] != '\n')))
1262 /* room for --More-- and one line of overlap: */
1263 # if (defined(SCREENWIDTH) && defined(SCREENLWRAP))
1264 SCREENSIZE(&((Uz_Globs
*)pG
)->height
, &((Uz_Globs
*)pG
)->width
);
1266 SCREENSIZE(&((Uz_Globs
*)pG
)->height
, (int *)NULL
);
1268 ((Uz_Globs
*)pG
)->height
-= 2;
1270 /* room for --More-- and one line of overlap: */
1271 ((Uz_Globs
*)pG
)->height
= SCREENLINES
- 2;
1272 # if (defined(SCREENWIDTH) && defined(SCREENLWRAP))
1273 ((Uz_Globs
*)pG
)->width
= SCREENWIDTH
;
1278 if (MSG_LNEWLN(flag
) && !((Uz_Globs
*)pG
)->sol
) {
1279 /* not at start of line: want newline */
1281 if (!((Uz_Globs
*)pG
)->redirect_text
) {
1286 if (((Uz_Globs
*)pG
)->M_flag
)
1288 #if (defined(SCREENWIDTH) && defined(SCREENLWRAP))
1289 ((Uz_Globs
*)pG
)->chars
= 0;
1291 ++((Uz_Globs
*)pG
)->numlines
;
1292 ++((Uz_Globs
*)pG
)->lines
;
1293 if (((Uz_Globs
*)pG
)->lines
>= ((Uz_Globs
*)pG
)->height
)
1294 (*((Uz_Globs
*)pG
)->mpause
)((zvoid
*)pG
,
1295 LoadFarString(MorePrompt
), 1);
1298 if (MSG_STDERR(flag
) && ((Uz_Globs
*)pG
)->UzO
.tflag
&&
1299 !isatty(1) && isatty(2))
1301 /* error output from testing redirected: also send to stderr */
1309 ((Uz_Globs
*)pG
)->sol
= TRUE
;
1312 /* put zipfile name, filename and/or error/warning keywords here */
1315 if (((Uz_Globs
*)pG
)->M_flag
1317 && !((Uz_Globs
*)pG
)->redirect_text
1321 while (p
< endbuf
) {
1323 #if (defined(SCREENWIDTH) && defined(SCREENLWRAP))
1325 } else if (SCREENLWRAP
) {
1327 ((Uz_Globs
*)pG
)->chars
= 0;
1331 ((Uz_Globs
*)pG
)->chars
+=
1332 (TABSIZE
- (((Uz_Globs
*)pG
)->chars
% TABSIZE
));
1335 ++((Uz_Globs
*)pG
)->chars
;
1337 if (((Uz_Globs
*)pG
)->chars
>= ((Uz_Globs
*)pG
)->width
)
1343 ((Uz_Globs
*)pG
)->chars
= 0;
1344 #endif /* (SCREENWIDTH && SCREEN_LWRAP) */
1345 ++((Uz_Globs
*)pG
)->numlines
;
1346 ++((Uz_Globs
*)pG
)->lines
;
1347 if (((Uz_Globs
*)pG
)->lines
>= ((Uz_Globs
*)pG
)->height
)
1349 if ((error
= WriteError(q
, p
-q
+1, outfp
)) != 0)
1352 ((Uz_Globs
*)pG
)->sol
= TRUE
;
1354 (*((Uz_Globs
*)pG
)->mpause
)((zvoid
*)pG
,
1355 LoadFarString(MorePrompt
), 1);
1360 size
= (ulg
)(p
- q
); /* remaining text */
1366 if (!((Uz_Globs
*)pG
)->redirect_text
) {
1368 if ((error
= WriteError(q
, size
, outfp
)) != 0)
1371 if (MSG_STDERR(flag
) && ((Uz_Globs
*)pG
)->UzO
.tflag
&&
1372 !isatty(1) && isatty(2))
1374 /* error output from testing redirected: also send to stderr */
1375 if ((error
= WriteError(q
, size
, stderr
)) != 0)
1380 } else { /* GRR: this is ugly: hide with macro */
1381 if ((error
= REDIRECTPRINT(q
, size
)) != 0)
1385 ((Uz_Globs
*)pG
)->sol
= (endbuf
[-1] == '\n');
1389 } /* end function UzpMessagePrnt() */
1397 /*****************************/
1398 /* Function UzpMessageNull() */ /* convenience routine for no output at all */
1399 /*****************************/
1401 int UZ_EXP
UzpMessageNull(pG
, buf
, size
, flag
)
1402 zvoid
*pG
; /* globals struct: always passed */
1403 uch
*buf
; /* preformatted string to be printed */
1404 ulg size
; /* length of string (may include nulls) */
1405 int flag
; /* flag bits */
1409 } /* end function UzpMessageNull() */
1417 /***********************/
1418 /* Function UzpInput() */ /* GRR: this is a placeholder for now */
1419 /***********************/
1421 int UZ_EXP
UzpInput(pG
, buf
, size
, flag
)
1422 zvoid
*pG
; /* globals struct: always passed */
1423 uch
*buf
; /* preformatted string to be printed */
1424 int *size
; /* (address of) size of buf and of returned string */
1425 int flag
; /* flag bits (bit 0: no echo) */
1427 /* tell picky compilers to shut up about "unused variable" warnings */
1428 pG
= pG
; buf
= buf
; flag
= flag
;
1433 } /* end function UzpInput() */
1439 #if (!defined(WINDLL) && !defined(MACOS))
1441 /***************************/
1442 /* Function UzpMorePause() */
1443 /***************************/
1445 void UZ_EXP
UzpMorePause(pG
, prompt
, flag
)
1446 zvoid
*pG
; /* globals struct: always passed */
1447 ZCONST
char *prompt
; /* "--More--" prompt */
1448 int flag
; /* 0 = any char OK; 1 = accept only '\n', ' ', q */
1452 /*---------------------------------------------------------------------------
1453 Print a prompt and wait for the user to press a key, then erase prompt
1455 ---------------------------------------------------------------------------*/
1457 if (!((Uz_Globs
*)pG
)->sol
)
1458 fprintf(stderr
, "\n");
1459 /* numlines may or may not be used: */
1460 fprintf(stderr
, prompt
, ((Uz_Globs
*)pG
)->numlines
);
1467 c
!= 17 && /* standard QUIT key */
1469 c
!= '\r' && c
!= '\n' && c
!= ' ' && c
!= 'q' && c
!= 'Q');
1473 /* newline was not echoed, so cover up prompt line */
1474 fprintf(stderr
, LoadFarString(HidePrompt
));
1479 (c
== 17) || /* standard QUIT key */
1481 (ToLower(c
) == 'q')) {
1486 ((Uz_Globs
*)pG
)->sol
= TRUE
;
1489 /* space for another screen, enter for another line. */
1490 if ((flag
& 1) && c
== ' ')
1491 ((Uz_Globs
*)pG
)->lines
= 0;
1494 } /* end function UzpMorePause() */
1496 #endif /* !WINDLL && !MACOS */
1503 /**************************/
1504 /* Function UzpPassword() */
1505 /**************************/
1507 int UZ_EXP
UzpPassword (pG
, rcnt
, pwbuf
, size
, zfn
, efn
)
1508 zvoid
*pG
; /* pointer to UnZip's internal global vars */
1509 int *rcnt
; /* retry counter */
1510 char *pwbuf
; /* buffer for password */
1511 int size
; /* size of password buffer */
1512 ZCONST
char *zfn
; /* name of zip archive */
1513 ZCONST
char *efn
; /* name of archive entry being processed */
1516 int r
= IZ_PW_ENTERED
;
1521 /* tell picky compilers to shut up about "unused variable" warnings */
1525 if (*rcnt
== 0) { /* First call for current entry */
1527 if ((prompt
= (char *)malloc(2*FILNAMSIZ
+ 15)) != (char *)NULL
) {
1528 sprintf(prompt
, LoadFarString(PasswPrompt
),
1529 FnFilter1(zfn
), FnFilter2(efn
));
1532 m
= (char *)LoadFarString(PasswPrompt2
);
1533 } else { /* Retry call, previous password was wrong */
1536 m
= (char *)LoadFarString(PasswRetry
);
1539 m
= getp(__G__ m
, pwbuf
, size
);
1540 if (prompt
!= (char *)NULL
) {
1543 if (m
== (char *)NULL
) {
1546 else if (*pwbuf
== '\0') {
1547 r
= IZ_PW_CANCELALL
;
1552 /* tell picky compilers to shut up about "unused variable" warnings */
1553 pG
= pG
; rcnt
= rcnt
; pwbuf
= pwbuf
; size
= size
; zfn
= zfn
; efn
= efn
;
1555 return IZ_PW_ERROR
; /* internal error; function should never get called */
1558 } /* end function UzpPassword() */
1564 /**********************/
1565 /* Function handler() */
1566 /**********************/
1568 void handler(signal
) /* upon interrupt, turn on echo and exit cleanly */
1573 #if !(defined(SIGBUS) || defined(SIGSEGV)) /* add a newline if not at */
1574 (*G
.message
)((zvoid
*)&G
, slide
, 0L, 0x41); /* start of line (to stderr; */
1575 #endif /* slide[] should be safe) */
1580 if (signal
== SIGBUS
) {
1581 Info(slide
, 0x421, ((char *)slide
, LoadFarString(ZipfileCorrupt
),
1589 if (signal
== SIGSEGV
) {
1590 Info(slide
, 0x421, ((char *)slide
, LoadFarString(ZipfileCorrupt
),
1591 "segmentation violation"));
1595 #endif /* SIGSEGV */
1597 /* probably ctrl-C */
1599 #if defined(AMIGA) && defined(__SASC)
1602 EXIT(IZ_CTRLC
); /* was EXIT(0), then EXIT(PK_ERR) */
1605 #endif /* !WINDLL */
1610 #if (!defined(VMS) && !defined(CMS_MVS))
1611 #if (!defined(OS2) || defined(TIMESTAMP))
1613 #if (!defined(HAVE_MKTIME) || defined(WIN32))
1614 /* also used in amiga/filedate.c and win32/win32.c */
1615 ZCONST ush ydays
[] =
1616 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
1619 /*******************************/
1620 /* Function dos_to_unix_time() */ /* used for freshening/updating/timestamps */
1621 /*******************************/
1623 time_t dos_to_unix_time(dosdatetime
)
1630 ZCONST
time_t now
= time(NULL
);
1632 # define YRBASE 1900
1634 tm
= localtime(&now
);
1635 tm
->tm_isdst
= -1; /* let mktime determine if DST is in effect */
1638 tm
->tm_year
= ((int)(dosdatetime
>> 25) & 0x7f) + (1980 - YRBASE
);
1639 tm
->tm_mon
= ((int)(dosdatetime
>> 21) & 0x0f) - 1;
1640 tm
->tm_mday
= ((int)(dosdatetime
>> 16) & 0x1f);
1643 tm
->tm_hour
= (int)((unsigned)dosdatetime
>> 11) & 0x1f;
1644 tm
->tm_min
= (int)((unsigned)dosdatetime
>> 5) & 0x3f;
1645 tm
->tm_sec
= (int)((unsigned)dosdatetime
<< 1) & 0x3e;
1647 m_time
= mktime(tm
);
1648 NATIVE_TO_TIMET(m_time
) /* NOP unless MSC 7.0 or Macintosh */
1649 TTrace((stderr
, " final m_time = %lu\n", (ulg
)m_time
));
1651 #else /* !HAVE_MKTIME */
1653 int yr
, mo
, dy
, hh
, mm
, ss
;
1655 # define YRBASE 1900
1659 # define YRBASE 1970
1663 #if (!defined(MACOS) && !defined(RISCOS) && !defined(QDOS) && !defined(TANDEM))
1665 TIME_ZONE_INFORMATION tzinfo
;
1668 #ifndef BSD4_4 /* GRR: change to !defined(MODERN) ? */
1669 #if (defined(BSD) || defined(MTS) || defined(__GO32__))
1671 #else /* !(BSD || MTS || __GO32__) */
1672 #ifdef DECLARE_TIMEZONE
1673 extern time_t timezone
;
1675 #endif /* ?(BSD || MTS || __GO32__) */
1676 #endif /* !BSD4_4 */
1678 #endif /* !MACOS && !RISCOS && !QDOS && !TANDEM */
1679 #endif /* ?TOPS20 */
1683 yr
= ((int)(dosdatetime
>> 25) & 0x7f) + (1980 - YRBASE
);
1684 mo
= ((int)(dosdatetime
>> 21) & 0x0f) - 1;
1685 dy
= ((int)(dosdatetime
>> 16) & 0x1f) - 1;
1688 hh
= (int)((unsigned)dosdatetime
>> 11) & 0x1f;
1689 mm
= (int)((unsigned)dosdatetime
>> 5) & 0x3f;
1690 ss
= (int)((unsigned)dosdatetime
& 0x1f) * 2;
1693 tmx
= (struct tmx
*)malloc(sizeof(struct tmx
));
1694 sprintf (temp
, "%02d/%02d/%02d %02d:%02d:%02d", mo
+1, dy
+1, yr
, hh
, mm
, ss
);
1695 time_parse(temp
, tmx
, (char *)0);
1696 m_time
= time_make(tmx
);
1701 /*---------------------------------------------------------------------------
1702 Calculate the number of seconds since the epoch, usually 1 January 1970.
1703 ---------------------------------------------------------------------------*/
1705 /* leap = # of leap yrs from YRBASE up to but not including current year */
1706 leap
= ((yr
+ YRBASE
- 1) / 4); /* leap year base factor */
1708 /* calculate days from BASE to this year and add expired days this year */
1709 days
= (yr
* 365) + (leap
- 492) + ydays
[mo
];
1711 /* if year is a leap year and month is after February, add another day */
1712 if ((mo
> 1) && ((yr
+YRBASE
)%4 == 0) && ((yr
+YRBASE
) != 2100))
1713 ++days
; /* OK through 2199 */
1715 /* convert date & time to seconds relative to 00:00:00, 01/01/YRBASE */
1716 m_time
= (time_t)((unsigned long)(days
+ dy
) * 86400L +
1717 (unsigned long)hh
* 3600L +
1718 (unsigned long)(mm
* 60 + ss
));
1719 /* - 1; MS-DOS times always rounded up to nearest even second */
1720 TTrace((stderr
, "dos_to_unix_time:\n"));
1721 TTrace((stderr
, " m_time before timezone = %lu\n", (ulg
)m_time
));
1723 /*---------------------------------------------------------------------------
1724 Adjust for local standard timezone offset.
1725 ---------------------------------------------------------------------------*/
1727 #if (!defined(MACOS) && !defined(RISCOS) && !defined(QDOS) && !defined(TANDEM))
1729 /* account for timezone differences */
1730 res
= GetTimeZoneInformation(&tzinfo
);
1731 if (res
!= TIME_ZONE_ID_INVALID
)
1733 m_time
+= 60*(tzinfo
.Bias
);
1735 #if (defined(BSD) || defined(MTS) || defined(__GO32__))
1737 if ( (dosdatetime
>= DOSTIME_2038_01_18
) &&
1738 (m_time
< (time_t)0x70000000L
) )
1739 m_time
= U_TIME_T_MAX
; /* saturate in case of (unsigned) overflow */
1740 if (m_time
< (time_t)0L) /* a converted DOS time cannot be negative */
1741 m_time
= S_TIME_T_MAX
; /* -> saturate at max signed time_t value */
1742 if ((tm
= localtime(&m_time
)) != (struct tm
*)NULL
)
1743 m_time
-= tm
->tm_gmtoff
; /* sec. EAST of GMT: subtr. */
1744 #else /* !(BSD4_4 */
1745 ftime(&tbp
); /* get `timezone' */
1746 m_time
+= tbp
.timezone
* 60L; /* seconds WEST of GMT: add */
1747 #endif /* ?(BSD4_4 || __EMX__) */
1748 #else /* !(BSD || MTS || __GO32__) */
1749 /* tzset was already called at start of process_zipfiles() */
1750 /* tzset(); */ /* set `timezone' variable */
1751 #if (!defined(__BEOS__) && !defined(__HAIKU__)) /* BeOS DR8 has no timezones... */
1752 m_time
+= timezone
; /* seconds WEST of GMT: add */
1754 #endif /* ?(BSD || MTS || __GO32__) */
1756 TTrace((stderr
, " m_time after timezone = %lu\n", (ulg
)m_time
));
1758 /*---------------------------------------------------------------------------
1759 Adjust for local daylight savings (summer) time.
1760 ---------------------------------------------------------------------------*/
1762 #ifndef BSD4_4 /* (DST already added to tm_gmtoff, so skip tm_isdst) */
1763 if ( (dosdatetime
>= DOSTIME_2038_01_18
) &&
1764 (m_time
< (time_t)0x70000000L
) )
1765 m_time
= U_TIME_T_MAX
; /* saturate in case of (unsigned) overflow */
1766 if (m_time
< (time_t)0L) /* a converted DOS time cannot be negative */
1767 m_time
= S_TIME_T_MAX
; /* -> saturate at max signed time_t value */
1768 TIMET_TO_NATIVE(m_time
) /* NOP unless MSC 7.0 or Macintosh */
1769 if (((tm
= localtime((time_t *)&m_time
)) != NULL
) && tm
->tm_isdst
)
1771 m_time
+= 60L * tzinfo
.DaylightBias
; /* adjust with DST bias */
1773 m_time
+= 60L * tzinfo
.StandardBias
; /* add StdBias (normally 0) */
1775 m_time
-= 60L * 60L; /* adjust for daylight savings time */
1777 NATIVE_TO_TIMET(m_time
) /* NOP unless MSC 7.0 or Macintosh */
1778 TTrace((stderr
, " m_time after DST = %lu\n", (ulg
)m_time
));
1779 #endif /* !BSD4_4 */
1783 #endif /* !MACOS && !RISCOS && !QDOS && !TANDEM */
1784 #endif /* ?TOPS20 */
1786 #endif /* ?HAVE_MKTIME */
1788 if ( (dosdatetime
>= DOSTIME_2038_01_18
) &&
1789 (m_time
< (time_t)0x70000000L
) )
1790 m_time
= U_TIME_T_MAX
; /* saturate in case of (unsigned) overflow */
1791 if (m_time
< (time_t)0L) /* a converted DOS time cannot be negative */
1792 m_time
= S_TIME_T_MAX
; /* -> saturate at max signed time_t value */
1796 } /* end function dos_to_unix_time() */
1798 #endif /* !OS2 || TIMESTAMP */
1799 #endif /* !VMS && !CMS_MVS */
1803 #if (!defined(VMS) && !defined(OS2) && !defined(CMS_MVS))
1805 /******************************/
1806 /* Function check_for_newer() */ /* used for overwriting/freshening/updating */
1807 /******************************/
1809 int check_for_newer(__G__ filename
) /* return 1 if existing file is newer */
1810 __GDEF
/* or equal; 0 if older; -1 if doesn't */
1811 char *filename
; /* exist yet */
1813 time_t existing
, archive
;
1814 #ifdef USE_EF_UT_TIME
1818 long dyy
, dmm
, ddd
, dhh
, dmin
, dss
;
1821 dyy
= (lrec
.last_mod_dos_datetime
>> 25) + 1980;
1822 dmm
= (lrec
.last_mod_dos_datetime
>> 21) & 0x0f;
1823 ddd
= (lrec
.last_mod_dos_datetime
>> 16) & 0x1f;
1824 dhh
= (lrec
.last_mod_dos_datetime
>> 11) & 0x1f;
1825 dmin
= (lrec
.last_mod_dos_datetime
>> 5) & 0x3f;
1826 dss
= (lrec
.last_mod_dos_datetime
& 0x1f) * 2;
1828 /* under AOS/VS, file times can only be set at creation time,
1829 * with the info in a special DG format. Make sure we can create
1830 * it here - we delete it later & re-create it, whether or not
1833 if (!zvs_create(filename
, (((ulg
)dgdate(dmm
, ddd
, dyy
)) << 16) |
1834 (dhh
*1800L + dmin
*30L + dss
/2L), -1L, -1L, (char *) -1, -1, -1, -1))
1835 return DOES_NOT_EXIST
;
1838 Trace((stderr
, "check_for_newer: doing stat(%s)\n", FnFilter1(filename
)));
1839 if (SSTAT(filename
, &G
.statbuf
)) {
1841 "check_for_newer: stat(%s) returns %d: file does not exist\n",
1842 FnFilter1(filename
), SSTAT(filename
, &G
.statbuf
)));
1844 Trace((stderr
, "check_for_newer: doing lstat(%s)\n",
1845 FnFilter1(filename
)));
1846 /* GRR OPTION: could instead do this test ONLY if G.symlnk is true */
1847 if (lstat(filename
, &G
.statbuf
) == 0) {
1849 "check_for_newer: lstat(%s) returns 0: symlink does exist\n",
1850 FnFilter1(filename
)));
1851 if (QCOND2
&& !IS_OVERWRT_ALL
)
1852 Info(slide
, 0, ((char *)slide
, LoadFarString(FileIsSymLink
),
1853 FnFilter1(filename
), " with no real file"));
1854 return EXISTS_AND_OLDER
; /* symlink dates are meaningless */
1856 #endif /* SYMLINKS */
1857 return DOES_NOT_EXIST
;
1859 Trace((stderr
, "check_for_newer: stat(%s) returns 0: file exists\n",
1860 FnFilter1(filename
)));
1863 /* GRR OPTION: could instead do this test ONLY if G.symlnk is true */
1864 if (lstat(filename
, &G
.statbuf
) == 0 && S_ISLNK(G
.statbuf
.st_mode
)) {
1865 Trace((stderr
, "check_for_newer: %s is a symbolic link\n",
1866 FnFilter1(filename
)));
1867 if (QCOND2
&& !IS_OVERWRT_ALL
)
1868 Info(slide
, 0, ((char *)slide
, LoadFarString(FileIsSymLink
),
1869 FnFilter1(filename
), ""));
1870 return EXISTS_AND_OLDER
; /* symlink dates are meaningless */
1872 #endif /* SYMLINKS */
1874 NATIVE_TO_TIMET(G
.statbuf
.st_mtime
) /* NOP unless MSC 7.0 or Macintosh */
1876 #ifdef USE_EF_UT_TIME
1877 /* The `Unix extra field mtime' should be used for comparison with the
1878 * time stamp of the existing file >>>ONLY<<< when the EF info is also
1879 * used to set the modification time of the extracted file.
1881 if (G
.extra_field
&&
1885 (ef_scan_for_izux(G
.extra_field
, G
.lrec
.extra_field_length
, 0,
1886 G
.lrec
.last_mod_dos_datetime
, &z_utime
, NULL
)
1889 TTrace((stderr
, "check_for_newer: using Unix extra field mtime\n"));
1890 existing
= G
.statbuf
.st_mtime
;
1891 archive
= z_utime
.mtime
;
1893 /* round up existing filetime to nearest 2 seconds for comparison,
1894 * but saturate in case of arithmetic overflow
1896 existing
= ((G
.statbuf
.st_mtime
& 1) &&
1897 (G
.statbuf
.st_mtime
+ 1 > G
.statbuf
.st_mtime
)) ?
1898 G
.statbuf
.st_mtime
+ 1 : G
.statbuf
.st_mtime
;
1899 archive
= dos_to_unix_time(G
.lrec
.last_mod_dos_datetime
);
1901 #else /* !USE_EF_UT_TIME */
1902 /* round up existing filetime to nearest 2 seconds for comparison,
1903 * but saturate in case of arithmetic overflow
1905 existing
= ((G
.statbuf
.st_mtime
& 1) &&
1906 (G
.statbuf
.st_mtime
+ 1 > G
.statbuf
.st_mtime
)) ?
1907 G
.statbuf
.st_mtime
+ 1 : G
.statbuf
.st_mtime
;
1908 archive
= dos_to_unix_time(G
.lrec
.last_mod_dos_datetime
);
1909 #endif /* ?USE_EF_UT_TIME */
1911 TTrace((stderr
, "check_for_newer: existing %lu, archive %lu, e-a %ld\n",
1912 (ulg
)existing
, (ulg
)archive
, (long)(existing
-archive
)));
1914 return (existing
>= archive
);
1916 } /* end function check_for_newer() */
1918 #endif /* !VMS && !OS2 && !CMS_MVS */
1924 /************************/
1925 /* Function do_string() */
1926 /************************/
1928 int do_string(__G__ length
, option
) /* return PK-type error code */
1930 unsigned int length
; /* without prototype, ush converted to this */
1933 unsigned comment_bytes_left
;
1934 unsigned int block_len
;
1937 char tmp_fnote
[2 * AMIGA_FILENOTELEN
]; /* extra room for squozen chars */
1941 /*---------------------------------------------------------------------------
1942 This function processes arbitrary-length (well, usually) strings. Four
1943 major options are allowed: SKIP, wherein the string is skipped (pretty
1944 logical, eh?); DISPLAY, wherein the string is printed to standard output
1945 after undergoing any necessary or unnecessary character conversions;
1946 DS_FN, wherein the string is put into the filename[] array after under-
1947 going appropriate conversions (including case-conversion, if that is
1948 indicated: see the global variable pInfo->lcflag); and EXTRA_FIELD,
1949 wherein the `string' is assumed to be an extra field and is copied to
1950 the (freshly malloced) buffer G.extra_field. The third option should
1951 be OK since filename is dimensioned at 1025, but we check anyway.
1953 The string, by the way, is assumed to start at the current file-pointer
1954 position; its length is given by 'length'. So start off by checking the
1955 length of the string: if zero, we're already done.
1956 ---------------------------------------------------------------------------*/
1963 #if (defined(SFX) && defined(CHEAP_SFX_AUTORUN))
1965 * Special case: See if the comment begins with an autorun command line.
1966 * Save that and display (or skip) the remainder.
1970 case CHECK_AUTORUN_Q
:
1971 comment_bytes_left
= length
;
1974 block_len
= readbuf(__G__ (char *)G
.outbuf
, 10);
1977 comment_bytes_left
-= block_len
;
1978 G
.outbuf
[block_len
] = '\0';
1979 if (!strcmp((char *)G
.outbuf
, "$AUTORUN$>")) {
1982 block_len
= readbuf(__G__ G
.autorun_command
,
1983 MIN(length
, sizeof(G
.autorun_command
)-1));
1986 comment_bytes_left
-= block_len
;
1987 G
.autorun_command
[block_len
] = '\0';
1988 A_TO_N(G
.autorun_command
);
1989 eol
= strchr(G
.autorun_command
, '\n');
1991 eol
= G
.autorun_command
+ strlen(G
.autorun_command
) - 1;
1992 length
-= eol
+ 1 - G
.autorun_command
;
1993 while (eol
>= G
.autorun_command
&& isspace(*eol
))
1996 /* Win9x console always uses OEM character coding, and
1997 WinNT console is set to OEM charset by default, too */
1998 INTERN_TO_OEM(G
.autorun_command
, G
.autorun_command
);
2002 if (option
== CHECK_AUTORUN_Q
) /* don't display the remainder */
2004 /* seek to beginning of remaining part of comment -- rewind if */
2005 /* displaying entire comment, or skip to end if discarding it */
2006 seek_zipf(__G__ G
.cur_zipfile_bufstart
- G
.extra_bytes
+
2007 (G
.inptr
- G
.inbuf
) + comment_bytes_left
- length
);
2010 /* FALL THROUGH... */
2011 #endif /* SFX && CHEAP_SFX_AUTORUN */
2014 * First normal case: print string on standard output. First set loop
2015 * variables, then loop through the comment in chunks of OUTBUFSIZ bytes,
2016 * converting formats and printing as we go. The second half of the
2017 * loop conditional was added because the file might be truncated, in
2018 * which case comment_bytes_left will remain at some non-zero value for
2019 * all time. outbuf and slide are used as scratch buffers because they
2020 * are available (we should be either before or in between any file pro-
2026 comment_bytes_left
= length
;
2027 block_len
= OUTBUFSIZ
; /* for the while statement, first time */
2028 while (comment_bytes_left
> 0 && block_len
> 0) {
2029 register uch
*p
= G
.outbuf
;
2030 register uch
*q
= G
.outbuf
;
2032 if ((block_len
= readbuf(__G__ (char *)G
.outbuf
,
2033 MIN((unsigned)OUTBUFSIZ
, comment_bytes_left
))) == 0)
2035 comment_bytes_left
-= block_len
;
2037 /* this is why we allocated an extra byte for outbuf: terminate
2038 * with zero (ASCIIZ) */
2039 G
.outbuf
[block_len
] = '\0';
2041 /* remove all ASCII carriage returns from comment before printing
2042 * (since used before A_TO_N(), check for CR instead of '\r')
2049 /* could check whether (p - outbuf) == block_len here */
2052 if (option
== DISPL_8
) {
2053 /* translate the text coded in the entry's host-dependent
2054 "extended ASCII" charset into the compiler's (system's)
2055 internal text code page */
2056 Ext_ASCII_TO_Native((char *)G
.outbuf
, G
.pInfo
->hostnum
,
2057 G
.pInfo
->hostver
, G
.pInfo
->HasUxAtt
,
2060 /* translate to ANSI (RTL internal codepage may be OEM) */
2061 INTERN_TO_ISO((char *)G
.outbuf
, (char *)G
.outbuf
);
2064 /* Win9x console always uses OEM character coding, and
2065 WinNT console is set to OEM charset by default, too */
2066 INTERN_TO_OEM((char *)G
.outbuf
, (char *)G
.outbuf
);
2068 #endif /* ?WINDLL */
2070 A_TO_N(G
.outbuf
); /* translate string to native */
2074 /* ran out of local mem -- had to cheat */
2075 win_fprintf((zvoid
*)&G
, stdout
, length
, (char *)G
.outbuf
);
2076 win_fprintf((zvoid
*)&G
, stdout
, 2, (char *)"\n\n");
2078 #ifdef NOANSIFILT /* GRR: can ANSI be used with EBCDIC? */
2079 (*G
.message
)((zvoid
*)&G
, G
.outbuf
, (ulg
)(q
-G
.outbuf
), 0);
2080 #else /* ASCII, filter out ANSI escape sequences and handle ^S (pause) */
2086 if (*p
== 0x1B) { /* ASCII escape char */
2089 } else if (*p
== 0x13) { /* ASCII ^S (pause) */
2091 if (p
[1] == LF
) /* ASCII LF */
2093 else if (p
[1] == CR
&& p
[2] == LF
) { /* ASCII CR LF */
2099 if ((unsigned)(q
-slide
) > WSIZE
-3 || pause
) { /* flush */
2100 (*G
.message
)((zvoid
*)&G
, slide
, (ulg
)(q
-slide
), 0);
2102 if (pause
&& G
.extract_flag
) /* don't pause for list/test */
2103 (*G
.mpause
)((zvoid
*)&G
, LoadFarString(QuitPrompt
), 0);
2106 (*G
.message
)((zvoid
*)&G
, slide
, (ulg
)(q
-slide
), 0);
2107 #endif /* ?NOANSIFILT */
2108 #endif /* ?WINDLL */
2110 /* add '\n' if not at start of line */
2111 (*G
.message
)((zvoid
*)&G
, slide
, 0L, 0x40);
2115 * Second case: read string into filename[] array. The filename should
2116 * never ever be longer than FILNAMSIZ-1 (1024), but for now we'll check,
2122 if (length
>= FILNAMSIZ
) {
2123 Info(slide
, 0x401, ((char *)slide
,
2124 LoadFarString(FilenameTooLongTrunc
)));
2126 /* remember excess length in block_len */
2127 block_len
= length
- (FILNAMSIZ
- 1);
2128 length
= FILNAMSIZ
- 1;
2130 /* no excess size */
2132 if (readbuf(__G__ G
.filename
, length
) == 0)
2134 G
.filename
[length
] = '\0'; /* terminate w/zero: ASCIIZ */
2136 /* translate the Zip entry filename coded in host-dependent "extended
2137 ASCII" into the compiler's (system's) internal text code page */
2138 Ext_ASCII_TO_Native(G
.filename
, G
.pInfo
->hostnum
, G
.pInfo
->hostver
,
2139 G
.pInfo
->HasUxAtt
, (option
== DS_FN_L
));
2141 if (G
.pInfo
->lcflag
) /* replace with lowercase filename */
2142 STRLOWER(G
.filename
, G
.filename
);
2144 if (G
.pInfo
->vollabel
&& length
> 8 && G
.filename
[8] == '.') {
2145 char *p
= G
.filename
+8;
2147 p
[-1] = *p
; /* disk label, and 8th char is dot: remove dot */
2150 if (!block_len
) /* no overflow, we're done here */
2154 * We truncated the filename, so print what's left and then fall
2155 * through to the SKIP routine.
2157 Info(slide
, 0x401, ((char *)slide
, "[ %s ]\n", FnFilter1(G
.filename
)));
2158 length
= block_len
; /* SKIP the excess bytes... */
2159 /* FALL THROUGH... */
2162 * Third case: skip string, adjusting readbuf's internal variables
2163 * as necessary (and possibly skipping to and reading a new block of
2168 /* cur_zipfile_bufstart already takes account of extra_bytes, so don't
2169 * correct for it twice: */
2170 seek_zipf(__G__ G
.cur_zipfile_bufstart
- G
.extra_bytes
+
2171 (G
.inptr
-G
.inbuf
) + length
);
2175 * Fourth case: assume we're at the start of an "extra field"; malloc
2176 * storage for it and read data into the allocated space.
2180 if (G
.extra_field
!= (uch
*)NULL
)
2181 free(G
.extra_field
);
2182 if ((G
.extra_field
= (uch
*)malloc(length
)) == (uch
*)NULL
) {
2183 Info(slide
, 0x401, ((char *)slide
, LoadFarString(ExtraFieldTooLong
),
2185 /* cur_zipfile_bufstart already takes account of extra_bytes,
2186 * so don't correct for it twice: */
2187 seek_zipf(__G__ G
.cur_zipfile_bufstart
- G
.extra_bytes
+
2188 (G
.inptr
-G
.inbuf
) + length
);
2190 if (readbuf(__G__ (char *)G
.extra_field
, length
) == 0)
2196 * Fifth case, for the Amiga only: take the comment that would ordinarily
2197 * be skipped over, and turn it into a 79 character string that will be
2198 * attached to the file as a "filenote" after it is extracted.
2202 if ((block_len
= readbuf(__G__ tmp_fnote
, (unsigned)
2203 MIN(length
, 2 * AMIGA_FILENOTELEN
- 1))) == 0)
2205 if ((length
-= block_len
) > 0) /* treat remainder as in case SKIP: */
2206 seek_zipf(__G__ G
.cur_zipfile_bufstart
- G
.extra_bytes
2207 + (G
.inptr
- G
.inbuf
) + length
);
2208 /* convert multi-line text into single line with no ctl-chars: */
2209 tmp_fnote
[block_len
] = '\0';
2210 while ((short int) --block_len
>= 0)
2211 if ((unsigned) tmp_fnote
[block_len
] < ' ')
2212 if (tmp_fnote
[block_len
+1] == ' ') /* no excess */
2213 strcpy(tmp_fnote
+block_len
, tmp_fnote
+block_len
+1);
2215 tmp_fnote
[block_len
] = ' ';
2216 tmp_fnote
[AMIGA_FILENOTELEN
- 1] = '\0';
2217 if (G
.filenotes
[G
.filenote_slot
])
2218 free(G
.filenotes
[G
.filenote_slot
]); /* should not happen */
2219 G
.filenotes
[G
.filenote_slot
] = NULL
;
2221 if (!(G
.filenotes
[G
.filenote_slot
] = malloc(strlen(tmp_fnote
)+1)))
2223 strcpy(G
.filenotes
[G
.filenote_slot
], tmp_fnote
);
2228 } /* end switch (option) */
2232 } /* end function do_string() */
2238 /***********************/
2239 /* Function makeword() */
2240 /***********************/
2246 * Convert Intel style 'short' integer to non-Intel non-16-bit
2247 * host format. This routine also takes care of byte-ordering.
2249 return (ush
)((b
[1] << 8) | b
[0]);
2256 /***********************/
2257 /* Function makelong() */
2258 /***********************/
2264 * Convert intel style 'long' variable to non-Intel non-16-bit
2265 * host format. This routine also takes care of byte-ordering.
2267 return (((ulg
)sig
[3]) << 24)
2268 + (((ulg
)sig
[2]) << 16)
2269 + (((ulg
)sig
[1]) << 8)
2278 /**********************/
2279 /* Function str2iso() */
2280 /**********************/
2282 char *str2iso(dst
, src
)
2283 char *dst
; /* destination buffer */
2284 register ZCONST
char *src
; /* source string */
2286 #ifdef INTERN_TO_ISO
2287 INTERN_TO_ISO(src
, dst
);
2290 register char *dstp
= dst
;
2293 c
= (uch
)foreign(*src
++);
2294 *dstp
++ = (char)ASCII2ISO(c
);
2295 } while (c
!= '\0');
2300 #endif /* NEED_STR2ISO */
2304 /**********************/
2305 /* Function str2oem() */
2306 /**********************/
2308 char *str2oem(dst
, src
)
2309 char *dst
; /* destination buffer */
2310 register ZCONST
char *src
; /* source string */
2312 #ifdef INTERN_TO_OEM
2313 INTERN_TO_OEM(src
, dst
);
2316 register char *dstp
= dst
;
2319 c
= (uch
)foreign(*src
++);
2320 *dstp
++ = (char)ASCII2OEM(c
);
2321 } while (c
!= '\0');
2326 #endif /* NEED_STR2OEM */
2331 #ifdef ZMEM /* memset/memcmp/memcpy for systems without either them or */
2332 /* bzero/bcmp/bcopy */
2333 /* (no known systems as of 960211) */
2335 /*********************/
2336 /* Function memset() */
2337 /*********************/
2339 zvoid
*memset(buf
, init
, len
)
2340 register zvoid
*buf
; /* buffer location */
2341 register int init
; /* initializer character */
2342 register unsigned int len
; /* length of the buffer */
2348 *((char *)buf
++) = (char)init
;
2354 /*********************/
2355 /* Function memcmp() */
2356 /*********************/
2358 int memcmp(b1
, b2
, len
)
2359 register ZCONST zvoid
*b1
;
2360 register ZCONST zvoid
*b2
;
2361 register unsigned int len
;
2366 if ((c
= (int)(*((ZCONST
unsigned char *)b1
)++) -
2367 (int)(*((ZCONST
unsigned char *)b2
)++)) != 0)
2375 /*********************/
2376 /* Function memcpy() */
2377 /*********************/
2379 zvoid
*memcpy(dst
, src
, len
)
2380 register zvoid
*dst
;
2381 register ZCONST zvoid
*src
;
2382 register unsigned int len
;
2388 *((char *)dst
)++ = *((ZCONST
char *)src
)++;
2399 /************************/
2400 /* Function zstrnicmp() */
2401 /************************/
2403 int zstrnicmp(s1
, s2
, n
)
2404 register ZCONST
char *s1
, *s2
;
2405 register unsigned n
;
2407 for (; n
> 0; --n
, ++s1
, ++s2
) {
2409 if (ToLower(*s1
) != ToLower(*s2
))
2410 /* test includes early termination of one string */
2411 return (ToLower(*s1
) < ToLower(*s2
))? -1 : 1;
2413 if (*s1
== '\0') /* both strings terminate early */
2419 #endif /* NO_STRNICMP */
2424 #ifdef REGULUS /* returns the inode number on success(!)...argh argh argh */
2427 /********************/
2428 /* Function zstat() */
2429 /********************/
2435 return (stat((char *)p
,s
) >= 0? 0 : (-1));
2438 #endif /* REGULUS */
2445 /* DBCS support for Info-ZIP's zip (mainly for japanese (-: )
2446 * by Yoshioka Tsuneo (QWF00133@nifty.ne.jp,tsuneo-y@is.aist-nara.ac.jp)
2447 * This code is public domain! Date: 1998/12/20
2450 /************************/
2451 /* Function plastchar() */
2452 /************************/
2454 char *plastchar(ptr
, len
)
2459 ZCONST
char *oldptr
= ptr
;
2460 while(*ptr
!= '\0' && len
> 0){
2466 return (char *)oldptr
;
2470 #ifdef NEED_UZMBSCHR
2471 /***********************/
2472 /* Function uzmbschr() */
2473 /***********************/
2475 unsigned char *uzmbschr(str
, c
)
2476 ZCONST
unsigned char *str
;
2479 while(*str
!= '\0'){
2480 if (*str
== c
) {return (unsigned char *)str
;}
2485 #endif /* NEED_UZMBSCHR */
2488 #ifdef NEED_UZMBSRCHR
2489 /************************/
2490 /* Function uzmbsrchr() */
2491 /************************/
2493 unsigned char *uzmbsrchr(str
, c
)
2494 ZCONST
unsigned char *str
;
2497 unsigned char *match
= NULL
;
2498 while(*str
!= '\0'){
2499 if (*str
== c
) {match
= (unsigned char *)str
;}
2504 #endif /* NEED_UZMBSRCHR */
2513 /*******************************/
2514 /* Function fLoadFarString() */ /* (and friends...) */
2515 /*******************************/
2517 char *fLoadFarString(__GPRO__
const char Far
*sz
)
2519 (void)zfstrcpy(G
.rgchBigBuffer
, sz
);
2520 return G
.rgchBigBuffer
;
2523 char *fLoadFarStringSmall(__GPRO__
const char Far
*sz
)
2525 (void)zfstrcpy(G
.rgchSmallBuffer
, sz
);
2526 return G
.rgchSmallBuffer
;
2529 char *fLoadFarStringSmall2(__GPRO__
const char Far
*sz
)
2531 (void)zfstrcpy(G
.rgchSmallBuffer2
, sz
);
2532 return G
.rgchSmallBuffer2
;
2538 #if (!defined(_MSC_VER) || (_MSC_VER < 600))
2539 /*************************/
2540 /* Function zfstrcpy() */ /* portable clone of _fstrcpy() */
2541 /*************************/
2543 char Far
* Far
zfstrcpy(char Far
*s1
, const char Far
*s2
)
2547 while ((*s1
++ = *s2
++) != '\0');
2550 #endif /* !_MSC_VER || (_MSC_VER < 600) */
2552 #endif /* SMALL_MEM */