sandy@conexch.UUCP (Sandford Zelkovitz) (04/08/89)
The following code is the fixed version of unzip, written by S.H. Smith. It now compiles problem under Xenix386 and also fixes the bug in subroutine get_string. I hope the author does not mind that I have reposted his program. ............ Sandy ---------------cut/ax/hack/snip/chop/whatever here ----------------------- #!/bin/sh # shar: Shell Archiver (v1.22) # # Run the following text with /bin/sh to create: # Makefile # addbfcrc.c # unzipbsd.c # sed 's/^X//' << 'SHAR_EOF' > Makefile && X# Makefile for unzipbsd X X X# "make unzip" -- makes unzip in current directory X# "make install" -- makes unzip, then moves it into DESTDIR defined below X# "make clean" -- deletes object files and executable unzip from current dir X# "make shar" -- make a SHell ARchive X X# Directory where we want to move executable unzip on "make install" XDESTDIR=/usr/public X X# CFLAGS are flags for the C compiler. LDFLAGS are flags for the loader. XCFLAGS= -O XLDFLAGS= -s X XCC=cc X X.c.o : X $(CC) -c $(CFLAGS) $*.c X XOBJS = unzipbsd.o addbfcrc.o X Xunzip: $(OBJS) X cc $(LDFLAGS) -o unzip $(OBJS) X Xunzip.o: unzip.c X Xaddbfcrc.o: addbfcrc.c X Xinstall: unzip X mv unzip $(DESTDIR)/unzip X Xclean: X /bin/rm -f $(OBJS) core unzip X Xshar: X @shar -a Makefile unzipbsd.c addbfcrc.c > unzipbsd.shar SHAR_EOF chmod 0644 Makefile || echo "restore of Makefile fails" sed 's/^X//' << 'SHAR_EOF' > addbfcrc.c && X/* @(#) addbfcrc.c 1.5 89/03/08 14:58:35 */ X/* Most of following CRC-32 stuff is from zmodem source code */ X X#ifndef LINT Xstatic char sccsid[]="::[[ @(#) addbfcrc.c 1.6 89/03/10 19:08:47 ]]::"; X#endif X X/* I claim no copyright over the contents of this file. -- Rahul Dhesi */ X X/* XChecksum: 951252172 (check or update this with "brik") X*/ X X Xlong crccode; X X/* X * Copyright (C) 1986 Gary S. Brown. You may use this program, or X * code or tables extracted from it, as desired without restriction. 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/* 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 Xlong crc_32_tab[] = { /* CRC polynomial 0xedb88320 */ X 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, X 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, X 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, X 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, X 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, X 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, X 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, X 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, X 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, X 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, X 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, X 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, X 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, X 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, X 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, X 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, X 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, X 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, X 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, X 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, X 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, X 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, X 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, X 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, X 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, X 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, X 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, X 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, X 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, X 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, X 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, X 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, X 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, X 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, X 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, X 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, X 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, X 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, X 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, X 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, X 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, X 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, X 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, X 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, X 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, X 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, X 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, X 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, X 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, X 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, X 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, X 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, X 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, X 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, X 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, X 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, X 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, X 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, X 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, X 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, X 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, X 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, X 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, X 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d X}; X Xaddbfcrc (buf, size) Xregister char *buf; Xregister int size; X{ X int i; X for (i = 0; i < size; i ++) { X crccode = crc_32_tab[(int) ((crccode) ^ (buf[i])) & 0xff] ^ X (((crccode) >> 8) & 0x00FFFFFFL); X } X} SHAR_EOF chmod 0644 addbfcrc.c || echo "restore of addbfcrc.c fails" sed 's/^X//' << 'SHAR_EOF' > unzipbsd.c && X/* X * Quick hack to use on BSD, on a DEC VAX X * By Michael Enkelis @ tektronix 04/03/89 X * X */ X X/* X * Copyright 1987, 1989 Samuel H. Smith; All rights reserved X * X * This is a component of the ProDoor System. X * Do not distribute modified versions without my permission. X * Do not remove or alter this notice or any other copyright notice. X * If you use this in your own program you must distribute source code. X * Do not use any of this in a commercial product. X * X */ X X/* X * UnZip - A simple zipfile extract utility X * X */ X X#define version "UnZip: Zipfile Extract v1.1b of 04-03-89; (C) 1989 S.H.Smith" X Xtypedef unsigned char byte; Xtypedef unsigned int word; Xtypedef unsigned long longint; Xtypedef unsigned char boolean; X#define STRSIZ 256 X X#include <stdio.h> X#include <sys/types.h> X#include <sys/file.h> X#include <sys/stat.h> X#include <fcntl.h> X X Xint errcount = 0; /* count of errors */ Xint debugging = 0; /* debug enable flag */ Xint verbose = 0; /* be verbose */ Xint test_zip = 0; /* test CRC's only */ X X#ifdef M_XENIX Xint L_SET = 1; X#endif X X/* XInitializing the CRC to all one bits avoids failure of detection Xshould entire data stream get cyclically bit-shifted by one position. XThe calculation of the probability of this happening is left as Xan exercise for the reader. X*/ X#define INITCRC 0xFFFFFFFFL; Xextern long crccode; X X/* ----------------------------------------------------------- */ X/* X * Zipfile layout declarations X * X */ X Xtypedef longint signature_type; X X X#define local_file_header_signature 0x04034b50L X Xchar *strchr(); X Xtypedef struct local_file_header { X word version_needed_to_extract; X word general_purpose_bit_flag; X word compression_method; X word last_mod_file_time; X word last_mod_file_date; X longint crc32; X longint compressed_size; X longint uncompressed_size; X word filename_length; X word extra_field_length; X } local_file_header; X X#define central_file_header_signature 0x02014b50L X Xtypedef struct central_directory_file_header { X word version_made_by; X word version_needed_to_extract; X word general_purpose_bit_flag; X word compression_method; X word last_mod_file_time; X word last_mod_file_date; X longint crc32; X longint compressed_size; X longint uncompressed_size; X word filename_length; X word extra_field_length; X word file_comment_length; X word disk_number_start; X word internal_file_attributes; X longint external_file_attributes; X longint relative_offset_local_header; X } central_directory_file_header; X X#define end_central_dir_signature 0x06054b50L X Xtypedef struct end_central_dir_record { X word number_this_disk; X word number_disk_with_start_central_directory; X word total_entries_central_dir_on_this_disk; X word total_entries_central_dir; X longint size_central_directory; X longint offset_start_central_directory; X word zipfile_comment_length; X } end_central_dir_record; X X X/* ----------------------------------------------------------- */ X/* X * input file variables X * X */ X X X#define uinbufsize 512L /* input buffer size */ X byte inbuf[uinbufsize]; X X boolean zipeof; X longint csize; X longint cusize; X int cmethod; X int inpos; X int incnt; X int pc; X int pcbits; X int pcbitv; X X int zipfd; X char zipfn[STRSIZ]; X local_file_header lrec; X X X X X/* ----------------------------------------------------------- */ X/* X * output stream variables X * X */ X X X byte outbuf[4096]; /* for rle look-back */ X longint outpos; /* absolute position in outfile */ X int outcnt; X X int outfd; X char filename[STRSIZ]; X char extra[STRSIZ]; X X X X/* ----------------------------------------------------------- */ X/* X * shrink/reduce working storage X * X */ X X X int factor; X byte followers[256][64]; X byte Slen[256]; X int ExState; X int C; X int V; X int Len; X X#define max_bits 13 X#define init_bits 9 X#define hsize 8192 X#define first_ent 257 X#define clear 256 X X typedef int hsize_array_integer[hsize+1]; X typedef byte hsize_array_byte[hsize+1]; X X hsize_array_integer prefix_of; X hsize_array_byte suffix_of; X hsize_array_byte stack; X X int cbits; X int maxcode; X int free_ent; X int maxcodemax; X int offset; X int sizex; X X X/* ------------------------------------------------------------- */ X Xskip_csize() X{ X lseek(zipfd,csize,L_SET); X zipeof = 1; X csize = 0L; X incnt = 0; X} X X X/* ------------------------------------------------------------- */ X XReadByte(x) Xint *x; X{ X if (incnt == 0) X { X if (csize == 0L) X { X zipeof = 1; X return; X } X X inpos = sizeof(inbuf); X if (inpos > csize) X inpos = (int)csize; X incnt = read(zipfd,inbuf,inpos); X X inpos = 1; X csize -= incnt; X } X X *x = inbuf[inpos-1]; X inpos++; X incnt--; X} X X X/* ------------------------------------------------------------- */ X XReadBits(bits,x) Xint bits,*x; X /* read the specified number of bits */ X{ X int bit; X int bitv; X X *x = 0; X bitv = 1; X X for (bit = 0; bit <= bits-1; bit++) X { X X if (pcbits > 0) X { X pcbits--; X pcbitv = pcbitv << 1; X } X else X X { X ReadByte(&pc); X pcbits = 7; X pcbitv = 1; X } X X if ((pc & pcbitv) != 0) X *x = *x | bitv; X X bitv = (int) (bitv << 1); X } X X} X X X/* ---------------------------------------------------------- */ X Xget_string(len, s) Xint len; Xchar *s; X{ X read(zipfd,s,len); X s[len] = 0; X} X X X/* ------------------------------------------------------------- */ X XOutByte(c) Xint c; X /* output each character from archive to screen */ X{ X outbuf[outcnt /* outpos % sizeof(outbuf) */] = c; X outpos++; X outcnt++; X X if (outcnt == sizeof(outbuf)) X { X if (test_zip == 0) X write(outfd,outbuf,outcnt); X addbfcrc (outbuf, outcnt); X outcnt = 0; X printf("."); X } X} X X X/* ----------------------------------------------------------- */ X Xreduce_L(x) Xint x; X { X switch (factor) { X case 1: return x & 0x7f; X case 2: return x & 0x3f; X case 3: return x & 0x1f; X case 4: return x & 0x0f; X } X return 0; /* error */ X } X X Xreduce_F(x) Xint x; X { X switch (factor) { X case 1: if (x == 127) return 2; else return 3; X case 2: if (x == 63) return 2; else return 3; X case 3: if (x == 31) return 2; else return 3; X case 4: if (x == 15) return 2; else return 3; X } X return 0; /* error */ X } X X Xreduce_D(x,y) Xint x,y; X { X switch (factor) { X case 1: return ((x >> 7) & 0x01) * 256 + y + 1; X case 2: return ((x >> 6) & 0x03) * 256 + y + 1; X case 3: return ((x >> 5) & 0x07) * 256 + y + 1; X case 4: return ((x >> 4) & 0x0f) * 256 + y + 1; X } X return 0; /* error */ X } X X Xreduce_B(x) Xint x; X /* number of bits needed to encode the specified number */ X { X switch (x - 1) { X X case 0: X case 1: return 1; X X case 2: X case 3: return 2; X X case 4: X case 5: X case 6: X case 7: return 3; X X case 8: X case 9: X case 10: X case 11: X case 12: X case 13: X case 14: X case 15: return 4; X X case 16: X case 17: X case 18: X case 19: X case 20: X case 21: X case 22: X case 23: X case 24: X case 25: X case 26: X case 27: X case 28: X case 29: X case 30: X case 31: return 5; X X case 32: X case 33: X case 34: X case 35: X case 36: X case 37: X case 38: X case 39: X case 40: X case 41: X case 42: X case 43: X case 44: X case 45: X case 46: X case 47: X case 48: X case 49: X case 50: X case 51: X case 52: X case 53: X case 54: X case 55: X case 56: X case 57: X case 58: X case 59: X case 60: X case 61: X case 62: X case 63: return 6; X X case 64: X case 65: X case 66: X case 67: X case 68: X case 69: X case 70: X case 71: X case 72: X case 73: X case 74: X case 75: X case 76: X case 77: X case 78: X case 79: X case 80: X case 81: X case 82: X case 83: X case 84: X case 85: X case 86: X case 87: X case 88: X case 89: X case 90: X case 91: X case 92: X case 93: X case 94: X case 95: X case 96: X case 97: X case 98: X case 99: X case 100: X case 101: X case 102: X case 103: X case 104: X case 105: X case 106: X case 107: X case 108: X case 109: X case 110: X case 111: X case 112: X case 113: X case 114: X case 115: X case 116: X case 117: X case 118: X case 119: X case 120: X case 121: X case 122: X case 123: X case 124: X case 125: X case 126: X case 127: return 7; X X default: return 8; X } X } X X X X/* ----------------------------------------------------------- */ X XExpand(c) Xint c; X { X#define DLE 144 X X switch (ExState) { X X case 0: X if (c != DLE) X OutByte(c); X else X ExState = 1; X break; X X case 1: X if (c != 0) X { X V = c; X Len = reduce_L(V); X ExState = reduce_F(Len); X } X else X { X OutByte(DLE); X ExState = 0; X } X break; X X case 2: { X Len = Len + c; X ExState = 3; X } X break; X X case 3: { X int i; X longint offset = reduce_D(V,c); X longint op = outpos - offset; X X for (i = 0; i <= Len + 2; i++) X { X if (op < 0L) X OutByte(0); X else X OutByte(outbuf[(int)(op % sizeof(outbuf))]); X op++; X } X X ExState = 0; X } X break; X } X } X X X/* ----------------------------------------------------------- */ X XLoadFollowers() X { X int x; X int i; X int b; X X for (x = 255; x >= 0; x--) X { X ReadBits(6,&b); X Slen[x] = b; X X for (i = 0; i < Slen[x]; i++) X { X ReadBits(8,&b); X followers[x][i] = b; X } X } X } X X X X/* ----------------------------------------------------------- */ X X/* X * The Reducing algorithm is actually a combination of two X * distinct algorithms. The first algorithm compresses repeated X * byte sequences, and the second algorithm takes the compressed X * stream from the first algorithm and applies a probabilistic X * compression method. X * X */ X XunReduce() X /* expand probablisticly reduced data */ X X { X X int lchar; X int lout; X int I; X X factor = cmethod - 1; X X if ((factor < 1) || (factor > 4)) X { X skip_csize(); X return; X } X X ExState = 0; X LoadFollowers(); X lchar = 0; X X while ((!zipeof) && (outpos < cusize)) X { X X if (Slen[lchar] == 0) X ReadBits(8,&lout); X else X X { X ReadBits(1,&lout); X if (lout != 0) X ReadBits(8,&lout); X else X { X ReadBits(reduce_B(Slen[lchar]),&I); X lout = followers[lchar][I]; X } X } X X Expand(lout); X lchar = lout; X } X} X X X/* ------------------------------------------------------------- */ X/* X * Shrinking is a Dynamic Ziv-Lempel-Welch compression algorithm X * with partial clearing. X * X */ X Xpartial_clear() X{ X int pr; X int cd; X X X /* mark all nodes as potentially unused */ X for (cd = first_ent; cd < free_ent; cd++) X prefix_of[cd] |= 0x8000; X X X /* unmark those that are used by other nodes */ X for (cd = first_ent; cd < free_ent; cd++) X { X pr = prefix_of[cd] & 0x7fff; /* reference to another node? */ X if (pr >= first_ent) /* flag node as referenced */ X prefix_of[pr] &= 0x7fff; X } X X X /* clear the ones that are still marked */ X for (cd = first_ent; cd < free_ent; cd++) X if ((prefix_of[cd] & 0x8000) != 0) X prefix_of[cd] = -1; X X X /* find first cleared node as next free_ent */ X free_ent = first_ent; X while ((free_ent < maxcodemax) && (prefix_of[free_ent] != -1)) X free_ent++; X} X X X/* ------------------------------------------------------------- */ X XunShrink() X X{ X int stackp; X int finchar; X int code; X int oldcode; X int incode; X X X /* decompress the file */ X maxcodemax = 1 << max_bits; X cbits = init_bits; X maxcode = (1 << cbits) - 1; X free_ent = first_ent; X offset = 0; X sizex = 0; X X for (code = maxcodemax; code > 255; code--) X prefix_of[code] = -1; X X for (code = 255; code >= 0; code--) X { X prefix_of[code] = 0; X suffix_of[code] = code; X } X X ReadBits(cbits,&oldcode); X if (zipeof) return; X finchar = oldcode; X X OutByte(finchar); X X stackp = 0; X X while ((!zipeof)) X { X ReadBits(cbits,&code); X if (zipeof) return; X X while (code == clear) X { X ReadBits(cbits,&code); X X switch (code) { X X case 1: { X cbits++; X if (cbits == max_bits) X maxcode = maxcodemax; X else X maxcode = (1 << cbits) - 1; X } X break; X X case 2: X partial_clear(); X break; X } X X ReadBits(cbits,&code); X if (zipeof) return; X } X X X /* special case for KwKwK string */ X incode = code; X if (prefix_of[code] == -1) X { X stack[stackp] = finchar; X stackp++; X code = oldcode; X } X X X /* generate output characters in reverse order */ X while (code >= first_ent) X { X stack[stackp] = suffix_of[code]; X stackp++; X code = prefix_of[code]; X } X X finchar = suffix_of[code]; X stack[stackp] = finchar; X stackp++; X X X /* and put them out in forward order */ X while (stackp > 0) X { X stackp--; X OutByte(stack[stackp]); X } X X X /* generate new entry */ X code = free_ent; X if (code < maxcodemax) X { X prefix_of[code] = oldcode; X suffix_of[code] = finchar; X while ((free_ent < maxcodemax) && (prefix_of[free_ent] != -1)) X free_ent++; X } X X X /* remember previous code */ X oldcode = incode; X } X X} X X X/* ---------------------------------------------------------- */ X Xextract_member() X{ X int b; X Xfor (b=0; b<sizeof(outbuf); b++) outbuf[b]=0; X pcbits = 0; X incnt = 0; X outpos = 0L; X outcnt = 0; X zipeof = 0; X X X if (test_zip == 0) { X outfd = creat(filename,S_IWRITE|S_IREAD); X if (outfd < 1) X { X printf("Can't create output: %s\n",filename); X exit(1); X } X close(outfd); X outfd = open(filename,O_RDWR); X } X X if (test_zip) X printf(" Testing: %s ...",filename); X X switch (cmethod) { X X case 0: /* stored */ X { X if (test_zip == 0) X printf(" Extract: %s ...",filename); X while ((!zipeof)) X { X ReadByte(&b); X OutByte(b); X } X } X break; X X case 1: { X if (test_zip == 0) X printf("UnShrink: %s ...",filename); X unShrink(); X } X break; X X case 2: X case 3: X case 4: X case 5: { X if (test_zip == 0) X printf(" Expand: %s ...",filename); X unReduce(); X } X break; X X default: printf("Unknown compression method."); X } X X if (outcnt > 0) { X if (test_zip == 0) X write(outfd,outbuf,outcnt); X addbfcrc (outbuf, outcnt); X } X X if (test_zip == 0) X close(outfd); X X if ((crccode + lrec.crc32) == -1) X printf(" Ok"); X else X printf(" Bad"); X X if (verbose) X printf(" [%d]\n",crccode); X else X printf("\n"); X} X X X/* ---------------------------------------------------------- */ X X/* UNIX support routines: Michael Enkelis */ Xget_byte() X{ X unsigned int nibble; X read(zipfd,&nibble,1); X return (nibble & 0xff); X} X Xget_word() X{ X unsigned int nibble[2]; X nibble[0] = get_byte(); X nibble[1] = get_byte(); X return (int) (nibble[0] | nibble[1] << 8); X} X Xget_long() X{ X unsigned int nibble[4]; X nibble[0] = get_byte(); X nibble[1] = get_byte(); X nibble[2] = get_byte(); X nibble[3] = get_byte(); X return (long) ((unsigned long) nibble[0] | X ((unsigned long) nibble[1] << 8) | X ((unsigned long) nibble[2] << 16) | X ((unsigned long) nibble[3] << 24)); X} X/** End of added support routines **/ X Xprocess_local_file_header() X{ X lrec.version_needed_to_extract = get_word(); X lrec.general_purpose_bit_flag = get_word(); X lrec.compression_method = get_word(); X lrec.last_mod_file_time = get_word(); X lrec.last_mod_file_date = get_word(); X lrec.crc32 = get_long(); X lrec.compressed_size = get_long(); X lrec.uncompressed_size = get_long(); X lrec.filename_length = get_word(); X lrec.extra_field_length = get_word(); X X get_string(lrec.filename_length,filename); X get_string(lrec.extra_field_length,extra); X X if (debugging) { X printf("Version used : %d\n",lrec.version_needed_to_extract); X printf("Bit flags : %d\n",lrec.general_purpose_bit_flag); X printf("Compression : %d\n",lrec.compression_method); X printf("Mod time : %d\n",lrec.last_mod_file_time); X printf("Mod date : %d\n",lrec.last_mod_file_date); X printf("Crc32 : %d\n",~lrec.crc32); X printf("Compressed size : %d\n",lrec.compressed_size); X printf("Normal file size: %d\n",lrec.uncompressed_size); X printf("File name : %s.%s\n",filename,extra); X } X X csize = lrec.compressed_size; X cusize = lrec.uncompressed_size; X cmethod = lrec.compression_method; X X crccode = INITCRC; X extract_member(); X} X X X/* ---------------------------------------------------------- */ X Xprocess_central_file_header() X{ X central_directory_file_header rec; X char filename[STRSIZ]; X char extra[STRSIZ]; X char comment[STRSIZ]; X X rec.version_made_by = get_word(); X rec.version_needed_to_extract = get_word(); X rec.general_purpose_bit_flag = get_word(); X rec.compression_method = get_word(); X rec.last_mod_file_time = get_word(); X rec.last_mod_file_date = get_word(); X rec.crc32 = get_long(); X rec.compressed_size = get_long(); X rec.uncompressed_size = get_long(); X rec.filename_length = get_word(); X rec.extra_field_length = get_word(); X rec.file_comment_length = get_word(); X rec.disk_number_start = get_word(); X rec.internal_file_attributes = get_word(); X rec.external_file_attributes = get_long(); X rec.relative_offset_local_header = get_long(); X X get_string(rec.filename_length,filename); X get_string(rec.extra_field_length,extra); X get_string(rec.file_comment_length,comment); X X crccode = INITCRC; X} X X X/* ---------------------------------------------------------- */ X Xprocess_end_central_dir() X{ X end_central_dir_record rec; X char comment[STRSIZ]; X X rec.number_this_disk = get_word(); X rec.number_disk_with_start_central_directory = get_word(); X rec.total_entries_central_dir_on_this_disk = get_word(); X rec.total_entries_central_dir = get_word(); X rec.size_central_directory = get_long(); X rec.offset_start_central_directory = get_long(); X rec.zipfile_comment_length = get_word(); X X get_string(rec.zipfile_comment_length,comment); X} X X X/* ---------------------------------------------------------- */ X Xprocess_headers() X{ X longint sig; X X while (1) X { X if (read(zipfd,&sig,sizeof(sig)) != sizeof(sig)) X return; X else X X if (sig == local_file_header_signature) X process_local_file_header(); X else X X if (sig == central_file_header_signature) X process_central_file_header(); X else X X if (sig == end_central_dir_signature) X { X process_end_central_dir(); X return; X } X X else X { X printf("Invalid Zipfile Header\n"); X return; X } X } X X} X X X/* ---------------------------------------------------------- */ X Xextract_zipfile() X{ X zipfd = open(zipfn,O_RDONLY); X if (zipfd < 1) { X printf("Can't open input file: %s\n",zipfn); X return; X } X X process_headers(); X X close(zipfd); X} X X X/* ---------------------------------------------------------- */ X/* X * main program X * X */ X Xmain(argc, argv) Xint argc; Xchar **argv; X{ X int c; /* next option letter */ X int count = 0; /* count of required options seen */ X X extern int optind; /* from getopt: next arg to process */ X extern int opterr; /* used by getopt */ X extern char *optarg; X X opterr = 0; /* so getopt won't print err msg */ X X printf("\n"); X printf("%s\n",version); X printf("Courtesy of: S.H.Smith and The Tool Shop BBS,(602) 279-2673."); X printf("\nModified by Sanford <Sandy> Zelkovitz - XBBS - (714) 898-8634"); X printf("\n\n"); X X while ((c = getopt (argc, argv, "dtv")) != EOF) X { X switch (c) { X case 'd': debugging++; break; X case 't': test_zip++; break; X case 'v': verbose++; break; X default: short_help(); X } X } X X strcpy(zipfn,argv[optind]); X if (strlen(zipfn) == 0) X short_help(); X X if (strchr(zipfn,'.') == NULL) X strcat(zipfn,".zip"); X X extract_zipfile(); X X exit(0); X} X Xshort_help() X{ X printf("Usage: UnZip -tv file[.zip]\n"); X exit(1); X} SHAR_EOF chmod 0644 unzipbsd.c || echo "restore of unzipbsd.c fails" exit 0
bturner@hpcvlx.HP.COM (Bill Turner) (04/12/89)
The only problem with both the original Unzip posting and this was that they were written for byte-swapping architectures. If you want to have it work on non-byte-swapping systems, apply the following changes: 1) All of the signature values need to be byte-swapped. I.e., local_file_header_signature is 0x504b0304L central_file_header_signature is 0x504b0102L end_central_dir_signature is 0x504b0506L 2) In the routine get_byte, declare nibble as unsigned char rather than unsigned int. ----Bill Turner HP Corvallis Workstation Operation
swh@hpsmtc1.HP.COM (Steve Harrold) (04/13/89)
Re: The UNZIP program Thank you for the "byte-swapped" and "nibble" corrections. An additional correction is that the declaration for the "get_long()" function should be "longint" rather than the default "int". Failure to do this ensures that the code calculates bad CRC32 checks on a machine that has 16-bit ints. The zip file is successfully extracted, but you get a series of unsettling "bad" messages. Furthermore, the "open()" functions have to set the file mode to include the "O_BINARY" attribute for those environments that distinguish "text" files from "binary" files (e.g. MSDOS). An additional question is the use of the symbol "L_SET" in the original posting. This has a value of 0 (from file "file.h") but I think the symbol L_INCR (value = 1) should be used. The XENIX adaptation sets L_SET = 1 to achieve this purpose. Can the original author comment on these fixes?