home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / UNZP50P1.ZIP / misc.c < prev    next >
C/C++ Source or Header  |  1993-01-23  |  25KB  |  744 lines

  1. /*---------------------------------------------------------------------------
  2.  
  3.   misc.c
  4.  
  5.   This file contains a number of useful but not particularly closely related
  6.   functions; their main claim to fame is that they don't change much, so this
  7.   file should rarely need to be recompiled.  The CRC-32 stuff is from crc32.c;
  8.   do_string() is from nunzip.c; makeword() and makelong() are from unzip.c;
  9.   memset() and memcpy() are from zmemset.c and zmemcpy.c, respectively; and
  10.   dos_to_unix_time() is from set_file_time_and_close() in file_io.c.  ebcdic[],
  11.   check_for_newer(), dateformat(), and return_VMS() are new.  Things lumped
  12.   together here to cut down on the size of unzip.c and the number of associ-
  13.   ated files floating around.
  14.  
  15.   ---------------------------------------------------------------------------
  16.  
  17.   Copyrights:  see accompanying file "COPYING" in UnZip source distribution.
  18.  
  19.   ---------------------------------------------------------------------------*/
  20.  
  21.  
  22. #include "unzip.h"
  23. #ifdef MSWIN
  24. #  include "wizunzip.h"
  25. #endif
  26.  
  27.  
  28.  
  29. #ifndef ZIPINFO   /* no need to calculate CRCs */
  30.  
  31. /**************************/
  32. /*  Function UpdateCRC()  */
  33. /**************************/
  34.  
  35.  /*--------------------------------------------------------------------
  36.  
  37.    First, the polynomial itself and its table of feedback terms.  The
  38.    polynomial is
  39.    X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
  40.  
  41.    Note that we take it "backwards" and put the highest-order term in
  42.    the lowest-order bit.  The X^32 term is "implied"; the LSB is the
  43.    X^31 term, etc.  The X^0 term (usually shown as "+1") results in
  44.    the MSB being 1.
  45.  
  46.    Note that the usual hardware shift register implementation, which
  47.    is what we're using (we're merely optimizing it by doing eight-bit
  48.    chunks at a time) shifts bits into the lowest-order term.  In our
  49.    implementation, that means shifting towards the right.  Why do we
  50.    do it this way?  Because the calculated CRC must be transmitted in
  51.    order from highest-order term to lowest-order term.  UARTs transmit
  52.    characters in order from LSB to MSB.  By storing the CRC this way,
  53.    we hand it to the UART in the order low-byte to high-byte; the UART
  54.    sends each low-bit to hight-bit; and the result is transmission bit
  55.    by bit from highest- to lowest-order term without requiring any bit
  56.    shuffling on our part.  Reception works similarly.
  57.  
  58.    The feedback terms table consists of 256, 32-bit entries.  Notes:
  59.  
  60.        The table can be generated at runtime if desired; code to do so
  61.        is shown later.  It might not be obvious, but the feedback
  62.        terms simply represent the results of eight shift/xor opera-
  63.        tions for all combinations of data and CRC register values.
  64.  
  65.        The values must be right-shifted by eight bits by the "updcrc"
  66.        logic; the shift must be unsigned (bring in zeroes).  On some
  67.        hardware you could probably optimize the shift in assembler by
  68.        using byte-swap instructions.
  69.        polynomial $edb88320
  70.  
  71.    --------------------------------------------------------------------*/
  72.  
  73. ULONG crc_32_tab[] =
  74. {
  75.     0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
  76.     0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
  77.     0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
  78.     0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
  79.     0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
  80.     0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
  81.     0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
  82.     0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
  83.     0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
  84.     0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
  85.     0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
  86.     0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
  87.     0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
  88.     0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
  89.     0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
  90.     0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
  91.     0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
  92.     0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
  93.     0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
  94.     0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
  95.     0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
  96.     0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
  97.     0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
  98.     0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
  99.     0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
  100.     0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
  101.     0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
  102.     0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
  103.     0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
  104.     0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
  105.     0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
  106.     0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
  107.     0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
  108.     0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
  109.     0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
  110.     0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
  111.     0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
  112.     0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
  113.     0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
  114.     0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
  115.     0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
  116.     0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
  117.     0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
  118.     0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
  119.     0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
  120.     0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
  121.     0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
  122.     0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
  123.     0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
  124.     0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
  125.     0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
  126.     0x2d02ef8dL
  127. }; /* end crc_32_tab[] */
  128.  
  129.  
  130. void UpdateCRC(s, len)
  131.     register byte *s;
  132.     register int len;
  133. {
  134.     register ULONG crcval = crc32val;
  135.  
  136.     /* update running CRC calculation with contents of a buffer */
  137.     while (len--)
  138.         crcval = crc_32_tab[((byte) crcval ^ (*s++)) & 0xff] ^ (crcval >> 8);
  139.     crc32val = crcval;
  140. }
  141.  
  142. #endif /* !ZIPINFO */
  143.  
  144.  
  145.  
  146.  
  147.  
  148. /**************************/
  149. /*  Function do_string()  */
  150. /**************************/
  151.  
  152. int do_string(len, option)      /* return PK-type error code */
  153.     unsigned int len;           /* without prototype, UWORD converted to this */
  154.     int option;
  155. {
  156.     int block_length, error = 0;
  157.     UWORD comment_bytes_left, extra_len;
  158.  
  159.  
  160. /*---------------------------------------------------------------------------
  161.     This function processes arbitrary-length (well, usually) strings.  Three
  162.     options are allowed:  SKIP, wherein the string is skipped pretty logical,
  163.     eh?); DISPLAY, wherein the string is printed to standard output after un-
  164.     dergoing any necessary or unnecessary character conversions; and FILENAME,
  165.     wherein the string is put into the filename[] array after undergoing ap-
  166.     propriate conversions (including case-conversion, if that is indicated:
  167.     see the global variable pInfo->lcflag).  The latter option should be OK,
  168.     since filename is now dimensioned at 1025, but we check anyway.
  169.  
  170.     The string, by the way, is assumed to start at the current file-pointer
  171.     position; its length is given by len.  So start off by checking length
  172.     of string:  if zero, we're already set.
  173.   ---------------------------------------------------------------------------*/
  174.  
  175.     if (!len)
  176.         return (0);             /* 0:  no error */
  177.  
  178.     switch (option) {
  179.  
  180.     /*
  181.      * First case:  print string on standard output.  First set loop vari-
  182.      * ables, then loop through the comment in chunks of OUTBUFSIZ bytes,
  183.      * converting formats and printing as we go.  The second half of the
  184.      * loop conditional was added because the file might be truncated, in
  185.      * which case comment_bytes_left will remain at some non-zero value for
  186.      * all time.  outbuf is used as a scratch buffer because it is avail-
  187.      * able (we should be either before or in between any file processing).
  188.      * [The typecast in front of the MIN() macro was added because of the
  189.      * new promotion rules under ANSI C; readbuf() wants an int, but MIN()
  190.      * returns a signed long, if I understand things correctly.  The proto-
  191.      * type should handle it, but just in case...]
  192.      */
  193.  
  194.     case DISPLAY:
  195.         comment_bytes_left = len;
  196.         block_length = OUTBUFSIZ;    /* for the while statement, first time */
  197.         while (comment_bytes_left > 0 && block_length > 0) {
  198.             if ((block_length = readbuf((char *)outbuf,
  199.                    (int) MIN(OUTBUFSIZ, comment_bytes_left))) <= 0)
  200.                 return 51;                      /* 51:  unexpected EOF */
  201.             comment_bytes_left -= block_length;
  202.             NUKE_CRs(outbuf, block_length);     /* (modifies block_length) */
  203.  
  204.             /*  this is why we allocated an extra byte for outbuf: */
  205.             outbuf[block_length] = '\0';        /* terminate w/zero:  ASCIIZ */
  206.  
  207.             A_TO_N(outbuf);     /* translate string to native */
  208.  
  209.             printf("%s", outbuf);
  210.         }
  211. #ifdef MSWIN
  212.         /* ran out of local mem -- had to cheat */
  213.         WriteStringToMsgWin(outbuf, bRealTimeMsgUpdate);
  214. #else /* !MSWIN */
  215.         printf("\n");   /* assume no newline at end */
  216. #endif /* ?MSWIN */
  217.         break;
  218.  
  219.     /*
  220.      * Second case:  read string into filename[] array.  The filename should
  221.      * never ever be longer than FILNAMSIZ-1 (1024), but for now we'll check,
  222.      * just to be sure.
  223.      */
  224.  
  225.     case FILENAME:
  226.         extra_len = 0;
  227.         if (len >= FILNAMSIZ) {
  228.             fprintf(stderr, "warning:  filename too long--truncating.\n");
  229.             error = 1;          /* 1:  warning error */
  230.             extra_len = len - FILNAMSIZ + 1;
  231.             len = FILNAMSIZ - 1;
  232.         }
  233.         if (readbuf(filename, len) <= 0)
  234.             return 51;          /* 51:  unexpected EOF */
  235.         filename[len] = '\0';   /* terminate w/zero:  ASCIIZ */
  236.  
  237.         A_TO_N(filename);       /* translate string to native */
  238.  
  239. #ifndef ZIPINFO
  240.         if (pInfo->lcflag)
  241.             TOLOWER(filename, filename);  /* replace with lowercase filename */
  242. #endif
  243.  
  244.         if (!extra_len)         /* we're done here */
  245.             break;
  246.  
  247.         /*
  248.          * We truncated the filename, so print what's left and then fall
  249.          * through to the SKIP routine.
  250.          */
  251.         fprintf(stderr, "[ %s ]\n", filename);
  252.         len = extra_len;
  253.         /*  FALL THROUGH...  */
  254.  
  255.     /*
  256.      * Third case:  skip string, adjusting readbuf's internal variables
  257.      * as necessary (and possibly skipping to and reading a new block of
  258.      * data).
  259.      */
  260.  
  261.     case SKIP:
  262.         LSEEK(cur_zipfile_bufstart + (inptr-inbuf) + len)
  263.         break;
  264.  
  265.     /*
  266.      * Fourth case:  assume we're at the start of an "extra field"; malloc
  267.      * storage for it and read data into the allocated space.
  268.      */
  269.  
  270.     case EXTRA_FIELD:
  271.         if (extra_field != (byte *)NULL)
  272.             free(extra_field);
  273.         if ((extra_field = (byte *)malloc(len)) == (byte *)NULL) {
  274.             fprintf(stderr,
  275.               "warning:  extra field too long (%d).  Ignoring...\n", len);
  276.             LSEEK(cur_zipfile_bufstart + (inptr-inbuf) + len)
  277.         } else
  278.             if (readbuf((char *)extra_field, len) <= 0)
  279.                 return 51;      /* 51:  unexpected EOF */
  280.         break;
  281.  
  282.     } /* end switch (option) */
  283.     return error;
  284.  
  285. } /* end function do_string() */
  286.  
  287.  
  288.  
  289.  
  290.  
  291. #ifndef ZIPINFO
  292. #ifndef VMS
  293.  
  294. /*********************************/
  295. /*  Function dos_to_unix_time()  */
  296. /*********************************/
  297.  
  298. time_t dos_to_unix_time(ddate, dtime)
  299.     unsigned ddate, dtime;
  300. {
  301.     static short yday[]={0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
  302.     int yr, mo, dy, hh, mm, ss, leap;
  303.     long m_time, days=0;
  304. #if (!defined(MACOS) && !defined(MSC) && !defined(__GO32__))
  305. #if (defined(BSD) || defined(MTS))
  306. #ifndef __386BSD__
  307.     static struct timeb tbp;
  308. #endif /* __386BSD__ */
  309. #else /* !(BSD || MTS) */
  310.     extern long timezone;    /* declared in <time.h> for MSC (& Borland?) */
  311. #endif /* ?(BSD || MTS) */
  312. #endif /* !MACOS && !MSC && !__GO32__ */
  313.  
  314. #   define YRBASE  1970
  315.  
  316.     /* dissect date */
  317.     yr = ((ddate >> 9) & 0x7f) + (1980 - YRBASE);
  318.     mo = ((ddate >> 5) & 0x0f) - 1;
  319.     dy = (ddate & 0x1f) - 1;
  320.  
  321.     /* dissect time */
  322.     hh = (dtime >> 11) & 0x1f;
  323.     mm = (dtime >> 5) & 0x3f;
  324.     ss = (dtime & 0x1f) * 2;
  325.  
  326.     /* leap = # of leap years from BASE up to but not including current year */
  327.     leap = ((yr + YRBASE - 1) / 4);   /* leap year base factor */
  328.  
  329.     /* How many days from BASE to this year? (& add expired days this year) */
  330.     days = (yr * 365) + (leap - 492) + yday[mo];
  331.  
  332.     /* if year is a leap year and month is after February, add another day */
  333.     if ((mo > 1) && ((yr+YRBASE)%4 == 0) && ((yr+YRBASE) != 2100))
  334.         ++days;                 /* OK through 2199 */
  335.  
  336.     /* convert date & time to seconds relative to 00:00:00, 01/01/YRBASE */
  337.     m_time = ((long)(days + dy) * 86400L) + ((long)hh * 3600) + (mm * 60) + ss;
  338.       /* - 1;   MS-DOS times always rounded up to nearest even second */
  339.  
  340. #if (!defined(MACOS) && !defined(__GO32__))
  341. #if (defined(BSD) || defined(MTS))
  342. #ifndef __386BSD__
  343.     ftime(&tbp);
  344.     m_time += tbp.timezone * 60L;
  345. #endif
  346. #else /* !(BSD || MTS) */
  347. #ifdef WIN32
  348.     /* later... */
  349. #else /* !WIN32 */
  350.     tzset();                    /* set `timezone' */
  351. #endif /* ?WIN32 */
  352.     m_time += timezone;         /* account for timezone differences */
  353. #endif /* ?(BSD || MTS) */
  354. #endif /* !MACOS && !__GO32__ */
  355.  
  356. #ifdef __386BSD__
  357.     m_time += localtime((time_t *) &m_time))->tm_gmtoff;
  358. #else
  359.     if (localtime((time_t *)&m_time)->tm_isdst)
  360.         m_time -= 60L * 60L;    /* adjust for daylight savings time */
  361. #endif /* __386BSD__ */
  362.  
  363.     return m_time;
  364.  
  365. } /* end function dos_to_unix_time() */
  366.  
  367. #endif /* !VMS */
  368.  
  369.  
  370.  
  371.  
  372.  
  373. /********************************/
  374. /*  Function check_for_newer()  */  /* could make this into a macro for Unix */
  375. /********************************/
  376.  
  377. int check_for_newer(filename)   /* return 1 if existing file newer or equal; */
  378.     char *filename;             /*  0 if older; -1 if doesn't exist yet */
  379. {
  380. #ifdef VMS
  381.     unsigned short timbuf[7];
  382.     int dy, mo, yr, hh, mm, ss, dy2, mo2, yr2, hh2, mm2, ss2;
  383.     struct FAB fab;
  384.     struct XABDAT xdat;
  385.  
  386.  
  387.     if (stat(filename, &statbuf))
  388.         return DOES_NOT_EXIST;
  389.  
  390.     fab  = cc$rms_fab;
  391.     xdat = cc$rms_xabdat;
  392.  
  393.     fab.fab$l_xab = &xdat;
  394.     fab.fab$l_fna = filename;
  395.     fab.fab$b_fns = strlen(filename);
  396.     fab.fab$l_fop = FAB$M_GET | FAB$M_UFO;
  397.  
  398.     if ((sys$open(&fab) & 1) == 0)       /* open failure:  report exists and */
  399.         return EXISTS_AND_OLDER;         /*  older so new copy will be made  */
  400.     sys$numtim(&timbuf,&xdat.xab$q_cdt);
  401.     fab.fab$l_xab = 0L;
  402.  
  403.     sys$dassgn(fab.fab$l_stv);
  404.     sys$close(&fab);   /* be sure file is closed and RMS knows about it */
  405.  
  406.     yr = timbuf[0];
  407.     yr2 = ((lrec.last_mod_file_date >> 9) & 0x7f) + 1980;
  408.     if (yr > yr2)
  409.         return EXISTS_AND_NEWER;
  410.     else if (yr < yr2)
  411.         return EXISTS_AND_OLDER;
  412.  
  413.     mo = timbuf[1];
  414.     mo2 = ((lrec.last_mod_file_date >> 5) & 0x0f);
  415.     if (mo > mo2)
  416.         return EXISTS_AND_NEWER;
  417.     else if (mo < mo2)
  418.         return EXISTS_AND_OLDER;
  419.  
  420.     dy = timbuf[2];
  421.     dy2 = (lrec.last_mod_file_date & 0x1f);
  422.     if (dy > dy2)
  423.         return EXISTS_AND_NEWER;
  424.     else if (dy < dy2)
  425.         return EXISTS_AND_OLDER;
  426.  
  427.     hh = timbuf[3];
  428.     hh2 = (lrec.last_mod_file_time >> 11) & 0x1f;
  429.     if (hh > hh2)
  430.         return EXISTS_AND_NEWER;
  431.     else if (hh < hh2)
  432.         return EXISTS_AND_OLDER;
  433.  
  434.     mm = timbuf[4];
  435.     mm2 = (lrec.last_mod_file_time >> 5) & 0x3f;
  436.     if (mm > mm2)
  437.         return EXISTS_AND_NEWER;
  438.     else if (mm < mm2)
  439.         return EXISTS_AND_OLDER;
  440.  
  441.     /* round to nearest 2 secs--may become 60, but doesn't matter for compare */
  442.     ss = (int)((float)timbuf[5] + (float)timbuf[6]*.01 + 1.) & -2;
  443.     ss2 = (lrec.last_mod_file_time & 0x1f) * 2;
  444.     if (ss >= ss2)
  445.         return EXISTS_AND_NEWER;
  446.  
  447.     return EXISTS_AND_OLDER;
  448.  
  449. #else /* !VMS */
  450. #ifdef OS2
  451.     long existing, archive;
  452.  
  453.     if ((existing = GetFileTime(filename)) == -1)
  454.         return DOES_NOT_EXIST;
  455.     archive = ((long) lrec.last_mod_file_date) << 16 | lrec.last_mod_file_time;
  456.  
  457.     return (existing >= archive);
  458. #else /* !OS2 */
  459.     time_t existing, archive;
  460.  
  461.     if (stat(filename, &statbuf))
  462.         return DOES_NOT_EXIST;
  463.  
  464.     /* round up existing filetime to nearest 2 seconds for comparison */
  465.     existing = (statbuf.st_mtime & 1) ? statbuf.st_mtime+1 : statbuf.st_mtime;
  466.     archive  = dos_to_unix_time(lrec.last_mod_file_date,
  467.                                 lrec.last_mod_file_time);
  468.  
  469.     return (existing >= archive);
  470. #endif /* ?OS2 */
  471. #endif /* ?VMS */
  472.  
  473. } /* end function check_for_newer() */
  474.  
  475.  
  476.  
  477.  
  478.  
  479. /***************************/
  480. /*  Function dateformat()  */
  481. /***************************/
  482.  
  483. int dateformat()
  484. {
  485.  
  486. /*-----------------------------------------------------------------------------
  487.   For those operating systems which support it, this function returns a value
  488.   which tells how national convention says that numeric dates are displayed.
  489.  
  490.   Return values are DF_YMD, DF_DMY and DF_MDY.  The meanings should be fairly
  491.   obvious.
  492.  -----------------------------------------------------------------------------*/
  493.  
  494. #ifdef OS2
  495.     switch (GetCountryInfo()) {
  496.             case 0 /* DATEFMT_MM_DD_YY */ :
  497.                 return DF_MDY;
  498.             case 1 /* DATEFMT_DD_MM_YY */ :
  499.                 return DF_DMY;
  500.             case 2 /* DATEFMT_YY_MM_DD */ :
  501.                 return DF_YMD;
  502.         }
  503. #else /* !OS2 */
  504. #if (defined(MSDOS) && !defined(MSWIN))
  505.     unsigned short _CountryInfo[18];
  506. #ifdef __GO32__
  507.     unsigned short *CountryInfo = _CountryInfo;
  508.  
  509.     bdos(0x38, (unsigned)CountryInfo, 0);
  510. #else /* !__GO32__ */
  511.     unsigned short far *CountryInfo = _CountryInfo;
  512.     union REGS regs;
  513.     struct SREGS sregs;
  514.  
  515.     regs.x.ax = 0x3800;
  516.     regs.x.dx = FP_OFF(CountryInfo);
  517.     sregs.ds  = FP_SEG(CountryInfo);
  518.     int86x(0x21, ®s, ®s, &sregs);
  519. #endif /* ?__GO32__ */
  520.  
  521.     switch(CountryInfo[0]) {
  522.         case 0:
  523.             return DF_MDY;
  524.         case 1:
  525.             return DF_DMY;
  526.         case 2:
  527.             return DF_YMD;
  528.     }
  529. #endif /* MSDOS && !MSWIN */
  530. #endif /* ?OS2 */
  531.  
  532.     return DF_MDY;   /* default for Unix, VMS, etc. */
  533.  
  534. } /* end function dateformat() */
  535.  
  536. #endif /* !ZIPINFO */
  537.  
  538.  
  539.  
  540.  
  541.  
  542. #ifdef EBCDIC
  543.  
  544. /*
  545.  * This is the MTS ASCII->EBCDIC translation table. It provides a 1-1
  546.  * translation from ISO 8859/1 8-bit ASCII to IBM Code Page 37 EBCDIC.
  547.  */
  548.  
  549. unsigned char ebcdic[] =
  550. {
  551.     0x00, 0x01, 0x02, 0x03, 0x37, 0x2d, 0x2e, 0x2f,
  552.     0x16, 0x05, 0x25, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  553.     0x10, 0x11, 0x12, 0x13, 0x3c, 0x3d, 0x32, 0x26,
  554.     0x18, 0x19, 0x3f, 0x27, 0x1c, 0x1d, 0x1e, 0x1f,
  555.     0x40, 0x5a, 0x7f, 0x7b, 0x5b, 0x6c, 0x50, 0x7d,
  556.     0x4d, 0x5d, 0x5c, 0x4e, 0x6b, 0x60, 0x4b, 0x61,
  557.     0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
  558.     0xf8, 0xf9, 0x7a, 0x5e, 0x4c, 0x7e, 0x6e, 0x6f,
  559.     0x7c, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
  560.     0xc8, 0xc9, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
  561.     0xd7, 0xd8, 0xd9, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6,
  562.     0xe7, 0xe8, 0xe9, 0xba, 0xe0, 0xbb, 0xb0, 0x6d,
  563.     0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
  564.     0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
  565.     0x97, 0x98, 0x99, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6,
  566.     0xa7, 0xa8, 0xa9, 0xc0, 0x4f, 0xd0, 0xa1, 0x07,
  567.     0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17,
  568.     0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x09, 0x0a, 0x1b,
  569.     0x30, 0x31, 0x1a, 0x33, 0x34, 0x35, 0x36, 0x08,
  570.     0x38, 0x39, 0x3a, 0x3b, 0x04, 0x14, 0x3e, 0xff,
  571.     0x41, 0xaa, 0x4a, 0xb1, 0x9f, 0xb2, 0x6a, 0xb5,
  572.     0xbd, 0xb4, 0x9a, 0x8a, 0x5f, 0xca, 0xaf, 0xbc,
  573.     0x90, 0x8f, 0xea, 0xfa, 0xbe, 0xa0, 0xb6, 0xb3,
  574.     0x9d, 0xda, 0x9b, 0x8b, 0xb7, 0xb8, 0xb9, 0xab,
  575.     0x64, 0x65, 0x62, 0x66, 0x63, 0x67, 0x9e, 0x68,
  576.     0x74, 0x71, 0x72, 0x73, 0x78, 0x75, 0x76, 0x77,
  577.     0xac, 0x69, 0xed, 0xee, 0xeb, 0xef, 0xec, 0xbf,
  578.     0x80, 0xfd, 0xfe, 0xfb, 0xfc, 0xad, 0xae, 0x59,
  579.     0x44, 0x45, 0x42, 0x46, 0x43, 0x47, 0x9c, 0x48,
  580.     0x54, 0x51, 0x52, 0x53, 0x58, 0x55, 0x56, 0x57,
  581.     0x8c, 0x49, 0xcd, 0xce, 0xcb, 0xcf, 0xcc, 0xe1,
  582.     0x70, 0xdd, 0xde, 0xdb, 0xdc, 0x8d, 0x8e, 0xdf
  583. }; /* end ebcdic[] */
  584.  
  585. #endif                          /* EBCDIC */
  586.  
  587.  
  588.  
  589.  
  590.  
  591. /*************************/
  592. /*  Function makeword()  */
  593. /*************************/
  594.  
  595. UWORD makeword(b)
  596.     byte *b;
  597. {
  598.     /*
  599.      * Convert Intel style 'short' integer to non-Intel non-16-bit
  600.      * host format.  This routine also takes care of byte-ordering.
  601.      */
  602.     return ((b[1] << 8) | b[0]);
  603. }
  604.  
  605.  
  606.  
  607.  
  608.  
  609. /*************************/
  610. /*  Function makelong()  */
  611. /*************************/
  612.  
  613. ULONG makelong(sig)
  614.     byte *sig;
  615. {
  616.     /*
  617.      * Convert intel style 'long' variable to non-Intel non-16-bit
  618.      * host format.  This routine also takes care of byte-ordering.
  619.      */
  620.     return (((ULONG) sig[3]) << 24)
  621.         + (((ULONG) sig[2]) << 16)
  622.         + (((ULONG) sig[1]) << 8)
  623.         + ((ULONG) sig[0]);
  624. }
  625.  
  626.  
  627.  
  628.  
  629.  
  630. #ifdef VMS
  631.  
  632. /***************************/
  633. /*  Function return_VMS()  */
  634. /***************************/
  635.  
  636. void return_VMS(zip_error)
  637.     int zip_error;
  638. {
  639. #ifdef RETURN_CODES
  640. /*---------------------------------------------------------------------------
  641.     Do our own, explicit processing of error codes and print message, since
  642.     VMS misinterprets return codes as rather obnoxious system errors ("access
  643.     violation," for example).
  644.   ---------------------------------------------------------------------------*/
  645.  
  646.     switch (zip_error) {
  647.  
  648.     case 0:
  649.         break;   /* life is fine... */
  650.     case 1:
  651.         fprintf(stderr, "\n[return-code 1:  warning error \
  652. (e.g., failed CRC or unknown compression method)]\n");
  653.         break;
  654.     case 2:
  655.     case 3:
  656.         fprintf(stderr, "\n[return-code %d:  error in zipfile \
  657. (e.g., can't find local file header sig)]\n",
  658.                 zip_error);
  659.         break;
  660.     case 4:
  661.     case 5:
  662.     case 6:
  663.     case 7:
  664.     case 8:
  665.         fprintf(stderr, "\n[return-code %d:  insufficient memory]\n",
  666.           zip_error);
  667.         break;
  668.     case 9:
  669.         fprintf(stderr, "\n[return-code 9:  zipfile not found]\n");
  670.         break;
  671.     case 10:   /* this is the one that gives "access violation," I think */
  672.         fprintf(stderr, "\n[return-code 10:  bad or illegal parameters \
  673. specified on command line]\n");
  674.         break;
  675.     case 11:   /* I'm not sure this one is implemented, but maybe soon? */
  676.         fprintf(stderr,
  677.           "\n[return-code 11:  no files found to extract/view/etc.]\n");
  678.         break;
  679.     case 50:
  680.         fprintf(stderr,
  681.   "\n[return-code 50:  disk full (or otherwise unable to open output file)]\n");
  682.         break;
  683.     case 51:
  684.         fprintf(stderr,
  685.           "\n[return-code 51:  unexpected EOF in zipfile (i.e., truncated)]\n");
  686.         break;
  687.     default:
  688.         fprintf(stderr, "\n[return-code %d:  unknown return-code \
  689. (who put this one in?  Wasn't me...)]\n",
  690.                 zip_error);
  691.         break;
  692.     }
  693. #endif /* RETURN_CODES */
  694.  
  695.     exit(0);   /* everything okey-dokey as far as VMS concerned */
  696.  
  697. } /* end function return_VMS() */
  698.  
  699. #endif /* VMS */
  700.  
  701.  
  702.  
  703.  
  704.  
  705. #ifdef ZMEM   /* memset, memcpy for systems without them */
  706.  
  707. /***********************/
  708. /*  Function memset()  */
  709. /***********************/
  710.  
  711. char *memset(buf, init, len)
  712.     register char *buf, init;   /* buffer loc and initializer */
  713.     register unsigned int len;  /* length of the buffer */
  714. {
  715.     char *start;
  716.  
  717.     start = buf;
  718.     while (len--)
  719.         *(buf++) = init;
  720.     return (start);
  721. }
  722.  
  723.  
  724.  
  725.  
  726.  
  727. /***********************/
  728. /*  Function memcpy()  */
  729. /***********************/
  730.  
  731. char *memcpy(dst, src, len)
  732.     register char *dst, *src;
  733.     register unsigned int len;
  734. {
  735.     char *start;
  736.  
  737.     start = dst;
  738.     while (len-- > 0)
  739.         *dst++ = *src++;
  740.     return (start);
  741. }
  742.  
  743. #endif /* ZMEM */
  744.