home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / msdos / opus / fvsrc620.arc / UNPAK.C < prev    next >
C/C++ Source or Header  |  1989-05-26  |  8KB  |  213 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. #include <io.h>
  21. #include <stdlib.h>
  22. #include <stdio.h>
  23. /*#include <conio.h>
  24. #include <ctype.h> */
  25. #include <fcntl.h>
  26. #ifndef TURBOC
  27. #include    <sys\types.h>
  28. #endif
  29. #include <sys\stat.h>
  30. #include <string.h>
  31. /*#include <time.h> */
  32. #include "compress.h"
  33.  
  34. #define MARKER_VALUE 26
  35. #define BUFFER_SIZE  32768
  36.  
  37. extern  FILE    *Log_fp;
  38. extern  void    unpack(int,int,long);
  39.  
  40. typedef struct {   /*  ARC file header record definition  */
  41.           char            marker;   /* should always be MARKER_VALUE */
  42.           char            packtype;
  43.           char            name[13];
  44.           long            size;
  45.           long                 datetime;
  46.           unsigned        crc;
  47.           long            length;
  48.          }  compress_header;
  49.  
  50. void        *variables;
  51. unsigned    variable_size;
  52. char        *input_buffer;
  53. char        *output_buffer;
  54.  
  55. unsigned expand_file(int input_handle, int output_handle, long size, int type)
  56.  {
  57.   unsigned input_remaining; /* data remaining in input block */
  58.   unsigned input_size;      /* size of current pass */
  59.   unsigned buf_pos;         /* position in input buffer */
  60.   long     total_input;     /* total input processed */
  61.   long     total_output;    /* total output processed */
  62.   unsigned output_size;     /* size of current output block */
  63.   int      done;            /* boolean flag when finished */
  64.   int      end_of_input;    /* boolean flag for last input block */
  65.   int       n;
  66.  
  67.   total_input = 0;   /* zero counters */
  68.   total_output = 0;
  69.  
  70.   switch(type) {
  71.     case 10:    init_expand_Crush(variables);  /* initialize variable area */
  72.                 break;
  73.  
  74.     case  9:    expand_LZW_size();
  75.                 init_expand_LZW(variables,13,0);
  76.                 break;
  77.  
  78.     case  8:    expand_LZW_size();
  79.                 read(input_handle,input_buffer,1);
  80.                 n = input_buffer[0];
  81.                 init_expand_LZW(variables,n,1);
  82.                 break;
  83.  
  84.     case  3:    init_expand_RLE();
  85.                 break;
  86.  
  87.     case  2:
  88.     case  1:    unpack(input_handle,output_handle,size);
  89.                 return(1);
  90.  
  91.     } /* End of switch */
  92.  
  93.   do {  /* for each input block */
  94.       /* read the block */
  95.     input_remaining = read(input_handle, input_buffer, BUFFER_SIZE);
  96.       /* check if buffered input larger than file to be expanded */
  97.     if (total_input + input_remaining > size) {
  98.       input_remaining = (unsigned) (size - total_input);
  99.      }
  100.  
  101.     total_input += input_remaining;  /* increment counter */
  102.     end_of_input = total_input == size;  /* flag if last input block */
  103.     buf_pos = 0;                        /* set buffer position to start */
  104.     do {
  105.       input_size = input_remaining; /* maximum input = remaining input */
  106.       output_size = BUFFER_SIZE;    /* maximum output = size of buffer */
  107.       switch(type) {
  108.         case 10:    done = expand_Crush(input_buffer + buf_pos, &input_size,
  109.                         output_buffer, &output_size, variables, end_of_input);
  110.                     break;
  111.  
  112.         case  9:    done = expand_LZW(input_buffer + buf_pos, &input_size,
  113.                         output_buffer, &output_size, variables, end_of_input);
  114.                     break;
  115.  
  116.         case  8:    done = expand_LZW(input_buffer + buf_pos, &input_size,
  117.                         output_buffer, &output_size, variables, end_of_input);
  118.                     break;
  119.  
  120.         case  3:    done = expand_RLE(input_buffer + buf_pos, &input_size,
  121.                         output_buffer, &output_size, end_of_input);
  122.                     break;
  123.         }        /* End of switch */
  124.  
  125.  
  126.       buf_pos += input_size;         /* move pointer */
  127.       input_remaining -= input_size; /* decrement input remaining */
  128.       total_output += output_size;   /* increment output counter */
  129.       write(output_handle, output_buffer, output_size); /* write out buffer */
  130.      } while(input_remaining);
  131.    } while (!done);
  132.    return(done);
  133.  }
  134.  
  135.  
  136. int init_buffers(void)  /* allocate buffers + variable area */
  137.  {
  138.   variable_size = expand_Crush_size();
  139.   if ((variables = malloc(variable_size)) == NULL) {
  140.     fprintf(Log_fp,"Not enough memory for Crushing variables\n");
  141.     return(2);
  142.    }
  143.   if ((input_buffer = (char *) malloc(BUFFER_SIZE)) == NULL) {
  144.     fprintf(Log_fp,"Not enough memory for input buffer\n");
  145.     return(2);
  146.    }
  147.   if ((output_buffer = (char *) malloc(BUFFER_SIZE)) == NULL) {
  148.     fprintf(Log_fp,"Not enough memory for output buffer\n");
  149.     return(2);
  150.    }
  151.    return(0);
  152.  }
  153.  
  154. int unpak(char *source,char *to)
  155.  {
  156.   compress_header header;        /* header describing files */
  157.   int           input_handle;
  158.   int           output_handle;
  159.   long          next_file;     /* position in input file of next header */
  160.   char          *name;
  161.   int           result = 1;
  162.   unsigned        check = 255;
  163.  
  164.     if ((name = strrchr(to,'\\')) == NULL)
  165.         name = to;
  166.     else
  167.         name++;
  168.     if ((result = init_buffers()) !=0)
  169.         return(2);
  170.  
  171.     if ((input_handle = open(source, O_RDONLY | O_BINARY)) < 0) {
  172.         fprintf(Log_fp,"could not open %s\n",source);
  173.         return(1);
  174.     }
  175.  
  176.  
  177.     _fmode = O_BINARY;
  178.     next_file = 0;    /* start at begining of file */
  179.     do {
  180.         lseek(input_handle, next_file, SEEK_SET); /* move to next header */
  181.  
  182.         /* read header */
  183.         if (read(input_handle,&header, sizeof(header)) < sizeof(header))
  184.             break;  /* we didn't get a full header, so quit. */
  185.  
  186.         if (header.marker != MARKER_VALUE)  /* first byte is always ^Z */
  187.             break;
  188.  
  189.         if (header.packtype == 0)  /* last header */
  190.             break;
  191.  
  192.         /* set position of next file */
  193.         next_file = tell(input_handle) + header.size;
  194.  
  195.         if (strcmp(header.name,name) == 0) {
  196.             if ((output_handle = creat(to, S_IREAD | S_IWRITE)) < 0) {
  197.                 fprintf(Log_fp,"Could not create %s\n",to);
  198.                 return(1);
  199.                 }
  200.             result = 1;
  201.             check = expand_file(input_handle, output_handle,
  202.                 header.size,header.packtype);
  203.             close(output_handle);
  204.             }        /* End of name match */
  205.  
  206.         } while (result == 0);  /* until we run out of file, actually. */
  207.   close(input_handle);
  208.   return(check-1);
  209.  }
  210.  
  211.  
  212.         
  213.