1 /*
2   Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.
3 
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
8 */
9 /*---------------------------------------------------------------------------
10 
11   fileio.c
12 
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.
16 
17   Contains:  open_input_file()
18              open_outfile()           (not: VMS, AOS/VS, CMSMVS, MACOS, TANDEM)
19              undefer_input()
20              defer_leftover_input()
21              readbuf()
22              readbyte()
23              fillinbuf()
24              seek_zipf()
25              flush()                  (non-VMS)
26              is_vms_varlen_txt()      (non-VMS, VMS_TEXT_CONV only)
27              disk_error()             (non-VMS)
28              UzpMessagePrnt()
29              UzpMessageNull()         (DLL only)
30              UzpInput()
31              UzpMorePause()
32              UzpPassword()            (non-WINDLL)
33              handler()
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)
36              do_string()
37              makeword()
38              makelong()
39              makeint64()
40              fzofft()
41              str2iso()                (CRYPT && NEED_STR2ISO, only)
42              str2oem()                (CRYPT && NEED_STR2OEM, only)
43              memset()                 (ZMEM only)
44              memcpy()                 (ZMEM 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)
56 
57   ---------------------------------------------------------------------------*/
58 
59 
60 #define __FILEIO_C      /* identifies this source module */
61 #define UNZIP_INTERNAL
62 #include "unzip.h"
63 #ifdef WINDLL
64 #  ifdef POCKET_UNZIP
65 #    include "wince/intrface.h"
66 #  else
67 #    include "windll/windll.h"
68 #  endif
69 #  include <setjmp.h>
70 #endif
71 #include "crc32.h"
72 #include "crypt.h"
73 #include "ttyio.h"
74 
75 /* setup of codepage conversion for decryption passwords */
76 #if CRYPT
77 #  if (defined(CRYP_USES_ISO2OEM) && !defined(IZ_ISO2OEM_ARRAY))
78 #    define IZ_ISO2OEM_ARRAY            /* pull in iso2oem[] table */
79 #  endif
80 #  if (defined(CRYP_USES_OEM2ISO) && !defined(IZ_OEM2ISO_ARRAY))
81 #    define IZ_OEM2ISO_ARRAY            /* pull in oem2iso[] table */
82 #  endif
83 #endif
84 #include "ebcdic.h"   /* definition/initialization of ebcdic[] */
85 
86 
87 /*
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).
93 */
94 #ifdef WINDLL
95 #  define WriteError(buf,len,strm) \
96    (win_fprintf(pG, strm, (extent)len, (char far *)buf) != (int)(len))
97 #else /* !WINDLL */
98 #  ifdef USE_FWRITE
99 #    define WriteError(buf,len,strm) \
100      ((extent)fwrite((char *)(buf),1,(extent)(len),strm) != (extent)(len))
101 #  else
102 #    define WriteError(buf,len,strm) \
103      ((extent)write(fileno(strm),(char *)(buf),(extent)(len)) != (extent)(len))
104 #  endif
105 #endif /* ?WINDLL */
106 
107 /*
108    2005-09-16 SMS.
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.
116 
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.
126 */
127 #ifdef VMS
128 #  define WriteTxtErr(buf,len,strm) \
129    ((extent)fprintf(strm, "%.*s", len, buf) != (extent)(len))
130 #else
131 #  define WriteTxtErr(buf,len,strm)  WriteError(buf,len,strm)
132 #endif
133 
134 #if (defined(USE_DEFLATE64) && defined(__16BIT__))
135 static int partflush OF((__GPRO__ uch *rawbuf, ulg size, int unshrink));
136 #endif
137 #ifdef VMS_TEXT_CONV
138 static int is_vms_varlen_txt OF((__GPRO__ uch *ef_buf, unsigned ef_len));
139 #endif
140 static int disk_error OF((__GPRO));
141 
142 
143 /****************************/
144 /* Strings used in fileio.c */
145 /****************************/
146 
147 static ZCONST char Far CannotOpenZipfile[] =
148   "error:  cannot open zipfile [ %s ]\n        %s\n";
149 
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";
155 #ifdef UNIXBACKUP
156    static ZCONST char Far CannotRenameOldFile[] =
157      "error:  cannot rename old %s\n        %s\n";
158    static ZCONST char Far BackupSuffix[] = "~";
159 #endif
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";
164 #endif
165    static ZCONST char Far CannotCreateFile[] =
166      "error:  cannot create %s\n        %s\n";
167 #endif /* !TANDEM */
168 #endif /* !VMS && !AOS_VS && !CMS_MVS && !MACOS */
169 
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";
176 #endif
177 static ZCONST char Far ExtraFieldTooLong[] =
178   "warning:  extra field too long (%d).  Ignoring...\n";
179 
180 #ifdef WINDLL
181    static ZCONST char Far DiskFullQuery[] =
182      "%s:  write error (disk full?).\n";
183 #else
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";
188 #  ifdef SYMLINKS
189      static ZCONST char Far FileIsSymLink[] =
190        "%s exists and is a symbolic link%s.\n";
191 #  endif
192 #  ifdef MORE
193      static ZCONST char Far MorePrompt[] = "--More--(%lu)";
194 #  endif
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"; */
198      "\r                                                         \r";
199 #  if CRYPT
200 #    ifdef MACOS
201        /* SPC: are names on MacOS REALLY so much longer than elsewhere ??? */
202        static ZCONST char Far PasswPrompt[] = "[%s]\n %s password: ";
203 #    else
204        static ZCONST char Far PasswPrompt[] = "[%s] %s password: ";
205 #    endif
206      static ZCONST char Far PasswPrompt2[] = "Enter password: ";
207      static ZCONST char Far PasswRetry[] = "password incorrect--reenter: ";
208 #  endif /* CRYPT */
209 #endif /* !WINDLL */
210 
211 
212 
213 
214 
215 /******************************/
216 /* Function open_input_file() */
217 /******************************/
218 
open_input_file(__G)219 int open_input_file(__G)    /* return 1 if open failed */
220     __GDEF
221 {
222     /*
223      *  open the zipfile for reading and in BINARY mode to prevent cr/lf
224      *  translation, which would corrupt the bitstreams
225      */
226 
227 #ifdef VMS
228     G.zipfd = open(G.zipfn, O_RDONLY, 0, OPNZIP_RMS_ARGS);
229 #else /* !VMS */
230 #ifdef MACOS
231     G.zipfd = open(G.zipfn, 0);
232 #else /* !MACOS */
233 #ifdef CMS_MVS
234     G.zipfd = vmmvs_open_infile(__G);
235 #else /* !CMS_MVS */
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 */
242 #endif /* ?MACOS */
243 #endif /* ?VMS */
244 
245 #ifdef USE_STRM_INPUT
246     if (G.zipfd == NULL)
247 #else
248     /* if (G.zipfd < 0) */  /* no good for Windows CE port */
249     if (G.zipfd == -1)
250 #endif
251     {
252         Info(slide, 0x401, ((char *)slide, LoadFarString(CannotOpenZipfile),
253           G.zipfn, strerror(errno)));
254         return 1;
255     }
256     return 0;
257 
258 } /* end function open_input_file() */
259 
260 
261 
262 
263 #if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS))
264 #if (!defined(TANDEM))
265 
266 /***************************/
267 /* Function open_outfile() */
268 /***************************/
269 
open_outfile(__G)270 int open_outfile(__G)           /* return 1 if fail */
271     __GDEF
272 {
273 #ifdef DLL
274     if (G.redirect_data)
275         return (redirect_outfile(__G) == FALSE);
276 #endif
277 #ifdef QDOS
278     QFilename(__G__ G.filename);
279 #endif
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+");
286 
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 */
290         fclose(tmp);
291     }
292 #endif /* BORLAND_STAT_BUG */
293 #ifdef SYMLINKS
294     if (SSTAT(G.filename, &G.statbuf) == 0 ||
295         lstat(G.filename, &G.statbuf) == 0)
296 #else
297     if (SSTAT(G.filename, &G.statbuf) == 0)
298 #endif /* ?SYMLINKS */
299     {
300         Trace((stderr, "open_outfile:  stat(%s) returns 0:  file exists\n",
301           FnFilter1(G.filename)));
302 #ifdef UNIXBACKUP
303         if (uO.B_flag) {    /* do backup */
304             char *tname;
305             z_stat tmpstat;
306             int blen, flen, tlen;
307 
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);
313                 if (tname == NULL)
314                     return 1;                 /* in case we run out of space */
315                 tlen = FILNAMSIZ - 1 - blen;
316                 strcpy(tname, G.filename);    /* make backup name */
317                 tname[tlen] = '\0';
318                 if (flen > tlen) flen = tlen;
319                 tlen = FILNAMSIZ;
320             } else {
321                 tname = (char *)malloc(tlen);
322                 if (tname == NULL)
323                     return 1;                 /* in case we run out of space */
324                 strcpy(tname, G.filename);    /* make backup name */
325             }
326             strcpy(tname+flen, BackupSuffix);
327 
328             if (IS_OVERWRT_ALL) {
329                 /* If there is a previous backup file, delete it,
330                  * otherwise the following rename operation may fail.
331                  */
332                 if (SSTAT(tname, &tmpstat) == 0)
333                     unlink(tname);
334             } else {
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.
339                  */
340                 unsigned maxtail, i;
341                 char *numtail = tname + flen + blen;
342 
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;
351                 }
352                 /* while filename exists */
353                 for (i = 0; (i < maxtail) && (SSTAT(tname, &tmpstat) == 0);)
354                     sprintf(numtail,"%u", ++i);
355             }
356 
357             if (rename(G.filename, tname) != 0) {   /* move file */
358                 Info(slide, 0x401, ((char *)slide,
359                   LoadFarString(CannotRenameOldFile),
360                   FnFilter1(G.filename), strerror(errno)));
361                 free(tname);
362                 return 1;
363             }
364             Trace((stderr, "open_outfile:  %s now renamed into %s\n",
365               FnFilter1(G.filename), FnFilter2(tname)));
366             free(tname);
367         } else
368 #endif /* UNIXBACKUP */
369         {
370 #ifdef DOS_FLX_OS2_W32
371             if (!(G.statbuf.st_mode & S_IWRITE)) {
372                 Trace((stderr,
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)));
378             }
379 #endif /* DOS_FLX_OS2_W32 */
380 #ifdef NLM
381             /* Give the file read/write permission (non-POSIX shortcut) */
382             chmod(G.filename, 0);
383 #endif /* NLM */
384             if (unlink(G.filename) != 0) {
385                 Info(slide, 0x401, ((char *)slide,
386                   LoadFarString(CannotDeleteOldFile),
387                   FnFilter1(G.filename), strerror(errno)));
388                 return 1;
389             }
390             Trace((stderr, "open_outfile:  %s now deleted\n",
391               FnFilter1(G.filename)));
392         }
393     }
394 #endif /* DOS_FLX_NLM_OS2_W32 || ATH_BEO_THS_UNX */
395 #ifdef RISCOS
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)));
399         return 1;
400     }
401 #endif /* RISCOS */
402 #ifdef TOPS20
403     char *tfilnam;
404 
405     if ((tfilnam = (char *)malloc(2*strlen(G.filename)+1)) == (char *)NULL)
406         return 1;
407     strcpy(tfilnam, G.filename);
408     upper(tfilnam);
409     enquote(tfilnam);
410     if ((G.outfile = fopen(tfilnam, FOPW)) == (FILE *)NULL) {
411         Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile),
412           tfilnam, strerror(errno)));
413         free(tfilnam);
414         return 1;
415     }
416     free(tfilnam);
417 #else /* !TOPS20 */
418 #ifdef MTS
419     if (uO.aflag)
420         G.outfile = zfopen(G.filename, FOPWT);
421     else
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)));
426         return 1;
427     }
428 #else /* !MTS */
429 #ifdef DEBUG
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)));
436     else {
437         Info(slide, 1, ((char *)slide,
438           "open_outfile:  fopen(%s) for reading succeeded:  file exists\n",
439           FnFilter1(G.filename)));
440         fclose(G.outfile);
441     }
442 #endif /* DEBUG */
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)));
447         fclose(G.outfile);
448         return 1;   /* with "./" fix in checkdir(), should never reach here */
449     }
450 #endif /* NOVELL_BUG_FAILSAFE */
451     Trace((stderr, "open_outfile:  doing fopen(%s) for writing\n",
452       FnFilter1(G.filename)));
453     {
454 #if defined(ATH_BE_UNX) || defined(AOS_VS) || defined(QDOS) || defined(TANDEM)
455         mode_t umask_sav = umask(0077);
456 #endif
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.
460          */
461         G.outfile = zfopen(G.filename, FOPWR);
462 #else
463         G.outfile = zfopen(G.filename, FOPW);
464 #endif
465 #if defined(ATH_BE_UNX) || defined(AOS_VS) || defined(QDOS) || defined(TANDEM)
466         umask(umask_sav);
467 #endif
468     }
469     if (G.outfile == (FILE *)NULL) {
470         Info(slide, 0x401, ((char *)slide, LoadFarString(CannotCreateFile),
471           FnFilter1(G.filename), strerror(errno)));
472         return 1;
473     }
474     Trace((stderr, "open_outfile:  fopen(%s) for writing succeeded\n",
475       FnFilter1(G.filename)));
476 #endif /* !MTS */
477 #endif /* !TOPS20 */
478 
479 #ifdef USE_FWRITE
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 */
484 #ifndef RISCOS
485 #ifdef _IOFBF  /* make output fully buffered (works just about like write()) */
486     setvbuf(G.outfile, (char *)slide, _IOFBF, WSIZE);
487 #else
488     setbuf(G.outfile, (char *)slide);
489 #endif
490 #endif /* !RISCOS */
491 #endif /* ?DOS_NLM_OS2_W32 */
492 #endif /* USE_FWRITE */
493 #ifdef OS2_W32
494     /* preallocate the final file size to prevent file fragmentation */
495     SetFileSize(G.outfile, G.lrec.ucsize);
496 #endif
497     return 0;
498 
499 } /* end function open_outfile() */
500 
501 #endif /* !TANDEM */
502 #endif /* !VMS && !AOS_VS && !CMS_MVS && !MACOS */
503 
504 
505 
506 
507 
508 /*
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.
517  */
518 
519 /****************************/
520 /* function undefer_input() */
521 /****************************/
522 
undefer_input(__G)523 void undefer_input(__G)
524     __GDEF
525 {
526     if (G.incnt > 0)
527         G.csize += G.incnt;
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) !!
534          */
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)
539         G.incnt = 0;
540 } /* end function undefer_input() */
541 
542 
543 
544 
545 
546 /***********************************/
547 /* function defer_leftover_input() */
548 /***********************************/
549 
defer_leftover_input(__G)550 void defer_leftover_input(__G)
551     __GDEF
552 {
553     if ((zoff_t)G.incnt > G.csize) {
554         /* (G.csize < MAXINT), we can safely cast it to int !! */
555         if (G.csize < 0L)
556             G.csize = 0L;
557         G.inptr_leftover = G.inptr + (int)G.csize;
558         G.incnt_leftover = G.incnt - (int)G.csize;
559         G.incnt = (int)G.csize;
560     } else
561         G.incnt_leftover = 0;
562     G.csize -= G.incnt;
563 } /* end function defer_leftover_input() */
564 
565 
566 
567 
568 
569 /**********************/
570 /* Function readbuf() */
571 /**********************/
572 
573 unsigned readbuf(__G__ buf, size)   /* return number of bytes read into buf */
574     __GDEF
575     char *buf;
576     register unsigned size;
577 {
578     register unsigned count;
579     unsigned n;
580 
581     n = size;
582     while (size) {
583         if (G.incnt <= 0) {
584             if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) == 0)
585                 return (n-size);
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 */
592             }
593             /* buffer ALWAYS starts on a block boundary:  */
594             G.cur_zipfile_bufstart += INBUFSIZ;
595             G.inptr = G.inbuf;
596         }
597         count = MIN(size, (unsigned)G.incnt);
598         memcpy(buf, G.inptr, count);
599         buf += count;
600         G.inptr += count;
601         G.incnt -= count;
602         size -= count;
603     }
604     return n;
605 
606 } /* end function readbuf() */
607 
608 
609 
610 
611 
612 /***********************/
613 /* Function readbyte() */
614 /***********************/
615 
readbyte(__G)616 int readbyte(__G)   /* refill inbuf and return a byte if available, else EOF */
617     __GDEF
618 {
619     if (G.mem_mode)
620         return EOF;
621     if (G.csize <= 0) {
622         G.csize--;             /* for tests done after exploding */
623         G.incnt = 0;
624         return EOF;
625     }
626     if (G.incnt <= 0) {
627         if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) == 0) {
628             return EOF;
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);
634             echon();
635 #ifdef WINDLL
636             longjmp(dll_error_return, 1);
637 #else
638             DESTROYGLOBALS();
639             EXIT(PK_BADERR);    /* totally bailing; better than lock-up */
640 #endif
641         }
642         G.cur_zipfile_bufstart += INBUFSIZ; /* always starts on block bndry */
643         G.inptr = G.inbuf;
644         defer_leftover_input(__G);           /* decrements G.csize */
645     }
646 
647 #if CRYPT
648     if (G.pInfo->encrypted) {
649         uch *p;
650         int n;
651 
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?
655          */
656         for (n = G.incnt, p = G.inptr;  n--;  p++)
657             zdecode(*p);
658     }
659 #endif /* CRYPT */
660 
661     --G.incnt;
662     return *G.inptr++;
663 
664 } /* end function readbyte() */
665 
666 
667 
668 
669 
670 #if defined(USE_ZLIB) || defined(USE_BZIP2)
671 
672 /************************/
673 /* Function fillinbuf() */
674 /************************/
675 
fillinbuf(__G)676 int fillinbuf(__G) /* like readbyte() except returns number of bytes in inbuf */
677     __GDEF
678 {
679     if (G.mem_mode ||
680                   (G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) <= 0)
681         return 0;
682     G.cur_zipfile_bufstart += INBUFSIZ;  /* always starts on a block boundary */
683     G.inptr = G.inbuf;
684     defer_leftover_input(__G);           /* decrements G.csize */
685 
686 #if CRYPT
687     if (G.pInfo->encrypted) {
688         uch *p;
689         int n;
690 
691         for (n = G.incnt, p = G.inptr;  n--;  p++)
692             zdecode(*p);
693     }
694 #endif /* CRYPT */
695 
696     return G.incnt;
697 
698 } /* end function fillinbuf() */
699 
700 #endif /* USE_ZLIB || USE_BZIP2 */
701 
702 
703 
704 
705 
706 /************************/
707 /* Function seek_zipf() */
708 /************************/
709 
710 int seek_zipf(__G__ abs_offset)
711     __GDEF
712     zoff_t abs_offset;
713 {
714 /*
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.
724  *
725  *  Since seek_zipf() is never used during decompression, it is safe to
726  *  use the slide[] buffer for the error message.
727  *
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
732  */
733     zoff_t request = abs_offset + G.extra_bytes;
734     zoff_t inbuf_offset = request % INBUFSIZ;
735     zoff_t bufstart = request - inbuf_offset;
736 
737     if (request < 0) {
738         Info(slide, 1, ((char *)slide, LoadFarStringSmall(SeekMsg),
739              G.zipfn, LoadFarString(ReportMsg)));
740         return(PK_BADERR);
741     } else if (bufstart != G.cur_zipfile_bufstart) {
742         Trace((stderr,
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 */
752         Trace((stderr,
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)
761             return(PK_EOF);
762         G.incnt -= (int)inbuf_offset;
763         G.inptr = G.inbuf + (int)inbuf_offset;
764     } else {
765         G.incnt += (G.inptr-G.inbuf) - (int)inbuf_offset;
766         G.inptr = G.inbuf + (int)inbuf_offset;
767     }
768     return(PK_OK);
769 } /* end function seek_zipf() */
770 
771 
772 
773 
774 
775 #ifndef VMS  /* for VMS use code in vms.c */
776 
777 /********************/
778 /* Function flush() */   /* returns PK error codes: */
779 /********************/   /* if tflag => always 0; PK_DISK if write error */
780 
781 int flush(__G__ rawbuf, size, unshrink)
782     __GDEF
783     uch *rawbuf;
784     ulg size;
785     int unshrink;
786 #if (defined(USE_DEFLATE64) && defined(__16BIT__))
787 {
788     int ret;
789 
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.
793      */
794     while (size > 0x8000L) {
795         ret = partflush(__G__ rawbuf, 0x8000L, unshrink);
796         if (ret != PK_OK)
797             return ret;
798         size -= 0x8000L;
799         rawbuf += (extent)0x8000;
800     }
801     return partflush(__G__ rawbuf, size, unshrink);
802 } /* end function flush() */
803 
804 
805 /************************/
806 /* Function partflush() */  /* returns PK error codes: */
807 /************************/  /* if tflag => always 0; PK_DISK if write error */
808 
809 static int partflush(__G__ rawbuf, size, unshrink)
810     __GDEF
811     uch *rawbuf;        /* cannot be ZCONST, gets passed to (*G.message)() */
812     ulg size;
813     int unshrink;
814 #endif /* USE_DEFLATE64 && __16BIT__ */
815 {
816     register uch *p;
817     register uch *q;
818     uch *transbuf;
819 #if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV))
820     ulg transbufsiz;
821 #endif
822     /* static int didCRlast = FALSE;    moved to globals.h */
823 
824 
825 /*---------------------------------------------------------------------------
826     Compute the CRC first; if testing or if disk is full, that's it.
827   ---------------------------------------------------------------------------*/
828 
829     G.crc32val = crc32(G.crc32val, rawbuf, (extent)size);
830 
831 #ifdef DLL
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 */
835 #endif
836 
837     if (uO.tflag || size == 0L)  /* testing or nothing to write:  all done */
838         return PK_OK;
839 
840     if (G.disk_full)
841         return PK_DISK;         /* disk already full:  ignore rest of file */
842 
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   ---------------------------------------------------------------------------*/
849 
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.
859          */
860 #ifdef DLL
861         if (G.redirect_data) {
862 #ifdef NO_SLIDE_REDIR
863             if (writeToMemory(__G__ rawbuf, (extent)size)) return PK_ERR;
864 #else
865             writeToMemory(__G__ rawbuf, (extent)size);
866 #endif
867         } else
868 #endif
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))
872             return PK_OK;
873     } else {   /* textmode:  aflag is true */
874         if (unshrink) {
875             /* rawbuf = outbuf */
876             transbuf = G.outbuf2;
877 #if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV))
878             transbufsiz = TRANSBUFSIZ;
879 #endif
880         } else {
881             /* rawbuf = slide */
882             transbuf = G.outbuf;
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));
887 #endif
888         }
889         if (G.newfile) {
890 #ifdef VMS_TEXT_CONV
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 */
895             else
896                 G.VMS_line_state = -1;   /* -1: don't treat as VMS text */
897 #endif
898             G.didCRlast = FALSE;         /* no previous buffers written */
899             G.newfile = FALSE;
900         }
901 
902 #ifdef VMS_TEXT_CONV
903         if (G.VMS_line_state >= 0)
904         {
905             p = rawbuf;
906             q = transbuf;
907             while ((extent)(p-rawbuf) < (extent)size) {
908                 switch (G.VMS_line_state) {
909 
910                     /* 0: ready to read line length */
911                     case 0:
912                         G.VMS_line_length = 0;
913                         if ((extent)(p-rawbuf) == (extent)size-1) {
914                             /* last char */
915                             G.VMS_line_length = (unsigned)(*p++);
916                             G.VMS_line_state = 1;
917                         } else {
918                             G.VMS_line_length = makeword(p);
919                             p += 2;
920                             G.VMS_line_state = 2;
921                         }
922                         G.VMS_line_pad =
923                                ((G.VMS_line_length & 1) != 0); /* odd */
924                         break;
925 
926                     /* 1: read one byte of length, need second */
927                     case 1:
928                         G.VMS_line_length += ((unsigned)(*p++) << 8);
929                         G.VMS_line_state = 2;
930                         break;
931 
932                     /* 2: ready to read VMS_line_length chars */
933                     case 2:
934                         {
935                             extent remaining = (extent)size+(rawbuf-p);
936                             extent outroom;
937 
938                             if (G.VMS_line_length < remaining) {
939                                 remaining = G.VMS_line_length;
940                                 G.VMS_line_state = 3;
941                             }
942 
943                             outroom = transbuf+(extent)transbufsiz-q;
944                             if (remaining >= outroom) {
945                                 remaining -= outroom;
946                                 for (;outroom > 0; p++, outroom--)
947                                     *q++ = native(*p);
948 #ifdef DLL
949                                 if (G.redirect_data) {
950                                     if (writeToMemory(__G__ transbuf,
951                                           (extent)(q-transbuf))) return PK_ERR;
952                                 } else
953 #endif
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))
959                                     return PK_OK;
960                                 q = transbuf;
961                                 /* fall through to normal case */
962                             }
963                             G.VMS_line_length -= remaining;
964                             for (;remaining > 0; p++, remaining--)
965                                 *q++ = native(*p);
966                         }
967                         break;
968 
969                     /* 3: ready to PutNativeEOL */
970                     case 3:
971                         if (q > transbuf+(extent)transbufsiz-lenEOL) {
972 #ifdef DLL
973                             if (G.redirect_data) {
974                                 if (writeToMemory(__G__ transbuf,
975                                       (extent)(q-transbuf))) return PK_ERR;
976                             } else
977 #endif
978                             if (!uO.cflag &&
979                                 WriteError(transbuf, (extent)(q-transbuf),
980                                   G.outfile))
981                                 return disk_error(__G);
982                             else if (uO.cflag && (*G.message)((zvoid *)&G,
983                                      transbuf, (ulg)(q-transbuf), 0))
984                                 return PK_OK;
985                             q = transbuf;
986                         }
987                         PutNativeEOL
988                         G.VMS_line_state = G.VMS_line_pad ? 4 : 0;
989                         break;
990 
991                     /* 4: ready to read pad byte */
992                     case 4:
993                         ++p;
994                         G.VMS_line_state = 0;
995                         break;
996                 }
997             } /* end while */
998 
999         } else
1000 #endif /* VMS_TEXT_CONV */
1001 
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       -----------------------------------------------------------------------*/
1007 
1008         /* else not VMS text */ {
1009             p = rawbuf;
1010             if (*p == LF && G.didCRlast)
1011                 ++p;
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  */
1015                     PutNativeEOL
1016                     if ((extent)(p-rawbuf) == (extent)size-1)
1017                         /* last char in buffer */
1018                         G.didCRlast = TRUE;
1019                     else if (p[1] == LF)  /* get rid of accompanying LF */
1020                         ++p;
1021                 } else if (*p == LF)      /* lone LF */
1022                     PutNativeEOL
1023                 else
1024 #ifndef DOS_FLX_OS2_W32
1025                 if (*p != CTRLZ)          /* lose all ^Z's */
1026 #endif
1027                     *q++ = native(*p);
1028 
1029 #if (defined(SMALL_MEM) || defined(MED_MEM))
1030 # if (lenEOL == 1)   /* don't check unshrink:  both buffers small but equal */
1031                 if (!unshrink)
1032 # endif
1033                     /* check for danger of buffer overflow and flush */
1034                     if (q > transbuf+(extent)transbufsiz-lenEOL) {
1035                         Trace((stderr,
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))
1043                             return PK_OK;
1044                         q = transbuf;
1045                         continue;
1046                     }
1047 #endif /* SMALL_MEM || MED_MEM */
1048             }
1049         }
1050 
1051     /*-----------------------------------------------------------------------
1052         Done translating:  write whatever we've got to file (or screen).
1053       -----------------------------------------------------------------------*/
1054 
1055         Trace((stderr, "p - rawbuf = %u   q-transbuf = %u   size = %lu\n",
1056           (unsigned)(p-rawbuf), (unsigned)(q-transbuf), size));
1057         if (q > transbuf) {
1058 #ifdef DLL
1059             if (G.redirect_data) {
1060                 if (writeToMemory(__G__ transbuf, (extent)(q-transbuf)))
1061                     return PK_ERR;
1062             } else
1063 #endif
1064             if (!uO.cflag && WriteError(transbuf, (extent)(q-transbuf),
1065                 G.outfile))
1066                 return disk_error(__G);
1067             else if (uO.cflag && (*G.message)((zvoid *)&G, transbuf,
1068                 (ulg)(q-transbuf), 0))
1069                 return PK_OK;
1070         }
1071     }
1072 
1073     return PK_OK;
1074 
1075 } /* end function flush() [resp. partflush() for 16-bit Deflate64 support] */
1076 
1077 
1078 
1079 
1080 
1081 #ifdef VMS_TEXT_CONV
1082 
1083 /********************************/
1084 /* Function is_vms_varlen_txt() */
1085 /********************************/
1086 
1087 static int is_vms_varlen_txt(__G__ ef_buf, ef_len)
1088     __GDEF
1089     uch *ef_buf;        /* buffer containing extra field */
1090     unsigned ef_len;    /* total length of extra field */
1091 {
1092     unsigned eb_id;
1093     unsigned eb_len;
1094     uch *eb_data;
1095     unsigned eb_datlen;
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... */
1100 
1101 #define VMSPK_ITEMID            0
1102 #define VMSPK_ITEMLEN           2
1103 #define VMSPK_ITEMHEADSZ        4
1104 
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 */
1110 
1111     if (ef_len == 0 || ef_buf == NULL)
1112         return FALSE;
1113 
1114     while (ef_len >= EB_HEADSIZE) {
1115         eb_id = makeword(EB_ID + ef_buf);
1116         eb_len = makeword(EB_LEN + ef_buf);
1117 
1118         if (eb_len > (ef_len - EB_HEADSIZE)) {
1119             /* discovered some extra field inconsistency! */
1120             Trace((stderr,
1121               "is_vms_varlen_txt: block length %u > rest ef_size %u\n", eb_len,
1122               ef_len - EB_HEADSIZE));
1123             break;
1124         }
1125 
1126         switch (eb_id) {
1127           case EF_PKVMS:
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
1135              */
1136 
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;
1140 
1141             /* test the CRC checksum */
1142             if (makelong(ef_buf+EB_HEADSIZE) !=
1143                 crc32(CRCVAL_INITIAL, eb_data, (extent)eb_datlen))
1144             {
1145                 Info(slide, 1, ((char *)slide,
1146                   "[Warning: CRC error, discarding PKWARE extra field]\n"));
1147                 /* skip over the data analysis code */
1148                 break;
1149             }
1150 
1151             /* scan through the attribute data items */
1152             while (eb_datlen > 4)
1153             {
1154                 unsigned fldsize = makeword(&eb_data[VMSPK_ITEMLEN]);
1155 
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
1160                      * data item */
1161                     if (fldsize >= 1) {
1162                         vms_rectype = eb_data[VMSPK_ITEMHEADSZ] & 15;
1163                      /* vms_fileorg = eb_data[VMSPK_ITEMHEADSZ] >> 4; */
1164                     }
1165                     break;
1166                   default:
1167                     break;
1168                 }
1169                 /* skip to next data item */
1170                 eb_datlen -= fldsize + VMSPK_ITEMHEADSZ;
1171                 eb_data += fldsize + VMSPK_ITEMHEADSZ;
1172             }
1173             break;
1174 
1175           case EF_IZVMS:
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))
1180                     != NULL)
1181                 {
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; */
1185                     }
1186                     free(eb_data);
1187                 }
1188             }
1189             break;
1190 
1191           default:
1192             break;
1193         }
1194 
1195         /* Skip this extra field block */
1196         ef_buf += (eb_len + EB_HEADSIZE);
1197         ef_len -= (eb_len + EB_HEADSIZE);
1198     }
1199 
1200     return (vms_rectype == VMSREC_C_VAR);
1201 
1202 } /* end function is_vms_varlen_txtfile() */
1203 
1204 #endif /* VMS_TEXT_CONV */
1205 
1206 
1207 
1208 
1209 /*************************/
1210 /* Function disk_error() */
1211 /*************************/
1212 
disk_error(__G)1213 static int disk_error(__G)
1214     __GDEF
1215 {
1216     /* OK to use slide[] here because this file is finished regardless */
1217     Info(slide, 0x4a1, ((char *)slide, LoadFarString(DiskFullQuery),
1218       FnFilter1(G.filename)));
1219 
1220 #ifndef WINDLL
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 */
1224     else
1225 #endif
1226         G.disk_full = 2;       /* no:  exit program */
1227 
1228     return PK_DISK;
1229 
1230 } /* end function disk_error() */
1231 
1232 #endif /* !VMS */
1233 
1234 
1235 
1236 
1237 
1238 /*****************************/
1239 /* Function UzpMessagePrnt() */
1240 /*****************************/
1241 
UzpMessagePrnt(pG,buf,size,flag)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 */
1247 {
1248     /* IMPORTANT NOTE:
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) !!!
1254      */
1255     int error;
1256     uch *q=buf, *endbuf=buf+(unsigned)size;
1257 #ifdef MORE
1258     uch *p=buf;
1259 #if (defined(SCREENWIDTH) && defined(SCREENLWRAP))
1260     int islinefeed = FALSE;
1261 #endif
1262 #endif
1263     FILE *outfp;
1264 
1265 
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
1272     of this one.
1273   ---------------------------------------------------------------------------*/
1274 
1275 #if (defined(OS2) && defined(DLL))
1276     if (MSG_NO_DLL2(flag))  /* if OS/2 DLL bit is set, do NOT print this msg */
1277         return 0;
1278 #endif
1279 #ifdef WINDLL
1280     if (MSG_NO_WDLL(flag))
1281         return 0;
1282 #endif
1283 #ifdef WINDLL
1284     if (MSG_NO_WGUI(flag))
1285         return 0;
1286 #endif
1287 /*
1288 #ifdef ACORN_GUI
1289     if (MSG_NO_AGUI(flag))
1290         return 0;
1291 #endif
1292  */
1293 #ifdef DLL                 /* don't display message if data is redirected */
1294     if (((Uz_Globs *)pG)->redirect_data &&
1295         !((Uz_Globs *)pG)->redirect_text)
1296         return 0;
1297 #endif
1298 
1299     if (MSG_STDERR(flag) && !((Uz_Globs *)pG)->UzO.tflag)
1300         outfp = (FILE *)stderr;
1301     else
1302         outfp = (FILE *)stdout;
1303 
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) */
1311 #endif
1312 
1313     if (MSG_TNEWLN(flag)) {   /* again assumes writable buffer:  fragile... */
1314         if ((!size && !((Uz_Globs *)pG)->sol) ||
1315             (size && (endbuf[-1] != '\n')))
1316         {
1317             *endbuf++ = '\n';
1318             ++size;
1319         }
1320     }
1321 
1322 #ifdef MORE
1323 # ifdef SCREENSIZE
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);
1327 #  else
1328     SCREENSIZE(&((Uz_Globs *)pG)->height, (int *)NULL);
1329 #  endif
1330     ((Uz_Globs *)pG)->height -= 2;
1331 # else
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;
1336 #  endif
1337 # endif
1338 #endif /* MORE */
1339 
1340     if (MSG_LNEWLN(flag) && !((Uz_Globs *)pG)->sol) {
1341         /* not at start of line:  want newline */
1342 #ifdef OS2DLL
1343         if (!((Uz_Globs *)pG)->redirect_text) {
1344 #endif
1345             putc('\n', outfp);
1346             fflush(outfp);
1347 #ifdef MORE
1348             if (((Uz_Globs *)pG)->M_flag)
1349             {
1350 #if (defined(SCREENWIDTH) && defined(SCREENLWRAP))
1351                 ((Uz_Globs *)pG)->chars = 0;
1352 #endif
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);
1358             }
1359 #endif /* MORE */
1360             if (MSG_STDERR(flag) && ((Uz_Globs *)pG)->UzO.tflag &&
1361                 !isatty(1) && isatty(2))
1362             {
1363                 /* error output from testing redirected:  also send to stderr */
1364                 putc('\n', stderr);
1365                 fflush(stderr);
1366             }
1367 #ifdef OS2DLL
1368         } else
1369            REDIRECTC('\n');
1370 #endif
1371         ((Uz_Globs *)pG)->sol = TRUE;
1372     }
1373 
1374     /* put zipfile name, filename and/or error/warning keywords here */
1375 
1376 #ifdef MORE
1377     if (((Uz_Globs *)pG)->M_flag
1378 #ifdef OS2DLL
1379          && !((Uz_Globs *)pG)->redirect_text
1380 #endif
1381                                                  )
1382     {
1383         while (p < endbuf) {
1384             if (*p == '\n') {
1385 #if (defined(SCREENWIDTH) && defined(SCREENLWRAP))
1386                 islinefeed = TRUE;
1387             } else if (SCREENLWRAP) {
1388                 if (*p == '\r') {
1389                     ((Uz_Globs *)pG)->chars = 0;
1390                 } else {
1391 #  ifdef TABSIZE
1392                     if (*p == '\t')
1393                         ((Uz_Globs *)pG)->chars +=
1394                             (TABSIZE - (((Uz_Globs *)pG)->chars % TABSIZE));
1395                     else
1396 #  endif
1397                         ++((Uz_Globs *)pG)->chars;
1398 
1399                     if (((Uz_Globs *)pG)->chars >= ((Uz_Globs *)pG)->width)
1400                         islinefeed = TRUE;
1401                 }
1402             }
1403             if (islinefeed) {
1404                 islinefeed = FALSE;
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)
1410                 {
1411                     if ((error = WriteTxtErr(q, p-q+1, outfp)) != 0)
1412                         return error;
1413                     fflush(outfp);
1414                     ((Uz_Globs *)pG)->sol = TRUE;
1415                     q = p + 1;
1416                     (*((Uz_Globs *)pG)->mpause)((zvoid *)pG,
1417                       LoadFarString(MorePrompt), 1);
1418                 }
1419             }
1420             INCSTR(p);
1421         } /* end while */
1422         size = (ulg)(p - q);   /* remaining text */
1423     }
1424 #endif /* MORE */
1425 
1426     if (size) {
1427 #ifdef OS2DLL
1428         if (!((Uz_Globs *)pG)->redirect_text) {
1429 #endif
1430             if ((error = WriteTxtErr(q, size, outfp)) != 0)
1431                 return error;
1432 #ifndef VMS     /* 2005-09-16 SMS.  See note at "WriteTxtErr()", above. */
1433             fflush(outfp);
1434 #endif
1435             if (MSG_STDERR(flag) && ((Uz_Globs *)pG)->UzO.tflag &&
1436                 !isatty(1) && isatty(2))
1437             {
1438                 /* error output from testing redirected:  also send to stderr */
1439                 if ((error = WriteTxtErr(q, size, stderr)) != 0)
1440                     return error;
1441                 fflush(stderr);
1442             }
1443 #ifdef OS2DLL
1444         } else {                /* GRR:  this is ugly:  hide with macro */
1445             if ((error = REDIRECTPRINT(q, size)) != 0)
1446                 return error;
1447         }
1448 #endif /* OS2DLL */
1449         ((Uz_Globs *)pG)->sol = (endbuf[-1] == '\n');
1450     }
1451     return 0;
1452 
1453 } /* end function UzpMessagePrnt() */
1454 
1455 
1456 
1457 
1458 
1459 #ifdef DLL
1460 
1461 /*****************************/
1462 /* Function UzpMessageNull() */  /* convenience routine for no output at all */
1463 /*****************************/
1464 
UzpMessageNull(pG,buf,size,flag)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 */
1470 {
1471     return 0;
1472 
1473 } /* end function UzpMessageNull() */
1474 
1475 #endif /* DLL */
1476 
1477 
1478 
1479 
1480 
1481 /***********************/
1482 /* Function UzpInput() */   /* GRR:  this is a placeholder for now */
1483 /***********************/
1484 
UzpInput(pG,buf,size,flag)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) */
1490 {
1491     /* tell picky compilers to shut up about "unused variable" warnings */
1492     pG = pG; buf = buf; flag = flag;
1493 
1494     *size = 0;
1495     return 0;
1496 
1497 } /* end function UzpInput() */
1498 
1499 
1500 
1501 
1502 
1503 #if (!defined(WINDLL) && !defined(MACOS))
1504 
1505 /***************************/
1506 /* Function UzpMorePause() */
1507 /***************************/
1508 
UzpMorePause(pG,prompt,flag)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 */
1513 {
1514     uch c;
1515 
1516 /*---------------------------------------------------------------------------
1517     Print a prompt and wait for the user to press a key, then erase prompt
1518     if possible.
1519   ---------------------------------------------------------------------------*/
1520 
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);
1525     fflush(stderr);
1526     if (flag & 1) {
1527         do {
1528             c = (uch)FGETCH(0);
1529         } while (
1530 #ifdef THEOS
1531                  c != 17 &&     /* standard QUIT key */
1532 #endif
1533                  c != '\r' && c != '\n' && c != ' ' && c != 'q' && c != 'Q');
1534     } else
1535         c = (uch)FGETCH(0);
1536 
1537     /* newline was not echoed, so cover up prompt line */
1538     fprintf(stderr, LoadFarString(HidePrompt));
1539     fflush(stderr);
1540 
1541     if (
1542 #ifdef THEOS
1543         (c == 17) ||            /* standard QUIT key */
1544 #endif
1545         (ToLower(c) == 'q')) {
1546         DESTROYGLOBALS();
1547         EXIT(PK_COOL);
1548     }
1549 
1550     ((Uz_Globs *)pG)->sol = TRUE;
1551 
1552 #ifdef MORE
1553     /* space for another screen, enter for another line. */
1554     if ((flag & 1) && c == ' ')
1555         ((Uz_Globs *)pG)->lines = 0;
1556 #endif /* MORE */
1557 
1558 } /* end function UzpMorePause() */
1559 
1560 #endif /* !WINDLL && !MACOS */
1561 
1562 
1563 
1564 
1565 #ifndef WINDLL
1566 
1567 /**************************/
1568 /* Function UzpPassword() */
1569 /**************************/
1570 
UzpPassword(pG,rcnt,pwbuf,size,zfn,efn)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 */
1578 {
1579 #if CRYPT
1580     int r = IZ_PW_ENTERED;
1581     char *m;
1582     char *prompt;
1583 
1584 #ifndef REENTRANT
1585     /* tell picky compilers to shut up about "unused variable" warnings */
1586     pG = pG;
1587 #endif
1588 
1589     if (*rcnt == 0) {           /* First call for current entry */
1590         *rcnt = 2;
1591         if ((prompt = (char *)malloc(2*FILNAMSIZ + 15)) != (char *)NULL) {
1592             sprintf(prompt, LoadFarString(PasswPrompt),
1593                     FnFilter1(zfn), FnFilter2(efn));
1594             m = prompt;
1595         } else
1596             m = (char *)LoadFarString(PasswPrompt2);
1597     } else {                    /* Retry call, previous password was wrong */
1598         (*rcnt)--;
1599         prompt = NULL;
1600         m = (char *)LoadFarString(PasswRetry);
1601     }
1602 
1603     m = getp(__G__ m, pwbuf, size);
1604     if (prompt != (char *)NULL) {
1605         free(prompt);
1606     }
1607     if (m == (char *)NULL) {
1608         r = IZ_PW_ERROR;
1609     }
1610     else if (*pwbuf == '\0') {
1611         r = IZ_PW_CANCELALL;
1612     }
1613     return r;
1614 
1615 #else /* !CRYPT */
1616     /* tell picky compilers to shut up about "unused variable" warnings */
1617     pG = pG; rcnt = rcnt; pwbuf = pwbuf; size = size; zfn = zfn; efn = efn;
1618 
1619     return IZ_PW_ERROR;  /* internal error; function should never get called */
1620 #endif /* ?CRYPT */
1621 
1622 } /* end function UzpPassword() */
1623 
1624 
1625 
1626 
1627 
1628 /**********************/
1629 /* Function handler() */
1630 /**********************/
1631 
handler(signal)1632 void handler(signal)   /* upon interrupt, turn on echo and exit cleanly */
1633     int signal;
1634 {
1635     GETGLOBALS();
1636 
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) */
1640 
1641     echon();
1642 
1643 #ifdef SIGBUS
1644     if (signal == SIGBUS) {
1645         Info(slide, 0x421, ((char *)slide, LoadFarString(ZipfileCorrupt),
1646           "bus error"));
1647         DESTROYGLOBALS();
1648         EXIT(PK_BADERR);
1649     }
1650 #endif /* SIGBUS */
1651 
1652 #ifdef SIGILL
1653     if (signal == SIGILL) {
1654         Info(slide, 0x421, ((char *)slide, LoadFarString(ZipfileCorrupt),
1655           "illegal instruction"));
1656         DESTROYGLOBALS();
1657         EXIT(PK_BADERR);
1658     }
1659 #endif /* SIGILL */
1660 
1661 #ifdef SIGSEGV
1662     if (signal == SIGSEGV) {
1663         Info(slide, 0x421, ((char *)slide, LoadFarString(ZipfileCorrupt),
1664           "segmentation violation"));
1665         DESTROYGLOBALS();
1666         EXIT(PK_BADERR);
1667     }
1668 #endif /* SIGSEGV */
1669 
1670     /* probably ctrl-C */
1671     DESTROYGLOBALS();
1672 #if defined(AMIGA) && defined(__SASC)
1673     _abort();
1674 #endif
1675     EXIT(IZ_CTRLC);       /* was EXIT(0), then EXIT(PK_ERR) */
1676 }
1677 
1678 #endif /* !WINDLL */
1679 
1680 
1681 
1682 
1683 #if (!defined(VMS) && !defined(CMS_MVS))
1684 #if (!defined(OS2) || defined(TIMESTAMP))
1685 
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 };
1690 #endif
1691 
1692 /*******************************/
1693 /* Function dos_to_unix_time() */ /* used for freshening/updating/timestamps */
1694 /*******************************/
1695 
dos_to_unix_time(dosdatetime)1696 time_t dos_to_unix_time(dosdatetime)
1697     ulg dosdatetime;
1698 {
1699     time_t m_time;
1700 
1701 #ifdef HAVE_MKTIME
1702 
1703     ZCONST time_t now = time(NULL);
1704     struct tm *tm;
1705 #   define YRBASE  1900
1706 
1707     tm = localtime(&now);
1708     tm->tm_isdst = -1;          /* let mktime determine if DST is in effect */
1709 
1710     /* dissect date */
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);
1714 
1715     /* dissect time */
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;
1719 
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));
1723 
1724 #else /* !HAVE_MKTIME */
1725 
1726     int yr, mo, dy, hh, mm, ss;
1727 #ifdef TOPS20
1728 #   define YRBASE  1900
1729     struct tmx *tmx;
1730     char temp[20];
1731 #else /* !TOPS20 */
1732 #   define YRBASE  1970
1733     int leap;
1734     unsigned days;
1735     struct tm *tm;
1736 #if (!defined(MACOS) && !defined(RISCOS) && !defined(QDOS) && !defined(TANDEM))
1737 #ifdef WIN32
1738     TIME_ZONE_INFORMATION tzinfo;
1739     DWORD res;
1740 #else /* ! WIN32 */
1741 #ifndef BSD4_4   /* GRR:  change to !defined(MODERN) ? */
1742 #if (defined(BSD) || defined(MTS) || defined(__GO32__))
1743     struct timeb tbp;
1744 #else /* !(BSD || MTS || __GO32__) */
1745 #ifdef DECLARE_TIMEZONE
1746     extern time_t timezone;
1747 #endif
1748 #endif /* ?(BSD || MTS || __GO32__) */
1749 #endif /* !BSD4_4 */
1750 #endif /* ?WIN32 */
1751 #endif /* !MACOS && !RISCOS && !QDOS && !TANDEM */
1752 #endif /* ?TOPS20 */
1753 
1754 
1755     /* dissect date */
1756     yr = ((int)(dosdatetime >> 25) & 0x7f) + (1980 - YRBASE);
1757     mo = ((int)(dosdatetime >> 21) & 0x0f) - 1;
1758     dy = ((int)(dosdatetime >> 16) & 0x1f) - 1;
1759 
1760     /* dissect time */
1761     hh = (int)((unsigned)dosdatetime >> 11) & 0x1f;
1762     mm = (int)((unsigned)dosdatetime >> 5) & 0x3f;
1763     ss = (int)((unsigned)dosdatetime & 0x1f) * 2;
1764 
1765 #ifdef TOPS20
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);
1770     free(tmx);
1771 
1772 #else /* !TOPS20 */
1773 
1774 /*---------------------------------------------------------------------------
1775     Calculate the number of seconds since the epoch, usually 1 January 1970.
1776   ---------------------------------------------------------------------------*/
1777 
1778     /* leap = # of leap yrs from YRBASE up to but not including current year */
1779     leap = ((yr + YRBASE - 1) / 4);   /* leap year base factor */
1780 
1781     /* calculate days from BASE to this year and add expired days this year */
1782     days = (yr * 365) + (leap - 492) + ydays[mo];
1783 
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 */
1787 
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));
1795 
1796 /*---------------------------------------------------------------------------
1797     Adjust for local standard timezone offset.
1798   ---------------------------------------------------------------------------*/
1799 
1800 #if (!defined(MACOS) && !defined(RISCOS) && !defined(QDOS) && !defined(TANDEM))
1801 #ifdef WIN32
1802     /* account for timezone differences */
1803     res = GetTimeZoneInformation(&tzinfo);
1804     if (res != TIME_ZONE_ID_INVALID)
1805     {
1806     m_time += 60*(tzinfo.Bias);
1807 #else /* !WIN32 */
1808 #if (defined(BSD) || defined(MTS) || defined(__GO32__))
1809 #ifdef BSD4_4
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 */
1826 #endif
1827 #endif /* ?(BSD || MTS || __GO32__) */
1828 #endif /* ?WIN32 */
1829     TTrace((stderr, "  m_time after timezone =  %lu\n", (ulg)m_time));
1830 
1831 /*---------------------------------------------------------------------------
1832     Adjust for local daylight savings (summer) time.
1833   ---------------------------------------------------------------------------*/
1834 
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)
1843 #ifdef WIN32
1844         m_time += 60L * tzinfo.DaylightBias;    /* adjust with DST bias */
1845     else
1846         m_time += 60L * tzinfo.StandardBias;    /* add StdBias (normally 0) */
1847 #else
1848         m_time -= 60L * 60L;    /* adjust for daylight savings time */
1849 #endif
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 */
1853 #ifdef WIN32
1854     }
1855 #endif
1856 #endif /* !MACOS && !RISCOS && !QDOS && !TANDEM */
1857 #endif /* ?TOPS20 */
1858 
1859 #endif /* ?HAVE_MKTIME */
1860 
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 */
1866 
1867     return m_time;
1868 
1869 } /* end function dos_to_unix_time() */
1870 
1871 #endif /* !OS2 || TIMESTAMP */
1872 #endif /* !VMS && !CMS_MVS */
1873 
1874 
1875 
1876 #if (!defined(VMS) && !defined(OS2) && !defined(CMS_MVS))
1877 
1878 /******************************/
1879 /* Function check_for_newer() */  /* used for overwriting/freshening/updating */
1880 /******************************/
1881 
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 */
1885 {
1886     time_t existing, archive;
1887 #ifdef USE_EF_UT_TIME
1888     iztimes z_utime;
1889 #endif
1890 #ifdef AOS_VS
1891     long    dyy, dmm, ddd, dhh, dmin, dss;
1892 
1893 
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;
1900 
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
1904      * it exists now.
1905      */
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;
1909 #endif /* AOS_VS */
1910 
1911     Trace((stderr, "check_for_newer:  doing stat(%s)\n", FnFilter1(filename)));
1912     if (SSTAT(filename, &G.statbuf)) {
1913         Trace((stderr,
1914           "check_for_newer:  stat(%s) returns %d:  file does not exist\n",
1915           FnFilter1(filename), SSTAT(filename, &G.statbuf)));
1916 #ifdef SYMLINKS
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) {
1921             Trace((stderr,
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 */
1928         }
1929 #endif /* SYMLINKS */
1930         return DOES_NOT_EXIST;
1931     }
1932     Trace((stderr, "check_for_newer:  stat(%s) returns 0:  file exists\n",
1933       FnFilter1(filename)));
1934 
1935 #ifdef SYMLINKS
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 */
1944     }
1945 #endif /* SYMLINKS */
1946 
1947     NATIVE_TO_TIMET(G.statbuf.st_mtime)   /* NOP unless MSC 7.0 or Macintosh */
1948 
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.
1953      */
1954     if (G.extra_field &&
1955 #ifdef IZ_CHECK_TZ
1956         G.tz_is_valid &&
1957 #endif
1958         (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0,
1959                           G.lrec.last_mod_dos_datetime, &z_utime, NULL)
1960          & EB_UT_FL_MTIME))
1961     {
1962         TTrace((stderr, "check_for_newer:  using Unix extra field mtime\n"));
1963         existing = G.statbuf.st_mtime;
1964         archive  = z_utime.mtime;
1965     } else {
1966         /* round up existing filetime to nearest 2 seconds for comparison,
1967          * but saturate in case of arithmetic overflow
1968          */
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);
1973     }
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
1977      */
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 */
1983 
1984     TTrace((stderr, "check_for_newer:  existing %lu, archive %lu, e-a %ld\n",
1985       (ulg)existing, (ulg)archive, (long)(existing-archive)));
1986 
1987     return (existing >= archive);
1988 
1989 } /* end function check_for_newer() */
1990 
1991 #endif /* !VMS && !OS2 && !CMS_MVS */
1992 
1993 
1994 
1995 
1996 
1997 /************************/
1998 /* Function do_string() */
1999 /************************/
2000 
2001 int do_string(__G__ length, option)   /* return PK-type error code */
2002     __GDEF
2003     unsigned int length;        /* without prototype, ush converted to this */
2004     int option;
2005 {
2006     unsigned comment_bytes_left;
2007     unsigned int block_len;
2008     int error=PK_OK;
2009 #ifdef AMIGA
2010     char tmp_fnote[2 * AMIGA_FILENOTELEN];   /* extra room for squozen chars */
2011 #endif
2012 
2013 
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.
2025 
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   ---------------------------------------------------------------------------*/
2030 
2031     if (!length)
2032         return PK_COOL;
2033 
2034     switch (option) {
2035 
2036 #if (defined(SFX) && defined(CHEAP_SFX_AUTORUN))
2037     /*
2038      * Special case: See if the comment begins with an autorun command line.
2039      * Save that and display (or skip) the remainder.
2040      */
2041 
2042     case CHECK_AUTORUN:
2043     case CHECK_AUTORUN_Q:
2044         comment_bytes_left = length;
2045         if (length >= 10)
2046         {
2047             block_len = readbuf(__G__ (char *)G.outbuf, 10);
2048             if (block_len == 0)
2049                 return PK_EOF;
2050             comment_bytes_left -= block_len;
2051             G.outbuf[block_len] = '\0';
2052             if (!strcmp((char *)G.outbuf, "$AUTORUN$>")) {
2053                 char *eol;
2054                 length -= 10;
2055                 block_len = readbuf(__G__ G.autorun_command,
2056                                     MIN(length, sizeof(G.autorun_command)-1));
2057                 if (block_len == 0)
2058                     return PK_EOF;
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');
2063                 if (!eol)
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))
2067                     *eol-- = '\0';
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) */
2073             }
2074         }
2075         if (option == CHECK_AUTORUN_Q)  /* don't display the remainder */
2076             length = 0;
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);
2081         if (!length)
2082             break;
2083         /*  FALL THROUGH...  */
2084 #endif /* SFX && CHEAP_SFX_AUTORUN */
2085 
2086     /*
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-
2094      * cessing).
2095      */
2096 
2097     case DISPLAY:
2098     case DISPL_8:
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;
2104 
2105             if ((block_len = readbuf(__G__ (char *)G.outbuf,
2106                    MIN((unsigned)OUTBUFSIZ, comment_bytes_left))) == 0)
2107                 return PK_EOF;
2108             comment_bytes_left -= block_len;
2109 
2110             /* this is why we allocated an extra byte for outbuf:  terminate
2111              *  with zero (ASCIIZ) */
2112             G.outbuf[block_len] = '\0';
2113 
2114             /* remove all ASCII carriage returns from comment before printing
2115              * (since used before A_TO_N(), check for CR instead of '\r')
2116              */
2117             while (*p) {
2118                 while (*p == CR)
2119                     ++p;
2120                 *q++ = *p++;
2121             }
2122             /* could check whether (p - outbuf) == block_len here */
2123             *q = '\0';
2124 
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,
2131                                     FALSE);
2132 #ifdef WINDLL
2133                 /* translate to ANSI (RTL internal codepage may be OEM) */
2134                 INTERN_TO_ISO((char *)G.outbuf, (char *)G.outbuf);
2135 #else /* !WINDLL */
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 */
2142             } else {
2143                 A_TO_N(G.outbuf);   /* translate string to native */
2144             }
2145 
2146 #ifdef WINDLL
2147             /* ran out of local mem -- had to cheat */
2148             win_fprintf((zvoid *)&G, stdout, (extent)(q-G.outbuf),
2149                         (char *)G.outbuf);
2150             win_fprintf((zvoid *)&G, stdout, 2, (char *)"\n\n");
2151 #else /* !WINDLL */
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) */
2155             p = G.outbuf - 1;
2156             q = slide;
2157             while (*++p) {
2158                 int pause = FALSE;
2159 
2160                 if (*p == 0x1B) {          /* ASCII escape char */
2161                     *q++ = '^';
2162                     *q++ = '[';
2163                 } else if (*p == 0x13) {   /* ASCII ^S (pause) */
2164                     pause = TRUE;
2165                     if (p[1] == LF)        /* ASCII LF */
2166                         *q++ = *++p;
2167                     else if (p[1] == CR && p[2] == LF) {  /* ASCII CR LF */
2168                         *q++ = *++p;
2169                         *q++ = *++p;
2170                     }
2171                 } else
2172                     *q++ = *p;
2173                 if ((unsigned)(q-slide) > WSIZE-3 || pause) {   /* flush */
2174                     (*G.message)((zvoid *)&G, slide, (ulg)(q-slide), 0);
2175                     q = slide;
2176                     if (pause && G.extract_flag) /* don't pause for list/test */
2177                         (*G.mpause)((zvoid *)&G, LoadFarString(QuitPrompt), 0);
2178                 }
2179             }
2180             (*G.message)((zvoid *)&G, slide, (ulg)(q-slide), 0);
2181 #endif /* ?NOANSIFILT */
2182 #endif /* ?WINDLL */
2183         }
2184         /* add '\n' if not at start of line */
2185         (*G.message)((zvoid *)&G, slide, 0L, 0x40);
2186         break;
2187 
2188     /*
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,
2191      * just to be sure.
2192      */
2193 
2194     case DS_FN:
2195     case DS_FN_L:
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;
2200 
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)
2207                 return PK_MEM;
2208             G.fnfull_bufsize = fnbufsiz;
2209         }
2210         if (readbuf(__G__ G.filename_full, length) == 0)
2211             return PK_EOF;
2212         G.filename_full[length] = '\0';      /* terminate w/zero:  ASCIIZ */
2213 
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)));
2218             error = PK_WARN;
2219             length = FILNAMSIZ - 1;
2220         }
2221         /* no excess size */
2222         block_len = 0;
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)));
2229             error = PK_WARN;
2230             /* remember excess length in block_len */
2231             block_len = length - (FILNAMSIZ - 1);
2232             length = FILNAMSIZ - 1;
2233         } else
2234             /* no excess size */
2235             block_len = 0;
2236         if (readbuf(__G__ G.filename, length) == 0)
2237             return PK_EOF;
2238         G.filename[length] = '\0';      /* terminate w/zero:  ASCIIZ */
2239 #endif /* ?UNICODE_SUPPORT */
2240 
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));
2245 
2246         if (G.pInfo->lcflag)      /* replace with lowercase filename */
2247             STRLOWER(G.filename, G.filename);
2248 
2249         if (G.pInfo->vollabel && length > 8 && G.filename[8] == '.') {
2250             char *p = G.filename+8;
2251             while (*p++)
2252                 p[-1] = *p;  /* disk label, and 8th char is dot:  remove dot */
2253         }
2254 
2255         if (!block_len)         /* no overflow, we're done here */
2256             break;
2257 
2258         /*
2259          * We truncated the filename, so print what's left and then fall
2260          * through to the SKIP routine.
2261          */
2262         Info(slide, 0x401, ((char *)slide, "[ %s ]\n", FnFilter1(G.filename)));
2263         length = block_len;     /* SKIP the excess bytes... */
2264         /*  FALL THROUGH...  */
2265 
2266     /*
2267      * Third case:  skip string, adjusting readbuf's internal variables
2268      * as necessary (and possibly skipping to and reading a new block of
2269      * data).
2270      */
2271 
2272     case SKIP:
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);
2277         break;
2278 
2279     /*
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.
2282      */
2283 
2284     case EXTRA_FIELD:
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),
2289               length));
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);
2294         } else {
2295             if (readbuf(__G__ (char *)G.extra_field, length) == 0)
2296                 return PK_EOF;
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;
2307               } else {
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;
2314                 }
2315               }
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)
2321 #  endif
2322                    ) {
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)));
2329                     error = PK_WARN;
2330                   }
2331                 }
2332 #  ifdef UNICODE_WCHAR
2333                 else
2334 #  endif
2335 # endif /* UTF8_MAYBE_NATIVE */
2336 # ifdef UNICODE_WCHAR
2337                 {
2338                   char *fn;
2339 
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)));
2348                     error = PK_WARN;
2349                   }
2350                   /* replace filename with converted UTF-8 */
2351                   strcpy(G.filename, fn);
2352                   free(fn);
2353                 }
2354 # endif /* UNICODE_WCHAR */
2355                 if (G.unipath_filename != G.filename_full)
2356                   free(G.unipath_filename);
2357                 G.unipath_filename = NULL;
2358               }
2359             }
2360 #endif /* UNICODE_SUPPORT */
2361         }
2362         break;
2363 
2364 #ifdef AMIGA
2365     /*
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.
2369      */
2370 
2371     case FILENOTE:
2372         if ((block_len = readbuf(__G__ tmp_fnote, (unsigned)
2373                                  MIN(length, 2 * AMIGA_FILENOTELEN - 1))) == 0)
2374             return PK_EOF;
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);
2384                 else
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;
2390         if (tmp_fnote[0]) {
2391             if (!(G.filenotes[G.filenote_slot] = malloc(strlen(tmp_fnote)+1)))
2392                 return PK_MEM;
2393             strcpy(G.filenotes[G.filenote_slot], tmp_fnote);
2394         }
2395         break;
2396 #endif /* AMIGA */
2397 
2398     } /* end switch (option) */
2399 
2400     return error;
2401 
2402 } /* end function do_string() */
2403 
2404 
2405 
2406 
2407 
2408 /***********************/
2409 /* Function makeword() */
2410 /***********************/
2411 
makeword(b)2412 ush makeword(b)
2413     ZCONST uch *b;
2414 {
2415     /*
2416      * Convert Intel style 'short' integer to non-Intel non-16-bit
2417      * host format.  This routine also takes care of byte-ordering.
2418      */
2419     return (ush)((b[1] << 8) | b[0]);
2420 }
2421 
2422 
2423 
2424 
2425 
2426 /***********************/
2427 /* Function makelong() */
2428 /***********************/
2429 
makelong(sig)2430 ulg makelong(sig)
2431     ZCONST uch *sig;
2432 {
2433     /*
2434      * Convert intel style 'long' variable to non-Intel non-16-bit
2435      * host format.  This routine also takes care of byte-ordering.
2436      */
2437     return (((ulg)sig[3]) << 24)
2438          + (((ulg)sig[2]) << 16)
2439          + (ulg)((((unsigned)sig[1]) << 8)
2440                + ((unsigned)sig[0]));
2441 }
2442 
2443 
2444 
2445 
2446 
2447 /************************/
2448 /* Function makeint64() */
2449 /************************/
2450 
makeint64(sig)2451 zusz_t makeint64(sig)
2452     ZCONST uch *sig;
2453 {
2454 #ifdef LARGE_FILE_SUPPORT
2455     /*
2456      * Convert intel style 'int64' variable to non-Intel non-16-bit
2457      * host format.  This routine also takes care of byte-ordering.
2458      */
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)
2465                  + (sig[0]));
2466 
2467 #else /* !LARGE_FILE_SUPPORT */
2468 
2469     if ((sig[7] | sig[6] | sig[5] | sig[4]) != 0)
2470         return (zusz_t)0xffffffffL;
2471     else
2472         return (zusz_t)((((ulg)sig[3]) << 24)
2473                       + (((ulg)sig[2]) << 16)
2474                       + (((unsigned)sig[1]) << 8)
2475                       + (sig[0]));
2476 
2477 #endif /* ?LARGE_FILE_SUPPORT */
2478 }
2479 
2480 
2481 
2482 
2483 
2484 /*********************/
2485 /* Function fzofft() */
2486 /*********************/
2487 
2488 /* Format a zoff_t value in a cylindrical buffer set. */
2489 char *fzofft(__G__ val, pre, post)
2490     __GDEF
2491     zoff_t val;
2492     ZCONST char *pre;
2493     ZCONST char *post;
2494 {
2495     /* Storage cylinder. (now in globals.h) */
2496     /*static char fzofft_buf[FZOFFT_NUM][FZOFFT_LEN];*/
2497     /*static int fzofft_index = 0;*/
2498 
2499     /* Temporary format string storage. */
2500     char fmt[16];
2501 
2502     /* Assemble the format string. */
2503     fmt[0] = '%';
2504     fmt[1] = '\0';             /* Start after initial "%". */
2505     if (pre == FZOFFT_HEX_WID)  /* Special hex width. */
2506     {
2507         strcat(fmt, FZOFFT_HEX_WID_VALUE);
2508     }
2509     else if (pre == FZOFFT_HEX_DOT_WID) /* Special hex ".width". */
2510     {
2511         strcat(fmt, ".");
2512         strcat(fmt, FZOFFT_HEX_WID_VALUE);
2513     }
2514     else if (pre != NULL)       /* Caller's prefix (width). */
2515     {
2516         strcat(fmt, pre);
2517     }
2518 
2519     strcat(fmt, FZOFFT_FMT);   /* Long or long-long or whatever. */
2520 
2521     if (post == NULL)
2522         strcat(fmt, "d");      /* Default radix = decimal. */
2523     else
2524         strcat(fmt, post);     /* Caller's radix. */
2525 
2526     /* Advance the cylinder. */
2527     G.fzofft_index = (G.fzofft_index + 1) % FZOFFT_NUM;
2528 
2529     /* Write into the current chamber. */
2530     sprintf(G.fzofft_buf[G.fzofft_index], fmt, val);
2531 
2532     /* Return a pointer to this chamber. */
2533     return G.fzofft_buf[G.fzofft_index];
2534 }
2535 
2536 
2537 
2538 
2539 #if CRYPT
2540 
2541 #ifdef NEED_STR2ISO
2542 /**********************/
2543 /* Function str2iso() */
2544 /**********************/
2545 
str2iso(dst,src)2546 char *str2iso(dst, src)
2547     char *dst;                          /* destination buffer */
2548     register ZCONST char *src;          /* source string */
2549 {
2550 #ifdef INTERN_TO_ISO
2551     INTERN_TO_ISO(src, dst);
2552 #else
2553     register uch c;
2554     register char *dstp = dst;
2555 
2556     do {
2557         c = (uch)foreign(*src++);
2558         *dstp++ = (char)ASCII2ISO(c);
2559     } while (c != '\0');
2560 #endif
2561 
2562     return dst;
2563 }
2564 #endif /* NEED_STR2ISO */
2565 
2566 
2567 #ifdef NEED_STR2OEM
2568 /**********************/
2569 /* Function str2oem() */
2570 /**********************/
2571 
str2oem(dst,src)2572 char *str2oem(dst, src)
2573     char *dst;                          /* destination buffer */
2574     register ZCONST char *src;          /* source string */
2575 {
2576 #ifdef INTERN_TO_OEM
2577     INTERN_TO_OEM(src, dst);
2578 #else
2579     register uch c;
2580     register char *dstp = dst;
2581 
2582     do {
2583         c = (uch)foreign(*src++);
2584         *dstp++ = (char)ASCII2OEM(c);
2585     } while (c != '\0');
2586 #endif
2587 
2588     return dst;
2589 }
2590 #endif /* NEED_STR2OEM */
2591 
2592 #endif /* CRYPT */
2593 
2594 
2595 #ifdef ZMEM  /* memset/memcmp/memcpy for systems without either them or */
2596              /* bzero/bcmp/bcopy */
2597              /* (no known systems as of 960211) */
2598 
2599 /*********************/
2600 /* Function memset() */
2601 /*********************/
2602 
memset(buf,init,len)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 */
2607 {
2608     zvoid *start;
2609 
2610     start = buf;
2611     while (len--)
2612         *((char *)buf++) = (char)init;
2613     return start;
2614 }
2615 
2616 
2617 
2618 /*********************/
2619 /* Function memcmp() */
2620 /*********************/
2621 
memcmp(b1,b2,len)2622 int memcmp(b1, b2, len)
2623     register ZCONST zvoid *b1;
2624     register ZCONST zvoid *b2;
2625     register unsigned int len;
2626 {
2627     register int c;
2628 
2629     if (len > 0) do {
2630         if ((c = (int)(*((ZCONST unsigned char *)b1)++) -
2631                  (int)(*((ZCONST unsigned char *)b2)++)) != 0)
2632            return c;
2633     } while (--len > 0)
2634     return 0;
2635 }
2636 
2637 
2638 
2639 /*********************/
2640 /* Function memcpy() */
2641 /*********************/
2642 
memcpy(dst,src,len)2643 zvoid *memcpy(dst, src, len)
2644     register zvoid *dst;
2645     register ZCONST zvoid *src;
2646     register unsigned int len;
2647 {
2648     zvoid *start;
2649 
2650     start = dst;
2651     while (len-- > 0)
2652         *((char *)dst)++ = *((ZCONST char *)src)++;
2653     return start;
2654 }
2655 
2656 #endif /* ZMEM */
2657 
2658 
2659 
2660 
2661 #ifdef NO_STRNICMP
2662 
2663 /************************/
2664 /* Function zstrnicmp() */
2665 /************************/
2666 
zstrnicmp(s1,s2,n)2667 int zstrnicmp(s1, s2, n)
2668     register ZCONST char *s1, *s2;
2669     register unsigned n;
2670 {
2671     for (; n > 0;  --n, ++s1, ++s2) {
2672 
2673         if (ToLower(*s1) != ToLower(*s2))
2674             /* test includes early termination of one string */
2675             return ((uch)ToLower(*s1) < (uch)ToLower(*s2))? -1 : 1;
2676 
2677         if (*s1 == '\0')   /* both strings terminate early */
2678             return 0;
2679     }
2680     return 0;
2681 }
2682 
2683 #endif /* NO_STRNICMP */
2684 
2685 
2686 
2687 
2688 #ifdef REGULUS  /* returns the inode number on success(!)...argh argh argh */
2689 #  undef stat
2690 
2691 /********************/
2692 /* Function zstat() */
2693 /********************/
2694 
zstat(p,s)2695 int zstat(p, s)
2696     ZCONST char *p;
2697     struct stat *s;
2698 {
2699     return (stat((char *)p,s) >= 0? 0 : (-1));
2700 }
2701 
2702 #endif /* REGULUS */
2703 
2704 
2705 
2706 
2707 #ifdef _MBCS
2708 
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
2712  */
2713 
2714 /************************/
2715 /* Function plastchar() */
2716 /************************/
2717 
plastchar(ptr,len)2718 char *plastchar(ptr, len)
2719     ZCONST char *ptr;
2720     extent len;
2721 {
2722     unsigned clen;
2723     ZCONST char *oldptr = ptr;
2724     while(*ptr != '\0' && len > 0){
2725         oldptr = ptr;
2726         clen = CLEN(ptr);
2727         ptr += clen;
2728         len -= clen;
2729     }
2730     return (char *)oldptr;
2731 }
2732 
2733 
2734 #ifdef NEED_UZMBCLEN
2735 /***********************/
2736 /* Function uzmbclen() */
2737 /***********************/
2738 
uzmbclen(ptr)2739 extent uzmbclen(ptr)
2740     ZCONST unsigned char *ptr;
2741 {
2742     int mbl;
2743 
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.
2750      */
2751     return (extent)(mbl > 0 ? mbl : 1);
2752 }
2753 #endif /* NEED_UZMBCLEN */
2754 
2755 
2756 #ifdef NEED_UZMBSCHR
2757 /***********************/
2758 /* Function uzmbschr() */
2759 /***********************/
2760 
uzmbschr(str,c)2761 unsigned char *uzmbschr(str, c)
2762     ZCONST unsigned char *str;
2763     unsigned int c;
2764 {
2765     while(*str != '\0'){
2766         if (*str == c) {return (unsigned char *)str;}
2767         INCSTR(str);
2768     }
2769     return NULL;
2770 }
2771 #endif /* NEED_UZMBSCHR */
2772 
2773 
2774 #ifdef NEED_UZMBSRCHR
2775 /************************/
2776 /* Function uzmbsrchr() */
2777 /************************/
2778 
uzmbsrchr(str,c)2779 unsigned char *uzmbsrchr(str, c)
2780     ZCONST unsigned char *str;
2781     unsigned int c;
2782 {
2783     unsigned char *match = NULL;
2784     while(*str != '\0'){
2785         if (*str == c) {match = (unsigned char *)str;}
2786         INCSTR(str);
2787     }
2788     return match;
2789 }
2790 #endif /* NEED_UZMBSRCHR */
2791 #endif /* _MBCS */
2792 
2793 
2794 
2795 
2796 
2797 #ifdef SMALL_MEM
2798 
2799 /*******************************/
2800 /*  Function fLoadFarString()  */   /* (and friends...) */
2801 /*******************************/
2802 
fLoadFarString(__GPRO__ const char Far * sz)2803 char *fLoadFarString(__GPRO__ const char Far *sz)
2804 {
2805     (void)zfstrcpy(G.rgchBigBuffer, sz);
2806     return G.rgchBigBuffer;
2807 }
2808 
fLoadFarStringSmall(__GPRO__ const char Far * sz)2809 char *fLoadFarStringSmall(__GPRO__ const char Far *sz)
2810 {
2811     (void)zfstrcpy(G.rgchSmallBuffer, sz);
2812     return G.rgchSmallBuffer;
2813 }
2814 
fLoadFarStringSmall2(__GPRO__ const char Far * sz)2815 char *fLoadFarStringSmall2(__GPRO__ const char Far *sz)
2816 {
2817     (void)zfstrcpy(G.rgchSmallBuffer2, sz);
2818     return G.rgchSmallBuffer2;
2819 }
2820 
2821 
2822 
2823 
2824 #if (!defined(_MSC_VER) || (_MSC_VER < 600))
2825 /*************************/
2826 /*  Function zfstrcpy()  */   /* portable clone of _fstrcpy() */
2827 /*************************/
2828 
zfstrcpy(char Far * s1,const char Far * s2)2829 char Far * Far zfstrcpy(char Far *s1, const char Far *s2)
2830 {
2831     char Far *p = s1;
2832 
2833     while ((*s1++ = *s2++) != '\0');
2834     return p;
2835 }
2836 
2837 #if (!(defined(SFX) || defined(FUNZIP)))
2838 /*************************/
2839 /*  Function zfstrcmp()  */   /* portable clone of _fstrcmp() */
2840 /*************************/
2841 
zfstrcmp(const char Far * s1,const char Far * s2)2842 int Far zfstrcmp(const char Far *s1, const char Far *s2)
2843 {
2844     int ret;
2845 
2846     while ((ret = (int)(uch)*s1 - (int)(uch)*s2) == 0
2847            && *s2 != '\0') {
2848         ++s2; ++s1;
2849     }
2850     return ret;
2851 }
2852 #endif /* !(SFX || FUNZIP) */
2853 #endif /* !_MSC_VER || (_MSC_VER < 600) */
2854 
2855 #endif /* SMALL_MEM */
2856