2 Copyright (c) 1990-2009 Info-ZIP. All rights reserved.
4 See the accompanying file LICENSE, version 2009-Jan-02 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)
41 str2iso() (CRYPT && NEED_STR2ISO, only)
42 str2oem() (CRYPT && NEED_STR2OEM, only)
45 zstrnicmp() (NO_STRNICMP only)
46 zstat() (REGULUS only)
47 plastchar() (_MBCS only)
48 uzmbclen() (_MBCS && NEED_UZMBCLEN, only)
49 uzmbschr() (_MBCS && NEED_UZMBSCHR, only)
50 uzmbsrchr() (_MBCS && NEED_UZMBSRCHR, only)
51 fLoadFarString() (SMALL_MEM only)
52 fLoadFarStringSmall() (SMALL_MEM only)
53 fLoadFarStringSmall2() (SMALL_MEM only)
54 zfstrcpy() (SMALL_MEM only)
55 zfstrcmp() (SMALL_MEM && !(SFX || FUNZIP) only)
57 ---------------------------------------------------------------------------*/
60 #define __FILEIO_C /* identifies this source module */
61 #define UNZIP_INTERNAL
65 # include "wince/intrface.h"
67 # include "windll/windll.h"
75 /* setup of codepage conversion for decryption passwords */
77 # if (defined(CRYP_USES_ISO2OEM) && !defined(IZ_ISO2OEM_ARRAY))
78 # define IZ_ISO2OEM_ARRAY /* pull in iso2oem[] table */
80 # if (defined(CRYP_USES_OEM2ISO) && !defined(IZ_OEM2ISO_ARRAY))
81 # define IZ_OEM2ISO_ARRAY /* pull in oem2iso[] table */
84 #include "ebcdic.h" /* definition/initialization of ebcdic[] */
88 Note: Under Windows, the maximum size of the buffer that can be used
89 with any of the *printf calls is 16,384, so win_fprintf was used to
90 feed the fprintf clone no more than 16K chunks at a time. This should
91 be valid for anything up to 64K (and probably beyond, assuming your
92 buffers are that big).
95 # define WriteError(buf,len,strm) \
96 (win_fprintf(pG, strm, (extent)len, (char far *)buf) != (int)(len))
99 # define WriteError(buf,len,strm) \
100 ((extent)fwrite((char *)(buf),1,(extent)(len),strm) != (extent)(len))
102 # define WriteError(buf,len,strm) \
103 ((extent)write(fileno(strm),(char *)(buf),(extent)(len)) != (extent)(len))
109 On VMS, when output is redirected to a file, as in a command like
110 "PIPE UNZIP -v > X.OUT", the output file is created with VFC record
111 format, and multiple calls to write() or fwrite() will produce multiple
112 records, even when there's no newline terminator in the buffer.
113 The result is unsightly output with spurious newlines. Using fprintf()
114 instead of write() here, and disabling a fflush(stdout) in UzpMessagePrnt()
115 below, together seem to solve the problem.
117 According to the C RTL manual, "The write and decc$record_write
118 functions always generate at least one record." Also, "[T]he fwrite
119 function always generates at least <number_items> records." So,
120 "fwrite(buf, len, 1, strm)" is much better ("1" record) than
121 "fwrite(buf, 1, len, strm)" ("len" (1-character) records, _really_
122 ugly), but neither is better than write(). Similarly, "The fflush
123 function always generates a record if there is unwritten data in the
124 buffer." Apparently fprintf() buffers the stuff somewhere, and puts
125 out a record (only) when it sees a newline.
128 # define WriteTxtErr(buf,len,strm) \
129 ((extent)fprintf(strm, "%.*s", len, buf) != (extent)(len))
131 # define WriteTxtErr(buf,len,strm) WriteError(buf,len,strm)
134 #if (defined(USE_DEFLATE64) && defined(__16BIT__))
135 static int partflush
OF((__GPRO__ uch
*rawbuf
, ulg size
, int unshrink
));
138 static int is_vms_varlen_txt
OF((__GPRO__ uch
*ef_buf
, unsigned ef_len
));
140 static int disk_error
OF((__GPRO
));
143 /****************************/
144 /* Strings used in fileio.c */
145 /****************************/
147 static ZCONST
char Far CannotOpenZipfile
[] =
148 "error: cannot open zipfile [ %s ]\n %s\n";
150 #if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS))
151 #if (!defined(TANDEM))
152 #if (defined(ATH_BEO_THS_UNX) || defined(DOS_FLX_NLM_OS2_W32))
153 static ZCONST
char Far CannotDeleteOldFile
[] =
154 "error: cannot delete old %s\n %s\n";
156 static ZCONST
char Far CannotRenameOldFile
[] =
157 "error: cannot rename old %s\n %s\n";
158 static ZCONST
char Far BackupSuffix
[] = "~";
160 #endif /* ATH_BEO_THS_UNX || DOS_FLX_NLM_OS2_W32 */
161 #ifdef NOVELL_BUG_FAILSAFE
162 static ZCONST
char Far NovellBug
[] =
163 "error: %s: stat() says does not exist, but fopen() found anyway\n";
165 static ZCONST
char Far CannotCreateFile
[] =
166 "error: cannot create %s\n %s\n";
168 #endif /* !VMS && !AOS_VS && !CMS_MVS && !MACOS */
170 static ZCONST
char Far ReadError
[] = "error: zipfile read error\n";
171 static ZCONST
char Far FilenameTooLongTrunc
[] =
172 "warning: filename too long--truncating.\n";
173 #ifdef UNICODE_SUPPORT
174 static ZCONST
char Far UFilenameTooLongTrunc
[] =
175 "warning: Converted unicode filename too long--truncating.\n";
177 static ZCONST
char Far ExtraFieldTooLong
[] =
178 "warning: extra field too long (%d). Ignoring...\n";
181 static ZCONST
char Far DiskFullQuery
[] =
182 "%s: write error (disk full?).\n";
184 static ZCONST
char Far DiskFullQuery
[] =
185 "%s: write error (disk full?). Continue? (y/n/^C) ";
186 static ZCONST
char Far ZipfileCorrupt
[] =
187 "error: zipfile probably corrupt (%s)\n";
189 static ZCONST
char Far FileIsSymLink
[] =
190 "%s exists and is a symbolic link%s.\n";
193 static ZCONST
char Far MorePrompt
[] = "--More--(%lu)";
195 static ZCONST
char Far QuitPrompt
[] =
196 "--- Press `Q' to quit, or any other key to continue ---";
197 static ZCONST
char Far HidePrompt
[] = /* "\r \r"; */
201 /* SPC: are names on MacOS REALLY so much longer than elsewhere ??? */
202 static ZCONST
char Far PasswPrompt
[] = "[%s]\n %s password: ";
204 static ZCONST
char Far PasswPrompt
[] = "[%s] %s password: ";
206 static ZCONST
char Far PasswPrompt2
[] = "Enter password: ";
207 static ZCONST
char Far PasswRetry
[] = "password incorrect--reenter: ";
215 /******************************/
216 /* Function open_input_file() */
217 /******************************/
219 int open_input_file(__G
) /* return 1 if open failed */
223 * open the zipfile for reading and in BINARY mode to prevent cr/lf
224 * translation, which would corrupt the bitstreams
228 G
.zipfd
= open(G
.zipfn
, O_RDONLY
, 0, OPNZIP_RMS_ARGS
);
231 G
.zipfd
= open(G
.zipfn
, 0);
234 G
.zipfd
= vmmvs_open_infile(__G
);
236 #ifdef USE_STRM_INPUT
237 G
.zipfd
= fopen(G
.zipfn
, FOPR
);
238 #else /* !USE_STRM_INPUT */
239 G
.zipfd
= open(G
.zipfn
, O_RDONLY
| O_BINARY
);
240 #endif /* ?USE_STRM_INPUT */
241 #endif /* ?CMS_MVS */
245 #ifdef USE_STRM_INPUT
248 /* if (G.zipfd < 0) */ /* no good for Windows CE port */
252 Info(slide
, 0x401, ((char *)slide
, LoadFarString(CannotOpenZipfile
),
253 G
.zipfn
, strerror(errno
)));
258 } /* end function open_input_file() */
263 #if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS))
264 #if (!defined(TANDEM))
266 /***************************/
267 /* Function open_outfile() */
268 /***************************/
270 int open_outfile(__G
) /* return 1 if fail */
275 return (redirect_outfile(__G
) == FALSE
);
278 QFilename(__G__ G
.filename
);
280 #if (defined(DOS_FLX_NLM_OS2_W32) || defined(ATH_BEO_THS_UNX))
281 #ifdef BORLAND_STAT_BUG
282 /* Borland 5.0's stat() barfs if the filename has no extension and the
283 * file doesn't exist. */
284 if (access(G
.filename
, 0) == -1) {
285 FILE *tmp
= fopen(G
.filename
, "wb+");
287 /* file doesn't exist, so create a dummy file to keep stat() from
288 * failing (will be over-written anyway) */
289 fputc('0', tmp
); /* just to have something in the file */
292 #endif /* BORLAND_STAT_BUG */
294 if (SSTAT(G
.filename
, &G
.statbuf
) == 0 ||
295 lstat(G
.filename
, &G
.statbuf
) == 0)
297 if (SSTAT(G
.filename
, &G
.statbuf
) == 0)
298 #endif /* ?SYMLINKS */
300 Trace((stderr
, "open_outfile: stat(%s) returns 0: file exists\n",
301 FnFilter1(G
.filename
)));
303 if (uO
.B_flag
) { /* do backup */
306 int blen
, flen
, tlen
;
308 blen
= strlen(BackupSuffix
);
309 flen
= strlen(G
.filename
);
310 tlen
= flen
+ blen
+ 6; /* includes space for 5 digits */
311 if (tlen
>= FILNAMSIZ
) { /* in case name is too long, truncate */
312 tname
= (char *)malloc(FILNAMSIZ
);
314 return 1; /* in case we run out of space */
315 tlen
= FILNAMSIZ
- 1 - blen
;
316 strcpy(tname
, G
.filename
); /* make backup name */
318 if (flen
> tlen
) flen
= tlen
;
321 tname
= (char *)malloc(tlen
);
323 return 1; /* in case we run out of space */
324 strcpy(tname
, G
.filename
); /* make backup name */
326 strcpy(tname
+flen
, BackupSuffix
);
328 if (IS_OVERWRT_ALL
) {
329 /* If there is a previous backup file, delete it,
330 * otherwise the following rename operation may fail.
332 if (SSTAT(tname
, &tmpstat
) == 0)
335 /* Check if backupname exists, and, if it's true, try
336 * appending numbers of up to 5 digits (or the maximum
337 * "unsigned int" number on 16-bit systems) to the
338 * BackupSuffix, until an unused name is found.
341 char *numtail
= tname
+ flen
+ blen
;
343 /* take account of the "unsigned" limit on 16-bit systems: */
344 maxtail
= ( ((~0) >= 99999L) ? 99999 : (~0) );
345 switch (tlen
- flen
- blen
- 1) {
346 case 4: maxtail
= 9999; break;
347 case 3: maxtail
= 999; break;
348 case 2: maxtail
= 99; break;
349 case 1: maxtail
= 9; break;
350 case 0: maxtail
= 0; break;
352 /* while filename exists */
353 for (i
= 0; (i
< maxtail
) && (SSTAT(tname
, &tmpstat
) == 0);)
354 sprintf(numtail
,"%u", ++i
);
357 if (rename(G
.filename
, tname
) != 0) { /* move file */
358 Info(slide
, 0x401, ((char *)slide
,
359 LoadFarString(CannotRenameOldFile
),
360 FnFilter1(G
.filename
), strerror(errno
)));
364 Trace((stderr
, "open_outfile: %s now renamed into %s\n",
365 FnFilter1(G
.filename
), FnFilter2(tname
)));
368 #endif /* UNIXBACKUP */
370 #ifdef DOS_FLX_OS2_W32
371 if (!(G
.statbuf
.st_mode
& S_IWRITE
)) {
373 "open_outfile: existing file %s is read-only\n",
374 FnFilter1(G
.filename
)));
375 chmod(G
.filename
, S_IREAD
| S_IWRITE
);
376 Trace((stderr
, "open_outfile: %s now writable\n",
377 FnFilter1(G
.filename
)));
379 #endif /* DOS_FLX_OS2_W32 */
381 /* Give the file read/write permission (non-POSIX shortcut) */
382 chmod(G
.filename
, 0);
384 if (unlink(G
.filename
) != 0) {
385 Info(slide
, 0x401, ((char *)slide
,
386 LoadFarString(CannotDeleteOldFile
),
387 FnFilter1(G
.filename
), strerror(errno
)));
390 Trace((stderr
, "open_outfile: %s now deleted\n",
391 FnFilter1(G
.filename
)));
394 #endif /* DOS_FLX_NLM_OS2_W32 || ATH_BEO_THS_UNX */
396 if (SWI_OS_File_7(G
.filename
,0xDEADDEAD,0xDEADDEAD,G
.lrec
.ucsize
)!=NULL
) {
397 Info(slide
, 1, ((char *)slide
, LoadFarString(CannotCreateFile
),
398 FnFilter1(G
.filename
), strerror(errno
)));
405 if ((tfilnam
= (char *)malloc(2*strlen(G
.filename
)+1)) == (char *)NULL
)
407 strcpy(tfilnam
, G
.filename
);
410 if ((G
.outfile
= fopen(tfilnam
, FOPW
)) == (FILE *)NULL
) {
411 Info(slide
, 1, ((char *)slide
, LoadFarString(CannotCreateFile
),
412 tfilnam
, strerror(errno
)));
420 G
.outfile
= zfopen(G
.filename
, FOPWT
);
422 G
.outfile
= zfopen(G
.filename
, FOPW
);
423 if (G
.outfile
== (FILE *)NULL
) {
424 Info(slide
, 1, ((char *)slide
, LoadFarString(CannotCreateFile
),
425 FnFilter1(G
.filename
), strerror(errno
)));
430 Info(slide
, 1, ((char *)slide
,
431 "open_outfile: doing fopen(%s) for reading\n", FnFilter1(G
.filename
)));
432 if ((G
.outfile
= zfopen(G
.filename
, FOPR
)) == (FILE *)NULL
)
433 Info(slide
, 1, ((char *)slide
,
434 "open_outfile: fopen(%s) for reading failed: does not exist\n",
435 FnFilter1(G
.filename
)));
437 Info(slide
, 1, ((char *)slide
,
438 "open_outfile: fopen(%s) for reading succeeded: file exists\n",
439 FnFilter1(G
.filename
)));
443 #ifdef NOVELL_BUG_FAILSAFE
444 if (G
.dne
&& ((G
.outfile
= zfopen(G
.filename
, FOPR
)) != (FILE *)NULL
)) {
445 Info(slide
, 0x401, ((char *)slide
, LoadFarString(NovellBug
),
446 FnFilter1(G
.filename
)));
448 return 1; /* with "./" fix in checkdir(), should never reach here */
450 #endif /* NOVELL_BUG_FAILSAFE */
451 Trace((stderr
, "open_outfile: doing fopen(%s) for writing\n",
452 FnFilter1(G
.filename
)));
454 #if defined(ATH_BE_UNX) || defined(AOS_VS) || defined(QDOS) || defined(TANDEM)
455 mode_t umask_sav
= umask(0077);
457 #if defined(SYMLINKS) || defined(QLZIP)
458 /* These features require the ability to re-read extracted data from
459 the output files. Output files are created with Read&Write access.
461 G
.outfile
= zfopen(G
.filename
, FOPWR
);
463 G
.outfile
= zfopen(G
.filename
, FOPW
);
465 #if defined(ATH_BE_UNX) || defined(AOS_VS) || defined(QDOS) || defined(TANDEM)
469 if (G
.outfile
== (FILE *)NULL
) {
470 Info(slide
, 0x401, ((char *)slide
, LoadFarString(CannotCreateFile
),
471 FnFilter1(G
.filename
), strerror(errno
)));
474 Trace((stderr
, "open_outfile: fopen(%s) for writing succeeded\n",
475 FnFilter1(G
.filename
)));
480 #ifdef DOS_NLM_OS2_W32
481 /* 16-bit MSC: buffer size must be strictly LESS than 32K (WSIZE): bogus */
482 setbuf(G
.outfile
, (char *)NULL
); /* make output unbuffered */
483 #else /* !DOS_NLM_OS2_W32 */
485 #ifdef _IOFBF /* make output fully buffered (works just about like write()) */
486 setvbuf(G
.outfile
, (char *)slide
, _IOFBF
, WSIZE
);
488 setbuf(G
.outfile
, (char *)slide
);
491 #endif /* ?DOS_NLM_OS2_W32 */
492 #endif /* USE_FWRITE */
494 /* preallocate the final file size to prevent file fragmentation */
495 SetFileSize(G
.outfile
, G
.lrec
.ucsize
);
499 } /* end function open_outfile() */
502 #endif /* !VMS && !AOS_VS && !CMS_MVS && !MACOS */
509 * These functions allow NEXTBYTE to function without needing two bounds
510 * checks. Call defer_leftover_input() if you ever have filled G.inbuf
511 * by some means other than readbyte(), and you then want to start using
512 * NEXTBYTE. When going back to processing bytes without NEXTBYTE, call
513 * undefer_input(). For example, extract_or_test_member brackets its
514 * central section that does the decompression with these two functions.
515 * If you need to check the number of bytes remaining in the current
516 * file while using NEXTBYTE, check (G.csize + G.incnt), not G.csize.
519 /****************************/
520 /* function undefer_input() */
521 /****************************/
523 void undefer_input(__G
)
528 if (G
.incnt_leftover
> 0) {
529 /* We know that "(G.csize < MAXINT)" so we can cast G.csize to int:
530 * This condition was checked when G.incnt_leftover was set > 0 in
531 * defer_leftover_input(), and it is NOT allowed to touch G.csize
532 * before calling undefer_input() when (G.incnt_leftover > 0)
533 * (single exception: see read_byte()'s "G.csize <= 0" handling) !!
535 G
.incnt
= G
.incnt_leftover
+ (int)G
.csize
;
536 G
.inptr
= G
.inptr_leftover
- (int)G
.csize
;
537 G
.incnt_leftover
= 0;
538 } else if (G
.incnt
< 0)
540 } /* end function undefer_input() */
546 /***********************************/
547 /* function defer_leftover_input() */
548 /***********************************/
550 void defer_leftover_input(__G
)
553 if ((zoff_t
)G
.incnt
> G
.csize
) {
554 /* (G.csize < MAXINT), we can safely cast it to int !! */
557 G
.inptr_leftover
= G
.inptr
+ (int)G
.csize
;
558 G
.incnt_leftover
= G
.incnt
- (int)G
.csize
;
559 G
.incnt
= (int)G
.csize
;
561 G
.incnt_leftover
= 0;
563 } /* end function defer_leftover_input() */
569 /**********************/
570 /* Function readbuf() */
571 /**********************/
573 unsigned readbuf(__G__ buf
, size
) /* return number of bytes read into buf */
576 register unsigned size
;
578 register unsigned count
;
584 if ((G
.incnt
= read(G
.zipfd
, (char *)G
.inbuf
, INBUFSIZ
)) == 0)
586 else if (G
.incnt
< 0) {
587 /* another hack, but no real harm copying same thing twice */
588 (*G
.message
)((zvoid
*)&G
,
589 (uch
*)LoadFarString(ReadError
), /* CANNOT use slide */
590 (ulg
)strlen(LoadFarString(ReadError
)), 0x401);
591 return 0; /* discarding some data; better than lock-up */
593 /* buffer ALWAYS starts on a block boundary: */
594 G
.cur_zipfile_bufstart
+= INBUFSIZ
;
597 count
= MIN(size
, (unsigned)G
.incnt
);
598 memcpy(buf
, G
.inptr
, count
);
606 } /* end function readbuf() */
612 /***********************/
613 /* Function readbyte() */
614 /***********************/
616 int readbyte(__G
) /* refill inbuf and return a byte if available, else EOF */
622 G
.csize
--; /* for tests done after exploding */
627 if ((G
.incnt
= read(G
.zipfd
, (char *)G
.inbuf
, INBUFSIZ
)) == 0) {
629 } else if (G
.incnt
< 0) { /* "fail" (abort, retry, ...) returns this */
630 /* another hack, but no real harm copying same thing twice */
631 (*G
.message
)((zvoid
*)&G
,
632 (uch
*)LoadFarString(ReadError
),
633 (ulg
)strlen(LoadFarString(ReadError
)), 0x401);
636 longjmp(dll_error_return
, 1);
639 EXIT(PK_BADERR
); /* totally bailing; better than lock-up */
642 G
.cur_zipfile_bufstart
+= INBUFSIZ
; /* always starts on block bndry */
644 defer_leftover_input(__G
); /* decrements G.csize */
648 if (G
.pInfo
->encrypted
) {
652 /* This was previously set to decrypt one byte beyond G.csize, when
653 * incnt reached that far. GRR said, "but it's required: why?" This
654 * was a bug in fillinbuf() -- was it also a bug here?
656 for (n
= G
.incnt
, p
= G
.inptr
; n
--; p
++)
664 } /* end function readbyte() */
670 #if defined(USE_ZLIB) || defined(USE_BZIP2)
672 /************************/
673 /* Function fillinbuf() */
674 /************************/
676 int fillinbuf(__G
) /* like readbyte() except returns number of bytes in inbuf */
680 (G
.incnt
= read(G
.zipfd
, (char *)G
.inbuf
, INBUFSIZ
)) <= 0)
682 G
.cur_zipfile_bufstart
+= INBUFSIZ
; /* always starts on a block boundary */
684 defer_leftover_input(__G
); /* decrements G.csize */
687 if (G
.pInfo
->encrypted
) {
691 for (n
= G
.incnt
, p
= G
.inptr
; n
--; p
++)
698 } /* end function fillinbuf() */
700 #endif /* USE_ZLIB || USE_BZIP2 */
706 /************************/
707 /* Function seek_zipf() */
708 /************************/
710 int seek_zipf(__G__ abs_offset
)
715 * Seek to the block boundary of the block which includes abs_offset,
716 * then read block into input buffer and set pointers appropriately.
717 * If block is already in the buffer, just set the pointers. This function
718 * is used by do_seekable (process.c), extract_or_test_entrylist (extract.c)
719 * and do_string (fileio.c). Also, a slightly modified version is embedded
720 * within extract_or_test_entrylist (extract.c). readbyte() and readbuf()
721 * (fileio.c) are compatible. NOTE THAT abs_offset is intended to be the
722 * "proper offset" (i.e., if there were no extra bytes prepended);
723 * cur_zipfile_bufstart contains the corrected offset.
725 * Since seek_zipf() is never used during decompression, it is safe to
726 * use the slide[] buffer for the error message.
728 * returns PK error codes:
729 * PK_BADERR if effective offset in zipfile is negative
730 * PK_EOF if seeking past end of zipfile
731 * PK_OK when seek was successful
733 zoff_t request
= abs_offset
+ G
.extra_bytes
;
734 zoff_t inbuf_offset
= request
% INBUFSIZ
;
735 zoff_t bufstart
= request
- inbuf_offset
;
738 Info(slide
, 1, ((char *)slide
, LoadFarStringSmall(SeekMsg
),
739 G
.zipfn
, LoadFarString(ReportMsg
)));
741 } else if (bufstart
!= G
.cur_zipfile_bufstart
) {
743 "fpos_zip: abs_offset = %s, G.extra_bytes = %s\n",
744 FmZofft(abs_offset
, NULL
, NULL
),
745 FmZofft(G
.extra_bytes
, NULL
, NULL
)));
746 #ifdef USE_STRM_INPUT
747 zfseeko(G
.zipfd
, bufstart
, SEEK_SET
);
748 G
.cur_zipfile_bufstart
= zftello(G
.zipfd
);
749 #else /* !USE_STRM_INPUT */
750 G
.cur_zipfile_bufstart
= zlseek(G
.zipfd
, bufstart
, SEEK_SET
);
751 #endif /* ?USE_STRM_INPUT */
753 " request = %s, (abs+extra) = %s, inbuf_offset = %s\n",
754 FmZofft(request
, NULL
, NULL
),
755 FmZofft((abs_offset
+G
.extra_bytes
), NULL
, NULL
),
756 FmZofft(inbuf_offset
, NULL
, NULL
)));
757 Trace((stderr
, " bufstart = %s, cur_zipfile_bufstart = %s\n",
758 FmZofft(bufstart
, NULL
, NULL
),
759 FmZofft(G
.cur_zipfile_bufstart
, NULL
, NULL
)));
760 if ((G
.incnt
= read(G
.zipfd
, (char *)G
.inbuf
, INBUFSIZ
)) <= 0)
762 G
.incnt
-= (int)inbuf_offset
;
763 G
.inptr
= G
.inbuf
+ (int)inbuf_offset
;
765 G
.incnt
+= (G
.inptr
-G
.inbuf
) - (int)inbuf_offset
;
766 G
.inptr
= G
.inbuf
+ (int)inbuf_offset
;
769 } /* end function seek_zipf() */
775 #ifndef VMS /* for VMS use code in vms.c */
777 /********************/
778 /* Function flush() */ /* returns PK error codes: */
779 /********************/ /* if tflag => always 0; PK_DISK if write error */
781 int flush(__G__ rawbuf
, size
, unshrink
)
786 #if (defined(USE_DEFLATE64) && defined(__16BIT__))
790 /* On 16-bit systems (MSDOS, OS/2 1.x), the standard C library functions
791 * cannot handle writes of 64k blocks at once. For these systems, the
792 * blocks to flush are split into pieces of 32k or less.
794 while (size
> 0x8000L
) {
795 ret
= partflush(__G__ rawbuf
, 0x8000L
, unshrink
);
799 rawbuf
+= (extent
)0x8000;
801 return partflush(__G__ rawbuf
, size
, unshrink
);
802 } /* end function flush() */
805 /************************/
806 /* Function partflush() */ /* returns PK error codes: */
807 /************************/ /* if tflag => always 0; PK_DISK if write error */
809 static int partflush(__G__ rawbuf
, size
, unshrink
)
811 uch
*rawbuf
; /* cannot be ZCONST, gets passed to (*G.message)() */
814 #endif /* USE_DEFLATE64 && __16BIT__ */
819 #if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV))
822 /* static int didCRlast = FALSE; moved to globals.h */
825 /*---------------------------------------------------------------------------
826 Compute the CRC first; if testing or if disk is full, that's it.
827 ---------------------------------------------------------------------------*/
829 G
.crc32val
= crc32(G
.crc32val
, rawbuf
, (extent
)size
);
832 if ((G
.statreportcb
!= NULL
) &&
833 (*G
.statreportcb
)(__G__ UZ_ST_IN_PROGRESS
, G
.zipfn
, G
.filename
, NULL
))
834 return IZ_CTRLC
; /* cancel operation by user request */
837 if (uO
.tflag
|| size
== 0L) /* testing or nothing to write: all done */
841 return PK_DISK
; /* disk already full: ignore rest of file */
843 /*---------------------------------------------------------------------------
844 Write the bytes rawbuf[0..size-1] to the output device, first converting
845 end-of-lines and ASCII/EBCDIC as needed. If SMALL_MEM or MED_MEM are NOT
846 defined, outbuf is assumed to be at least as large as rawbuf and is not
847 necessarily checked for overflow.
848 ---------------------------------------------------------------------------*/
850 if (!G
.pInfo
->textmode
) { /* write raw binary data */
851 /* GRR: note that for standard MS-DOS compilers, size argument to
852 * fwrite() can never be more than 65534, so WriteError macro will
853 * have to be rewritten if size can ever be that large. For now,
854 * never more than 32K. Also note that write() returns an int, which
855 * doesn't necessarily limit size to 32767 bytes if write() is used
856 * on 16-bit systems but does make it more of a pain; however, because
857 * at least MSC 5.1 has a lousy implementation of fwrite() (as does
858 * DEC Ultrix cc), write() is used anyway.
861 if (G
.redirect_data
) {
862 #ifdef NO_SLIDE_REDIR
863 if (writeToMemory(__G__ rawbuf
, (extent
)size
)) return PK_ERR
;
865 writeToMemory(__G__ rawbuf
, (extent
)size
);
869 if (!uO
.cflag
&& WriteError(rawbuf
, size
, G
.outfile
))
870 return disk_error(__G
);
871 else if (uO
.cflag
&& (*G
.message
)((zvoid
*)&G
, rawbuf
, size
, 0))
873 } else { /* textmode: aflag is true */
875 /* rawbuf = outbuf */
876 transbuf
= G
.outbuf2
;
877 #if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV))
878 transbufsiz
= TRANSBUFSIZ
;
883 #if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV))
884 transbufsiz
= OUTBUFSIZ
;
885 Trace((stderr
, "\ntransbufsiz = OUTBUFSIZ = %u\n",
886 (unsigned)OUTBUFSIZ
));
891 if (G
.pInfo
->hostnum
== VMS_
&& G
.extra_field
&&
892 is_vms_varlen_txt(__G__ G
.extra_field
,
893 G
.lrec
.extra_field_length
))
894 G
.VMS_line_state
= 0; /* 0: ready to read line length */
896 G
.VMS_line_state
= -1; /* -1: don't treat as VMS text */
898 G
.didCRlast
= FALSE
; /* no previous buffers written */
903 if (G
.VMS_line_state
>= 0)
907 while ((extent
)(p
-rawbuf
) < (extent
)size
) {
908 switch (G
.VMS_line_state
) {
910 /* 0: ready to read line length */
912 G
.VMS_line_length
= 0;
913 if ((extent
)(p
-rawbuf
) == (extent
)size
-1) {
915 G
.VMS_line_length
= (unsigned)(*p
++);
916 G
.VMS_line_state
= 1;
918 G
.VMS_line_length
= makeword(p
);
920 G
.VMS_line_state
= 2;
923 ((G
.VMS_line_length
& 1) != 0); /* odd */
926 /* 1: read one byte of length, need second */
928 G
.VMS_line_length
+= ((unsigned)(*p
++) << 8);
929 G
.VMS_line_state
= 2;
932 /* 2: ready to read VMS_line_length chars */
935 extent remaining
= (extent
)size
+(rawbuf
-p
);
938 if (G
.VMS_line_length
< remaining
) {
939 remaining
= G
.VMS_line_length
;
940 G
.VMS_line_state
= 3;
943 outroom
= transbuf
+(extent
)transbufsiz
-q
;
944 if (remaining
>= outroom
) {
945 remaining
-= outroom
;
946 for (;outroom
> 0; p
++, outroom
--)
949 if (G
.redirect_data
) {
950 if (writeToMemory(__G__ transbuf
,
951 (extent
)(q
-transbuf
))) return PK_ERR
;
954 if (!uO
.cflag
&& WriteError(transbuf
,
955 (extent
)(q
-transbuf
), G
.outfile
))
956 return disk_error(__G
);
957 else if (uO
.cflag
&& (*G
.message
)((zvoid
*)&G
,
958 transbuf
, (ulg
)(q
-transbuf
), 0))
961 /* fall through to normal case */
963 G
.VMS_line_length
-= remaining
;
964 for (;remaining
> 0; p
++, remaining
--)
969 /* 3: ready to PutNativeEOL */
971 if (q
> transbuf
+(extent
)transbufsiz
-lenEOL
) {
973 if (G
.redirect_data
) {
974 if (writeToMemory(__G__ transbuf
,
975 (extent
)(q
-transbuf
))) return PK_ERR
;
979 WriteError(transbuf
, (extent
)(q
-transbuf
),
981 return disk_error(__G
);
982 else if (uO
.cflag
&& (*G
.message
)((zvoid
*)&G
,
983 transbuf
, (ulg
)(q
-transbuf
), 0))
988 G
.VMS_line_state
= G
.VMS_line_pad
? 4 : 0;
991 /* 4: ready to read pad byte */
994 G
.VMS_line_state
= 0;
1000 #endif /* VMS_TEXT_CONV */
1002 /*-----------------------------------------------------------------------
1003 Algorithm: CR/LF => native; lone CR => native; lone LF => native.
1004 This routine is only for non-raw-VMS, non-raw-VM/CMS files (i.e.,
1005 stream-oriented files, not record-oriented).
1006 -----------------------------------------------------------------------*/
1008 /* else not VMS text */ {
1010 if (*p
== LF
&& G
.didCRlast
)
1012 G
.didCRlast
= FALSE
;
1013 for (q
= transbuf
; (extent
)(p
-rawbuf
) < (extent
)size
; ++p
) {
1014 if (*p
== CR
) { /* lone CR or CR/LF: treat as EOL */
1016 if ((extent
)(p
-rawbuf
) == (extent
)size
-1)
1017 /* last char in buffer */
1019 else if (p
[1] == LF
) /* get rid of accompanying LF */
1021 } else if (*p
== LF
) /* lone LF */
1024 #ifndef DOS_FLX_OS2_W32
1025 if (*p
!= CTRLZ
) /* lose all ^Z's */
1029 #if (defined(SMALL_MEM) || defined(MED_MEM))
1030 # if (lenEOL == 1) /* don't check unshrink: both buffers small but equal */
1033 /* check for danger of buffer overflow and flush */
1034 if (q
> transbuf
+(extent
)transbufsiz
-lenEOL
) {
1036 "p - rawbuf = %u q-transbuf = %u size = %lu\n",
1037 (unsigned)(p
-rawbuf
), (unsigned)(q
-transbuf
), size
));
1038 if (!uO
.cflag
&& WriteError(transbuf
,
1039 (extent
)(q
-transbuf
), G
.outfile
))
1040 return disk_error(__G
);
1041 else if (uO
.cflag
&& (*G
.message
)((zvoid
*)&G
,
1042 transbuf
, (ulg
)(q
-transbuf
), 0))
1047 #endif /* SMALL_MEM || MED_MEM */
1051 /*-----------------------------------------------------------------------
1052 Done translating: write whatever we've got to file (or screen).
1053 -----------------------------------------------------------------------*/
1055 Trace((stderr
, "p - rawbuf = %u q-transbuf = %u size = %lu\n",
1056 (unsigned)(p
-rawbuf
), (unsigned)(q
-transbuf
), size
));
1059 if (G
.redirect_data
) {
1060 if (writeToMemory(__G__ transbuf
, (extent
)(q
-transbuf
)))
1064 if (!uO
.cflag
&& WriteError(transbuf
, (extent
)(q
-transbuf
),
1066 return disk_error(__G
);
1067 else if (uO
.cflag
&& (*G
.message
)((zvoid
*)&G
, transbuf
,
1068 (ulg
)(q
-transbuf
), 0))
1075 } /* end function flush() [resp. partflush() for 16-bit Deflate64 support] */
1081 #ifdef VMS_TEXT_CONV
1083 /********************************/
1084 /* Function is_vms_varlen_txt() */
1085 /********************************/
1087 static int is_vms_varlen_txt(__G__ ef_buf
, ef_len
)
1089 uch
*ef_buf
; /* buffer containing extra field */
1090 unsigned ef_len
; /* total length of extra field */
1096 #define VMSREC_C_UNDEF 0
1097 #define VMSREC_C_VAR 2
1098 uch vms_rectype
= VMSREC_C_UNDEF
;
1099 /* uch vms_fileorg = 0; */ /* currently, fileorg is not used... */
1101 #define VMSPK_ITEMID 0
1102 #define VMSPK_ITEMLEN 2
1103 #define VMSPK_ITEMHEADSZ 4
1105 #define VMSATR_C_RECATTR 4
1106 #define VMS_FABSIG 0x42414656 /* "VFAB" */
1107 /* offsets of interesting fields in VMS fabdef structure */
1108 #define VMSFAB_B_RFM 31 /* record format byte */
1109 #define VMSFAB_B_ORG 29 /* file organization byte */
1111 if (ef_len
== 0 || ef_buf
== NULL
)
1114 while (ef_len
>= EB_HEADSIZE
) {
1115 eb_id
= makeword(EB_ID
+ ef_buf
);
1116 eb_len
= makeword(EB_LEN
+ ef_buf
);
1118 if (eb_len
> (ef_len
- EB_HEADSIZE
)) {
1119 /* discovered some extra field inconsistency! */
1121 "is_vms_varlen_txt: block length %u > rest ef_size %u\n", eb_len
,
1122 ef_len
- EB_HEADSIZE
));
1128 /* The PKVMS e.f. raw data part consists of:
1129 * a) 4 bytes CRC checksum
1130 * b) list of uncompressed variable-length data items
1131 * Each data item is introduced by a fixed header
1132 * - 2 bytes data type ID
1133 * - 2 bytes <size> of data
1134 * - <size> bytes of actual attribute data
1137 /* get pointer to start of data and its total length */
1138 eb_data
= ef_buf
+(EB_HEADSIZE
+4);
1139 eb_datlen
= eb_len
-4;
1141 /* test the CRC checksum */
1142 if (makelong(ef_buf
+EB_HEADSIZE
) !=
1143 crc32(CRCVAL_INITIAL
, eb_data
, (extent
)eb_datlen
))
1145 Info(slide
, 1, ((char *)slide
,
1146 "[Warning: CRC error, discarding PKWARE extra field]\n"));
1147 /* skip over the data analysis code */
1151 /* scan through the attribute data items */
1152 while (eb_datlen
> 4)
1154 unsigned fldsize
= makeword(&eb_data
[VMSPK_ITEMLEN
]);
1156 /* check the item type word */
1157 switch (makeword(&eb_data
[VMSPK_ITEMID
])) {
1158 case VMSATR_C_RECATTR
:
1159 /* we have found the (currently only) interesting
1162 vms_rectype
= eb_data
[VMSPK_ITEMHEADSZ
] & 15;
1163 /* vms_fileorg = eb_data[VMSPK_ITEMHEADSZ] >> 4; */
1169 /* skip to next data item */
1170 eb_datlen
-= fldsize
+ VMSPK_ITEMHEADSZ
;
1171 eb_data
+= fldsize
+ VMSPK_ITEMHEADSZ
;
1176 if (makelong(ef_buf
+EB_HEADSIZE
) == VMS_FABSIG
) {
1177 if ((eb_data
= extract_izvms_block(__G__
1178 ef_buf
+EB_HEADSIZE
, eb_len
,
1179 &eb_datlen
, NULL
, 0))
1182 if (eb_datlen
>= VMSFAB_B_RFM
+1) {
1183 vms_rectype
= eb_data
[VMSFAB_B_RFM
] & 15;
1184 /* vms_fileorg = eb_data[VMSFAB_B_ORG] >> 4; */
1195 /* Skip this extra field block */
1196 ef_buf
+= (eb_len
+ EB_HEADSIZE
);
1197 ef_len
-= (eb_len
+ EB_HEADSIZE
);
1200 return (vms_rectype
== VMSREC_C_VAR
);
1202 } /* end function is_vms_varlen_txtfile() */
1204 #endif /* VMS_TEXT_CONV */
1209 /*************************/
1210 /* Function disk_error() */
1211 /*************************/
1213 static int disk_error(__G
)
1216 /* OK to use slide[] here because this file is finished regardless */
1217 Info(slide
, 0x4a1, ((char *)slide
, LoadFarString(DiskFullQuery
),
1218 FnFilter1(G
.filename
)));
1221 fgets(G
.answerbuf
, sizeof(G
.answerbuf
), stdin
);
1222 if (*G
.answerbuf
== 'y') /* stop writing to this file */
1223 G
.disk_full
= 1; /* (outfile bad?), but new OK */
1226 G
.disk_full
= 2; /* no: exit program */
1230 } /* end function disk_error() */
1238 /*****************************/
1239 /* Function UzpMessagePrnt() */
1240 /*****************************/
1242 int UZ_EXP
UzpMessagePrnt(pG
, buf
, size
, flag
)
1243 zvoid
*pG
; /* globals struct: always passed */
1244 uch
*buf
; /* preformatted string to be printed */
1245 ulg size
; /* length of string (may include nulls) */
1246 int flag
; /* flag bits */
1249 * The name of the first parameter of UzpMessagePrnt(), which passes
1250 * the "Uz_Globs" address, >>> MUST <<< be identical to the string
1251 * expansion of the __G__ macro in the REENTRANT case (see globals.h).
1252 * This name identity is mandatory for the LoadFarString() macro
1253 * (in the SMALL_MEM case) !!!
1256 uch
*q
=buf
, *endbuf
=buf
+(unsigned)size
;
1259 #if (defined(SCREENWIDTH) && defined(SCREENLWRAP))
1260 int islinefeed
= FALSE
;
1266 /*---------------------------------------------------------------------------
1267 These tests are here to allow fine-tuning of UnZip's output messages,
1268 but none of them will do anything without setting the appropriate bit
1269 in the flag argument of every Info() statement which is to be turned
1270 *off*. That is, all messages are currently turned on for all ports.
1271 To turn off *all* messages, use the UzpMessageNull() function instead
1273 ---------------------------------------------------------------------------*/
1275 #if (defined(OS2) && defined(DLL))
1276 if (MSG_NO_DLL2(flag
)) /* if OS/2 DLL bit is set, do NOT print this msg */
1280 if (MSG_NO_WDLL(flag
))
1284 if (MSG_NO_WGUI(flag
))
1289 if (MSG_NO_AGUI(flag))
1293 #ifdef DLL /* don't display message if data is redirected */
1294 if (((Uz_Globs
*)pG
)->redirect_data
&&
1295 !((Uz_Globs
*)pG
)->redirect_text
)
1299 if (MSG_STDERR(flag
) && !((Uz_Globs
*)pG
)->UzO
.tflag
)
1300 outfp
= (FILE *)stderr
;
1302 outfp
= (FILE *)stdout
;
1304 #ifdef QUERY_TRNEWLN
1305 /* some systems require termination of query prompts with '\n' to force
1306 * immediate display */
1307 if (MSG_MNEWLN(flag
)) { /* assumes writable buffer (e.g., slide[]) */
1308 *endbuf
++ = '\n'; /* with room for one more char at end of buf */
1309 ++size
; /* (safe assumption: only used for four */
1310 } /* short queries in extract.c and fileio.c) */
1313 if (MSG_TNEWLN(flag
)) { /* again assumes writable buffer: fragile... */
1314 if ((!size
&& !((Uz_Globs
*)pG
)->sol
) ||
1315 (size
&& (endbuf
[-1] != '\n')))
1324 /* room for --More-- and one line of overlap: */
1325 # if (defined(SCREENWIDTH) && defined(SCREENLWRAP))
1326 SCREENSIZE(&((Uz_Globs
*)pG
)->height
, &((Uz_Globs
*)pG
)->width
);
1328 SCREENSIZE(&((Uz_Globs
*)pG
)->height
, (int *)NULL
);
1330 ((Uz_Globs
*)pG
)->height
-= 2;
1332 /* room for --More-- and one line of overlap: */
1333 ((Uz_Globs
*)pG
)->height
= SCREENLINES
- 2;
1334 # if (defined(SCREENWIDTH) && defined(SCREENLWRAP))
1335 ((Uz_Globs
*)pG
)->width
= SCREENWIDTH
;
1340 if (MSG_LNEWLN(flag
) && !((Uz_Globs
*)pG
)->sol
) {
1341 /* not at start of line: want newline */
1343 if (!((Uz_Globs
*)pG
)->redirect_text
) {
1348 if (((Uz_Globs
*)pG
)->M_flag
)
1350 #if (defined(SCREENWIDTH) && defined(SCREENLWRAP))
1351 ((Uz_Globs
*)pG
)->chars
= 0;
1353 ++((Uz_Globs
*)pG
)->numlines
;
1354 ++((Uz_Globs
*)pG
)->lines
;
1355 if (((Uz_Globs
*)pG
)->lines
>= ((Uz_Globs
*)pG
)->height
)
1356 (*((Uz_Globs
*)pG
)->mpause
)((zvoid
*)pG
,
1357 LoadFarString(MorePrompt
), 1);
1360 if (MSG_STDERR(flag
) && ((Uz_Globs
*)pG
)->UzO
.tflag
&&
1361 !isatty(1) && isatty(2))
1363 /* error output from testing redirected: also send to stderr */
1371 ((Uz_Globs
*)pG
)->sol
= TRUE
;
1374 /* put zipfile name, filename and/or error/warning keywords here */
1377 if (((Uz_Globs
*)pG
)->M_flag
1379 && !((Uz_Globs
*)pG
)->redirect_text
1383 while (p
< endbuf
) {
1385 #if (defined(SCREENWIDTH) && defined(SCREENLWRAP))
1387 } else if (SCREENLWRAP
) {
1389 ((Uz_Globs
*)pG
)->chars
= 0;
1393 ((Uz_Globs
*)pG
)->chars
+=
1394 (TABSIZE
- (((Uz_Globs
*)pG
)->chars
% TABSIZE
));
1397 ++((Uz_Globs
*)pG
)->chars
;
1399 if (((Uz_Globs
*)pG
)->chars
>= ((Uz_Globs
*)pG
)->width
)
1405 ((Uz_Globs
*)pG
)->chars
= 0;
1406 #endif /* (SCREENWIDTH && SCREEN_LWRAP) */
1407 ++((Uz_Globs
*)pG
)->numlines
;
1408 ++((Uz_Globs
*)pG
)->lines
;
1409 if (((Uz_Globs
*)pG
)->lines
>= ((Uz_Globs
*)pG
)->height
)
1411 if ((error
= WriteTxtErr(q
, p
-q
+1, outfp
)) != 0)
1414 ((Uz_Globs
*)pG
)->sol
= TRUE
;
1416 (*((Uz_Globs
*)pG
)->mpause
)((zvoid
*)pG
,
1417 LoadFarString(MorePrompt
), 1);
1422 size
= (ulg
)(p
- q
); /* remaining text */
1428 if (!((Uz_Globs
*)pG
)->redirect_text
) {
1430 if ((error
= WriteTxtErr(q
, size
, outfp
)) != 0)
1432 #ifndef VMS /* 2005-09-16 SMS. See note at "WriteTxtErr()", above. */
1435 if (MSG_STDERR(flag
) && ((Uz_Globs
*)pG
)->UzO
.tflag
&&
1436 !isatty(1) && isatty(2))
1438 /* error output from testing redirected: also send to stderr */
1439 if ((error
= WriteTxtErr(q
, size
, stderr
)) != 0)
1444 } else { /* GRR: this is ugly: hide with macro */
1445 if ((error
= REDIRECTPRINT(q
, size
)) != 0)
1449 ((Uz_Globs
*)pG
)->sol
= (endbuf
[-1] == '\n');
1453 } /* end function UzpMessagePrnt() */
1461 /*****************************/
1462 /* Function UzpMessageNull() */ /* convenience routine for no output at all */
1463 /*****************************/
1465 int UZ_EXP
UzpMessageNull(pG
, buf
, size
, flag
)
1466 zvoid
*pG
; /* globals struct: always passed */
1467 uch
*buf
; /* preformatted string to be printed */
1468 ulg size
; /* length of string (may include nulls) */
1469 int flag
; /* flag bits */
1473 } /* end function UzpMessageNull() */
1481 /***********************/
1482 /* Function UzpInput() */ /* GRR: this is a placeholder for now */
1483 /***********************/
1485 int UZ_EXP
UzpInput(pG
, buf
, size
, flag
)
1486 zvoid
*pG
; /* globals struct: always passed */
1487 uch
*buf
; /* preformatted string to be printed */
1488 int *size
; /* (address of) size of buf and of returned string */
1489 int flag
; /* flag bits (bit 0: no echo) */
1491 /* tell picky compilers to shut up about "unused variable" warnings */
1492 pG
= pG
; buf
= buf
; flag
= flag
;
1497 } /* end function UzpInput() */
1503 #if (!defined(WINDLL) && !defined(MACOS))
1505 /***************************/
1506 /* Function UzpMorePause() */
1507 /***************************/
1509 void UZ_EXP
UzpMorePause(pG
, prompt
, flag
)
1510 zvoid
*pG
; /* globals struct: always passed */
1511 ZCONST
char *prompt
; /* "--More--" prompt */
1512 int flag
; /* 0 = any char OK; 1 = accept only '\n', ' ', q */
1516 /*---------------------------------------------------------------------------
1517 Print a prompt and wait for the user to press a key, then erase prompt
1519 ---------------------------------------------------------------------------*/
1521 if (!((Uz_Globs
*)pG
)->sol
)
1522 fprintf(stderr
, "\n");
1523 /* numlines may or may not be used: */
1524 fprintf(stderr
, prompt
, ((Uz_Globs
*)pG
)->numlines
);
1531 c
!= 17 && /* standard QUIT key */
1533 c
!= '\r' && c
!= '\n' && c
!= ' ' && c
!= 'q' && c
!= 'Q');
1537 /* newline was not echoed, so cover up prompt line */
1538 fprintf(stderr
, LoadFarString(HidePrompt
));
1543 (c
== 17) || /* standard QUIT key */
1545 (ToLower(c
) == 'q')) {
1550 ((Uz_Globs
*)pG
)->sol
= TRUE
;
1553 /* space for another screen, enter for another line. */
1554 if ((flag
& 1) && c
== ' ')
1555 ((Uz_Globs
*)pG
)->lines
= 0;
1558 } /* end function UzpMorePause() */
1560 #endif /* !WINDLL && !MACOS */
1567 /**************************/
1568 /* Function UzpPassword() */
1569 /**************************/
1571 int UZ_EXP
UzpPassword (pG
, rcnt
, pwbuf
, size
, zfn
, efn
)
1572 zvoid
*pG
; /* pointer to UnZip's internal global vars */
1573 int *rcnt
; /* retry counter */
1574 char *pwbuf
; /* buffer for password */
1575 int size
; /* size of password buffer */
1576 ZCONST
char *zfn
; /* name of zip archive */
1577 ZCONST
char *efn
; /* name of archive entry being processed */
1580 int r
= IZ_PW_ENTERED
;
1585 /* tell picky compilers to shut up about "unused variable" warnings */
1589 if (*rcnt
== 0) { /* First call for current entry */
1591 if ((prompt
= (char *)malloc(2*FILNAMSIZ
+ 15)) != (char *)NULL
) {
1592 sprintf(prompt
, LoadFarString(PasswPrompt
),
1593 FnFilter1(zfn
), FnFilter2(efn
));
1596 m
= (char *)LoadFarString(PasswPrompt2
);
1597 } else { /* Retry call, previous password was wrong */
1600 m
= (char *)LoadFarString(PasswRetry
);
1603 m
= getp(__G__ m
, pwbuf
, size
);
1604 if (prompt
!= (char *)NULL
) {
1607 if (m
== (char *)NULL
) {
1610 else if (*pwbuf
== '\0') {
1611 r
= IZ_PW_CANCELALL
;
1616 /* tell picky compilers to shut up about "unused variable" warnings */
1617 pG
= pG
; rcnt
= rcnt
; pwbuf
= pwbuf
; size
= size
; zfn
= zfn
; efn
= efn
;
1619 return IZ_PW_ERROR
; /* internal error; function should never get called */
1622 } /* end function UzpPassword() */
1628 /**********************/
1629 /* Function handler() */
1630 /**********************/
1632 void handler(signal
) /* upon interrupt, turn on echo and exit cleanly */
1637 #if !(defined(SIGBUS) || defined(SIGSEGV)) /* add a newline if not at */
1638 (*G
.message
)((zvoid
*)&G
, slide
, 0L, 0x41); /* start of line (to stderr; */
1639 #endif /* slide[] should be safe) */
1644 if (signal
== SIGBUS
) {
1645 Info(slide
, 0x421, ((char *)slide
, LoadFarString(ZipfileCorrupt
),
1653 if (signal
== SIGILL
) {
1654 Info(slide
, 0x421, ((char *)slide
, LoadFarString(ZipfileCorrupt
),
1655 "illegal instruction"));
1662 if (signal
== SIGSEGV
) {
1663 Info(slide
, 0x421, ((char *)slide
, LoadFarString(ZipfileCorrupt
),
1664 "segmentation violation"));
1668 #endif /* SIGSEGV */
1670 /* probably ctrl-C */
1672 #if defined(AMIGA) && defined(__SASC)
1675 EXIT(IZ_CTRLC
); /* was EXIT(0), then EXIT(PK_ERR) */
1678 #endif /* !WINDLL */
1683 #if (!defined(VMS) && !defined(CMS_MVS))
1684 #if (!defined(OS2) || defined(TIMESTAMP))
1686 #if (!defined(HAVE_MKTIME) || defined(WIN32))
1687 /* also used in amiga/filedate.c and win32/win32.c */
1688 ZCONST ush ydays
[] =
1689 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
1692 /*******************************/
1693 /* Function dos_to_unix_time() */ /* used for freshening/updating/timestamps */
1694 /*******************************/
1696 time_t dos_to_unix_time(dosdatetime
)
1703 ZCONST
time_t now
= time(NULL
);
1705 # define YRBASE 1900
1707 tm
= localtime(&now
);
1708 tm
->tm_isdst
= -1; /* let mktime determine if DST is in effect */
1711 tm
->tm_year
= ((int)(dosdatetime
>> 25) & 0x7f) + (1980 - YRBASE
);
1712 tm
->tm_mon
= ((int)(dosdatetime
>> 21) & 0x0f) - 1;
1713 tm
->tm_mday
= ((int)(dosdatetime
>> 16) & 0x1f);
1716 tm
->tm_hour
= (int)((unsigned)dosdatetime
>> 11) & 0x1f;
1717 tm
->tm_min
= (int)((unsigned)dosdatetime
>> 5) & 0x3f;
1718 tm
->tm_sec
= (int)((unsigned)dosdatetime
<< 1) & 0x3e;
1720 m_time
= mktime(tm
);
1721 NATIVE_TO_TIMET(m_time
) /* NOP unless MSC 7.0 or Macintosh */
1722 TTrace((stderr
, " final m_time = %lu\n", (ulg
)m_time
));
1724 #else /* !HAVE_MKTIME */
1726 int yr
, mo
, dy
, hh
, mm
, ss
;
1728 # define YRBASE 1900
1732 # define YRBASE 1970
1736 #if (!defined(MACOS) && !defined(RISCOS) && !defined(QDOS) && !defined(TANDEM))
1738 TIME_ZONE_INFORMATION tzinfo
;
1741 #ifndef BSD4_4 /* GRR: change to !defined(MODERN) ? */
1742 #if (defined(BSD) || defined(MTS) || defined(__GO32__))
1744 #else /* !(BSD || MTS || __GO32__) */
1745 #ifdef DECLARE_TIMEZONE
1746 extern time_t timezone
;
1748 #endif /* ?(BSD || MTS || __GO32__) */
1749 #endif /* !BSD4_4 */
1751 #endif /* !MACOS && !RISCOS && !QDOS && !TANDEM */
1752 #endif /* ?TOPS20 */
1756 yr
= ((int)(dosdatetime
>> 25) & 0x7f) + (1980 - YRBASE
);
1757 mo
= ((int)(dosdatetime
>> 21) & 0x0f) - 1;
1758 dy
= ((int)(dosdatetime
>> 16) & 0x1f) - 1;
1761 hh
= (int)((unsigned)dosdatetime
>> 11) & 0x1f;
1762 mm
= (int)((unsigned)dosdatetime
>> 5) & 0x3f;
1763 ss
= (int)((unsigned)dosdatetime
& 0x1f) * 2;
1766 tmx
= (struct tmx
*)malloc(sizeof(struct tmx
));
1767 sprintf (temp
, "%02d/%02d/%02d %02d:%02d:%02d", mo
+1, dy
+1, yr
, hh
, mm
, ss
);
1768 time_parse(temp
, tmx
, (char *)0);
1769 m_time
= time_make(tmx
);
1774 /*---------------------------------------------------------------------------
1775 Calculate the number of seconds since the epoch, usually 1 January 1970.
1776 ---------------------------------------------------------------------------*/
1778 /* leap = # of leap yrs from YRBASE up to but not including current year */
1779 leap
= ((yr
+ YRBASE
- 1) / 4); /* leap year base factor */
1781 /* calculate days from BASE to this year and add expired days this year */
1782 days
= (yr
* 365) + (leap
- 492) + ydays
[mo
];
1784 /* if year is a leap year and month is after February, add another day */
1785 if ((mo
> 1) && ((yr
+YRBASE
)%4 == 0) && ((yr
+YRBASE
) != 2100))
1786 ++days
; /* OK through 2199 */
1788 /* convert date & time to seconds relative to 00:00:00, 01/01/YRBASE */
1789 m_time
= (time_t)((unsigned long)(days
+ dy
) * 86400L +
1790 (unsigned long)hh
* 3600L +
1791 (unsigned long)(mm
* 60 + ss
));
1792 /* - 1; MS-DOS times always rounded up to nearest even second */
1793 TTrace((stderr
, "dos_to_unix_time:\n"));
1794 TTrace((stderr
, " m_time before timezone = %lu\n", (ulg
)m_time
));
1796 /*---------------------------------------------------------------------------
1797 Adjust for local standard timezone offset.
1798 ---------------------------------------------------------------------------*/
1800 #if (!defined(MACOS) && !defined(RISCOS) && !defined(QDOS) && !defined(TANDEM))
1802 /* account for timezone differences */
1803 res
= GetTimeZoneInformation(&tzinfo
);
1804 if (res
!= TIME_ZONE_ID_INVALID
)
1806 m_time
+= 60*(tzinfo
.Bias
);
1808 #if (defined(BSD) || defined(MTS) || defined(__GO32__))
1810 if ( (dosdatetime
>= DOSTIME_2038_01_18
) &&
1811 (m_time
< (time_t)0x70000000L
) )
1812 m_time
= U_TIME_T_MAX
; /* saturate in case of (unsigned) overflow */
1813 if (m_time
< (time_t)0L) /* a converted DOS time cannot be negative */
1814 m_time
= S_TIME_T_MAX
; /* -> saturate at max signed time_t value */
1815 if ((tm
= localtime(&m_time
)) != (struct tm
*)NULL
)
1816 m_time
-= tm
->tm_gmtoff
; /* sec. EAST of GMT: subtr. */
1817 #else /* !(BSD4_4 */
1818 ftime(&tbp
); /* get `timezone' */
1819 m_time
+= tbp
.timezone
* 60L; /* seconds WEST of GMT: add */
1820 #endif /* ?(BSD4_4 || __EMX__) */
1821 #else /* !(BSD || MTS || __GO32__) */
1822 /* tzset was already called at start of process_zipfiles() */
1823 /* tzset(); */ /* set `timezone' variable */
1824 #ifndef __BEOS__ /* BeOS DR8 has no timezones... */
1825 m_time
+= timezone
; /* seconds WEST of GMT: add */
1827 #endif /* ?(BSD || MTS || __GO32__) */
1829 TTrace((stderr
, " m_time after timezone = %lu\n", (ulg
)m_time
));
1831 /*---------------------------------------------------------------------------
1832 Adjust for local daylight savings (summer) time.
1833 ---------------------------------------------------------------------------*/
1835 #ifndef BSD4_4 /* (DST already added to tm_gmtoff, so skip tm_isdst) */
1836 if ( (dosdatetime
>= DOSTIME_2038_01_18
) &&
1837 (m_time
< (time_t)0x70000000L
) )
1838 m_time
= U_TIME_T_MAX
; /* saturate in case of (unsigned) overflow */
1839 if (m_time
< (time_t)0L) /* a converted DOS time cannot be negative */
1840 m_time
= S_TIME_T_MAX
; /* -> saturate at max signed time_t value */
1841 TIMET_TO_NATIVE(m_time
) /* NOP unless MSC 7.0 or Macintosh */
1842 if (((tm
= localtime((time_t *)&m_time
)) != NULL
) && tm
->tm_isdst
)
1844 m_time
+= 60L * tzinfo
.DaylightBias
; /* adjust with DST bias */
1846 m_time
+= 60L * tzinfo
.StandardBias
; /* add StdBias (normally 0) */
1848 m_time
-= 60L * 60L; /* adjust for daylight savings time */
1850 NATIVE_TO_TIMET(m_time
) /* NOP unless MSC 7.0 or Macintosh */
1851 TTrace((stderr
, " m_time after DST = %lu\n", (ulg
)m_time
));
1852 #endif /* !BSD4_4 */
1856 #endif /* !MACOS && !RISCOS && !QDOS && !TANDEM */
1857 #endif /* ?TOPS20 */
1859 #endif /* ?HAVE_MKTIME */
1861 if ( (dosdatetime
>= DOSTIME_2038_01_18
) &&
1862 (m_time
< (time_t)0x70000000L
) )
1863 m_time
= U_TIME_T_MAX
; /* saturate in case of (unsigned) overflow */
1864 if (m_time
< (time_t)0L) /* a converted DOS time cannot be negative */
1865 m_time
= S_TIME_T_MAX
; /* -> saturate at max signed time_t value */
1869 } /* end function dos_to_unix_time() */
1871 #endif /* !OS2 || TIMESTAMP */
1872 #endif /* !VMS && !CMS_MVS */
1876 #if (!defined(VMS) && !defined(OS2) && !defined(CMS_MVS))
1878 /******************************/
1879 /* Function check_for_newer() */ /* used for overwriting/freshening/updating */
1880 /******************************/
1882 int check_for_newer(__G__ filename
) /* return 1 if existing file is newer */
1883 __GDEF
/* or equal; 0 if older; -1 if doesn't */
1884 char *filename
; /* exist yet */
1886 time_t existing
, archive
;
1887 #ifdef USE_EF_UT_TIME
1891 long dyy
, dmm
, ddd
, dhh
, dmin
, dss
;
1894 dyy
= (lrec
.last_mod_dos_datetime
>> 25) + 1980;
1895 dmm
= (lrec
.last_mod_dos_datetime
>> 21) & 0x0f;
1896 ddd
= (lrec
.last_mod_dos_datetime
>> 16) & 0x1f;
1897 dhh
= (lrec
.last_mod_dos_datetime
>> 11) & 0x1f;
1898 dmin
= (lrec
.last_mod_dos_datetime
>> 5) & 0x3f;
1899 dss
= (lrec
.last_mod_dos_datetime
& 0x1f) * 2;
1901 /* under AOS/VS, file times can only be set at creation time,
1902 * with the info in a special DG format. Make sure we can create
1903 * it here - we delete it later & re-create it, whether or not
1906 if (!zvs_create(filename
, (((ulg
)dgdate(dmm
, ddd
, dyy
)) << 16) |
1907 (dhh
*1800L + dmin
*30L + dss
/2L), -1L, -1L, (char *) -1, -1, -1, -1))
1908 return DOES_NOT_EXIST
;
1911 Trace((stderr
, "check_for_newer: doing stat(%s)\n", FnFilter1(filename
)));
1912 if (SSTAT(filename
, &G
.statbuf
)) {
1914 "check_for_newer: stat(%s) returns %d: file does not exist\n",
1915 FnFilter1(filename
), SSTAT(filename
, &G
.statbuf
)));
1917 Trace((stderr
, "check_for_newer: doing lstat(%s)\n",
1918 FnFilter1(filename
)));
1919 /* GRR OPTION: could instead do this test ONLY if G.symlnk is true */
1920 if (lstat(filename
, &G
.statbuf
) == 0) {
1922 "check_for_newer: lstat(%s) returns 0: symlink does exist\n",
1923 FnFilter1(filename
)));
1924 if (QCOND2
&& !IS_OVERWRT_ALL
)
1925 Info(slide
, 0, ((char *)slide
, LoadFarString(FileIsSymLink
),
1926 FnFilter1(filename
), " with no real file"));
1927 return EXISTS_AND_OLDER
; /* symlink dates are meaningless */
1929 #endif /* SYMLINKS */
1930 return DOES_NOT_EXIST
;
1932 Trace((stderr
, "check_for_newer: stat(%s) returns 0: file exists\n",
1933 FnFilter1(filename
)));
1936 /* GRR OPTION: could instead do this test ONLY if G.symlnk is true */
1937 if (lstat(filename
, &G
.statbuf
) == 0 && S_ISLNK(G
.statbuf
.st_mode
)) {
1938 Trace((stderr
, "check_for_newer: %s is a symbolic link\n",
1939 FnFilter1(filename
)));
1940 if (QCOND2
&& !IS_OVERWRT_ALL
)
1941 Info(slide
, 0, ((char *)slide
, LoadFarString(FileIsSymLink
),
1942 FnFilter1(filename
), ""));
1943 return EXISTS_AND_OLDER
; /* symlink dates are meaningless */
1945 #endif /* SYMLINKS */
1947 NATIVE_TO_TIMET(G
.statbuf
.st_mtime
) /* NOP unless MSC 7.0 or Macintosh */
1949 #ifdef USE_EF_UT_TIME
1950 /* The `Unix extra field mtime' should be used for comparison with the
1951 * time stamp of the existing file >>>ONLY<<< when the EF info is also
1952 * used to set the modification time of the extracted file.
1954 if (G
.extra_field
&&
1958 (ef_scan_for_izux(G
.extra_field
, G
.lrec
.extra_field_length
, 0,
1959 G
.lrec
.last_mod_dos_datetime
, &z_utime
, NULL
)
1962 TTrace((stderr
, "check_for_newer: using Unix extra field mtime\n"));
1963 existing
= G
.statbuf
.st_mtime
;
1964 archive
= z_utime
.mtime
;
1966 /* round up existing filetime to nearest 2 seconds for comparison,
1967 * but saturate in case of arithmetic overflow
1969 existing
= ((G
.statbuf
.st_mtime
& 1) &&
1970 (G
.statbuf
.st_mtime
+ 1 > G
.statbuf
.st_mtime
)) ?
1971 G
.statbuf
.st_mtime
+ 1 : G
.statbuf
.st_mtime
;
1972 archive
= dos_to_unix_time(G
.lrec
.last_mod_dos_datetime
);
1974 #else /* !USE_EF_UT_TIME */
1975 /* round up existing filetime to nearest 2 seconds for comparison,
1976 * but saturate in case of arithmetic overflow
1978 existing
= ((G
.statbuf
.st_mtime
& 1) &&
1979 (G
.statbuf
.st_mtime
+ 1 > G
.statbuf
.st_mtime
)) ?
1980 G
.statbuf
.st_mtime
+ 1 : G
.statbuf
.st_mtime
;
1981 archive
= dos_to_unix_time(G
.lrec
.last_mod_dos_datetime
);
1982 #endif /* ?USE_EF_UT_TIME */
1984 TTrace((stderr
, "check_for_newer: existing %lu, archive %lu, e-a %ld\n",
1985 (ulg
)existing
, (ulg
)archive
, (long)(existing
-archive
)));
1987 return (existing
>= archive
);
1989 } /* end function check_for_newer() */
1991 #endif /* !VMS && !OS2 && !CMS_MVS */
1997 /************************/
1998 /* Function do_string() */
1999 /************************/
2001 int do_string(__G__ length
, option
) /* return PK-type error code */
2003 unsigned int length
; /* without prototype, ush converted to this */
2006 unsigned comment_bytes_left
;
2007 unsigned int block_len
;
2010 char tmp_fnote
[2 * AMIGA_FILENOTELEN
]; /* extra room for squozen chars */
2014 /*---------------------------------------------------------------------------
2015 This function processes arbitrary-length (well, usually) strings. Four
2016 major options are allowed: SKIP, wherein the string is skipped (pretty
2017 logical, eh?); DISPLAY, wherein the string is printed to standard output
2018 after undergoing any necessary or unnecessary character conversions;
2019 DS_FN, wherein the string is put into the filename[] array after under-
2020 going appropriate conversions (including case-conversion, if that is
2021 indicated: see the global variable pInfo->lcflag); and EXTRA_FIELD,
2022 wherein the `string' is assumed to be an extra field and is copied to
2023 the (freshly malloced) buffer G.extra_field. The third option should
2024 be OK since filename is dimensioned at 1025, but we check anyway.
2026 The string, by the way, is assumed to start at the current file-pointer
2027 position; its length is given by 'length'. So start off by checking the
2028 length of the string: if zero, we're already done.
2029 ---------------------------------------------------------------------------*/
2036 #if (defined(SFX) && defined(CHEAP_SFX_AUTORUN))
2038 * Special case: See if the comment begins with an autorun command line.
2039 * Save that and display (or skip) the remainder.
2043 case CHECK_AUTORUN_Q
:
2044 comment_bytes_left
= length
;
2047 block_len
= readbuf(__G__ (char *)G
.outbuf
, 10);
2050 comment_bytes_left
-= block_len
;
2051 G
.outbuf
[block_len
] = '\0';
2052 if (!strcmp((char *)G
.outbuf
, "$AUTORUN$>")) {
2055 block_len
= readbuf(__G__ G
.autorun_command
,
2056 MIN(length
, sizeof(G
.autorun_command
)-1));
2059 comment_bytes_left
-= block_len
;
2060 G
.autorun_command
[block_len
] = '\0';
2061 A_TO_N(G
.autorun_command
);
2062 eol
= strchr(G
.autorun_command
, '\n');
2064 eol
= G
.autorun_command
+ strlen(G
.autorun_command
) - 1;
2065 length
-= eol
+ 1 - G
.autorun_command
;
2066 while (eol
>= G
.autorun_command
&& isspace(*eol
))
2068 #if (defined(WIN32) && !defined(_WIN32_WCE))
2069 /* Win9x console always uses OEM character coding, and
2070 WinNT console is set to OEM charset by default, too */
2071 INTERN_TO_OEM(G
.autorun_command
, G
.autorun_command
);
2072 #endif /* (WIN32 && !_WIN32_WCE) */
2075 if (option
== CHECK_AUTORUN_Q
) /* don't display the remainder */
2077 /* seek to beginning of remaining part of comment -- rewind if */
2078 /* displaying entire comment, or skip to end if discarding it */
2079 seek_zipf(__G__ G
.cur_zipfile_bufstart
- G
.extra_bytes
+
2080 (G
.inptr
- G
.inbuf
) + comment_bytes_left
- length
);
2083 /* FALL THROUGH... */
2084 #endif /* SFX && CHEAP_SFX_AUTORUN */
2087 * First normal case: print string on standard output. First set loop
2088 * variables, then loop through the comment in chunks of OUTBUFSIZ bytes,
2089 * converting formats and printing as we go. The second half of the
2090 * loop conditional was added because the file might be truncated, in
2091 * which case comment_bytes_left will remain at some non-zero value for
2092 * all time. outbuf and slide are used as scratch buffers because they
2093 * are available (we should be either before or in between any file pro-
2099 comment_bytes_left
= length
;
2100 block_len
= OUTBUFSIZ
; /* for the while statement, first time */
2101 while (comment_bytes_left
> 0 && block_len
> 0) {
2102 register uch
*p
= G
.outbuf
;
2103 register uch
*q
= G
.outbuf
;
2105 if ((block_len
= readbuf(__G__ (char *)G
.outbuf
,
2106 MIN((unsigned)OUTBUFSIZ
, comment_bytes_left
))) == 0)
2108 comment_bytes_left
-= block_len
;
2110 /* this is why we allocated an extra byte for outbuf: terminate
2111 * with zero (ASCIIZ) */
2112 G
.outbuf
[block_len
] = '\0';
2114 /* remove all ASCII carriage returns from comment before printing
2115 * (since used before A_TO_N(), check for CR instead of '\r')
2122 /* could check whether (p - outbuf) == block_len here */
2125 if (option
== DISPL_8
) {
2126 /* translate the text coded in the entry's host-dependent
2127 "extended ASCII" charset into the compiler's (system's)
2128 internal text code page */
2129 Ext_ASCII_TO_Native((char *)G
.outbuf
, G
.pInfo
->hostnum
,
2130 G
.pInfo
->hostver
, G
.pInfo
->HasUxAtt
,
2133 /* translate to ANSI (RTL internal codepage may be OEM) */
2134 INTERN_TO_ISO((char *)G
.outbuf
, (char *)G
.outbuf
);
2136 #if (defined(WIN32) && !defined(_WIN32_WCE))
2137 /* Win9x console always uses OEM character coding, and
2138 WinNT console is set to OEM charset by default, too */
2139 INTERN_TO_OEM((char *)G
.outbuf
, (char *)G
.outbuf
);
2140 #endif /* (WIN32 && !_WIN32_WCE) */
2141 #endif /* ?WINDLL */
2143 A_TO_N(G
.outbuf
); /* translate string to native */
2147 /* ran out of local mem -- had to cheat */
2148 win_fprintf((zvoid
*)&G
, stdout
, (extent
)(q
-G
.outbuf
),
2150 win_fprintf((zvoid
*)&G
, stdout
, 2, (char *)"\n\n");
2152 #ifdef NOANSIFILT /* GRR: can ANSI be used with EBCDIC? */
2153 (*G
.message
)((zvoid
*)&G
, G
.outbuf
, (ulg
)(q
-G
.outbuf
), 0);
2154 #else /* ASCII, filter out ANSI escape sequences and handle ^S (pause) */
2160 if (*p
== 0x1B) { /* ASCII escape char */
2163 } else if (*p
== 0x13) { /* ASCII ^S (pause) */
2165 if (p
[1] == LF
) /* ASCII LF */
2167 else if (p
[1] == CR
&& p
[2] == LF
) { /* ASCII CR LF */
2173 if ((unsigned)(q
-slide
) > WSIZE
-3 || pause
) { /* flush */
2174 (*G
.message
)((zvoid
*)&G
, slide
, (ulg
)(q
-slide
), 0);
2176 if (pause
&& G
.extract_flag
) /* don't pause for list/test */
2177 (*G
.mpause
)((zvoid
*)&G
, LoadFarString(QuitPrompt
), 0);
2180 (*G
.message
)((zvoid
*)&G
, slide
, (ulg
)(q
-slide
), 0);
2181 #endif /* ?NOANSIFILT */
2182 #endif /* ?WINDLL */
2184 /* add '\n' if not at start of line */
2185 (*G
.message
)((zvoid
*)&G
, slide
, 0L, 0x40);
2189 * Second case: read string into filename[] array. The filename should
2190 * never ever be longer than FILNAMSIZ-1 (1024), but for now we'll check,
2196 #ifdef UNICODE_SUPPORT
2197 /* get the whole filename as need it for Unicode checksum */
2198 if (G
.fnfull_bufsize
<= length
) {
2199 extent fnbufsiz
= FILNAMSIZ
;
2201 if (fnbufsiz
<= length
)
2202 fnbufsiz
= length
+ 1;
2203 if (G
.filename_full
)
2204 free(G
.filename_full
);
2205 G
.filename_full
= malloc(fnbufsiz
);
2206 if (G
.filename_full
== NULL
)
2208 G
.fnfull_bufsize
= fnbufsiz
;
2210 if (readbuf(__G__ G
.filename_full
, length
) == 0)
2212 G
.filename_full
[length
] = '\0'; /* terminate w/zero: ASCIIZ */
2214 /* if needed, chop off end so standard filename is a valid length */
2215 if (length
>= FILNAMSIZ
) {
2216 Info(slide
, 0x401, ((char *)slide
,
2217 LoadFarString(FilenameTooLongTrunc
)));
2219 length
= FILNAMSIZ
- 1;
2221 /* no excess size */
2223 strncpy(G
.filename
, G
.filename_full
, length
);
2224 G
.filename
[length
] = '\0'; /* terminate w/zero: ASCIIZ */
2225 #else /* !UNICODE_SUPPORT */
2226 if (length
>= FILNAMSIZ
) {
2227 Info(slide
, 0x401, ((char *)slide
,
2228 LoadFarString(FilenameTooLongTrunc
)));
2230 /* remember excess length in block_len */
2231 block_len
= length
- (FILNAMSIZ
- 1);
2232 length
= FILNAMSIZ
- 1;
2234 /* no excess size */
2236 if (readbuf(__G__ G
.filename
, length
) == 0)
2238 G
.filename
[length
] = '\0'; /* terminate w/zero: ASCIIZ */
2239 #endif /* ?UNICODE_SUPPORT */
2241 /* translate the Zip entry filename coded in host-dependent "extended
2242 ASCII" into the compiler's (system's) internal text code page */
2243 Ext_ASCII_TO_Native(G
.filename
, G
.pInfo
->hostnum
, G
.pInfo
->hostver
,
2244 G
.pInfo
->HasUxAtt
, (option
== DS_FN_L
));
2246 if (G
.pInfo
->lcflag
) /* replace with lowercase filename */
2247 STRLOWER(G
.filename
, G
.filename
);
2249 if (G
.pInfo
->vollabel
&& length
> 8 && G
.filename
[8] == '.') {
2250 char *p
= G
.filename
+8;
2252 p
[-1] = *p
; /* disk label, and 8th char is dot: remove dot */
2255 if (!block_len
) /* no overflow, we're done here */
2259 * We truncated the filename, so print what's left and then fall
2260 * through to the SKIP routine.
2262 Info(slide
, 0x401, ((char *)slide
, "[ %s ]\n", FnFilter1(G
.filename
)));
2263 length
= block_len
; /* SKIP the excess bytes... */
2264 /* FALL THROUGH... */
2267 * Third case: skip string, adjusting readbuf's internal variables
2268 * as necessary (and possibly skipping to and reading a new block of
2273 /* cur_zipfile_bufstart already takes account of extra_bytes, so don't
2274 * correct for it twice: */
2275 seek_zipf(__G__ G
.cur_zipfile_bufstart
- G
.extra_bytes
+
2276 (G
.inptr
-G
.inbuf
) + length
);
2280 * Fourth case: assume we're at the start of an "extra field"; malloc
2281 * storage for it and read data into the allocated space.
2285 if (G
.extra_field
!= (uch
*)NULL
)
2286 free(G
.extra_field
);
2287 if ((G
.extra_field
= (uch
*)malloc(length
)) == (uch
*)NULL
) {
2288 Info(slide
, 0x401, ((char *)slide
, LoadFarString(ExtraFieldTooLong
),
2290 /* cur_zipfile_bufstart already takes account of extra_bytes,
2291 * so don't correct for it twice: */
2292 seek_zipf(__G__ G
.cur_zipfile_bufstart
- G
.extra_bytes
+
2293 (G
.inptr
-G
.inbuf
) + length
);
2295 if (readbuf(__G__ (char *)G
.extra_field
, length
) == 0)
2297 /* Looks like here is where extra fields are read */
2298 getZip64Data(__G__ G
.extra_field
, length
);
2299 #ifdef UNICODE_SUPPORT
2300 G
.unipath_filename
= NULL
;
2301 if (G
.UzO
.U_flag
< 2) {
2302 /* check if GPB11 (General Purpuse Bit 11) is set indicating
2303 the standard path and comment are UTF-8 */
2304 if (G
.pInfo
->GPFIsUTF8
) {
2305 /* if GPB11 set then filename_full is untruncated UTF-8 */
2306 G
.unipath_filename
= G
.filename_full
;
2308 /* Get the Unicode fields if exist */
2309 getUnicodeData(__G__ G
.extra_field
, length
);
2310 if (G
.unipath_filename
&& strlen(G
.unipath_filename
) == 0) {
2311 /* the standard filename field is UTF-8 */
2312 free(G
.unipath_filename
);
2313 G
.unipath_filename
= G
.filename_full
;
2316 if (G
.unipath_filename
) {
2317 # ifdef UTF8_MAYBE_NATIVE
2318 if (G
.native_is_utf8
2319 # ifdef UNICODE_WCHAR
2320 && (!G
.unicode_escape_all
)
2323 strncpy(G
.filename
, G
.unipath_filename
, FILNAMSIZ
- 1);
2324 /* make sure filename is short enough */
2325 if (strlen(G
.unipath_filename
) >= FILNAMSIZ
) {
2326 G
.filename
[FILNAMSIZ
- 1] = '\0';
2327 Info(slide
, 0x401, ((char *)slide
,
2328 LoadFarString(UFilenameTooLongTrunc
)));
2332 # ifdef UNICODE_WCHAR
2335 # endif /* UTF8_MAYBE_NATIVE */
2336 # ifdef UNICODE_WCHAR
2340 /* convert UTF-8 to local character set */
2341 fn
= utf8_to_local_string(G
.unipath_filename
,
2342 G
.unicode_escape_all
);
2343 /* make sure filename is short enough */
2344 if (strlen(fn
) >= FILNAMSIZ
) {
2345 fn
[FILNAMSIZ
- 1] = '\0';
2346 Info(slide
, 0x401, ((char *)slide
,
2347 LoadFarString(UFilenameTooLongTrunc
)));
2350 /* replace filename with converted UTF-8 */
2351 strcpy(G
.filename
, fn
);
2354 # endif /* UNICODE_WCHAR */
2355 if (G
.unipath_filename
!= G
.filename_full
)
2356 free(G
.unipath_filename
);
2357 G
.unipath_filename
= NULL
;
2360 #endif /* UNICODE_SUPPORT */
2366 * Fifth case, for the Amiga only: take the comment that would ordinarily
2367 * be skipped over, and turn it into a 79 character string that will be
2368 * attached to the file as a "filenote" after it is extracted.
2372 if ((block_len
= readbuf(__G__ tmp_fnote
, (unsigned)
2373 MIN(length
, 2 * AMIGA_FILENOTELEN
- 1))) == 0)
2375 if ((length
-= block_len
) > 0) /* treat remainder as in case SKIP: */
2376 seek_zipf(__G__ G
.cur_zipfile_bufstart
- G
.extra_bytes
2377 + (G
.inptr
- G
.inbuf
) + length
);
2378 /* convert multi-line text into single line with no ctl-chars: */
2379 tmp_fnote
[block_len
] = '\0';
2380 while ((short int) --block_len
>= 0)
2381 if ((unsigned) tmp_fnote
[block_len
] < ' ')
2382 if (tmp_fnote
[block_len
+1] == ' ') /* no excess */
2383 strcpy(tmp_fnote
+block_len
, tmp_fnote
+block_len
+1);
2385 tmp_fnote
[block_len
] = ' ';
2386 tmp_fnote
[AMIGA_FILENOTELEN
- 1] = '\0';
2387 if (G
.filenotes
[G
.filenote_slot
])
2388 free(G
.filenotes
[G
.filenote_slot
]); /* should not happen */
2389 G
.filenotes
[G
.filenote_slot
] = NULL
;
2391 if (!(G
.filenotes
[G
.filenote_slot
] = malloc(strlen(tmp_fnote
)+1)))
2393 strcpy(G
.filenotes
[G
.filenote_slot
], tmp_fnote
);
2398 } /* end switch (option) */
2402 } /* end function do_string() */
2408 /***********************/
2409 /* Function makeword() */
2410 /***********************/
2416 * Convert Intel style 'short' integer to non-Intel non-16-bit
2417 * host format. This routine also takes care of byte-ordering.
2419 return (ush
)((b
[1] << 8) | b
[0]);
2426 /***********************/
2427 /* Function makelong() */
2428 /***********************/
2434 * Convert intel style 'long' variable to non-Intel non-16-bit
2435 * host format. This routine also takes care of byte-ordering.
2437 return (((ulg
)sig
[3]) << 24)
2438 + (((ulg
)sig
[2]) << 16)
2439 + (ulg
)((((unsigned)sig
[1]) << 8)
2440 + ((unsigned)sig
[0]));
2447 /************************/
2448 /* Function makeint64() */
2449 /************************/
2451 zusz_t
makeint64(sig
)
2454 #ifdef LARGE_FILE_SUPPORT
2456 * Convert intel style 'int64' variable to non-Intel non-16-bit
2457 * host format. This routine also takes care of byte-ordering.
2459 return (((zusz_t
)sig
[7]) << 56)
2460 + (((zusz_t
)sig
[6]) << 48)
2461 + (((zusz_t
)sig
[4]) << 32)
2462 + (zusz_t
)((((ulg
)sig
[3]) << 24)
2463 + (((ulg
)sig
[2]) << 16)
2464 + (((unsigned)sig
[1]) << 8)
2467 #else /* !LARGE_FILE_SUPPORT */
2469 if ((sig
[7] | sig
[6] | sig
[5] | sig
[4]) != 0)
2470 return (zusz_t
)0xffffffffL
;
2472 return (zusz_t
)((((ulg
)sig
[3]) << 24)
2473 + (((ulg
)sig
[2]) << 16)
2474 + (((unsigned)sig
[1]) << 8)
2477 #endif /* ?LARGE_FILE_SUPPORT */
2484 /*********************/
2485 /* Function fzofft() */
2486 /*********************/
2488 /* Format a zoff_t value in a cylindrical buffer set. */
2489 char *fzofft(__G__ val
, pre
, post
)
2495 /* Storage cylinder. (now in globals.h) */
2496 /*static char fzofft_buf[FZOFFT_NUM][FZOFFT_LEN];*/
2497 /*static int fzofft_index = 0;*/
2499 /* Temporary format string storage. */
2502 /* Assemble the format string. */
2504 fmt
[1] = '\0'; /* Start after initial "%". */
2505 if (pre
== FZOFFT_HEX_WID
) /* Special hex width. */
2507 strcat(fmt
, FZOFFT_HEX_WID_VALUE
);
2509 else if (pre
== FZOFFT_HEX_DOT_WID
) /* Special hex ".width". */
2512 strcat(fmt
, FZOFFT_HEX_WID_VALUE
);
2514 else if (pre
!= NULL
) /* Caller's prefix (width). */
2519 strcat(fmt
, FZOFFT_FMT
); /* Long or long-long or whatever. */
2522 strcat(fmt
, "d"); /* Default radix = decimal. */
2524 strcat(fmt
, post
); /* Caller's radix. */
2526 /* Advance the cylinder. */
2527 G
.fzofft_index
= (G
.fzofft_index
+ 1) % FZOFFT_NUM
;
2529 /* Write into the current chamber. */
2530 sprintf(G
.fzofft_buf
[G
.fzofft_index
], fmt
, val
);
2532 /* Return a pointer to this chamber. */
2533 return G
.fzofft_buf
[G
.fzofft_index
];
2542 /**********************/
2543 /* Function str2iso() */
2544 /**********************/
2546 char *str2iso(dst
, src
)
2547 char *dst
; /* destination buffer */
2548 register ZCONST
char *src
; /* source string */
2550 #ifdef INTERN_TO_ISO
2551 INTERN_TO_ISO(src
, dst
);
2554 register char *dstp
= dst
;
2557 c
= (uch
)foreign(*src
++);
2558 *dstp
++ = (char)ASCII2ISO(c
);
2559 } while (c
!= '\0');
2564 #endif /* NEED_STR2ISO */
2568 /**********************/
2569 /* Function str2oem() */
2570 /**********************/
2572 char *str2oem(dst
, src
)
2573 char *dst
; /* destination buffer */
2574 register ZCONST
char *src
; /* source string */
2576 #ifdef INTERN_TO_OEM
2577 INTERN_TO_OEM(src
, dst
);
2580 register char *dstp
= dst
;
2583 c
= (uch
)foreign(*src
++);
2584 *dstp
++ = (char)ASCII2OEM(c
);
2585 } while (c
!= '\0');
2590 #endif /* NEED_STR2OEM */
2595 #ifdef ZMEM /* memset/memcmp/memcpy for systems without either them or */
2596 /* bzero/bcmp/bcopy */
2597 /* (no known systems as of 960211) */
2599 /*********************/
2600 /* Function memset() */
2601 /*********************/
2603 zvoid
*memset(buf
, init
, len
)
2604 register zvoid
*buf
; /* buffer location */
2605 register int init
; /* initializer character */
2606 register unsigned int len
; /* length of the buffer */
2612 *((char *)buf
++) = (char)init
;
2618 /*********************/
2619 /* Function memcmp() */
2620 /*********************/
2622 int memcmp(b1
, b2
, len
)
2623 register ZCONST zvoid
*b1
;
2624 register ZCONST zvoid
*b2
;
2625 register unsigned int len
;
2630 if ((c
= (int)(*((ZCONST
unsigned char *)b1
)++) -
2631 (int)(*((ZCONST
unsigned char *)b2
)++)) != 0)
2639 /*********************/
2640 /* Function memcpy() */
2641 /*********************/
2643 zvoid
*memcpy(dst
, src
, len
)
2644 register zvoid
*dst
;
2645 register ZCONST zvoid
*src
;
2646 register unsigned int len
;
2652 *((char *)dst
)++ = *((ZCONST
char *)src
)++;
2663 /************************/
2664 /* Function zstrnicmp() */
2665 /************************/
2667 int zstrnicmp(s1
, s2
, n
)
2668 register ZCONST
char *s1
, *s2
;
2669 register unsigned n
;
2671 for (; n
> 0; --n
, ++s1
, ++s2
) {
2673 if (ToLower(*s1
) != ToLower(*s2
))
2674 /* test includes early termination of one string */
2675 return ((uch
)ToLower(*s1
) < (uch
)ToLower(*s2
))? -1 : 1;
2677 if (*s1
== '\0') /* both strings terminate early */
2683 #endif /* NO_STRNICMP */
2688 #ifdef REGULUS /* returns the inode number on success(!)...argh argh argh */
2691 /********************/
2692 /* Function zstat() */
2693 /********************/
2699 return (stat((char *)p
,s
) >= 0? 0 : (-1));
2702 #endif /* REGULUS */
2709 /* DBCS support for Info-ZIP's zip (mainly for japanese (-: )
2710 * by Yoshioka Tsuneo (QWF00133@nifty.ne.jp,tsuneo-y@is.aist-nara.ac.jp)
2711 * This code is public domain! Date: 1998/12/20
2714 /************************/
2715 /* Function plastchar() */
2716 /************************/
2718 char *plastchar(ptr
, len
)
2723 ZCONST
char *oldptr
= ptr
;
2724 while(*ptr
!= '\0' && len
> 0){
2730 return (char *)oldptr
;
2734 #ifdef NEED_UZMBCLEN
2735 /***********************/
2736 /* Function uzmbclen() */
2737 /***********************/
2739 extent
uzmbclen(ptr
)
2740 ZCONST
unsigned char *ptr
;
2744 mbl
= mblen((ZCONST
char *)ptr
, MB_CUR_MAX
);
2745 /* For use in code scanning through MBCS strings, we need a strictly
2746 positive "MB char bytes count". For our scanning purpose, it is not
2747 not relevant whether the MB character is valid or not. And, the NUL
2748 char '\0' has a byte count of 1, but mblen() returns 0. So, we make
2749 sure that the uzmbclen() return value is not less than 1.
2751 return (extent
)(mbl
> 0 ? mbl
: 1);
2753 #endif /* NEED_UZMBCLEN */
2756 #ifdef NEED_UZMBSCHR
2757 /***********************/
2758 /* Function uzmbschr() */
2759 /***********************/
2761 unsigned char *uzmbschr(str
, c
)
2762 ZCONST
unsigned char *str
;
2765 while(*str
!= '\0'){
2766 if (*str
== c
) {return (unsigned char *)str
;}
2771 #endif /* NEED_UZMBSCHR */
2774 #ifdef NEED_UZMBSRCHR
2775 /************************/
2776 /* Function uzmbsrchr() */
2777 /************************/
2779 unsigned char *uzmbsrchr(str
, c
)
2780 ZCONST
unsigned char *str
;
2783 unsigned char *match
= NULL
;
2784 while(*str
!= '\0'){
2785 if (*str
== c
) {match
= (unsigned char *)str
;}
2790 #endif /* NEED_UZMBSRCHR */
2799 /*******************************/
2800 /* Function fLoadFarString() */ /* (and friends...) */
2801 /*******************************/
2803 char *fLoadFarString(__GPRO__
const char Far
*sz
)
2805 (void)zfstrcpy(G
.rgchBigBuffer
, sz
);
2806 return G
.rgchBigBuffer
;
2809 char *fLoadFarStringSmall(__GPRO__
const char Far
*sz
)
2811 (void)zfstrcpy(G
.rgchSmallBuffer
, sz
);
2812 return G
.rgchSmallBuffer
;
2815 char *fLoadFarStringSmall2(__GPRO__
const char Far
*sz
)
2817 (void)zfstrcpy(G
.rgchSmallBuffer2
, sz
);
2818 return G
.rgchSmallBuffer2
;
2824 #if (!defined(_MSC_VER) || (_MSC_VER < 600))
2825 /*************************/
2826 /* Function zfstrcpy() */ /* portable clone of _fstrcpy() */
2827 /*************************/
2829 char Far
* Far
zfstrcpy(char Far
*s1
, const char Far
*s2
)
2833 while ((*s1
++ = *s2
++) != '\0');
2837 #if (!(defined(SFX) || defined(FUNZIP)))
2838 /*************************/
2839 /* Function zfstrcmp() */ /* portable clone of _fstrcmp() */
2840 /*************************/
2842 int Far
zfstrcmp(const char Far
*s1
, const char Far
*s2
)
2846 while ((ret
= (int)(uch
)*s1
- (int)(uch
)*s2
) == 0
2852 #endif /* !(SFX || FUNZIP) */
2853 #endif /* !_MSC_VER || (_MSC_VER < 600) */
2855 #endif /* SMALL_MEM */