Repost of unzipbsd.
Michael Enkelis
michaele at vice.ICO.TEK.COM
Wed May 31 02:36:40 AEST 1989
Do to requests, I am reposting unzipbsd at patch level 4.
This has been tested on a BSD 4.3 system (VAX 8xxx cpu)
and the IFDEF's are in place for MSDOS or XENIX (? SYS-V ?).
Patchlevel 4:
This release has a "patchlevel.h" file to help keep track of
versions, and will display the patchlevel in the long help screen.
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# Makefile
# patchlevel.h
# unzipbsd.c
# crc32.c
# This archive created: Tue May 30 09:32:46 1989
export PATH; PATH=/bin:$PATH
echo shar: extracting "'Makefile'" '(917 characters)'
if test -f 'Makefile'
then
echo shar: will not over-write existing file "'Makefile'"
else
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# "make arc" -- make a DOS 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
X# This is used for DBX
X#CFLAGS= -g
X
XLDFLAGS= -s
X
XCC=cc
X
X.c.o:
X $(CC) -c $(CFLAGS) $*.c
X
XOBJS = unzipbsd.o crc32.o
X
Xunzip: $(OBJS)
X cc $(LDFLAGS) -o unzip $(OBJS)
X
Xunzip.o: unzip.c
X
Xcrc32.o: crc32.c
X
Xinstall: unzip
X mv unzip $(DESTDIR)/unzip
X
Xclean:
X /bin/rm -f $(OBJS) core unzip
X
Xshar:
X @shar -a Makefile patchlevel.h unzipbsd.c crc32.c > unzipbsd.shar
X
Xarc:
X @arc -a unzipbsd.arc Makefile patchlevel.h unzipbsd.c crc32.c
X
SHAR_EOF
if test 917 -ne "`wc -c < 'Makefile'`"
then
echo shar: error transmitting "'Makefile'" '(should have been 917 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'patchlevel.h'" '(16 characters)'
if test -f 'patchlevel.h'
then
echo shar: will not over-write existing file "'patchlevel.h'"
else
sed 's/^ X//' << \SHAR_EOF > 'patchlevel.h'
X#define PATCH 4
SHAR_EOF
if test 16 -ne "`wc -c < 'patchlevel.h'`"
then
echo shar: error transmitting "'patchlevel.h'" '(should have been 16 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'unzipbsd.c'" '(30392 characters)'
if test -f 'unzipbsd.c'
then
echo shar: will not over-write existing file "'unzipbsd.c'"
else
sed 's/^ X//' << \SHAR_EOF > 'unzipbsd.c'
X
X/*
X * Copyright 1989 Samuel H. Smith; All rights reserved
X *
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 * To compile:
X * tcc -B -O -Z -G -mc unzip.c ;turbo C 2.0, compact model
X *
X */
X
X#include "patchlevel.h"
X#define VERSION "1.2"
X
Xtypedef unsigned char byte; /* code assumes UNSIGNED bytes */
Xtypedef long longint;
Xtypedef unsigned word;
Xtypedef char boolean;
X
X#define STRSIZ 256
X
X#include <stdio.h>
X /* this is your standard header for all C compiles */
X
X#ifdef MSDOS || M_XENIX
X#include <stdlib.h>
X /* this include defines various standard library prototypes */
X#endif
X
X
X/*
X * SEE HOST OPERATING SYSTEM SPECIFICS SECTION STARTING NEAR LINE 180
X *
X */
X
X
X/* ----------------------------------------------------------- */
X/*
X * Zipfile layout declarations
X *
X */
X
X
Xchar local_file_header_signature[] = {0x50,0x4b,0x03,0x04};
X
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
Xchar central_file_header_signature[] = {0x50,0x4b,0x01,0x02};
X
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
Xchar end_central_dir_signature[] = {0x50,0x4b,0x05,0x06};
X
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/*
X * input file variables
X *
X */
X
X#define INBUFSIZ 0x2000
Xbyte *inbuf; /* input file buffer - any size is legal */
Xbyte *inptr;
Xbyte *comment;
X
Xint incnt;
Xunsigned bitbuf;
Xint bits_left;
Xboolean zipeof;
X
Xint zipfd;
Xchar zipfn[STRSIZ];
Xlocal_file_header lrec;
X
X
X/* ----------------------------------------------------------- */
X/*
X * output stream variables
X *
X */
X
X#define OUTBUFSIZ 0x6000
Xbyte *outbuf; /* buffer for rle look-back */
Xbyte *outptr;
X
Xlongint outpos; /* absolute position in outfile */
Xint outcnt; /* current position in outbuf */
X
Xint outfd;
Xchar filename[STRSIZ];
Xchar extra[STRSIZ];
X
X#define DLE 144
X
X
X/* ----------------------------------------------------------- */
X/*
X * shrink/reduce working storage
X *
X */
X
Xint factor;
Xbyte followers[256][64];
Xbyte Slen[256];
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
Xtypedef int hsize_array_integer[hsize+1];
Xtypedef byte hsize_array_byte[hsize+1];
X
Xhsize_array_integer prefix_of;
Xhsize_array_byte suffix_of;
Xhsize_array_byte stack;
X
Xint codesize;
Xint maxcode;
Xint free_ent;
Xint maxcodemax;
Xint offset;
Xint sizex;
X
X
X
X/* ============================================================= */
X/*
X * Host operating system details
X *
X */
X
X#include <string.h>
X /* this include defines strcpy, strcmp, etc. */
X
X#ifdef MSDOS || M_XENIX
X#include <io.h>
X /*
X * this include file defines
X * struct ftime ... (* file time/date stamp info *)
X * int setftime (int handle, struct ftime *ftimep);
X * #define SEEK_CUR 1 (* lseek() modes *)
X * #define SEEK_END 2
X * #define SEEK_SET 0
X */
X#else
X#include <sys/file.h>
X /*
X * this include file defines
X * #define L_SET 0 (* Seek to absolute record *)
X */
X#define SEEK_SET L_SET
X#endif
X
X
X
X#ifdef MSDOS || M_XENIX
X#include <fcntl.h>
X /*
X * this include file defines
X * #define O_BINARY 0x8000 (* no cr-lf translation *)
X * as used in the open() standard function
X */
X#ifndef L_SET
X#define L_SET 1
X#endif
X#endif
X
X#ifndef O_BINARY
X#define O_BINARY 0 /* BSD don't have a Open_BINARY mode */
X#endif
X
X#include <sys/types.h>
X#include <sys/stat.h>
X /*
X * this include file defines
X * #define S_IREAD 0x0100 (* owner may read *)
X * #define S_IWRITE 0x0080 (* owner may write *)
X * as used in the creat() standard function
X */
X
Xvoid set_file_time()
X /*
X * set the output file date/time stamp according to information from the
X * zipfile directory record for this file
X */
X{
X/*
X * On a BSD system, You can't change the creation date/time
X * (at least i think so) so for now, skip this code.
X */
X#ifdef MSDOS || M_XENIX
X union {
X struct ftime ft; /* system file time record */
X struct {
X word ztime; /* date and time words */
X word zdate; /* .. same format as in .ZIP file */
X } zt;
X } td;
X
X /*
X * set output file date and time - this is optional and can be
X * deleted if your compiler does not easily support setftime()
X */
X
X td.zt.ztime = lrec.last_mod_file_time;
X td.zt.zdate = lrec.last_mod_file_date;
X
X setftime(outfd, &td.ft);
X#endif
X}
X
X/*
X * Some defines to use the GETOPT functions
X * that are on most systems, even TURBO-C has these.
X */
X#define USE_GETOPT /* Use the GETOPT package */
Xint extract = 1; /* Extract contents */
Xint debugging = 0; /* debug enable */
Xint verbose = 0; /* be verbose */
Xint list_zip = 0; /* list contents only */
Xint test_zip = 0; /* test CRC's only */
X
Xlong crc32val; /* The CRC value we calculate */
Xint numbad =0;
Xint Total_files =0;
Xlong Total_bytes =0;
Xlong Total_length =0;
X
X/* ============================================================= */
X
Xint create_output_file()
X /* return non-0 if creat failed */
X{
X if (!extract)
X return 0;
X
X /* create the output file with READ and WRITE permissions */
X outfd = creat(filename, S_IWRITE | S_IREAD);
X if (outfd < 1) {
X printf("Can't create output: %s\n", filename);
X return 1;
X }
X
X /*
X * close the newly created file and reopen it in BINARY mode to
X * disable all CR/LF translations
X */
X close(outfd);
X outfd = open(filename, O_RDWR | O_BINARY);
X
X /* write a single byte at EOF to pre-allocate the file */
X lseek(outfd, lrec.uncompressed_size - 1L, SEEK_SET);
X write(outfd, "?", 1);
X lseek(outfd, 0L, SEEK_SET);
X return 0;
X}
X
X
Xint open_input_file()
X /* return non-0 if creat failed */
X{
X /*
X * open the zipfile for reading and in BINARY mode to prevent cr/lf
X * translation, which would corrupt the bitstreams
X */
X
X zipfd = open(zipfn, O_RDONLY | O_BINARY);
X if (zipfd < 1) {
X printf("Can't open input file: %s\n", zipfn);
X return (1);
X }
X return 0;
X}
X
X
Xint FillBuffer()
X /* fill input buffer if possible */
X{
X int readsize;
X
X if (lrec.compressed_size <= 0)
X return incnt = 0;
X
X if (lrec.compressed_size > INBUFSIZ)
X readsize = INBUFSIZ;
X else
X readsize = (int) lrec.compressed_size;
X incnt = read(zipfd, inbuf, readsize);
X
X lrec.compressed_size -= incnt;
X inptr = inbuf;
X return incnt--;
X}
X
Xint ReadByte(x)
Xunsigned *x;
X /* read a byte; return 8 if byte available, 0 if not */
X{
X if (incnt-- == 0)
X if (FillBuffer() == 0)
X return 0;
X
X *x = *inptr++;
X return 8;
X}
X
X
X/* ------------------------------------------------------------- */
Xstatic unsigned mask_bits[] =
X {0, 0x0001, 0x0003, 0x0007, 0x000f,
X 0x001f, 0x003f, 0x007f, 0x00ff,
X 0x01ff, 0x03ff, 0x07ff, 0x0fff,
X 0x1fff, 0x3fff, 0x7fff, 0xffff
X };
X
X
Xint FillBitBuffer(bits)
Xregister int bits;
X{
X /* get the bits that are left and read the next word */
X unsigned temp;
X register int result = bitbuf;
X int sbits = bits_left;
X bits -= bits_left;
X
X /* read next word of input */
X bits_left = ReadByte(&bitbuf);
X bits_left += ReadByte(&temp);
X bitbuf |= (temp << 8);
X if (bits_left == 0)
X zipeof = 1;
X
X /* get the remaining bits */
X result = result | (int) ((bitbuf & mask_bits[bits]) << sbits);
X bitbuf >>= bits;
X bits_left -= bits;
X return result;
X}
X
X#define READBIT(nbits,zdest) { if (nbits <= bits_left) { zdest = (int)(bitbuf & mask_bits[nbits]); bitbuf >>= nbits; bits_left -= nbits; } else zdest = FillBitBuffer(nbits);}
X
X/*
X * macro READBIT(nbits,zdest)
X * {
X * if (nbits <= bits_left) {
X * zdest = (int)(bitbuf & mask_bits[nbits]);
X * bitbuf >>= nbits;
X * bits_left -= nbits;
X * } else
X * zdest = FillBitBuffer(nbits);
X * }
X *
X */
X
X
X/* ------------------------------------------------------------- */
X
Xvoid Write_file()
X{
X if (extract)
X write(outfd, outbuf, outcnt);
X}
X
X/* ------------------------------------------------------------- */
X
Xvoid FlushOutput()
X /* flush contents of output buffer */
X{
X UpdateCRC(outbuf, outcnt);
X Write_file();
X outpos += outcnt;
X outcnt = 0;
X outptr = outbuf;
X}
X
X#define OUTB(intc) { *outptr++=intc; if (++outcnt==OUTBUFSIZ) FlushOutput(); }
X
X/*
X * macro OUTB(intc)
X * {
X * *outptr++=intc;
X * if (++outcnt==OUTBUFSIZ)
X * FlushOutput();
X * }
X *
X */
X
X
X/* ----------------------------------------------------------- */
X
Xvoid LoadFollowers()
X{
X register int x;
X register int i;
X
X for (x = 255; x >= 0; x--) {
X READBIT(6,Slen[x]);
X for (i = 0; i < Slen[x]; i++) {
X READBIT(8,followers[x][i]);
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
Xint L_table[] = {0, 0x7f, 0x3f, 0x1f, 0x0f};
X
Xint D_shift[] = {0, 0x07, 0x06, 0x05, 0x04};
Xint D_mask[] = {0, 0x01, 0x03, 0x07, 0x0f};
X
Xint B_table[] = {8, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5,
X 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6,
X 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
X 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7,
X 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
X 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
X 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
X 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
X 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
X 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
X 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
X 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
X 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
X 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
X 8, 8, 8, 8};
X
X/* ----------------------------------------------------------- */
X
Xvoid unReduce()
X /* expand probablisticly reduced data */
X{
X register int lchar;
X int nchar;
X int ExState;
X int V;
X int Len;
X
X factor = lrec.compression_method - 1;
X ExState = 0;
X lchar = 0;
X LoadFollowers();
X
X while (((outpos + outcnt) < lrec.uncompressed_size) && (!zipeof)) {
X if (Slen[lchar] == 0)
X READBIT(8,nchar) /* ; */
X else
X {
X READBIT(1,nchar);
X if (nchar != 0)
X READBIT(8,nchar) /* ; */
X else
X {
X int follower;
X int bitsneeded = B_table[Slen[lchar]];
X READBIT(bitsneeded,follower);
X nchar = followers[lchar][follower];
X }
X }
X
X /* expand the resulting byte */
X switch (ExState) {
X
X case 0:
X if (nchar != DLE)
X OUTB(nchar) /*;*/
X else
X ExState = 1;
X break;
X
X case 1:
X if (nchar != 0) {
X V = nchar;
X Len = V & L_table[factor];
X if (Len == L_table[factor])
X ExState = 2;
X else
X ExState = 3;
X }
X else {
X OUTB(DLE);
X ExState = 0;
X }
X break;
X
X case 2: {
X Len += nchar;
X ExState = 3;
X }
X break;
X
X case 3: {
X register int i = Len + 3;
X int offset = (((V >> D_shift[factor]) &
X D_mask[factor]) << 8) + nchar + 1;
X longint op = outpos + outcnt - offset;
X
X /* special case- before start of file */
X while ((op < 0L) && (i > 0)) {
X OUTB(0);
X op++;
X i--;
X }
X
X /* normal copy of data from output buffer */
X {
X register int ix = (int) (op % OUTBUFSIZ);
X
X /* do a block memory copy if possible */
X if ( ((ix +i) < OUTBUFSIZ) &&
X ((outcnt+i) < OUTBUFSIZ) ) {
X memcpy(outptr,&outbuf[ix],i);
X outptr += i;
X outcnt += i;
X }
X
X /* otherwise copy byte by byte */
X else while (i--) {
X OUTB(outbuf[ix]);
X if (++ix >= OUTBUFSIZ)
X ix = 0;
X }
X }
X
X ExState = 0;
X }
X break;
X }
X
X /* store character for next iteration */
X lchar = nchar;
X }
X}
X
X
X/* ------------------------------------------------------------- */
X/*
X * Shrinking is a Dynamic Ziv-Lempel-Welch compression algorithm
X * with partial clearing.
X *
X */
X
Xvoid partial_clear()
X{
X register int pr;
X register int cd;
X
X /* mark all nodes as potentially unused */
X for (cd = first_ent; cd < free_ent; cd++)
X prefix_of[cd] |= 0x8000;
X
X /* unmark those that are used by other nodes */
X for (cd = first_ent; cd < free_ent; cd++) {
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 /* 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 /* find first cleared node as next free_ent */
X cd = first_ent;
X while ((cd < maxcodemax) && (prefix_of[cd] != -1))
X cd++;
X free_ent = cd;
X}
X
X
X/* ------------------------------------------------------------- */
X
Xvoid unShrink()
X{
X#define GetCode(dest) READBIT(codesize,dest)
X
X register int code;
X register int stackp;
X int finchar;
X int oldcode;
X int incode;
X
X
X /* decompress the file */
X maxcodemax = 1 << max_bits;
X codesize = init_bits;
X maxcode = (1 << codesize) - 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 prefix_of[code] = 0;
X suffix_of[code] = code;
X }
X
X GetCode(oldcode);
X if (zipeof)
X return;
X finchar = oldcode;
X
X OUTB(finchar);
X
X stackp = hsize;
X
X while (!zipeof) {
X GetCode(code);
X if (zipeof)
X return;
X
X while (code == clear) {
X GetCode(code);
X switch (code) {
X
X case 1:{
X codesize++;
X if (codesize == max_bits)
X maxcode = maxcodemax;
X else
X maxcode = (1 << codesize) - 1;
X }
X break;
X
X case 2:
X partial_clear();
X break;
X }
X
X GetCode(code);
X if (zipeof)
X return;
X }
X
X
X /* special case for KwKwK string */
X incode = code;
X if (prefix_of[code] == -1) {
X stack[--stackp] = finchar;
X code = oldcode;
X }
X
X
X /* generate output characters in reverse order */
X while (code >= first_ent) {
X stack[--stackp] = suffix_of[code];
X code = prefix_of[code];
X }
X
X finchar = suffix_of[code];
X stack[--stackp] = finchar;
X
X
X /* and put them out in forward order, block copy */
X if ((hsize-stackp+outcnt) < OUTBUFSIZ) {
X memcpy(outptr,&stack[stackp],hsize-stackp);
X outptr += hsize-stackp;
X outcnt += hsize-stackp;
X stackp = hsize;
X }
X
X /* output byte by byte if we can't go by blocks */
X else while (stackp < hsize)
X OUTB(stack[stackp++]);
X
X
X /* generate new entry */
X code = free_ent;
X if (code < maxcodemax) {
X prefix_of[code] = oldcode;
X suffix_of[code] = finchar;
X
X do
X code++;
X while ((code < maxcodemax) && (prefix_of[code] != -1));
X
X free_ent = code;
X }
X
X /* remember previous code */
X oldcode = incode;
X }
X
X}
X
X
X/* ---------------------------------------------------------- */
X
Xvoid extract_member()
X{
X unsigned b;
X
X bits_left = 0;
X bitbuf = 0;
X incnt = 0;
X outpos = 0L;
X outcnt = 0;
X outptr = outbuf;
X zipeof = 0;
X crc32val = 0xFFFFFFFFL;
X
X
X /* create the output file with READ and WRITE permissions */
X if (create_output_file())
X exit(1);
X
X switch (lrec.compression_method) {
X
X case 0: /* stored */
X {
X if (test_zip)
X printf("Testing: %-12s ", filename);
X if (extract)
X printf(" Extracting: %-12s ", filename);
X while (ReadByte(&b))
X OUTB(b);
X }
X break;
X
X case 1: {
X if (test_zip)
X printf("Testing: %-12s ", filename);
X if (extract)
X printf("UnShrinking: %-12s ", filename);
X unShrink();
X }
X break;
X
X case 2:
X case 3:
X case 4:
X case 5: {
X if (test_zip)
X printf("Testing: %-12s ", filename);
X if (extract)
X printf(" Expanding: %-12s ", filename);
X unReduce();
X }
X break;
X
X default:
X printf("Unknown compression method.");
X }
X
X
X /* write the last partial buffer, if any */
X if (outcnt > 0) {
X UpdateCRC(outbuf, outcnt);
X Write_file();
X }
X
X /* set output file date and time */
X set_file_time();
X
X close(outfd);
X
X crc32val = -1 - crc32val;
X if (!list_zip) {
X if (crc32val != lrec.crc32) {
X numbad++;
X printf(" Bad");
X if(verbose)
X printf(", CRC %08lx (should be %08lx)", lrec.crc32, crc32val);
X } else {
X printf(" Ok");
X if (verbose)
X printf(", CRC = %08lx", lrec.crc32);
X }
X printf("\n");
X }
X}
X
X
X/* ---------------------------------------------------------- */
X
Xvoid get_string(len, s)
Xint len;
Xchar *s;
X{
X read(zipfd, s, len);
X s[len] = 0;
X}
X
X/* UNIX support routines: Michael Enkelis */
Xget_byte()
X{
X byte nibble;
X read(zipfd,&nibble,1);
X return (byte) (nibble & 0xff);
X}
X
Xget_word()
X{
X byte nibble[2];
X nibble[0] = get_byte();
X nibble[1] = get_byte();
X return (word) (nibble[0] | nibble[1] << 8);
X}
X
Xget_long()
X{
X byte nibble[4];
X nibble[0] = get_byte();
X nibble[1] = get_byte();
X nibble[2] = get_byte();
X nibble[3] = get_byte();
X return (longint) ((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
X
X/* ---------------------------------------------------------- */
X
Xvoid process_local_file_header()
X{
X byte yr, mo, dy; /* parts of a date */
X byte hh, mm, ss; /* parts of a time */
X
X static char *mon[] = /* month abbreviations */
X {
X "Jan", "Feb", "Mar", "Apr",
X "May", "Jun", "Jul", "Aug",
X "Sep", "Oct", "Nov", "Dec"
X };
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 yr = (lrec.last_mod_file_date >> 9) & 0x7f; /* dissect the date */
X mo = (lrec.last_mod_file_date >> 5) & 0x0f;
X dy = lrec.last_mod_file_date & 0x1f;
X
X hh = (lrec.last_mod_file_time >> 11) & 0x1f; /* dissect the time */
X mm = (lrec.last_mod_file_time >> 5) & 0x3f;
X ss = (lrec.last_mod_file_time & 0x1f) * 2;
X
X if (debugging) {
X printf("\n\nProcess LOCAL file header.\n");
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 :");
X printf("%2d:%02d%c\n",
X (hh > 12 ? hh - 12 : hh), mm, (hh > 11 ? 'p' : 'a'));
X printf("Mod date :");
X printf("%2d %3s %02d\n", dy, mon[mo - 1], (yr + 80) % 100);
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 extract_member();
X}
X
X
X/* ---------------------------------------------------------- */
X
Xvoid process_central_file_header()
X{
X central_directory_file_header rec;
X char filename[STRSIZ];
X char extra[STRSIZ];
X
X byte yr, mo, dy; /* parts of a date */
X byte hh, mm, ss; /* parts of a time */
X
X static char *mon[] = /* month abbreviations */
X {
X "Jan", "Feb", "Mar", "Apr",
X "May", "Jun", "Jul", "Aug",
X "Sep", "Oct", "Nov", "Dec"
X };
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
X comment = (byte *) (realloc(comment, rec.file_comment_length));
X get_string(rec.file_comment_length,comment);
X
X yr = (rec.last_mod_file_date >> 9) & 0x7f; /* dissect the date */
X mo = (rec.last_mod_file_date >> 5) & 0x0f;
X dy = rec.last_mod_file_date & 0x1f;
X
X hh = (rec.last_mod_file_time >> 11) & 0x1f; /* dissect the time */
X mm = (rec.last_mod_file_time >> 5) & 0x3f;
X ss = (rec.last_mod_file_time & 0x1f) * 2;
X
X if (debugging) {
X printf("\n\nProcess CENTRAL file header.\n");
X printf("Version made by : %d\n",rec.version_made_by);
X printf("Version used : %d\n",rec.version_needed_to_extract);
X printf("Bit flags : %d\n",rec.general_purpose_bit_flag);
X printf("Compression : %d\n",rec.compression_method);
X printf("Mod time :");
X printf("%2d:%02d%c\n",
X (hh > 12 ? hh - 12 : hh), mm, (hh > 11 ? 'p' : 'a'));
X printf("Mod date :");
X printf("%2d %3s %02d\n", dy, mon[mo - 1], (yr + 80) % 100);
X printf("Crc32 : %d\n",~rec.crc32);
X printf("Compressed size : %d\n",rec.compressed_size);
X printf("Normal file size: %d\n",rec.uncompressed_size);
X printf("File name : %s.%s\n",filename,extra);
X printf("Comment size : %d\n",rec.file_comment_length);
X printf("Disk start # : %d\n",rec.disk_number_start);
X printf("File attributes : %d\n",rec.internal_file_attributes);
X printf("Os attributes : %d\n",rec.external_file_attributes);
X printf("Offset to header: %d\n",rec.relative_offset_local_header);
X printf("Comment : %s\n",comment);
X }
X
X if (list_zip) {
X Total_files++;
X Total_bytes += rec.uncompressed_size;
X Total_length += rec.compressed_size;
X
X printf("%-12s %8d ", filename,rec.uncompressed_size);
X if (verbose) {
X printf("%8d ",rec.compressed_size);
X if (rec.compressed_size)
X printf("%3d%% ",100L - (100L * rec.compressed_size)/
X rec.uncompressed_size);
X else
X printf("--- ");
X }
X
X printf("%2d %3s %02d", dy, mon[mo - 1], (yr + 80) % 100);
X
X if (verbose)
X printf(" %2d:%02d%c",
X (hh > 12 ? hh - 12 : hh), mm, (hh > 11 ? 'p' : 'a'));
X printf("\n");
X }
X
X}
X
X
X/* ---------------------------------------------------------- */
X
Xvoid process_end_central_dir()
X{
X end_central_dir_record rec;
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 comment = (byte *) (realloc(comment, rec.zipfile_comment_length));
X get_string(rec.zipfile_comment_length,comment);
X
X if (debugging) {
X printf("\n\nProcess END_CENTRAL directory header.\n");
X printf("This disk : %d\n",rec.number_this_disk);
X printf("Starting disk : %d\n",
X rec.number_disk_with_start_central_directory);
X printf("Total this disk : %d\n",
X rec.total_entries_central_dir_on_this_disk);
X printf("Total entries : %d\n",rec.total_entries_central_dir);
X printf("Central dir size: %d\n",rec.size_central_directory);
X printf("Offset to dir : %d\n",rec.offset_start_central_directory);
X printf("Comment size : %d\n",rec.zipfile_comment_length);
X printf("Comment : %s\n",comment);
X }
X}
X
X
X/* ---------------------------------------------------------- */
X
Xvoid process_headers()
X{
X int i;
X char sig[4];
X
X if (list_zip) {
X if (verbose) {
X printf("\nName Length Size now SF Date Time");
X printf("\n============ ======== ======== ==== ========= ========\n");
X } else {
X printf("\nName Length Date");
X printf("\n============ ======== =========\n");
X }
X }
X
X while (1)
X {
X for (i=0; i<4; i++) /* Read the ZIP file sig */
X sig[i] = get_byte();
X
X if (strncmp(sig,local_file_header_signature,4) == 0)
X process_local_file_header();
X else
X if (strncmp(sig,central_file_header_signature,4) == 0)
X process_central_file_header();
X else
X if (strncmp(sig,end_central_dir_signature,4) == 0)
X {
X process_end_central_dir();
X if (test_zip) {
X if (numbad < 1)
X printf("No errors detected\n");
X else
X if (numbad == 1)
X printf("One error detected\n");
X else
X printf("%d errors detected\n",numbad);
X }
X if (list_zip) {
X if (verbose) {
X printf(" ==== ======== ======== ==== \n");
X printf("Total: %4d %8d %8d ",
X Total_files,Total_bytes,Total_length);
X if (Total_length)
X printf("%3d%%\n", 100 - (100 * Total_length)/
X Total_bytes);
X else
X printf("---\n");
X } else {
X printf(" ==== ========\n");
X printf("Total: %4d %8d\n",
X Total_files,Total_bytes);
X }
X }
X if (strlen(comment))
X printf("%s\n",comment);
X return;
X }
X else
X {
X printf("Invalid Zipfile Header\n");
X return;
X }
X }
X}
X
X
X
X/* ---------------------------------------------------------- */
X
Xvoid extract_zipfile()
X{
X /*
X * open the zipfile for reading and in BINARY mode to prevent cr/lf
X * translation, which would corrupt the bitstreams
X */
X
X if (open_input_file())
X exit(1);
X
X process_headers();
X
X close(zipfd);
X}
X
X
X/* ---------------------------------------------------------- */
X/*
X * main program
X *
X */
X
Xvoid main(argc, argv)
Xint argc;
Xchar **argv;
X{
X
X#ifdef USE_GETOPT
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 while ((c = getopt (argc, argv, "dltv")) != EOF)
X {
X switch (c) {
X case 'd': debugging++; break;
X case 'l': list_zip =1;extract =0; break;
X case 't': test_zip =1;extract =0; break;
X case 'v': verbose++; break;
X default: short_help();
X }
X }
X
X strcpy(zipfn,argv[optind]);
X if (strlen(zipfn) == 0)
X long_help();
X
X /* .ZIP default if none provided by user */
X if (strchr(zipfn,'.') == NULL)
X strcat(zipfn,".zip");
X#else
X if (argc != 2)
X long_help();
X
X /* .ZIP default if none provided by user */
X strcpy(zipfn, argv[1]);
X if (strchr(zipfn, '.') == NULL)
X strcat(zipfn, ".zip");
X#endif
X
X /* allocate i/o buffers */
X inbuf = (byte *) (malloc(INBUFSIZ));
X outbuf = (byte *) (malloc(OUTBUFSIZ));
X comment = (byte *) (malloc(STRSIZ));
X if ((inbuf == NULL) || (outbuf == NULL) || (comment == NULL)) {
X printf("Can't allocate buffers!\n");
X exit(1);
X }
X
X /* do the job... */
X extract_zipfile();
X exit(0);
X}
X
Xlong_help()
X{
Xprintf("\nUnZip: Zipfile Extract Version:%s Patchlevel:%d",VERSION,PATCH);
Xprintf("; (C) 1989 Samuel H. Smith\n");
Xprintf("Courtesy of: S.H.Smith and The Tool Shop BBS, (602) 279-2673.");
Xprintf("\n\n");
Xprintf("UNIX mods by: Michael Enkelis\n\n");
Xprintf("You may copy and distribute this program freely, provided that:\n");
Xprintf(" 1) No fee is charged for such copying and distribution, and\n");
Xprintf(" 2) It is distributed ONLY in its original, unmodified state.");
Xprintf("\n\n");
Xprintf("If you wish to distribute a modified version of this program, you MUST\n");
Xprintf("include the source code.\n\n");
Xprintf("If you modify this program, I would appreciate a copy of the new source\n");
Xprintf("code. I am holding the copyright on the source code, so please don't\n");
Xprintf("delete my name from the program files or from the documentation.\n\n");
Xprintf("IN NO EVENT WILL I BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING ANY LOST\n");
Xprintf("PROFITS, LOST SAVINGS OR OTHER INCIDENTAL OR CONSEQUENTIAL DAMAGES\n");
Xprintf("ARISING OUT OF YOUR USE OR INABILITY TO USE THE PROGRAM, OR FOR ANY\n");
Xprintf("CLAIM BY ANY OTHER PARTY.\n\n");
Xshort_help();
Xexit(1);
X}
X
Xshort_help()
X{
X printf("Usage: UnZip -hltv FILE[.zip]\n\n");
X printf(" -h This help listing.\n");
X printf(" -l List zip archive.\n");
X printf(" -t Test zip archive.\n");
X printf(" -v Verbose output.\n\n");
X exit(1);
X}
SHAR_EOF
if test 30392 -ne "`wc -c < 'unzipbsd.c'`"
then
echo shar: error transmitting "'unzipbsd.c'" '(should have been 30392 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'crc32.c'" '(7120 characters)'
if test -f 'crc32.c'
then
echo shar: will not over-write existing file "'crc32.c'"
else
sed 's/^ X//' << \SHAR_EOF > 'crc32.c'
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 /* 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
Xlong crc_32_tab[] = {
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 };
X
X/* ------------------------------------------------------------- */
X
Xextern long crc32val;
X
Xvoid UpdateCRC(s, len)
Xregister char *s;
Xregister int len;
X /* update running CRC calculation with contents of a buffer */
X{
X int i;
X for (i = 0; i < len; i ++) {
X crc32val = crc_32_tab[(int) ((crc32val) ^ (s[i])) & 0xff] ^
X (((crc32val) >> 8) & 0x00FFFFFFL);
X }
X}
SHAR_EOF
if test 7120 -ne "`wc -c < 'crc32.c'`"
then
echo shar: error transmitting "'crc32.c'" '(should have been 7120 characters)'
fi
fi # end of overwriting check
# End of shell archive
exit 0
--
_ _ _ __
' ) ) ) / /) / ` / /) Michael Enkelis
/ / / o _. /_ __. _ // /-- __ /_ _ // o _ tektronix!vice!michaele
/ ' (_(_(__/ /_(_(_(<_(/_ (___, /) )_/ <_(<_(/_(_/_)_ (503) 627-4099
More information about the Alt.sources
mailing list