home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PROGRAMS / UTILS / COMPRESS / UNZIP12.ZIP / UNZIP.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-03-15  |  22.7 KB  |  970 lines

  1.  
  2. /*
  3.  * Copyright 1989 Samuel H. Smith;  All rights reserved
  4.  *
  5.  * Do not distribute modified versions without my permission.
  6.  * Do not remove or alter this notice or any other copyright notice.
  7.  * If you use this in your own program you must distribute source code.
  8.  * Do not use any of this in a commercial product.
  9.  *
  10.  */
  11.  
  12. /*
  13.  * UnZip - A simple zipfile extract utility
  14.  *
  15.  * To compile:
  16.  *      tcc -B -O -Z -G -mc unzip.c        ;turbo C 2.0, compact model
  17.  *
  18.  */
  19.  
  20. #define VERSION  "UnZip:  Zipfile Extract v1.2 of 03-15-89;  (C) 1989 Samuel H. Smith"
  21.  
  22. typedef unsigned char byte;    /* code assumes UNSIGNED bytes */
  23. typedef long longint;
  24. typedef unsigned word;
  25. typedef char boolean;
  26.  
  27. #define STRSIZ 256
  28.  
  29. #include <stdio.h>
  30.  /* this is your standard header for all C compiles */
  31.  
  32. #include <stdlib.h>
  33.  /* this include defines various standard library prototypes */
  34.  
  35.  
  36. /*
  37.  * SEE HOST OPERATING SYSTEM SPECIFICS SECTION STARTING NEAR LINE 180
  38.  *
  39.  */
  40.  
  41.  
  42. /* ----------------------------------------------------------- */
  43. /*
  44.  * Zipfile layout declarations
  45.  *
  46.  */
  47.  
  48. typedef longint signature_type;
  49.  
  50.  
  51. #define LOCAL_FILE_HEADER_SIGNATURE  0x04034b50L
  52.  
  53.  
  54. typedef struct local_file_header {
  55.     word version_needed_to_extract;
  56.     word general_purpose_bit_flag;
  57.     word compression_method;
  58.     word last_mod_file_time;
  59.     word last_mod_file_date;
  60.     longint crc32;
  61.     longint compressed_size;
  62.     longint uncompressed_size;
  63.     word filename_length;
  64.     word extra_field_length;
  65. } local_file_header;
  66.  
  67.  
  68. #define CENTRAL_FILE_HEADER_SIGNATURE  0x02014b50L
  69.  
  70.  
  71. typedef struct central_directory_file_header {
  72.     word version_made_by;
  73.     word version_needed_to_extract;
  74.     word general_purpose_bit_flag;
  75.     word compression_method;
  76.     word last_mod_file_time;
  77.     word last_mod_file_date;
  78.     longint crc32;
  79.     longint compressed_size;
  80.     longint uncompressed_size;
  81.     word filename_length;
  82.     word extra_field_length;
  83.     word file_comment_length;
  84.     word disk_number_start;
  85.     word internal_file_attributes;
  86.     longint external_file_attributes;
  87.     longint relative_offset_local_header;
  88. } central_directory_file_header;
  89.  
  90.  
  91. #define END_CENTRAL_DIR_SIGNATURE  0x06054b50L
  92.  
  93.  
  94. typedef struct end_central_dir_record {
  95.     word number_this_disk;
  96.     word number_disk_with_start_central_directory;
  97.     word total_entries_central_dir_on_this_disk;
  98.     word total_entries_central_dir;
  99.     longint size_central_directory;
  100.     longint offset_start_central_directory;
  101.     word zipfile_comment_length;
  102. } end_central_dir_record;
  103.  
  104.  
  105.  
  106. /* ----------------------------------------------------------- */
  107. /*
  108.  * input file variables
  109.  *
  110.  */
  111.  
  112. #define INBUFSIZ 0x2000
  113. byte *inbuf;            /* input file buffer - any size is legal */
  114. byte *inptr;
  115.  
  116. int incnt;
  117. unsigned bitbuf;
  118. int bits_left;
  119. boolean zipeof;
  120.  
  121. int zipfd;
  122. char zipfn[STRSIZ];
  123. local_file_header lrec;
  124.  
  125.  
  126. /* ----------------------------------------------------------- */
  127. /*
  128.  * output stream variables
  129.  *
  130.  */
  131.  
  132. #define OUTBUFSIZ 0x6000
  133. byte *outbuf;                   /* buffer for rle look-back */
  134. byte *outptr;
  135.  
  136. longint outpos;            /* absolute position in outfile */
  137. int outcnt;            /* current position in outbuf */
  138.  
  139. int outfd;
  140. char filename[STRSIZ];
  141. char extra[STRSIZ];
  142.  
  143. #define DLE 144
  144.  
  145.  
  146. /* ----------------------------------------------------------- */
  147. /*
  148.  * shrink/reduce working storage
  149.  *
  150.  */
  151.  
  152. int factor;
  153. byte followers[256][64];
  154. byte Slen[256];
  155.  
  156. #define max_bits 13
  157. #define init_bits 9
  158. #define hsize 8192
  159. #define first_ent 257
  160. #define clear 256
  161.  
  162. typedef int hsize_array_integer[hsize+1];
  163. typedef byte hsize_array_byte[hsize+1];
  164.  
  165. hsize_array_integer prefix_of;
  166. hsize_array_byte suffix_of;
  167. hsize_array_byte stack;
  168.  
  169. int codesize;
  170. int maxcode;
  171. int free_ent;
  172. int maxcodemax;
  173. int offset;
  174. int sizex;
  175.  
  176.  
  177.  
  178. /* ============================================================= */
  179. /*
  180.  * Host operating system details
  181.  *
  182.  */
  183.  
  184. #include <string.h>
  185.  /* this include defines strcpy, strcmp, etc. */
  186.  
  187. #include <io.h>
  188.  /*
  189.   * this include file defines
  190.   *             struct ftime ...        (* file time/date stamp info *)
  191.   *             int setftime (int handle, struct ftime *ftimep);
  192.   *             #define SEEK_CUR  1     (* lseek() modes *)
  193.   *             #define SEEK_END  2
  194.   *             #define SEEK_SET  0
  195.   */
  196.  
  197. #include <fcntl.h>
  198.  /*
  199.   * this include file defines
  200.   *             #define O_BINARY 0x8000  (* no cr-lf translation *)
  201.   * as used in the open() standard function
  202.   */
  203.  
  204. #include <sys/stat.h>
  205.  /*
  206.   * this include file defines
  207.   *             #define S_IREAD 0x0100  (* owner may read *)
  208.   *             #define S_IWRITE 0x0080 (* owner may write *)
  209.   * as used in the creat() standard function
  210.   */
  211.  
  212. #undef HIGH_LOW
  213.  /*
  214.   * change 'undef' to 'define' if your machine stores high order bytes in
  215.   * lower addresses.
  216.   */
  217.  
  218. void set_file_time(void)
  219.  /*
  220.   * set the output file date/time stamp according to information from the
  221.   * zipfile directory record for this file 
  222.   */
  223. {
  224.     union {
  225.                 struct ftime ft;        /* system file time record */
  226.         struct {
  227.                         word ztime;     /* date and time words */
  228.                         word zdate;     /* .. same format as in .ZIP file */
  229.         } zt;
  230.     } td;
  231.  
  232.     /*
  233.      * set output file date and time - this is optional and can be
  234.      * deleted if your compiler does not easily support setftime() 
  235.      */
  236.  
  237.     td.zt.ztime = lrec.last_mod_file_time;
  238.     td.zt.zdate = lrec.last_mod_file_date;
  239.  
  240.     setftime(outfd, &td.ft);
  241. }
  242.  
  243.  
  244. int create_output_file(void)
  245.  /* return non-0 if creat failed */
  246. {
  247.     /* create the output file with READ and WRITE permissions */
  248.     outfd = creat(filename, S_IWRITE | S_IREAD);
  249.     if (outfd < 1) {
  250.         printf("Can't create output: %s\n", filename);
  251.         return 1;
  252.     }
  253.  
  254.     /*
  255.      * close the newly created file and reopen it in BINARY mode to
  256.      * disable all CR/LF translations 
  257.      */
  258.     close(outfd);
  259.     outfd = open(filename, O_RDWR | O_BINARY);
  260.  
  261.     /* write a single byte at EOF to pre-allocate the file */
  262.         lseek(outfd, lrec.uncompressed_size - 1L, SEEK_SET);
  263.     write(outfd, "?", 1);
  264.     lseek(outfd, 0L, SEEK_SET);
  265.     return 0;
  266. }
  267.  
  268.  
  269. int open_input_file(void)
  270.  /* return non-0 if creat failed */
  271. {
  272.     /*
  273.      * open the zipfile for reading and in BINARY mode to prevent cr/lf
  274.      * translation, which would corrupt the bitstreams 
  275.      */
  276.  
  277.     zipfd = open(zipfn, O_RDONLY | O_BINARY);
  278.     if (zipfd < 1) {
  279.         printf("Can't open input file: %s\n", zipfn);
  280.         return (1);
  281.     }
  282.     return 0;
  283. }
  284.  
  285.  
  286. #ifdef HIGH_LOW
  287.  
  288. void swap_bytes(word *wordp)
  289.  /* convert intel style 'short int' variable to host format */
  290. {
  291.     char *charp = (char *) wordp;
  292.     char temp;
  293.  
  294.     temp = charp[0];
  295.     charp[0] = charp[1];
  296.     charp[1] = temp;
  297. }
  298.  
  299. void swap_lbytes(longint *longp)
  300.  /* convert intel style 'long' variable to host format */
  301. {
  302.     char *charp = (char *) longp;
  303.     char temp[4];
  304.  
  305.     temp[3] = charp[0];
  306.     temp[2] = charp[1];
  307.     temp[1] = charp[2];
  308.     temp[0] = charp[3];
  309.  
  310.     charp[0] = temp[0];
  311.     charp[1] = temp[1];
  312.     charp[2] = temp[2];
  313.     charp[3] = temp[3];
  314. }
  315.  
  316. #endif
  317.  
  318.  
  319.  
  320. /* ============================================================= */
  321.  
  322. int FillBuffer(void)
  323.  /* fill input buffer if possible */
  324. {
  325.     int readsize;
  326.  
  327.         if (lrec.compressed_size <= 0)
  328.         return incnt = 0;
  329.  
  330.         if (lrec.compressed_size > INBUFSIZ)
  331.         readsize = INBUFSIZ;
  332.     else
  333.                 readsize = (int) lrec.compressed_size;
  334.     incnt = read(zipfd, inbuf, readsize);
  335.  
  336.         lrec.compressed_size -= incnt;
  337.     inptr = inbuf;
  338.     return incnt--;
  339. }
  340.  
  341. int ReadByte(unsigned *x)
  342.  /* read a byte; return 8 if byte available, 0 if not */
  343. {
  344.     if (incnt-- == 0)
  345.         if (FillBuffer() == 0)
  346.             return 0;
  347.  
  348.     *x = *inptr++;
  349.     return 8;
  350. }
  351.  
  352.  
  353. /* ------------------------------------------------------------- */
  354. static unsigned mask_bits[] =
  355.         {0,     0x0001, 0x0003, 0x0007, 0x000f,
  356.                 0x001f, 0x003f, 0x007f, 0x00ff,
  357.                 0x01ff, 0x03ff, 0x07ff, 0x0fff,
  358.                 0x1fff, 0x3fff, 0x7fff, 0xffff
  359.         };
  360.  
  361.  
  362. int FillBitBuffer(register int bits)
  363. {
  364.     /* get the bits that are left and read the next word */
  365.     unsigned temp;
  366.         register int result = bitbuf;
  367.     int sbits = bits_left;
  368.     bits -= bits_left;
  369.  
  370.     /* read next word of input */
  371.     bits_left = ReadByte(&bitbuf);
  372.     bits_left += ReadByte(&temp);
  373.     bitbuf |= (temp << 8);
  374.     if (bits_left == 0)
  375.         zipeof = 1;
  376.  
  377.     /* get the remaining bits */
  378.         result = result | (int) ((bitbuf & mask_bits[bits]) << sbits);
  379.         bitbuf >>= bits;
  380.         bits_left -= bits;
  381.         return result;
  382. }
  383.  
  384. #define READBIT(nbits,zdest) { if (nbits <= bits_left) { zdest = (int)(bitbuf & mask_bits[nbits]); bitbuf >>= nbits; bits_left -= nbits; } else zdest = FillBitBuffer(nbits);}
  385.  
  386. /*
  387.  * macro READBIT(nbits,zdest)
  388.  *  {
  389.  *      if (nbits <= bits_left) {
  390.  *          zdest = (int)(bitbuf & mask_bits[nbits]);
  391.  *          bitbuf >>= nbits;
  392.  *          bits_left -= nbits;
  393.  *      } else
  394.  *          zdest = FillBitBuffer(nbits);
  395.  *  }
  396.  *
  397.  */
  398.  
  399.  
  400. /* ------------------------------------------------------------- */
  401.  
  402. #include "crc32.h"
  403.  
  404.  
  405. /* ------------------------------------------------------------- */
  406.  
  407. void FlushOutput(void)
  408.  /* flush contents of output buffer */
  409. {
  410.     UpdateCRC(outbuf, outcnt);
  411.     write(outfd, outbuf, outcnt);
  412.     outpos += outcnt;
  413.     outcnt = 0;
  414.     outptr = outbuf;
  415. }
  416.  
  417. #define OUTB(intc) { *outptr++=intc; if (++outcnt==OUTBUFSIZ) FlushOutput(); }
  418.  
  419. /*
  420.  *  macro OUTB(intc)
  421.  *  {
  422.  *      *outptr++=intc;
  423.  *      if (++outcnt==OUTBUFSIZ)
  424.  *          FlushOutput();
  425.  *  }
  426.  *
  427.  */
  428.  
  429.  
  430. /* ----------------------------------------------------------- */
  431.  
  432. void LoadFollowers(void)
  433. {
  434.         register int x;
  435.         register int i;
  436.  
  437.     for (x = 255; x >= 0; x--) {
  438.                 READBIT(6,Slen[x]);
  439.         for (i = 0; i < Slen[x]; i++) {
  440.                         READBIT(8,followers[x][i]);
  441.         }
  442.     }
  443. }
  444.  
  445.  
  446. /* ----------------------------------------------------------- */
  447. /*
  448.  * The Reducing algorithm is actually a combination of two
  449.  * distinct algorithms.  The first algorithm compresses repeated
  450.  * byte sequences, and the second algorithm takes the compressed
  451.  * stream from the first algorithm and applies a probabilistic
  452.  * compression method.
  453.  */
  454.  
  455. int L_table[] = {0, 0x7f, 0x3f, 0x1f, 0x0f};
  456.  
  457. int D_shift[] = {0, 0x07, 0x06, 0x05, 0x04};
  458. int D_mask[]  = {0, 0x01, 0x03, 0x07, 0x0f};
  459.  
  460. int B_table[] = {8, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5,
  461.          5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6,
  462.          6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  463.          6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7,
  464.          7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  465.          7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  466.          7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  467.          7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  468.          8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  469.          8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  470.          8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  471.          8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  472.          8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  473.          8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  474.          8, 8, 8, 8};
  475.  
  476. /* ----------------------------------------------------------- */
  477.  
  478. void unReduce(void)
  479.  /* expand probablisticly reduced data */
  480. {
  481.         register int lchar;
  482.         int nchar;
  483.         int ExState;
  484.         int V;
  485.         int Len;
  486.  
  487.         factor = lrec.compression_method - 1;
  488.     ExState = 0;
  489.     lchar = 0;
  490.     LoadFollowers();
  491.  
  492.         while (((outpos + outcnt) < lrec.uncompressed_size) && (!zipeof)) {
  493.         if (Slen[lchar] == 0)
  494.                         READBIT(8,nchar)      /* ; */
  495.                 else
  496.         {
  497.                         READBIT(1,nchar);
  498.                         if (nchar != 0)
  499.                                 READBIT(8,nchar)      /* ; */
  500.                         else
  501.             {
  502.                                 int follower;
  503.                                 int bitsneeded = B_table[Slen[lchar]];
  504.                                 READBIT(bitsneeded,follower);
  505.                                 nchar = followers[lchar][follower];
  506.             }
  507.         }
  508.  
  509.         /* expand the resulting byte */
  510.         switch (ExState) {
  511.  
  512.         case 0:
  513.                         if (nchar != DLE)
  514.                                 OUTB(nchar) /*;*/
  515.             else
  516.                 ExState = 1;
  517.             break;
  518.  
  519.         case 1:
  520.                         if (nchar != 0) {
  521.                                 V = nchar;
  522.                 Len = V & L_table[factor];
  523.                 if (Len == L_table[factor])
  524.                     ExState = 2;
  525.                 else
  526.                     ExState = 3;
  527.             }
  528.             else {
  529.                                 OUTB(DLE);
  530.                 ExState = 0;
  531.             }
  532.             break;
  533.  
  534.                 case 2: {
  535.                                 Len += nchar;
  536.                 ExState = 3;
  537.             }
  538.             break;
  539.  
  540.                 case 3: {
  541.                 register int i = Len + 3;
  542.                 int offset = (((V >> D_shift[factor]) &
  543.                                           D_mask[factor]) << 8) + nchar + 1;
  544.                 longint op = outpos + outcnt - offset;
  545.  
  546.                 /* special case- before start of file */
  547.                 while ((op < 0L) && (i > 0)) {
  548.                     OUTB(0);
  549.                     op++;
  550.                     i--;
  551.                 }
  552.  
  553.                 /* normal copy of data from output buffer */
  554.                 {
  555.                     register int ix = (int) (op % OUTBUFSIZ);
  556.  
  557.                                         /* do a block memory copy if possible */
  558.                                         if ( ((ix    +i) < OUTBUFSIZ) &&
  559.                                              ((outcnt+i) < OUTBUFSIZ) ) {
  560.                                                 memcpy(outptr,&outbuf[ix],i);
  561.                                                 outptr += i;
  562.                                                 outcnt += i;
  563.                                         }
  564.  
  565.                                         /* otherwise copy byte by byte */
  566.                                         else while (i--) {
  567.                                                 OUTB(outbuf[ix]);
  568.                                                 if (++ix >= OUTBUFSIZ)
  569.                                                         ix = 0;
  570.                                         }
  571.                                 }
  572.  
  573.                 ExState = 0;
  574.             }
  575.             break;
  576.         }
  577.  
  578.                 /* store character for next iteration */
  579.                 lchar = nchar;
  580.         }
  581. }
  582.  
  583.  
  584. /* ------------------------------------------------------------- */
  585. /*
  586.  * Shrinking is a Dynamic Ziv-Lempel-Welch compression algorithm
  587.  * with partial clearing.
  588.  *
  589.  */
  590.  
  591. void partial_clear(void)
  592. {
  593.         register int pr;
  594.         register int cd;
  595.  
  596.     /* mark all nodes as potentially unused */
  597.     for (cd = first_ent; cd < free_ent; cd++)
  598.         prefix_of[cd] |= 0x8000;
  599.  
  600.     /* unmark those that are used by other nodes */
  601.     for (cd = first_ent; cd < free_ent; cd++) {
  602.         pr = prefix_of[cd] & 0x7fff;    /* reference to another node? */
  603.                 if (pr >= first_ent)            /* flag node as referenced */
  604.             prefix_of[pr] &= 0x7fff;
  605.     }
  606.  
  607.     /* clear the ones that are still marked */
  608.     for (cd = first_ent; cd < free_ent; cd++)
  609.         if ((prefix_of[cd] & 0x8000) != 0)
  610.             prefix_of[cd] = -1;
  611.  
  612.     /* find first cleared node as next free_ent */
  613.         cd = first_ent;
  614.         while ((cd < maxcodemax) && (prefix_of[cd] != -1))
  615.                 cd++;
  616.         free_ent = cd;
  617. }
  618.  
  619.  
  620. /* ------------------------------------------------------------- */
  621.  
  622. void unShrink(void)
  623. {
  624.         #define  GetCode(dest) READBIT(codesize,dest)
  625.  
  626.     register int code;
  627.     register int stackp;
  628.     int finchar;
  629.     int oldcode;
  630.     int incode;
  631.  
  632.  
  633.     /* decompress the file */
  634.     maxcodemax = 1 << max_bits;
  635.     codesize = init_bits;
  636.     maxcode = (1 << codesize) - 1;
  637.     free_ent = first_ent;
  638.     offset = 0;
  639.     sizex = 0;
  640.  
  641.     for (code = maxcodemax; code > 255; code--)
  642.         prefix_of[code] = -1;
  643.  
  644.     for (code = 255; code >= 0; code--) {
  645.         prefix_of[code] = 0;
  646.         suffix_of[code] = code;
  647.     }
  648.  
  649.     GetCode(oldcode);
  650.     if (zipeof)
  651.         return;
  652.     finchar = oldcode;
  653.  
  654.         OUTB(finchar);
  655.  
  656.         stackp = hsize;
  657.  
  658.     while (!zipeof) {
  659.         GetCode(code);
  660.         if (zipeof)
  661.             return;
  662.  
  663.         while (code == clear) {
  664.             GetCode(code);
  665.             switch (code) {
  666.  
  667.             case 1:{
  668.                     codesize++;
  669.                     if (codesize == max_bits)
  670.                         maxcode = maxcodemax;
  671.                     else
  672.                         maxcode = (1 << codesize) - 1;
  673.                 }
  674.                 break;
  675.  
  676.             case 2:
  677.                 partial_clear();
  678.                 break;
  679.             }
  680.  
  681.             GetCode(code);
  682.             if (zipeof)
  683.                 return;
  684.         }
  685.  
  686.  
  687.         /* special case for KwKwK string */
  688.         incode = code;
  689.         if (prefix_of[code] == -1) {
  690.                         stack[--stackp] = finchar;
  691.             code = oldcode;
  692.         }
  693.  
  694.  
  695.         /* generate output characters in reverse order */
  696.         while (code >= first_ent) {
  697.                         stack[--stackp] = suffix_of[code];
  698.             code = prefix_of[code];
  699.         }
  700.  
  701.         finchar = suffix_of[code];
  702.                 stack[--stackp] = finchar;
  703.  
  704.  
  705.                 /* and put them out in forward order, block copy */
  706.                 if ((hsize-stackp+outcnt) < OUTBUFSIZ) {
  707.                         memcpy(outptr,&stack[stackp],hsize-stackp);
  708.                         outptr += hsize-stackp;
  709.                         outcnt += hsize-stackp;
  710.                         stackp = hsize;
  711.                 }
  712.  
  713.                 /* output byte by byte if we can't go by blocks */
  714.                 else while (stackp < hsize)
  715.                         OUTB(stack[stackp++]);
  716.  
  717.  
  718.         /* generate new entry */
  719.         code = free_ent;
  720.         if (code < maxcodemax) {
  721.             prefix_of[code] = oldcode;
  722.             suffix_of[code] = finchar;
  723.  
  724.             do
  725.                 code++;
  726.             while ((code < maxcodemax) && (prefix_of[code] != -1));
  727.  
  728.             free_ent = code;
  729.         }
  730.  
  731.         /* remember previous code */
  732.         oldcode = incode;
  733.     }
  734.  
  735. }
  736.  
  737.  
  738. /* ---------------------------------------------------------- */
  739.  
  740. void extract_member(void)
  741. {
  742.     unsigned b;
  743.  
  744.     bits_left = 0;
  745.     bitbuf = 0;
  746.     incnt = 0;
  747.     outpos = 0L;
  748.     outcnt = 0;
  749.     outptr = outbuf;
  750.     zipeof = 0;
  751.     crc32val = 0xFFFFFFFFL;
  752.  
  753.  
  754.     /* create the output file with READ and WRITE permissions */
  755.     if (create_output_file())
  756.         exit(1);
  757.  
  758.         switch (lrec.compression_method) {
  759.  
  760.     case 0:        /* stored */
  761.         {
  762.             printf(" Extracting: %-12s ", filename);
  763.             while (ReadByte(&b))
  764.                 OUTB(b);
  765.         }
  766.         break;
  767.  
  768.         case 1: {
  769.             printf("UnShrinking: %-12s ", filename);
  770.             unShrink();
  771.         }
  772.         break;
  773.  
  774.     case 2:
  775.     case 3:
  776.     case 4:
  777.         case 5: {
  778.             printf("  Expanding: %-12s ", filename);
  779.             unReduce();
  780.         }
  781.         break;
  782.  
  783.     default:
  784.         printf("Unknown compression method.");
  785.     }
  786.  
  787.  
  788.     /* write the last partial buffer, if any */
  789.     if (outcnt > 0) {
  790.         UpdateCRC(outbuf, outcnt);
  791.         write(outfd, outbuf, outcnt);
  792.     }
  793.  
  794.     /* set output file date and time */
  795.     set_file_time();
  796.  
  797.     close(outfd);
  798.  
  799.     crc32val = -1 - crc32val;
  800.         if (crc32val != lrec.crc32)
  801.                 printf(" Bad CRC %08lx  (should be %08lx)", lrec.crc32, crc32val);
  802.  
  803.     printf("\n");
  804. }
  805.  
  806.  
  807. /* ---------------------------------------------------------- */
  808.  
  809. void get_string(int len,
  810.                 char *s)
  811. {
  812.     read(zipfd, s, len);
  813.     s[len] = 0;
  814. }
  815.  
  816.  
  817. /* ---------------------------------------------------------- */
  818.  
  819. void process_local_file_header(void)
  820. {
  821.     read(zipfd, &lrec, sizeof(lrec));
  822.  
  823. #ifdef HIGH_LOW
  824.     swap_bytes(&lrec.filename_length);
  825.     swap_bytes(&lrec.extra_field_length);
  826.     swap_lbytes(&lrec.compressed_size);
  827.     swap_lbytes(&lrec.uncompressed_size);
  828.     swap_bytes(&lrec.compression_method);
  829. #endif
  830.  
  831.     get_string(lrec.filename_length, filename);
  832.     get_string(lrec.extra_field_length, extra);
  833.     extract_member();
  834. }
  835.  
  836.  
  837. /* ---------------------------------------------------------- */
  838.  
  839. void process_central_file_header(void)
  840. {
  841.     central_directory_file_header rec;
  842.     char filename[STRSIZ];
  843.     char extra[STRSIZ];
  844.     char comment[STRSIZ];
  845.  
  846.     read(zipfd, &rec, sizeof(rec));
  847.  
  848. #ifdef HIGH_LOW
  849.     swap_bytes(&rec.filename_length);
  850.     swap_bytes(&rec.extra_field_length);
  851.     swap_bytes(&rec.file_comment_length);
  852. #endif
  853.  
  854.         get_string(rec.filename_length, filename);
  855.     get_string(rec.extra_field_length, extra);
  856.     get_string(rec.file_comment_length, comment);
  857. }
  858.  
  859.  
  860. /* ---------------------------------------------------------- */
  861.  
  862. void process_end_central_dir(void)
  863. {
  864.     end_central_dir_record rec;
  865.     char comment[STRSIZ];
  866.  
  867.     read(zipfd, &rec, sizeof(rec));
  868.  
  869. #ifdef HIGH_LOW
  870.     swap_bytes(&rec.zipfile_comment_length);
  871. #endif
  872.  
  873.     get_string(rec.zipfile_comment_length, comment);
  874. }
  875.  
  876.  
  877. /* ---------------------------------------------------------- */
  878.  
  879. void process_headers(void)
  880. {
  881.     longint sig;
  882.  
  883.     while (1) {
  884.         if (read(zipfd, &sig, sizeof(sig)) != sizeof(sig))
  885.             return;
  886.  
  887. #ifdef HIGH_LOW
  888.         swap_lbytes(&sig);
  889. #endif
  890.  
  891.                 if (sig == LOCAL_FILE_HEADER_SIGNATURE)
  892.             process_local_file_header();
  893.                 else if (sig == CENTRAL_FILE_HEADER_SIGNATURE)
  894.             process_central_file_header();
  895.                 else if (sig == END_CENTRAL_DIR_SIGNATURE) {
  896.             process_end_central_dir();
  897.             return;
  898.         }
  899.                 else {
  900.             printf("Invalid Zipfile Header\n");
  901.             return;
  902.         }
  903.     }
  904.  
  905. }
  906.  
  907.  
  908. /* ---------------------------------------------------------- */
  909.  
  910. void extract_zipfile(void)
  911. {
  912.     /*
  913.      * open the zipfile for reading and in BINARY mode to prevent cr/lf
  914.      * translation, which would corrupt the bitstreams 
  915.      */
  916.  
  917.     if (open_input_file())
  918.         exit(1);
  919.  
  920.     process_headers();
  921.  
  922.     close(zipfd);
  923. }
  924.  
  925.  
  926. /* ---------------------------------------------------------- */
  927. /*
  928.  * main program
  929.  *
  930.  */
  931.  
  932. void main(int argc, char **argv)
  933. {
  934.     if (argc != 2) {
  935.                 printf("\n%s\nCourtesy of:  S.H.Smith  and  The Tool Shop BBS,  (602) 279-2673.\n\n",VERSION);
  936.         printf("You may copy and distribute this program freely, provided that:\n");
  937.         printf("    1)   No fee is charged for such copying and distribution, and\n");
  938.         printf("    2)   It is distributed ONLY in its original, unmodified state.\n\n");
  939.         printf("If you wish to distribute a modified version of this program, you MUST\n");
  940.         printf("include the source code.\n\n");
  941.         printf("If you modify this program, I would appreciate a copy of the  new source\n");
  942.         printf("code.   I am holding the copyright on the source code, so please don't\n");
  943.         printf("delete my name from the program files or from the documentation.\n\n");
  944.                 printf("IN NO EVENT WILL I BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING ANY LOST\n");
  945.                 printf("PROFITS, LOST SAVINGS OR OTHER INCIDENTAL OR CONSEQUENTIAL DAMAGES\n");
  946.                 printf("ARISING OUT OF YOUR USE OR INABILITY TO USE THE PROGRAM, OR FOR ANY\n");
  947.                 printf("CLAIM BY ANY OTHER PARTY.\n\n");
  948.                 printf("Usage:  UnZip FILE[.zip]\n");
  949.                 exit(1);
  950.     }
  951.  
  952.     /* .ZIP default if none provided by user */
  953.     strcpy(zipfn, argv[1]);
  954.     if (strchr(zipfn, '.') == NULL)
  955.         strcat(zipfn, ".ZIP");
  956.  
  957.         /* allocate i/o buffers */
  958.     inbuf = (byte *) (malloc(INBUFSIZ));
  959.     outbuf = (byte *) (malloc(OUTBUFSIZ));
  960.     if ((inbuf == NULL) || (outbuf == NULL)) {
  961.         printf("Can't allocate buffers!\n");
  962.         exit(1);
  963.     }
  964.  
  965.         /* do the job... */
  966.         extract_zipfile();
  967.     exit(0);
  968. }
  969.  
  970.