home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-08-22 | 58.7 KB | 1,558 lines |
- Newsgroups: comp.sources.misc
- From: zip-bugs@cs.ucla.edu (Info-ZIP group)
- Subject: v31i108: unzip50 - Info-ZIP portable UnZip, version 5.0, Part05/14
- Message-ID: <1992Aug24.025340.24367@sparky.imd.sterling.com>
- X-Md4-Signature: 98e992236da685418380831738bd265e
- Date: Mon, 24 Aug 1992 02:53:40 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: zip-bugs@cs.ucla.edu (Info-ZIP group)
- Posting-number: Volume 31, Issue 108
- Archive-name: unzip50/part05
- Supersedes: unzip: Volume 29, Issue 31-42
- Environment: UNIX, VMS, OS/2, MS-DOS, MACINTOSH, WIN-NT, LINUX, MINIX, COHERENT AMIGA?, !ATARI, symlink, SGI, DEC, Cray, Convex, Amdahl, Sun
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # The tool that generated this appeared in the comp.sources.unix newsgroup;
- # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
- # Contents: misc.c unzip.c.B
- # Wrapped by kent@sparky on Sun Aug 23 21:09:32 1992
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 5 (of 14)."'
- if test -f 'misc.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'misc.c'\"
- else
- echo shar: Extracting \"'misc.c'\" \(24826 characters\)
- sed "s/^X//" >'misc.c' <<'END_OF_FILE'
- X/*---------------------------------------------------------------------------
- X
- X misc.c
- X
- X This file contains a number of useful but not particularly closely related
- X functions; their main claim to fame is that they don't change much, so this
- X file should rarely need to be recompiled. The CRC-32 stuff is from crc32.c;
- X do_string() is from nunzip.c; makeword() and makelong() are from unzip.c;
- X memset() and memcpy() are from zmemset.c and zmemcpy.c, respectively; and
- X dos_to_unix_time() is from set_file_time_and_close() in file_io.c. ebcdic[],
- X check_for_newer(), dateformat(), and return_VMS() are new. Things lumped
- X together here to cut down on the size of unzip.c and the number of associ-
- X ated files floating around.
- X
- X ---------------------------------------------------------------------------
- X
- X Copyrights: see accompanying file "COPYING" in UnZip source distribution.
- X
- X ---------------------------------------------------------------------------*/
- X
- X
- X#include "unzip.h"
- X#ifdef MSWIN
- X# include "wizunzip.h"
- X#endif
- X
- X
- X
- X#ifndef ZIPINFO /* no need to calculate CRCs */
- X
- X/**************************/
- X/* Function UpdateCRC() */
- X/**************************/
- X
- X /*--------------------------------------------------------------------
- X
- X First, the polynomial itself and its table of feedback terms. The
- X polynomial is
- X 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
- X
- X Note that we take it "backwards" and put the highest-order term in
- X the lowest-order bit. The X^32 term is "implied"; the LSB is the
- X X^31 term, etc. The X^0 term (usually shown as "+1") results in
- X the MSB being 1.
- X
- X Note that the usual hardware shift register implementation, which
- X is what we're using (we're merely optimizing it by doing eight-bit
- X chunks at a time) shifts bits into the lowest-order term. In our
- X implementation, that means shifting towards the right. Why do we
- X do it this way? Because the calculated CRC must be transmitted in
- X order from highest-order term to lowest-order term. UARTs transmit
- X characters in order from LSB to MSB. By storing the CRC this way,
- X we hand it to the UART in the order low-byte to high-byte; the UART
- X sends each low-bit to hight-bit; and the result is transmission bit
- X by bit from highest- to lowest-order term without requiring any bit
- X shuffling on our part. Reception works similarly.
- X
- X The feedback terms table consists of 256, 32-bit entries. Notes:
- X
- X The table can be generated at runtime if desired; code to do so
- X is shown later. It might not be obvious, but the feedback
- X terms simply represent the results of eight shift/xor opera-
- X tions for all combinations of data and CRC register values.
- X
- X The values must be right-shifted by eight bits by the "updcrc"
- X logic; the shift must be unsigned (bring in zeroes). On some
- X hardware you could probably optimize the shift in assembler by
- X using byte-swap instructions.
- X polynomial $edb88320
- X
- X --------------------------------------------------------------------*/
- X
- XULONG crc_32_tab[] =
- X{
- X 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
- X 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
- X 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
- X 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
- X 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
- X 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
- X 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
- X 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
- X 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
- X 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
- X 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
- X 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
- X 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
- X 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
- X 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
- X 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
- X 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
- X 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
- X 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
- X 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
- X 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
- X 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
- X 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
- X 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
- X 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
- X 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
- X 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
- X 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
- X 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
- X 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
- X 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
- X 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
- X 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
- X 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
- X 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
- X 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
- X 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
- X 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
- X 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
- X 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
- X 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
- X 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
- X 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
- X 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
- X 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
- X 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
- X 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
- X 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
- X 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
- X 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
- X 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
- X 0x2d02ef8dL
- X}; /* end crc_32_tab[] */
- X
- X
- Xvoid UpdateCRC(s, len)
- X register byte *s;
- X register int len;
- X{
- X register ULONG crcval = crc32val;
- X
- X /* update running CRC calculation with contents of a buffer */
- X while (len--)
- X crcval = crc_32_tab[((byte) crcval ^ (*s++)) & 0xff] ^ (crcval >> 8);
- X crc32val = crcval;
- X}
- X
- X#endif /* !ZIPINFO */
- X
- X
- X
- X
- X
- X/**************************/
- X/* Function do_string() */
- X/**************************/
- X
- Xint do_string(len, option) /* return PK-type error code */
- X unsigned int len; /* without prototype, UWORD converted to this */
- X int option;
- X{
- X int block_length, error = 0;
- X UWORD comment_bytes_left, extra_len;
- X
- X
- X/*---------------------------------------------------------------------------
- X This function processes arbitrary-length (well, usually) strings. Three
- X options are allowed: SKIP, wherein the string is skipped pretty logical,
- X eh?); DISPLAY, wherein the string is printed to standard output after un-
- X dergoing any necessary or unnecessary character conversions; and FILENAME,
- X wherein the string is put into the filename[] array after undergoing ap-
- X propriate conversions (including case-conversion, if that is indicated:
- X see the global variable pInfo->lcflag). The latter option should be OK,
- X since filename is now dimensioned at 1025, but we check anyway.
- X
- X The string, by the way, is assumed to start at the current file-pointer
- X position; its length is given by len. So start off by checking length
- X of string: if zero, we're already set.
- X ---------------------------------------------------------------------------*/
- X
- X if (!len)
- X return (0); /* 0: no error */
- X
- X switch (option) {
- X
- X /*
- X * First case: print string on standard output. First set loop vari-
- X * ables, then loop through the comment in chunks of OUTBUFSIZ bytes,
- X * converting formats and printing as we go. The second half of the
- X * loop conditional was added because the file might be truncated, in
- X * which case comment_bytes_left will remain at some non-zero value for
- X * all time. outbuf is used as a scratch buffer because it is avail-
- X * able (we should be either before or in between any file processing).
- X * [The typecast in front of the MIN() macro was added because of the
- X * new promotion rules under ANSI C; readbuf() wants an int, but MIN()
- X * returns a signed long, if I understand things correctly. The proto-
- X * type should handle it, but just in case...]
- X */
- X
- X case DISPLAY:
- X comment_bytes_left = len;
- X block_length = OUTBUFSIZ; /* for the while statement, first time */
- X while (comment_bytes_left > 0 && block_length > 0) {
- X if ((block_length = readbuf((char *)outbuf,
- X (int) MIN(OUTBUFSIZ, comment_bytes_left))) <= 0)
- X return 51; /* 51: unexpected EOF */
- X comment_bytes_left -= block_length;
- X NUKE_CRs(outbuf, block_length); /* (modifies block_length) */
- X
- X /* this is why we allocated an extra byte for outbuf: */
- X outbuf[block_length] = '\0'; /* terminate w/zero: ASCIIZ */
- X
- X A_TO_N(outbuf); /* translate string to native */
- X
- X printf("%s", outbuf);
- X }
- X#ifdef MSWIN
- X /* ran out of local mem -- had to cheat */
- X WriteStringToMsgWin(outbuf, bRealTimeMsgUpdate);
- X#else /* !MSWIN */
- X printf("\n"); /* assume no newline at end */
- X#endif /* ?MSWIN */
- X break;
- X
- X /*
- X * Second case: read string into filename[] array. The filename should
- X * never ever be longer than FILNAMSIZ-1 (1024), but for now we'll check,
- X * just to be sure.
- X */
- X
- X case FILENAME:
- X extra_len = 0;
- X if (len >= FILNAMSIZ) {
- X fprintf(stderr, "warning: filename too long--truncating.\n");
- X error = 1; /* 1: warning error */
- X extra_len = len - FILNAMSIZ + 1;
- X len = FILNAMSIZ - 1;
- X }
- X if (readbuf(filename, len) <= 0)
- X return 51; /* 51: unexpected EOF */
- X filename[len] = '\0'; /* terminate w/zero: ASCIIZ */
- X
- X A_TO_N(filename); /* translate string to native */
- X
- X#ifndef ZIPINFO
- X if (pInfo->lcflag)
- X TOLOWER(filename, filename); /* replace with lowercase filename */
- X#endif
- X
- X if (!extra_len) /* we're done here */
- X break;
- X
- X /*
- X * We truncated the filename, so print what's left and then fall
- X * through to the SKIP routine.
- X */
- X fprintf(stderr, "[ %s ]\n", filename);
- X len = extra_len;
- X /* FALL THROUGH... */
- X
- X /*
- X * Third case: skip string, adjusting readbuf's internal variables
- X * as necessary (and possibly skipping to and reading a new block of
- X * data).
- X */
- X
- X case SKIP:
- X LSEEK(cur_zipfile_bufstart + (inptr-inbuf) + len)
- X break;
- X
- X /*
- X * Fourth case: assume we're at the start of an "extra field"; malloc
- X * storage for it and read data into the allocated space.
- X */
- X
- X case EXTRA_FIELD:
- X if (extra_field != (byte *)NULL)
- X free(extra_field);
- X if ((extra_field = (byte *)malloc(len)) == (byte *)NULL) {
- X fprintf(stderr,
- X "warning: extra field too long (%d). Ignoring...\n", len);
- X LSEEK(cur_zipfile_bufstart + (inptr-inbuf) + len)
- X } else
- X if (readbuf((char *)extra_field, len) <= 0)
- X return 51; /* 51: unexpected EOF */
- X break;
- X
- X } /* end switch (option) */
- X return error;
- X
- X} /* end function do_string() */
- X
- X
- X
- X
- X
- X#ifndef ZIPINFO
- X#ifndef VMS
- X
- X/*********************************/
- X/* Function dos_to_unix_time() */
- X/*********************************/
- X
- Xtime_t dos_to_unix_time(ddate, dtime)
- X unsigned ddate, dtime;
- X{
- X static short yday[]={0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
- X int yr, mo, dy, hh, mm, ss, leap;
- X long m_time, days=0;
- X#if (!defined(MACOS) && !defined(MSC) && !defined(__GO32__))
- X#if (defined(BSD) || defined(MTS))
- X#ifndef __386BSD__
- X static struct timeb tbp;
- X#endif /* __386BSD__ */
- X#else /* !(BSD || MTS) */
- X extern long timezone; /* declared in <time.h> for MSC (& Borland?) */
- X#endif /* ?(BSD || MTS) */
- X#endif /* !MACOS && !MSC && !__GO32__ */
- X
- X# define YRBASE 1970
- X
- X /* dissect date */
- X yr = ((ddate >> 9) & 0x7f) + (1980 - YRBASE);
- X mo = ((ddate >> 5) & 0x0f) - 1;
- X dy = (ddate & 0x1f) - 1;
- X
- X /* dissect time */
- X hh = (dtime >> 11) & 0x1f;
- X mm = (dtime >> 5) & 0x3f;
- X ss = (dtime & 0x1f) * 2;
- X
- X /* leap = # of leap years from BASE up to but not including current year */
- X leap = ((yr + YRBASE - 1) / 4); /* leap year base factor */
- X
- X /* How many days from BASE to this year? (& add expired days this year) */
- X days = (yr * 365) + (leap - 492) + yday[mo];
- X
- X /* if year is a leap year and month is after February, add another day */
- X if ((mo > 1) && ((yr+YRBASE)%4 == 0) && ((yr+YRBASE) != 2100))
- X ++days; /* OK through 2199 */
- X
- X /* convert date & time to seconds relative to 00:00:00, 01/01/YRBASE */
- X m_time = ((long)(days + dy) * 86400L) + ((long)hh * 3600) + (mm * 60) + ss;
- X /* - 1; MS-DOS times always rounded up to nearest even second */
- X
- X#if (!defined(MACOS) && !defined(__GO32__))
- X#if (defined(BSD) || defined(MTS))
- X#ifndef __386BSD__
- X ftime(&tbp);
- X m_time += tbp.timezone * 60L;
- X#endif
- X#else /* !(BSD || MTS) */
- X#ifdef WIN32
- X /* later... */
- X#else /* !WIN32 */
- X tzset(); /* set `timezone' */
- X#endif /* ?WIN32 */
- X m_time += timezone; /* account for timezone differences */
- X#endif /* ?(BSD || MTS) */
- X#endif /* !MACOS && !__GO32__ */
- X
- X#ifdef __386BSD__
- X m_time += localtime((time_t *) &m_time))->tm_gmtoff;
- X#else
- X if (localtime((time_t *)&m_time)->tm_isdst)
- X m_time -= 60L * 60L; /* adjust for daylight savings time */
- X#endif /* __386BSD__ */
- X
- X return m_time;
- X
- X} /* end function dos_to_unix_time() */
- X
- X#endif /* !VMS */
- X
- X
- X
- X
- X
- X/********************************/
- X/* Function check_for_newer() */ /* could make this into a macro for Unix */
- X/********************************/
- X
- Xint check_for_newer(filename) /* return 1 if existing file newer or equal; */
- X char *filename; /* 0 if older; -1 if doesn't exist yet */
- X{
- X#ifdef VMS
- X unsigned short timbuf[7];
- X int dy, mo, yr, hh, mm, ss, dy2, mo2, yr2, hh2, mm2, ss2;
- X struct FAB fab;
- X struct XABDAT xdat;
- X
- X
- X if (stat(filename, &statbuf))
- X return DOES_NOT_EXIST;
- X
- X fab = cc$rms_fab;
- X xdat = cc$rms_xabdat;
- X
- X fab.fab$l_xab = &xdat;
- X fab.fab$l_fna = filename;
- X fab.fab$b_fns = strlen(filename);
- X fab.fab$l_fop = FAB$M_GET | FAB$M_UFO;
- X
- X if ((sys$open(&fab) & 1) == 0) /* open failure: report exists and */
- X return EXISTS_AND_OLDER; /* older so new copy will be made */
- X sys$numtim(&timbuf,&xdat.xab$q_cdt);
- X fab.fab$l_xab = 0L;
- X
- X sys$dassgn(fab.fab$l_stv);
- X sys$close(&fab); /* be sure file is closed and RMS knows about it */
- X
- X yr = timbuf[0];
- X yr2 = ((lrec.last_mod_file_date >> 9) & 0x7f) + 1980;
- X if (yr > yr2)
- X return EXISTS_AND_NEWER;
- X else if (yr < yr2)
- X return EXISTS_AND_OLDER;
- X
- X mo = timbuf[1];
- X mo2 = ((lrec.last_mod_file_date >> 5) & 0x0f);
- X if (mo > mo2)
- X return EXISTS_AND_NEWER;
- X else if (mo < mo2)
- X return EXISTS_AND_OLDER;
- X
- X dy = timbuf[2];
- X dy2 = (lrec.last_mod_file_date & 0x1f);
- X if (dy > dy2)
- X return EXISTS_AND_NEWER;
- X else if (dy < dy2)
- X return EXISTS_AND_OLDER;
- X
- X hh = timbuf[3];
- X hh2 = (lrec.last_mod_file_time >> 11) & 0x1f;
- X if (hh > hh2)
- X return EXISTS_AND_NEWER;
- X else if (hh < hh2)
- X return EXISTS_AND_OLDER;
- X
- X mm = timbuf[4];
- X mm2 = (lrec.last_mod_file_time >> 5) & 0x3f;
- X if (mm > mm2)
- X return EXISTS_AND_NEWER;
- X else if (mm < mm2)
- X return EXISTS_AND_OLDER;
- X
- X /* round to nearest 2 secs--may become 60, but doesn't matter for compare */
- X ss = (int)((float)timbuf[5] + (float)timbuf[6]*.01 + 1.) & -2;
- X ss2 = (lrec.last_mod_file_time & 0x1f) * 2;
- X if (ss >= ss2)
- X return EXISTS_AND_NEWER;
- X
- X return EXISTS_AND_OLDER;
- X
- X#else /* !VMS */
- X#ifdef OS2
- X long existing, archive;
- X
- X if ((existing = GetFileTime(filename)) == -1)
- X return DOES_NOT_EXIST;
- X archive = ((long) lrec.last_mod_file_date) << 16 | lrec.last_mod_file_time;
- X
- X return (existing >= archive);
- X#else /* !OS2 */
- X time_t existing, archive;
- X
- X if (stat(filename, &statbuf))
- X return DOES_NOT_EXIST;
- X
- X /* round up existing filetime to nearest 2 seconds for comparison */
- X existing = (statbuf.st_mtime & 1) ? statbuf.st_mtime+1 : statbuf.st_mtime;
- X archive = dos_to_unix_time(lrec.last_mod_file_date,
- X lrec.last_mod_file_time);
- X
- X return (existing >= archive);
- X#endif /* ?OS2 */
- X#endif /* ?VMS */
- X
- X} /* end function check_for_newer() */
- X
- X
- X
- X
- X
- X/***************************/
- X/* Function dateformat() */
- X/***************************/
- X
- Xint dateformat()
- X{
- X
- X/*-----------------------------------------------------------------------------
- X For those operating systems which support it, this function returns a value
- X which tells how national convention says that numeric dates are displayed.
- X
- X Return values are DF_YMD, DF_DMY and DF_MDY. The meanings should be fairly
- X obvious.
- X -----------------------------------------------------------------------------*/
- X
- X#ifdef OS2
- X switch (GetCountryInfo()) {
- X case 0 /* DATEFMT_MM_DD_YY */ :
- X return DF_MDY;
- X case 1 /* DATEFMT_DD_MM_YY */ :
- X return DF_DMY;
- X case 2 /* DATEFMT_YY_MM_DD */ :
- X return DF_YMD;
- X }
- X#else /* !OS2 */
- X#if (defined(MSDOS) && !defined(MSWIN))
- X unsigned short _CountryInfo[18];
- X#ifdef __GO32__
- X unsigned short *CountryInfo = _CountryInfo;
- X
- X bdos(0x38, (unsigned)CountryInfo, 0);
- X#else /* !__GO32__ */
- X unsigned short far *CountryInfo = _CountryInfo;
- X union REGS regs;
- X struct SREGS sregs;
- X
- X regs.x.ax = 0x3800;
- X regs.x.dx = FP_OFF(CountryInfo);
- X sregs.ds = FP_SEG(CountryInfo);
- X int86x(0x21, ®s, ®s, &sregs);
- X#endif /* ?__GO32__ */
- X
- X switch(CountryInfo[0]) {
- X case 0:
- X return DF_MDY;
- X case 1:
- X return DF_DMY;
- X case 2:
- X return DF_YMD;
- X }
- X#endif /* MSDOS && !MSWIN */
- X#endif /* ?OS2 */
- X
- X return DF_MDY; /* default for Unix, VMS, etc. */
- X
- X} /* end function dateformat() */
- X
- X#endif /* !ZIPINFO */
- X
- X
- X
- X
- X
- X#ifdef EBCDIC
- X
- X/*
- X * This is the MTS ASCII->EBCDIC translation table. It provides a 1-1
- X * translation from ISO 8859/1 8-bit ASCII to IBM Code Page 37 EBCDIC.
- X */
- X
- Xunsigned char ebcdic[] =
- X{
- X 0x00, 0x01, 0x02, 0x03, 0x37, 0x2d, 0x2e, 0x2f,
- X 0x16, 0x05, 0x25, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- X 0x10, 0x11, 0x12, 0x13, 0x3c, 0x3d, 0x32, 0x26,
- X 0x18, 0x19, 0x3f, 0x27, 0x1c, 0x1d, 0x1e, 0x1f,
- X 0x40, 0x5a, 0x7f, 0x7b, 0x5b, 0x6c, 0x50, 0x7d,
- X 0x4d, 0x5d, 0x5c, 0x4e, 0x6b, 0x60, 0x4b, 0x61,
- X 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
- X 0xf8, 0xf9, 0x7a, 0x5e, 0x4c, 0x7e, 0x6e, 0x6f,
- X 0x7c, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
- X 0xc8, 0xc9, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
- X 0xd7, 0xd8, 0xd9, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6,
- X 0xe7, 0xe8, 0xe9, 0xba, 0xe0, 0xbb, 0xb0, 0x6d,
- X 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
- X 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
- X 0x97, 0x98, 0x99, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6,
- X 0xa7, 0xa8, 0xa9, 0xc0, 0x4f, 0xd0, 0xa1, 0x07,
- X 0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17,
- X 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x09, 0x0a, 0x1b,
- X 0x30, 0x31, 0x1a, 0x33, 0x34, 0x35, 0x36, 0x08,
- X 0x38, 0x39, 0x3a, 0x3b, 0x04, 0x14, 0x3e, 0xff,
- X 0x41, 0xaa, 0x4a, 0xb1, 0x9f, 0xb2, 0x6a, 0xb5,
- X 0xbd, 0xb4, 0x9a, 0x8a, 0x5f, 0xca, 0xaf, 0xbc,
- X 0x90, 0x8f, 0xea, 0xfa, 0xbe, 0xa0, 0xb6, 0xb3,
- X 0x9d, 0xda, 0x9b, 0x8b, 0xb7, 0xb8, 0xb9, 0xab,
- X 0x64, 0x65, 0x62, 0x66, 0x63, 0x67, 0x9e, 0x68,
- X 0x74, 0x71, 0x72, 0x73, 0x78, 0x75, 0x76, 0x77,
- X 0xac, 0x69, 0xed, 0xee, 0xeb, 0xef, 0xec, 0xbf,
- X 0x80, 0xfd, 0xfe, 0xfb, 0xfc, 0xad, 0xae, 0x59,
- X 0x44, 0x45, 0x42, 0x46, 0x43, 0x47, 0x9c, 0x48,
- X 0x54, 0x51, 0x52, 0x53, 0x58, 0x55, 0x56, 0x57,
- X 0x8c, 0x49, 0xcd, 0xce, 0xcb, 0xcf, 0xcc, 0xe1,
- X 0x70, 0xdd, 0xde, 0xdb, 0xdc, 0x8d, 0x8e, 0xdf
- X}; /* end ebcdic[] */
- X
- X#endif /* EBCDIC */
- X
- X
- X
- X
- X
- X/*************************/
- X/* Function makeword() */
- X/*************************/
- X
- XUWORD makeword(b)
- X byte *b;
- X{
- X /*
- X * Convert Intel style 'short' integer to non-Intel non-16-bit
- X * host format. This routine also takes care of byte-ordering.
- X */
- X return ((b[1] << 8) | b[0]);
- X}
- X
- X
- X
- X
- X
- X/*************************/
- X/* Function makelong() */
- X/*************************/
- X
- XULONG makelong(sig)
- X byte *sig;
- X{
- X /*
- X * Convert intel style 'long' variable to non-Intel non-16-bit
- X * host format. This routine also takes care of byte-ordering.
- X */
- X return (((ULONG) sig[3]) << 24)
- X + (((ULONG) sig[2]) << 16)
- X + (((ULONG) sig[1]) << 8)
- X + ((ULONG) sig[0]);
- X}
- X
- X
- X
- X
- X
- X#ifdef VMS
- X
- X/***************************/
- X/* Function return_VMS() */
- X/***************************/
- X
- Xvoid return_VMS(zip_error)
- X int zip_error;
- X{
- X#ifdef RETURN_CODES
- X/*---------------------------------------------------------------------------
- X Do our own, explicit processing of error codes and print message, since
- X VMS misinterprets return codes as rather obnoxious system errors ("access
- X violation," for example).
- X ---------------------------------------------------------------------------*/
- X
- X switch (zip_error) {
- X
- X case 0:
- X break; /* life is fine... */
- X case 1:
- X fprintf(stderr, "\n[return-code 1: warning error \
- X(e.g., failed CRC or unknown compression method)]\n");
- X break;
- X case 2:
- X case 3:
- X fprintf(stderr, "\n[return-code %d: error in zipfile \
- X(e.g., can't find local file header sig)]\n",
- X zip_error);
- X break;
- X case 4:
- X case 5:
- X case 6:
- X case 7:
- X case 8:
- X fprintf(stderr, "\n[return-code %d: insufficient memory]\n",
- X zip_error);
- X break;
- X case 9:
- X fprintf(stderr, "\n[return-code 9: zipfile not found]\n");
- X break;
- X case 10: /* this is the one that gives "access violation," I think */
- X fprintf(stderr, "\n[return-code 10: bad or illegal parameters \
- Xspecified on command line]\n");
- X break;
- X case 11: /* I'm not sure this one is implemented, but maybe soon? */
- X fprintf(stderr,
- X "\n[return-code 11: no files found to extract/view/etc.]\n");
- X break;
- X case 50:
- X fprintf(stderr,
- X "\n[return-code 50: disk full (or otherwise unable to open output file)]\n");
- X break;
- X case 51:
- X fprintf(stderr,
- X "\n[return-code 51: unexpected EOF in zipfile (i.e., truncated)]\n");
- X break;
- X default:
- X fprintf(stderr, "\n[return-code %d: unknown return-code \
- X(who put this one in? Wasn't me...)]\n",
- X zip_error);
- X break;
- X }
- X#endif /* RETURN_CODES */
- X
- X exit(0); /* everything okey-dokey as far as VMS concerned */
- X
- X} /* end function return_VMS() */
- X
- X#endif /* VMS */
- X
- X
- X
- X
- X
- X#ifdef ZMEM /* memset, memcpy for systems without them */
- X
- X/***********************/
- X/* Function memset() */
- X/***********************/
- X
- Xchar *memset(buf, init, len)
- X register char *buf, init; /* buffer loc and initializer */
- X register unsigned int len; /* length of the buffer */
- X{
- X char *start;
- X
- X start = buf;
- X while (len--)
- X *(buf++) = init;
- X return (start);
- X}
- X
- X
- X
- X
- X
- X/***********************/
- X/* Function memcpy() */
- X/***********************/
- X
- Xchar *memcpy(dst, src, len)
- X register char *dst, *src;
- X register unsigned int len;
- X{
- X char *start;
- X
- X start = dst;
- X while (len-- > 0)
- X *dst++ = *src++;
- X return (start);
- X}
- X
- X#endif /* ZMEM */
- END_OF_FILE
- if test 24826 -ne `wc -c <'misc.c'`; then
- echo shar: \"'misc.c'\" unpacked with wrong size!
- fi
- # end of 'misc.c'
- fi
- if test -f 'unzip.c.B' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'unzip.c.B'\"
- else
- echo shar: Extracting \"'unzip.c.B'\" \(31190 characters\)
- sed "s/^X//" >'unzip.c.B' <<'END_OF_FILE'
- X
- X/********************************/
- X/* Function process_zipfile() */
- X/********************************/
- X
- Xint process_zipfile() /* return PK-type error code */
- X{
- X int error=0, error_in_archive;
- X longint real_ecrec_offset, expect_ecrec_offset;
- X
- X
- X/*---------------------------------------------------------------------------
- X Open the zipfile for reading and in BINARY mode to prevent CR/LF trans-
- X lation, which would corrupt the bitstreams.
- X ---------------------------------------------------------------------------*/
- X
- X#ifdef VMS
- X if (check_format()) /* check for variable-length format */
- X return 2; /* 2: error in zipfile */
- X#endif /* VMS */
- X
- X if (open_input_file()) /* this should never happen, given the */
- X return 9; /* stat() test in main(), but... */
- X
- X/*---------------------------------------------------------------------------
- X Reconstruct the various PK signature strings, and find and process the
- X end-of-central-directory header.
- X ---------------------------------------------------------------------------*/
- X
- X strcat(local_hdr_sig, LOCAL_HDR_SIG);
- X strcat(central_hdr_sig, CENTRAL_HDR_SIG);
- X strcat(end_central_sig, END_CENTRAL_SIG);
- X/* strcat(extd_local_sig, EXTD_LOCAL_SIG); */
- X
- X if (find_end_central_dir()) { /* not found; nothing to do */
- X close(zipfd);
- X return 2; /* 2: error in zipfile */
- X }
- X
- X real_ecrec_offset = cur_zipfile_bufstart+(inptr-inbuf);
- X#ifdef TEST
- X printf("\n found end-of-central-dir signature at offset %ld (%.8lXh)\n",
- X real_ecrec_offset, real_ecrec_offset);
- X printf(" from beginning of file; offset %d (%.4Xh) within block\n",
- X inptr-inbuf, inptr-inbuf);
- X#endif
- X
- X if ((error_in_archive = process_end_central_dir()) > 1) {
- X close(zipfd);
- X return error_in_archive;
- X }
- X
- X if (zflag) {
- X close(zipfd);
- X return 0;
- X }
- X
- X/*---------------------------------------------------------------------------
- X Test the end-of-central-directory info for incompatibilities and incon-
- X sistencies.
- X ---------------------------------------------------------------------------*/
- X
- X#ifndef PAKFIX
- X if (ecrec.number_this_disk == 0) {
- X#else /* PAKFIX */
- X error = ((ecrec.number_this_disk == 1) &&
- X (ecrec.num_disk_with_start_central_dir == 1));
- X if ((ecrec.number_this_disk == 0) || error) {
- X if (error) {
- X fprintf(stderr,
- X "\n Warning: zipfile claims to be disk 2 of a two-part archive;\n\
- X attempting to process anyway. If no further errors occur, this\n\
- X archive was probably created by PAK v2.51 or earlier. This bug\n\
- X was reported to NoGate in March 1991 and was supposed to have been\n\
- X fixed by mid-1991; as of mid-1992 it still hadn't been.\n\n");
- X error_in_archive = 1; /* 1: warning */
- X }
- X#endif /* ?PAKFIX */
- X expect_ecrec_offset = ecrec.offset_start_central_directory +
- X ecrec.size_central_directory;
- X if ((extra_bytes = real_ecrec_offset - expect_ecrec_offset) < 0) {
- X fprintf(stderr, "\nerror: missing %ld bytes in zipfile (\
- Xattempting to process anyway)\n\n", -extra_bytes);
- X error_in_archive = 2; /* 2: (weak) error in zipfile */
- X } else if (extra_bytes > 0) {
- X if ((ecrec.offset_start_central_directory == 0) &&
- X (ecrec.size_central_directory != 0)) /* zip 1.5 -go bug */
- X {
- X fprintf(stderr, "\nerror: NULL central directory offset (\
- Xattempting to process anyway)\n\n");
- X ecrec.offset_start_central_directory = extra_bytes;
- X extra_bytes = 0;
- X error_in_archive = 2; /* 2: (weak) error in zipfile */
- X } else {
- X fprintf(stderr, "\nwarning: extra %ld bytes at beginning or\
- X within zipfile\n (attempting to process anyway)\n\n", extra_bytes);
- X error_in_archive = 1; /* 1: warning error */
- X }
- X }
- X
- X /*-----------------------------------------------------------------------
- X Check for empty zipfile and exit now if so.
- X -----------------------------------------------------------------------*/
- X
- X if (expect_ecrec_offset == 0L && ecrec.size_central_directory == 0) {
- X fprintf(stderr, "warning: zipfile is empty\n");
- X close(zipfd);
- X return (error_in_archive > 1)? error_in_archive : 1;
- X }
- X
- X /*-----------------------------------------------------------------------
- X Compensate for missing or extra bytes, and seek to where the start
- X of central directory should be. If header not found, uncompensate
- X and try again (necessary for at least some Atari archives created
- X with STZIP, as well as archives created by J.H. Holm's ZIPSPLIT).
- X -----------------------------------------------------------------------*/
- X
- X LSEEK( ecrec.offset_start_central_directory )
- X if ((readbuf(sig, 4) <= 0) || strncmp(sig, central_hdr_sig, 4)) {
- X longint tmp = extra_bytes;
- X
- X extra_bytes = 0;
- X LSEEK( ecrec.offset_start_central_directory )
- X if ((readbuf(sig, 4) <= 0) || strncmp(sig, central_hdr_sig, 4)) {
- X fprintf(stderr,
- X "error: start of central directory not found; zipfile corrupt.\n");
- X fprintf(stderr, ReportMsg);
- X close(zipfd);
- X return 3; /* 3: severe error in zipfile */
- X }
- X fprintf(stderr, "error: reported length of central directory is \
- X%d bytes too\n long (Atari STZIP zipfile? J.H. Holm ZIPSPLIT zipfile?)\
- X.\n Compensating...\n\n", -tmp);
- X error_in_archive = 2; /* 2: (weak) error in zipfile */
- X }
- X
- X /*-----------------------------------------------------------------------
- X Seek to the start of the central directory one last time, since we
- X have just read the first entry's signature bytes; then list, extract
- X or test member files as instructed, and close the zipfile.
- X -----------------------------------------------------------------------*/
- X
- X LSEEK( ecrec.offset_start_central_directory )
- X if (vflag)
- X error = list_files(); /* LIST 'EM */
- X else
- X error = extract_or_test_files(); /* EXTRACT OR TEST 'EM */
- X if (error > error_in_archive) /* don't overwrite stronger error */
- X error_in_archive = error; /* with (for example) a warning */
- X } else {
- X fprintf(stderr, "\nerror: zipfile is part of multi-disk archive \
- X(sorry, not supported).\n");
- X /* fprintf(stderr, "Please report to zip-bugs@cs.ucla.edu\n"); */
- X error_in_archive = 11; /* 11: no files found */
- X }
- X
- X close(zipfd);
- X return error_in_archive;
- X
- X} /* end function process_zipfile() */
- X
- X
- X
- X
- X
- X/************************************/
- X/* Function find_end_central_dir() */
- X/************************************/
- X
- Xint find_end_central_dir() /* return 0 if found, 1 otherwise */
- X{
- X int i, numblks;
- X longint tail_len;
- X
- X
- X
- X/*---------------------------------------------------------------------------
- X Treat case of short zipfile separately.
- X ---------------------------------------------------------------------------*/
- X
- X if (ziplen <= INBUFSIZ) {
- X lseek(zipfd, 0L, SEEK_SET);
- X if ((incnt = read(zipfd,(char *)inbuf,(unsigned int)ziplen)) ==
- X (int)ziplen)
- X
- X /* 'P' must be at least 22 bytes from end of zipfile */
- X for (inptr = inbuf+(int)ziplen-22; inptr >= inbuf; --inptr)
- X if ((ascii_to_native(*inptr) == 'P') &&
- X !strncmp((char *)inptr, end_central_sig, 4)) {
- X incnt -= inptr - inbuf;
- X return 0; /* found it! */
- X } /* ...otherwise fall through & fail */
- X
- X/*---------------------------------------------------------------------------
- X Zipfile is longer than INBUFSIZ: may need to loop. Start with short
- X block at end of zipfile (if not TOO short).
- X ---------------------------------------------------------------------------*/
- X
- X } else {
- X if ((tail_len = ziplen % INBUFSIZ) > ECREC_SIZE) {
- X cur_zipfile_bufstart = lseek(zipfd, ziplen-tail_len, SEEK_SET);
- X if ((incnt = read(zipfd,(char *)inbuf,(unsigned int)tail_len)) !=
- X (int)tail_len)
- X goto fail; /* shut up; it's expedient. */
- X
- X /* 'P' must be at least 22 bytes from end of zipfile */
- X for (inptr = inbuf+(int)tail_len-22; inptr >= inbuf; --inptr)
- X if ((ascii_to_native(*inptr) == 'P') &&
- X !strncmp((char *)inptr, end_central_sig, 4)) {
- X incnt -= inptr - inbuf;
- X return 0; /* found it */
- X } /* ...otherwise search next block */
- X strncpy((char *)hold, (char *)inbuf, 3); /* sig may span block
- X boundary */
- X } else {
- X cur_zipfile_bufstart = ziplen - tail_len;
- X }
- X
- X /*-----------------------------------------------------------------------
- X Loop through blocks of zipfile data, starting at the end and going
- X toward the beginning. Need only check last 65557 bytes of zipfile:
- X comment may be up to 65535 bytes long, end-of-central-directory rec-
- X ord is 18 bytes (shouldn't hardcode this number, but what the hell:
- X already did so above (22=18+4)), and sig itself is 4 bytes.
- X -----------------------------------------------------------------------*/
- X
- X numblks = (int)
- X ((MIN(ziplen,65557L) - tail_len + (INBUFSIZ-1)) / INBUFSIZ);
- X /* =amount to search= ==done== ==rounding== =blksiz= */
- X
- X for (i = 1; i <= numblks; ++i) {
- X cur_zipfile_bufstart -= INBUFSIZ;
- X lseek(zipfd, cur_zipfile_bufstart, SEEK_SET);
- X if ((incnt = read(zipfd,(char *)inbuf,INBUFSIZ)) != INBUFSIZ)
- X break; /* fall through and fail */
- X
- X for (inptr = inbuf+INBUFSIZ-1; inptr >= inbuf; --inptr)
- X if ((ascii_to_native(*inptr) == 'P') &&
- X !strncmp((char *)inptr, end_central_sig, 4)) {
- X incnt -= inptr - inbuf;
- X return 0; /* found it */
- X }
- X strncpy((char *)hold, (char *)inbuf, 3); /* sig may span block
- X boundary */
- X }
- X
- X } /* end if (ziplen > INBUFSIZ) */
- X
- X/*---------------------------------------------------------------------------
- X Searched through whole region where signature should be without finding
- X it. Print informational message and die a horrible death.
- X ---------------------------------------------------------------------------*/
- X
- Xfail:
- X#ifdef MSWIN
- X MessageBeep(1);
- X#endif
- X
- X fprintf(stderr, "\nFile: %s\n\n\
- X End-of-central-directory signature not found. Either this file is not\n\
- X a zipfile, or it constitutes one disk of a multi-part archive. In the\n\
- X latter case the central directory and zipfile comment will be found on\n\
- X the last disk(s) of this archive.\n", zipfn);
- X return 1;
- X
- X} /* end function find_end_central_dir() */
- X
- X
- X
- X
- X
- X/***************************************/
- X/* Function process_end_central_dir() */
- X/***************************************/
- X
- Xint process_end_central_dir() /* return PK-type error code */
- X{
- X ec_byte_rec byterec;
- X int error=0;
- X
- X
- X/*---------------------------------------------------------------------------
- X Read the end-of-central-directory record and do any necessary machine-
- X type conversions (byte ordering, structure padding compensation) by
- X reading data into character array, then copying to struct.
- X ---------------------------------------------------------------------------*/
- X
- X if (readbuf((char *) byterec, ECREC_SIZE+4) <= 0)
- X return 51;
- X
- X ecrec.number_this_disk =
- X makeword(&byterec[NUMBER_THIS_DISK]);
- X ecrec.num_disk_with_start_central_dir =
- X makeword(&byterec[NUM_DISK_WITH_START_CENTRAL_DIR]);
- X ecrec.num_entries_centrl_dir_ths_disk =
- X makeword(&byterec[NUM_ENTRIES_CENTRL_DIR_THS_DISK]);
- X ecrec.total_entries_central_dir =
- X makeword(&byterec[TOTAL_ENTRIES_CENTRAL_DIR]);
- X ecrec.size_central_directory =
- X makelong(&byterec[SIZE_CENTRAL_DIRECTORY]);
- X ecrec.offset_start_central_directory =
- X makelong(&byterec[OFFSET_START_CENTRAL_DIRECTORY]);
- X ecrec.zipfile_comment_length =
- X makeword(&byterec[ZIPFILE_COMMENT_LENGTH]);
- X
- X/*---------------------------------------------------------------------------
- X Get the zipfile comment, if any, and print it out. (Comment may be up
- X to 64KB long. May the fleas of a thousand camels infest the armpits of
- X anyone who actually takes advantage of this fact.) Then position the
- X file pointer to the beginning of the central directory and fill buffer.
- X ---------------------------------------------------------------------------*/
- X
- X#ifdef MSWIN
- X cchComment = ecrec.zipfile_comment_length; /* save for comment button */
- X if (ecrec.zipfile_comment_length && zflag) {
- X#else /* !MSWIN */
- X if (ecrec.zipfile_comment_length && !quietflg) {
- X if (!zflag)
- X printf("[%s] comment:\n", zipfn);
- X#endif /* ?MSWIN */
- X if (do_string(ecrec.zipfile_comment_length,DISPLAY)) {
- X fprintf(stderr, "\ncaution: zipfile comment truncated\n");
- X error = 1; /* 1: warning error */
- X }
- X }
- X
- X return error;
- X
- X} /* end function process_end_central_dir() */
- X
- X
- X
- X
- X
- X/* also referenced in UpdateListBox() in updatelb.c (Windows version) */
- Xchar *Headers[][2] = {
- X {" Length Date Time Name",
- X " ------ ---- ---- ----"},
- X {" Length Method Size Ratio Date Time CRC-32 Name",
- X " ------ ------ ---- ----- ---- ---- ------ ----"}
- X};
- X
- X/*************************/
- X/* Function list_files() */
- X/*************************/
- X
- Xint list_files() /* return PK-type error code */
- X{
- X char **fnamev;
- X int do_this_file=FALSE, ratio, error, error_in_archive=0;
- X int which_hdr=(vflag>1), date_format;
- X UWORD j, yr, mo, dy, hh, mm, members=0;
- X ULONG tot_csize=0L, tot_ucsize=0L;
- X#ifdef OS2
- X ULONG tot_easize=0L, tot_eafiles=0L, ea_size;
- X#endif
- X#ifdef MSWIN
- X PSTR psLBEntry; /* list box entry */
- X#endif
- X min_info info;
- X static char *method[NUM_METHODS+1] =
- X {"Stored", "Shrunk", "Reduce1", "Reduce2", "Reduce3", "Reduce4",
- X "Implode", "Token", "Deflate", unkn};
- X
- X
- X
- X/*---------------------------------------------------------------------------
- X Unlike extract_or_test_files(), this routine confines itself to the cen-
- X tral directory. Thus its structure is somewhat simpler, since we can do
- X just a single loop through the entire directory, listing files as we go.
- X
- X So to start off, print the heading line and then begin main loop through
- X the central directory. The results will look vaguely like the following:
- X
- X Length Method Size Ratio Date Time CRC-32 Name ("^" ==> case
- X ------ ------ ---- ----- ---- ---- ------ ---- conversion)
- X 44004 Implode 13041 71% 11-02-89 19:34 8b4207f7 Makefile.UNIX
- X 3438 Shrunk 2209 36% 09-15-90 14:07 a2394fd8 ^dos-file.ext
- X ---------------------------------------------------------------------------*/
- X
- X pInfo = &info;
- X date_format = dateformat();
- X
- X#ifndef MSWIN
- X if (quietflg < 2)
- X if (U_flag)
- X printf("%s\n%s\n", Headers[which_hdr][0], Headers[which_hdr][1]);
- X else
- X printf("%s (\"^\" ==> case\n%s conversion)\n",
- X Headers[which_hdr][0], Headers[which_hdr][1]);
- X#endif /* !MSWIN */
- X
- X for (j = 0; j < ecrec.total_entries_central_dir; ++j) {
- X
- X if (readbuf(sig, 4) <= 0)
- X return 51; /* 51: unexpected EOF */
- X if (strncmp(sig, central_hdr_sig, 4)) { /* just to make sure */
- X fprintf(stderr, CentSigMsg, j); /* sig not found */
- X fprintf(stderr, ReportMsg); /* check binary transfers */
- X return 3; /* 3: error in zipfile */
- X }
- X if ((error = process_cdir_file_hdr()) != 0) /* (sets pInfo->lcflag) */
- X return error; /* only 51 (EOF) defined */
- X
- X /*
- X * We could DISPLAY the filename instead of storing (and possibly trun-
- X * cating, in the case of a very long name) and printing it, but that
- X * has the disadvantage of not allowing case conversion--and it's nice
- X * to be able to see in the listing precisely how you have to type each
- X * filename in order for unzip to consider it a match. Speaking of
- X * which, if member names were specified on the command line, check in
- X * with match() to see if the current file is one of them, and make a
- X * note of it if it is.
- X */
- X
- X if ((error = do_string(crec.filename_length, FILENAME)) != 0) {
- X error_in_archive = error; /* ^--(uses pInfo->lcflag) */
- X if (error > 1) /* fatal: can't continue */
- X return error;
- X }
- X if (extra_field != (byte *)NULL)
- X free(extra_field);
- X extra_field = (byte *)NULL;
- X if ((error = do_string(crec.extra_field_length, EXTRA_FIELD)) != 0) {
- X error_in_archive = error;
- X if (error > 1) /* fatal: can't continue */
- X return error;
- X }
- X if (!process_all_files) { /* check if specified on command line */
- X do_this_file = FALSE;
- X fnamev = fnv; /* don't destroy permanent filename ptr */
- X for (--fnamev; *++fnamev;)
- X if (match(filename, *fnamev)) {
- X do_this_file = TRUE;
- X break; /* found match, so stop looping */
- X }
- X }
- X /*
- X * If current file was specified on command line, or if no names were
- X * specified, do the listing for this file. Otherwise, get rid of the
- X * file comment and go back for the next file.
- X */
- X
- X if (process_all_files || do_this_file) {
- X
- X yr = (((crec.last_mod_file_date >> 9) & 0x7f) + 80) % (unsigned)100;
- X mo = (crec.last_mod_file_date >> 5) & 0x0f;
- X dy = crec.last_mod_file_date & 0x1f;
- X
- X /* twist date so it displays according to national convention */
- X switch (date_format) {
- X case DF_YMD:
- X hh = mo; mo = yr; yr = dy; dy = hh; break;
- X case DF_DMY:
- X hh = mo; mo = dy; dy = hh;
- X }
- X hh = (crec.last_mod_file_time >> 11) & 0x1f;
- X mm = (crec.last_mod_file_time >> 5) & 0x3f;
- X
- X csize = (longint) crec.compressed_size;
- X ucsize = (longint) crec.uncompressed_size;
- X if (crec.general_purpose_bit_flag & 1)
- X csize -= 12; /* if encrypted, don't count encrypt hdr */
- X
- X ratio = (ucsize == 0) ? 0 : /* .zip can have 0-length members */
- X ((ucsize > 2000000L) ? /* risk signed overflow if mult. */
- X (int) ((ucsize-csize) / (ucsize/1000L)) + 5 : /* big */
- X (int) ((1000L*(ucsize-csize)) / ucsize) + 5); /* small */
- X
- X#if 0 /* GRR/Euro: add this? define p above */
- X#if (defined(DOS_OS2) || (defined(UNIX) && !defined(VMS)))
- X for (p = filename; *p; ++p)
- X if (!isprint(*p))
- X *p = '?'; /* change non-printable chars to '?' */
- X#endif /* DOS_OS2 || UNIX */
- X#endif /* 0 */
- X
- X#ifdef MSWIN
- X#ifdef NEED_EARLY_REDRAW
- X /* turn on listbox redrawing just before adding last line */
- X if (j == (ecrec.total_entries_central_dir-1))
- X (void)SendMessage(hWndList, WM_SETREDRAW, TRUE, 0L);
- X#endif /* NEED_EARLY_REDRAW */
- X psLBEntry =
- X (PSTR)LocalAlloc(LMEM_FIXED, FILNAMSIZ+LONG_FORM_FNAME_INX);
- X switch (which_hdr) {
- X case 0: /* short form */
- X OemToAnsi(filename, filename); /* translate to ANSI */
- X wsprintf(psLBEntry, "%7ld %02u-%02u-%02u %02u:%02u %c%s",
- X (long)ucsize, mo, dy, yr, hh, mm, (pInfo->lcflag?'^':' '),
- X (LPSTR)filename);
- X SendMessage(hWndList, LB_ADDSTRING, 0,
- X (LONG)(LPSTR)psLBEntry);
- X break;
- X case 1: /* verbose */
- X OemToAnsi(filename, filename); /* translate to ANSI */
- X wsprintf(psLBEntry,
- X "%7ld %-7s%7ld %3d%% %02u-%02u-%02u %02u:%02u %08lx %c%s",
- X (long)ucsize, (LPSTR)method[methnum], (long)csize,
- X ratio/10, mo, dy, yr, hh, mm, (unsigned long)crec.crc32,
- X (pInfo->lcflag?'^':' '), (LPSTR)filename);
- X SendMessage(hWndList, LB_ADDSTRING, 0,
- X (LONG)(LPSTR)psLBEntry);
- X }
- X LocalFree((HANDLE)psLBEntry);
- X#else /* !MSWIN */
- X switch (which_hdr) {
- X case 0: /* short form */
- X printf("%7ld %02u-%02u-%02u %02u:%02u %c%s\n",
- X ucsize, mo, dy, yr, hh, mm, (pInfo->lcflag?'^':' '),
- X filename);
- X break;
- X case 1: /* verbose */
- X printf(
- X "%7ld %-7s%7ld %3d%% %02u-%02u-%02u %02u:%02u %08lx %c%s\n",
- X ucsize, method[methnum], csize, ratio/10, mo, dy, yr,
- X hh, mm, crec.crc32, (pInfo->lcflag?'^':' '), filename);
- X }
- X#endif /* ?MSWIN */
- X
- X error = do_string(crec.file_comment_length, (QCOND? DISPLAY:SKIP));
- X if (error) {
- X error_in_archive = error; /* might be just warning */
- X if (error > 1) /* fatal */
- X return error;
- X }
- X tot_ucsize += (ULONG) ucsize;
- X tot_csize += (ULONG) csize;
- X ++members;
- X#ifdef OS2
- X if ((ea_size = SizeOfEAs(extra_field)) != 0) {
- X tot_easize += ea_size;
- X tot_eafiles++;
- X }
- X#endif
- X } else { /* not listing this file */
- X SKIP_(crec.file_comment_length)
- X }
- X } /* end for-loop (j: files in central directory) */
- X
- X/*---------------------------------------------------------------------------
- X Print footer line and totals (compressed size, uncompressed size, number
- X of members in zipfile).
- X ---------------------------------------------------------------------------*/
- X
- X ratio = (tot_ucsize == 0) ?
- X 0 : ((tot_ucsize > 4000000L) ? /* risk unsigned overflow if mult. */
- X (int) ((tot_ucsize - tot_csize) / (tot_ucsize/1000L)) + 5 :
- X (int) ((tot_ucsize - tot_csize) * 1000L / tot_ucsize) + 5);
- X
- X if (quietflg < 2) {
- X#ifdef MSWIN
- X /* Display just the totals since the dashed lines get displayed
- X * in UpdateListBox(). Get just enough space to display total.
- X */
- X switch (which_hdr) {
- X case 0: /* short */
- X wsprintf(lpumb->szTotalsLine, "%7lu %-7u",
- X (ULONG)tot_ucsize, members);
- X break;
- X case 1: /* verbose */
- X wsprintf(lpumb->szTotalsLine,
- X "%7lu %7lu %3d%% %-7u",
- X (ULONG)tot_ucsize, (ULONG)tot_csize, ratio / 10, members);
- X break;
- X }
- X#else /* !MSWIN */
- X switch (which_hdr) {
- X case 0: /* short */
- X printf("%s\n%7lu %-7u\n",
- X " ------ -------",
- X tot_ucsize, members);
- X break;
- X case 1: /* verbose */
- X printf(
- X "%s\n%7lu %7lu %3d%% %-7u\n",
- X " ------ ------ --- -------",
- X tot_ucsize, tot_csize, ratio / 10, members);
- X }
- X#endif /* ?MSWIN */
- X#ifdef OS2
- X if (tot_eafiles && tot_easize)
- X printf("\n%ld file%s %ld bytes of EA's attached.\n", tot_eafiles,
- X tot_eafiles == 1 ? " has" : "s have a total of", tot_easize);
- X#endif
- X }
- X/*---------------------------------------------------------------------------
- X Double check that we're back at the end-of-central-directory record.
- X ---------------------------------------------------------------------------*/
- X
- X readbuf(sig, 4);
- X if (strncmp(sig, end_central_sig, 4)) { /* just to make sure again */
- X fprintf(stderr, EndSigMsg); /* didn't find end-of-central-dir sig */
- X/* fprintf(stderr, ReportMsg); */
- X error_in_archive = 1; /* 1: warning error */
- X }
- X return error_in_archive;
- X
- X} /* end function list_files() */
- X
- X
- X
- X
- X
- X/**************************************/
- X/* Function process_cdir_file_hdr() */
- X/**************************************/
- X
- Xint process_cdir_file_hdr() /* return PK-type error code */
- X{
- X cdir_byte_hdr byterec;
- X
- X
- X/*---------------------------------------------------------------------------
- X Read the next central directory entry and do any necessary machine-type
- X conversions (byte ordering, structure padding compensation--do so by
- X copying the data from the array into which it was read (byterec) to the
- X usable struct (crec)).
- X ---------------------------------------------------------------------------*/
- X
- X if (readbuf((char *) byterec, CREC_SIZE) <= 0)
- X return 51; /* 51: unexpected EOF */
- X
- X crec.version_made_by[0] = byterec[C_VERSION_MADE_BY_0];
- X crec.version_made_by[1] = byterec[C_VERSION_MADE_BY_1];
- X crec.version_needed_to_extract[0] = byterec[C_VERSION_NEEDED_TO_EXTRACT_0];
- X crec.version_needed_to_extract[1] = byterec[C_VERSION_NEEDED_TO_EXTRACT_1];
- X
- X crec.general_purpose_bit_flag =
- X makeword(&byterec[C_GENERAL_PURPOSE_BIT_FLAG]);
- X crec.compression_method =
- X makeword(&byterec[C_COMPRESSION_METHOD]);
- X crec.last_mod_file_time =
- X makeword(&byterec[C_LAST_MOD_FILE_TIME]);
- X crec.last_mod_file_date =
- X makeword(&byterec[C_LAST_MOD_FILE_DATE]);
- X crec.crc32 =
- X makelong(&byterec[C_CRC32]);
- X crec.compressed_size =
- X makelong(&byterec[C_COMPRESSED_SIZE]);
- X crec.uncompressed_size =
- X makelong(&byterec[C_UNCOMPRESSED_SIZE]);
- X crec.filename_length =
- X makeword(&byterec[C_FILENAME_LENGTH]);
- X crec.extra_field_length =
- X makeword(&byterec[C_EXTRA_FIELD_LENGTH]);
- X crec.file_comment_length =
- X makeword(&byterec[C_FILE_COMMENT_LENGTH]);
- X crec.disk_number_start =
- X makeword(&byterec[C_DISK_NUMBER_START]);
- X crec.internal_file_attributes =
- X makeword(&byterec[C_INTERNAL_FILE_ATTRIBUTES]);
- X crec.external_file_attributes =
- X makelong(&byterec[C_EXTERNAL_FILE_ATTRIBUTES]); /* LONG, not word! */
- X crec.relative_offset_local_header =
- X makelong(&byterec[C_RELATIVE_OFFSET_LOCAL_HEADER]);
- X
- X pInfo->hostnum = MIN(crec.version_made_by[1], NUM_HOSTS);
- X/* extnum = MIN(crec.version_needed_to_extract[1], NUM_HOSTS); */
- X methnum = MIN(crec.compression_method, NUM_METHODS);
- X if (methnum == NUM_METHODS)
- X sprintf(unkn, "Unk:%03d", crec.compression_method);
- X
- X/*---------------------------------------------------------------------------
- X Set flag for lowercase conversion of filename, depending on which OS the
- X file is coming from. This section could be ifdef'd if some people have
- X come to love DOS uppercase filenames under Unix...but really, guys, get
- X a life. :) NOTE THAT ALL SYSTEM NAMES NOW HAVE TRAILING UNDERSCORES!!!
- X This is to prevent interference with compiler command-line defines such
- X as -DUNIX, for example, which are then used in "#ifdef UNIX" constructs.
- X ---------------------------------------------------------------------------*/
- X
- X pInfo->lcflag = 0;
- X if (!U_flag) /* as long as user hasn't specified case-preservation */
- X switch (pInfo->hostnum) {
- X case DOS_OS2_FAT_:
- X /* case VMS_: VMS Zip converts filenames to lowercase */
- X case VM_CMS_: /* all caps? */
- X case CPM_: /* like DOS, right? */
- X /* case ATARI_: ? */
- X /* case Z_SYSTEM_: ? */
- X /* case TOPS20_: (if we had such a thing...) */
- X pInfo->lcflag = 1; /* convert filename to lowercase */
- X break;
- X
- X default: /* AMIGA_, UNIX_, (ATARI_), OS2_HPFS_, */
- X break; /* MAC_, (Z_SYSTEM_): no conversion */
- X }
- X
- X return 0;
- X
- X} /* end function process_cdir_file_hdr() */
- X
- X
- X
- X
- X
- X/***************************************/
- X/* Function process_local_file_hdr() */
- X/***************************************/
- X
- Xint process_local_file_hdr() /* return PK-type error code */
- X{
- X local_byte_hdr byterec;
- X
- X
- X/*---------------------------------------------------------------------------
- X Read the next local file header and do any necessary machine-type con-
- X versions (byte ordering, structure padding compensation--do so by copy-
- X ing the data from the array into which it was read (byterec) to the
- X usable struct (lrec)).
- X ---------------------------------------------------------------------------*/
- X
- X if (readbuf((char *) byterec, LREC_SIZE) <= 0)
- X return 51; /* 51: unexpected EOF */
- X
- X lrec.version_needed_to_extract[0] = byterec[L_VERSION_NEEDED_TO_EXTRACT_0];
- X lrec.version_needed_to_extract[1] = byterec[L_VERSION_NEEDED_TO_EXTRACT_1];
- X
- X lrec.general_purpose_bit_flag = makeword(&byterec[L_GENERAL_PURPOSE_BIT_FLAG]);
- X lrec.compression_method = makeword(&byterec[L_COMPRESSION_METHOD]);
- X lrec.last_mod_file_time = makeword(&byterec[L_LAST_MOD_FILE_TIME]);
- X lrec.last_mod_file_date = makeword(&byterec[L_LAST_MOD_FILE_DATE]);
- X lrec.crc32 = makelong(&byterec[L_CRC32]);
- X lrec.compressed_size = makelong(&byterec[L_COMPRESSED_SIZE]);
- X lrec.uncompressed_size = makelong(&byterec[L_UNCOMPRESSED_SIZE]);
- X lrec.filename_length = makeword(&byterec[L_FILENAME_LENGTH]);
- X lrec.extra_field_length = makeword(&byterec[L_EXTRA_FIELD_LENGTH]);
- X
- X csize = (longint) lrec.compressed_size;
- X ucsize = (longint) lrec.uncompressed_size;
- X
- X if ((lrec.general_purpose_bit_flag & 8) != 0) {
- X /* Can't trust local header, use central directory: */
- X lrec.crc32 = pInfo->crc;
- X lrec.compressed_size = pInfo->compr_size;
- X csize = (longint) lrec.compressed_size;
- X }
- X
- X return 0; /* 0: no error */
- X
- X} /* end function process_local_file_hdr() */
- END_OF_FILE
- if test 31190 -ne `wc -c <'unzip.c.B'`; then
- echo shar: \"'unzip.c.B'\" unpacked with wrong size!
- elif test -f 'unzip.c.A'; then
- echo shar: Combining \"'unzip.c'\" \(60418 characters\)
- cat 'unzip.c.A' 'unzip.c.B' > 'unzip.c'
- if test 60418 -ne `wc -c <'unzip.c'`; then
- echo shar: \"'unzip.c'\" combined with wrong size!
- else
- rm unzip.c.A unzip.c.B
- fi
- fi
- # end of 'unzip.c.B'
- fi
- echo shar: End of archive 5 \(of 14\).
- cp /dev/null ark5isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 14 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
- exit 0 # Just in case...
-