home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 December / simtel1292_SIMTEL_1292_Walnut_Creek.iso / msdos / opus / fvsrc620.arc / UNZIP.C < prev    next >
C/C++ Source or Header  |  1989-05-26  |  16KB  |  570 lines

  1. /*--------------------------------------------------------------------------*/
  2. /*                                                                          */
  3. /* Copyright 1989, Doug Boone.  FidoNet 119/5                               */
  4. /*                              (916) 893-9019 Data                         */
  5. /*                              (916) 891-0748 voice                        */
  6. /*                              P.O. Box 5108, Chico, CA. 95928             */
  7. /*                                                                          */
  8. /* This program is not for sale. It is for the free use with Opus systems.  */
  9. /* You may not sell it in ANY way. If you have an access charge to your     */
  10. /* Bulletin Board, consider this to be like Opus, you can ONLY make it      */
  11. /* available for download in an open area, where non-members can get access */
  12. /*                                                                          */
  13. /* If you need to modify this source code, please send me a copy of the     */
  14. /* changes you've made so that everyone can share in the updates.           */
  15. /*                                                                          */
  16. /* "Don't rip me off!" -- Tom Jennings, FidoNet's founder                   */
  17. /*                                                                          */
  18. /*--------------------------------------------------------------------------*/
  19. /*--------------------------------------------------------------------------*/
  20. /* This is basically UNZIP.C by Samuel H. Smith. There have been several    */
  21. /* modifications to meet the needs of FVIEW, as opposed to a stand-alone    */
  22. /* program. Who can judge when source code has been so modified as to no    */
  23. /* longer belongs to the original person? So you better respect his copy-   */
  24. /* right. I still want to do more work on this thing. There's an AWFUL      */
  25. /* amount of global data here.                                              */
  26. /*                                                                          */
  27. /* Copyright 1989, Doug Boone                                               */
  28. /*--------------------------------------------------------------------------*/
  29.  
  30. #include    <stdio.h>
  31. #include    <stdlib.h>
  32. #include    <io.h>
  33. #ifndef TURBOC
  34. #include    <sys\types.h>
  35. #include    <malloc.h>
  36. #endif
  37. #include    <sys\stat.h>
  38. #include    <fcntl.h>
  39. #include    <string.h>
  40. #include    "archdr.h"
  41. #include    "unzip.h"
  42.  
  43. extern  void    unpack(int,int,long);        /* In Arc_View.C */
  44.  
  45. int     unzip(char *,char *);
  46. int     loadup(void);
  47. int     read_bytes(unsigned *);
  48. int     load_bits(int);
  49. void    flushout(void);
  50. void    load_follower(void);
  51. void    reduced(void);
  52. void    clear_part(void);
  53. void    shrunk(void);
  54. int     get_file(char *);
  55. void    do_header(char *);
  56.  
  57.  
  58. /* Main entry point for this module */
  59.  
  60. int unzip(char *in_name,char *out_name)
  61. {
  62.  
  63.     bits_left = 0;
  64.     bitbuf = 0;
  65.     inpos = 0;
  66.     outpos = 0;
  67.     zipeof = 0;
  68.     insize  = INBUF_SIZE;
  69.     outsize = OUTBUF_SIZE;
  70.     outcnt = 0L;
  71.  
  72.  
  73.     if ((infile = open(in_name,O_RDONLY|O_BINARY)) < 1) {
  74.         free(inbuf);
  75.         free(outbuf);
  76.         return(1);
  77.         }
  78.  
  79.     do_header(out_name);
  80.  
  81.     return(0);
  82. }
  83.  
  84. int loadup(void)
  85. {
  86.  
  87.     if (packed <= 0)
  88.         return inpos = 0;
  89.  
  90.     if (packed < insize)
  91.         insize = (int) packed;
  92.  
  93.     inpos = read(infile, inbuf, insize);
  94.  
  95.     packed -= inpos;
  96.     inptr = inbuf;
  97.     return inpos--;
  98. }
  99.  
  100. int read_bytes(unsigned *x)
  101. {
  102.     if (inpos-- == 0)
  103.         if (loadup() == 0)
  104.             return 0;
  105.     *x = *inptr++;
  106.     return 8;
  107. }
  108.  
  109.  
  110. int load_bits(register int bits)
  111. {
  112.  
  113.     unsigned temp;
  114.     register int result = bitbuf;
  115.     int sbits = bits_left;
  116.  
  117.     bits -= bits_left;
  118.  
  119.     bits_left = read_bytes(&bitbuf);
  120.     bits_left += read_bytes(&temp);
  121.     bitbuf |= (temp << 8);
  122.     if (bits_left == 0)
  123.     zipeof = 1;
  124.  
  125.     result = result | (int) ((bitbuf & mask_bits[bits]) << sbits);
  126.     bitbuf >>= bits;
  127.     bits_left -= bits;
  128.     return result;
  129. }
  130.  
  131. void flushout(void)
  132. {
  133.     write(outfile, outbuf, outpos);
  134.     outcnt += (long) outpos;
  135.     outpos = 0;
  136.     outptr = outbuf;
  137. }
  138.  
  139. void load_follower(void)
  140. {
  141.     register int x;
  142.     register int i;
  143.  
  144.     for (x = 255; x >= 0; x--) {
  145.         if (6 <= bits_left) {
  146.             Slen[x] = (byte)(bitbuf & mask_bits[6]);
  147.             bitbuf >>= 6;
  148.             bits_left -= 6;
  149.             }
  150.         else
  151.             Slen[x] = (byte) load_bits(6);
  152.  
  153.         for (i = 0; i < Slen[x]; i++) {
  154.             if (8 <= bits_left) {
  155.                 followers[x][i] = (byte)(bitbuf & mask_bits[8]);
  156.                 bitbuf >>= 8; bits_left -= 8;
  157.                 }
  158.             else
  159.                 followers[x][i] = (byte) load_bits(8);
  160.             } /* end of for(Slen[x]) loop */
  161.         } /* end of for(x) loop */
  162. }
  163.  
  164.  
  165.  
  166. void reduced(void)
  167. {
  168.     int     lchar;
  169.     int        i;
  170.     int        ix;
  171.     int     nchar;
  172.     int     ExState;
  173.     int     V;
  174.     int     Len;
  175.     int        offset;
  176.     int        follower;
  177.     int        bitsneeded;
  178.     int     factor;
  179.     long    op;
  180.  
  181.     factor = method - 1;
  182.     ExState = 0;
  183.     lchar = 0;
  184.     load_follower();
  185.  
  186.     while ((unpacked > (outpos+outcnt)) && (!zipeof)) {
  187.         if (Slen[lchar] == 0) {
  188.             if (8 <= bits_left) {
  189.                 nchar = (int)(bitbuf & mask_bits[8]);
  190.                 bitbuf >>= 8;
  191.                 bits_left -= 8;
  192.                 }
  193.             else
  194.                 nchar = load_bits(8);
  195.             }
  196.         else {
  197.             if (1 <= bits_left) {
  198.                 nchar = (int)(bitbuf & mask_bits[1]);
  199.                 bitbuf >>= 1;
  200.                 bits_left -= 1;
  201.                 }
  202.             else
  203.                 nchar = load_bits(1);
  204.  
  205.             if (nchar != 0) {
  206.                 if (8 <= bits_left) {
  207.                     nchar = (int)(bitbuf & mask_bits[8]);
  208.                     bitbuf >>= 8;
  209.                     bits_left -= 8;
  210.                     }
  211.                 else
  212.                     nchar = load_bits(8);
  213.                 }
  214.             else  {
  215.                 bitsneeded = B_table[Slen[lchar]];
  216.                 if (bitsneeded <= bits_left) {
  217.                     follower = (int)(bitbuf & mask_bits[bitsneeded]);
  218.                     bitbuf >>= bitsneeded;
  219.                     bits_left -= bitsneeded;
  220.                     }
  221.                 else
  222.                     follower = load_bits(bitsneeded);
  223.                 nchar = followers[lchar][follower];
  224.                 }
  225.         }  /* This one is questionable! */
  226.  
  227.         switch (ExState) {
  228.  
  229.             case 0:
  230.                         if (nchar != DLE ) {
  231.                             *outptr++ = (byte) nchar;
  232.                             if (++outpos >= outsize)
  233.                                 flushout();
  234.                             }
  235.                         else
  236.                         ExState = 1;
  237.                         break;
  238.  
  239.             case 1:
  240.                         if (nchar != 0) {
  241.                             V = nchar;
  242.                             Len = V & L_table[factor];
  243.                             if (Len == L_table[factor])
  244.                                 ExState = 2;
  245.                             else
  246.                                 ExState = 3;
  247.                             }
  248.                         else {
  249.                             *outptr++ = DLE;
  250.                             if (++outpos >= outsize)
  251.                                 flushout();
  252.                             ExState = 0;
  253.                             }
  254.                         break;
  255.  
  256.             case 2:
  257.                         Len += nchar;
  258.                         ExState = 3;
  259.                         break;
  260.  
  261.             case 3:        i = Len + 3;
  262.                         offset = (((V >> D_shift[factor]) &
  263.                             D_mask[factor]) << 8) + nchar + 1;
  264.                         op = outcnt + outpos - offset;
  265.  
  266.                         while ((op < 0L) && (i > 0)) {
  267.                             *outptr++=0;
  268.                             if (++outpos >= outsize)
  269.                                 flushout();
  270.                             op++;
  271.                             i--;
  272.                             } /* End of while((op<0L && (i>0)) */
  273.  
  274.                         ix = (int) (op % outsize );
  275.                         if ( (((long)(ix + i)) < outsize ) &&
  276.                             ((outpos+i) < outsize ) ) {
  277.                                  memcpy(outptr,&outbuf[ix],i);
  278.                                  outptr += i;
  279.                                  outpos += i;
  280.                                  }
  281.                         else {
  282.                             while (i--) {
  283.                                 *outptr++=outbuf[ix];
  284.                                 if (++outpos==outsize )
  285.                                     flushout();
  286.                                 if (((long)++ix) >= outsize )
  287.                                     ix = 0;
  288.                                 }
  289.                             }
  290.  
  291.                         ExState = 0;
  292.                         break;        /* End of case 3 */
  293.             }        /* End of Switch statement */
  294.  
  295.         lchar = nchar;
  296.         }  /* End of WHILE loop */
  297.     return;
  298. }
  299.  
  300.  
  301. void clear_part(void)
  302. {
  303.     register int pr;
  304.     register int cd;
  305.  
  306.     for (cd = FIRST ; cd < free_ent; cd++)
  307.         prefix[cd] |= 0x8000;
  308.  
  309.     for (cd = FIRST ; cd < free_ent; cd++) {
  310.         pr = prefix[cd] & 0x7fff;    
  311.         if (pr >= FIRST )            
  312.             prefix[pr] &= 0x7fff;
  313.         }
  314.  
  315.  
  316.     for (cd = FIRST ; cd < free_ent; cd++)
  317.         if ((prefix[cd] & 0x8000) != 0)
  318.             prefix[cd] = -1;
  319.  
  320.  
  321.     cd = FIRST ;
  322.     while ((cd < maxcodemax) && (prefix[cd] != -1))
  323.         cd++;
  324.     free_ent = cd;
  325. }
  326.  
  327. void shrunk(void)
  328. {
  329.  
  330.     register int code;
  331.     register int stackp;
  332.     int finchar;
  333.     int oldcode;
  334.     int incode;
  335.  
  336.     maxcodemax = 1 << MAX_BITS ;
  337.     codesize = INIT_BITS ;
  338.     maxcode = (1 << codesize) - 1;
  339.     free_ent = FIRST ;
  340.     offset = 0;
  341.  
  342.     for (code = maxcodemax; code > 255; code--)
  343.         prefix[code] = -1;
  344.  
  345.     for (code = 255; code >= 0; code--) {
  346.         prefix[code] = 0;
  347.         suffix[code] = (byte) code;
  348.         }
  349.  
  350.     if (codesize <= bits_left) {
  351.         oldcode = (int)(bitbuf & mask_bits[codesize]);
  352.         bitbuf >>= codesize;
  353.         bits_left -= codesize;
  354.         }
  355.     else
  356.         oldcode = load_bits(codesize);
  357.  
  358.     if (zipeof)
  359.         return;
  360.     finchar = oldcode;
  361.  
  362.     *outptr++ = (byte) finchar;
  363.     if (++outpos==outsize )
  364.         flushout(); 
  365.  
  366.     stackp = HSIZE ;
  367.  
  368.     while (!zipeof) {
  369.         if (codesize <= bits_left) {
  370.             code = (int)(bitbuf & mask_bits[codesize]);
  371.             bitbuf >>= codesize;
  372.             bits_left -= codesize;
  373.             }
  374.         else
  375.             code = load_bits(codesize);
  376.  
  377.         if (zipeof)
  378.             return;
  379.  
  380.         while (code == CLEAR ) {
  381.             if (codesize <= bits_left) {
  382.                 code = (int)(bitbuf & mask_bits[codesize]);
  383.                 bitbuf >>= codesize;
  384.                 bits_left -= codesize;
  385.                 }
  386.             else
  387.                 code = load_bits(codesize);
  388.             /*}*/
  389.             switch (code) {
  390.  
  391.                 case 1:
  392.                             codesize++;
  393.                             if (codesize == MAX_BITS )
  394.                                 maxcode = maxcodemax;
  395.                             else
  396.                                 maxcode = (1 << codesize) - 1;
  397.                             break;
  398.  
  399.                 case 2:
  400.                             clear_part();
  401.                             break;
  402.                 }        /* End of switch(code) */
  403.  
  404.             
  405.             if (codesize <= bits_left) {
  406.                 code = (int)(bitbuf & mask_bits[codesize]);
  407.                 bitbuf >>= codesize;
  408.                 bits_left -= codesize;
  409.                 }
  410.             else
  411.                 code = load_bits(codesize);
  412.  
  413.             if (zipeof)
  414.                 return;
  415.             }        /* End of while(code == CLEAR) */
  416.  
  417.         incode = code;
  418.         if (prefix[code] == -1) {
  419.             stack[--stackp] = (byte) finchar;
  420.             code = oldcode;
  421.             }
  422.  
  423.  
  424.         while (code >= FIRST ) {
  425.             stack[--stackp] = suffix[code];
  426.             code = prefix[code];
  427.             }
  428.  
  429.         finchar = suffix[code];
  430.         stack[--stackp] = (byte) finchar;
  431.  
  432.         if ((HSIZE -stackp+outpos) < outsize ) {
  433.             memcpy(outptr,&stack[stackp],HSIZE -stackp);
  434.             outptr += HSIZE -stackp;
  435.             outpos += HSIZE -stackp;
  436.             stackp = HSIZE ;
  437.             }
  438.  
  439.         else while (stackp < HSIZE ) {
  440.             *outptr++=stack[stackp++];
  441.             if (++outpos==outsize )
  442.                 flushout();
  443.             } 
  444.  
  445.         code = free_ent;
  446.         if (code < maxcodemax) {
  447.             prefix[code] = oldcode;
  448.             suffix[code] = (byte) finchar;
  449.  
  450.             do
  451.                 code++;
  452.                 while ((code < maxcodemax) && (prefix[code] != -1));
  453.  
  454.             free_ent = code;
  455.             }
  456.  
  457.         oldcode = incode;
  458.         }        /* End of while(!zipeof) */
  459.  
  460. }
  461.  
  462.  
  463. int get_file(char *dearc)
  464. {
  465.  
  466.     if ((outfile = open(dearc,O_RDWR|O_BINARY|O_CREAT,S_IREAD|S_IWRITE)) < 1 ) {
  467.         fprintf(Log_fp,"Can't create output: %s\n", dearc);
  468.         return 1;
  469.         }
  470.  
  471.     write(outfile, "?", 1);
  472.     lseek(outfile, 0L,SEEK_SET);
  473.  
  474.     switch (method) {
  475.  
  476.         case 0:        unpack(infile,outfile,outsize);
  477.                     break;
  478.  
  479.         case 1: 
  480.                     inbuf = (byte *) malloc(insize);
  481.                     outbuf = (byte *) malloc(outsize);
  482.  
  483.                     inptr = inbuf;
  484.                     outptr = outbuf;
  485.  
  486.                     if ((inbuf == 0L ) || (outbuf == 0L )) {
  487.                         fprintf(Log_fp,"Can't allocate buffers!\n");
  488.                         return(1);
  489.                         }
  490.                     shrunk();
  491.                     break;
  492.  
  493.         case 2:
  494.         case 3:
  495.         case 4:
  496.         case 5: 
  497.                     inbuf = (byte *) malloc(insize);
  498.                     outbuf = (byte *) malloc(outsize);
  499.  
  500.                     inptr = inbuf;
  501.                     outptr = outbuf;
  502.  
  503.                     if ((inbuf == 0L ) || (outbuf == 0L )) {
  504.                         fprintf(Log_fp,"Can't allocate buffers!\n");
  505.                         return(1);
  506.                         }
  507.                     reduced();
  508.                     break;
  509.  
  510.         default:
  511.                     fprintf(Log_fp,"Unknown compression method.\n");
  512.         }
  513.     if (outpos > 0)
  514.         write(outfile, outbuf, (int) outpos);
  515.     close(outfile);
  516.     return(0);
  517. }
  518.  
  519.  
  520. void do_header(char *dearc)
  521. {
  522.     struct  ID_Hdr          *ID;
  523.     struct  Local_Hdr       *local;
  524.     char    *mbrname;
  525.     int        check;
  526.     char    *test;
  527.  
  528.     if ((test = strrchr(dearc,'\\')) == 0L )
  529.         test = dearc;
  530.     else
  531.         test++;
  532.  
  533.     ID = (struct ID_Hdr *) malloc(sizeof(struct ID_Hdr));
  534.     local = (struct Local_Hdr *) malloc(sizeof(struct Local_Hdr));
  535.     mbrname = (char *) malloc(80);
  536.  
  537.     do {
  538.         check = read(infile,(void *)ID,sizeof(struct ID_Hdr));
  539.         if (ID->Head_Type == LOCAL_HEADER) {
  540.             if ((check = read(infile,(void *)local,sizeof(struct Local_Hdr))) != -1) {
  541.                 memset(mbrname,EOS,80);
  542.                 check = read(infile,mbrname,local->name_length);
  543.                 lseek(infile,((long)local->Xfield_length),SEEK_CUR);
  544.  
  545.                 if (stricmp(test,mbrname) == 0) {
  546.                     packed = local->size_now;
  547.                     method = local->compression;
  548.                     unpacked = local->real_size;
  549.                     get_file(dearc);
  550.                     zipeof = 1;
  551.                     }
  552.                 else
  553.                     lseek(infile,local->size_now,SEEK_CUR);
  554.  
  555.                 }        /* End of one entry */
  556.             }        /* End of grabbing local directory entries */
  557.         else
  558.             check = -1;
  559.         } while(check >0 && !zipeof);        /* End of file */
  560.     free(local);
  561.     free(mbrname);
  562.     free(ID);
  563.     close(infile);
  564.     free(inbuf);
  565.     free(outbuf);
  566.     return;
  567. }
  568.  
  569.  
  570.