Subversion Repositories Kolibri OS

Rev

Rev 6725 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  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 & 0xFE, ((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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  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. #if !defined(__BEOS__) && !defined(KOS32)   /* 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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  2803. char *fLoadFarString(__GPRO__ const char Far *sz)
  2804. {
  2805.     (void)zfstrcpy(G.rgchBigBuffer, sz);
  2806.     return G.rgchBigBuffer;
  2807. }
  2808.  
  2809. char *fLoadFarStringSmall(__GPRO__ const char Far *sz)
  2810. {
  2811.     (void)zfstrcpy(G.rgchSmallBuffer, sz);
  2812.     return G.rgchSmallBuffer;
  2813. }
  2814.  
  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.  
  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.  
  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.