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 >
Wrap
C/C++ Source or Header
|
1989-05-26
|
8KB
|
213 lines
/*--------------------------------------------------------------------------*/
/* */
/* Copyright 1989, Doug Boone. FidoNet 119/5 */
/* (916) 893-9019 Data */
/* (916) 891-0748 voice */
/* P.O. Box 5108, Chico, CA. 95928 */
/* */
/* This program is not for sale. It is for the free use with Opus systems. */
/* You may not sell it in ANY way. If you have an access charge to your */
/* Bulletin Board, consider this to be like Opus, you can ONLY make it */
/* available for download in an open area, where non-members can get access */
/* */
/* If you need to modify this source code, please send me a copy of the */
/* changes you've made so that everyone can share in the updates. */
/* */
/* "Don't rip me off!" -- Tom Jennings, FidoNet's founder */
/* */
/*--------------------------------------------------------------------------*/
#include <io.h>
#include <stdlib.h>
#include <stdio.h>
/*#include <conio.h>
#include <ctype.h> */
#include <fcntl.h>
#ifndef TURBOC
#include <sys\types.h>
#endif
#include <sys\stat.h>
#include <string.h>
/*#include <time.h> */
#include "compress.h"
#define MARKER_VALUE 26
#define BUFFER_SIZE 32768
extern FILE *Log_fp;
extern void unpack(int,int,long);
typedef struct { /* ARC file header record definition */
char marker; /* should always be MARKER_VALUE */
char packtype;
char name[13];
long size;
long datetime;
unsigned crc;
long length;
} compress_header;
void *variables;
unsigned variable_size;
char *input_buffer;
char *output_buffer;
unsigned expand_file(int input_handle, int output_handle, long size, int type)
{
unsigned input_remaining; /* data remaining in input block */
unsigned input_size; /* size of current pass */
unsigned buf_pos; /* position in input buffer */
long total_input; /* total input processed */
long total_output; /* total output processed */
unsigned output_size; /* size of current output block */
int done; /* boolean flag when finished */
int end_of_input; /* boolean flag for last input block */
int n;
total_input = 0; /* zero counters */
total_output = 0;
switch(type) {
case 10: init_expand_Crush(variables); /* initialize variable area */
break;
case 9: expand_LZW_size();
init_expand_LZW(variables,13,0);
break;
case 8: expand_LZW_size();
read(input_handle,input_buffer,1);
n = input_buffer[0];
init_expand_LZW(variables,n,1);
break;
case 3: init_expand_RLE();
break;
case 2:
case 1: unpack(input_handle,output_handle,size);
return(1);
} /* End of switch */
do { /* for each input block */
/* read the block */
input_remaining = read(input_handle, input_buffer, BUFFER_SIZE);
/* check if buffered input larger than file to be expanded */
if (total_input + input_remaining > size) {
input_remaining = (unsigned) (size - total_input);
}
total_input += input_remaining; /* increment counter */
end_of_input = total_input == size; /* flag if last input block */
buf_pos = 0; /* set buffer position to start */
do {
input_size = input_remaining; /* maximum input = remaining input */
output_size = BUFFER_SIZE; /* maximum output = size of buffer */
switch(type) {
case 10: done = expand_Crush(input_buffer + buf_pos, &input_size,
output_buffer, &output_size, variables, end_of_input);
break;
case 9: done = expand_LZW(input_buffer + buf_pos, &input_size,
output_buffer, &output_size, variables, end_of_input);
break;
case 8: done = expand_LZW(input_buffer + buf_pos, &input_size,
output_buffer, &output_size, variables, end_of_input);
break;
case 3: done = expand_RLE(input_buffer + buf_pos, &input_size,
output_buffer, &output_size, end_of_input);
break;
} /* End of switch */
buf_pos += input_size; /* move pointer */
input_remaining -= input_size; /* decrement input remaining */
total_output += output_size; /* increment output counter */
write(output_handle, output_buffer, output_size); /* write out buffer */
} while(input_remaining);
} while (!done);
return(done);
}
int init_buffers(void) /* allocate buffers + variable area */
{
variable_size = expand_Crush_size();
if ((variables = malloc(variable_size)) == NULL) {
fprintf(Log_fp,"Not enough memory for Crushing variables\n");
return(2);
}
if ((input_buffer = (char *) malloc(BUFFER_SIZE)) == NULL) {
fprintf(Log_fp,"Not enough memory for input buffer\n");
return(2);
}
if ((output_buffer = (char *) malloc(BUFFER_SIZE)) == NULL) {
fprintf(Log_fp,"Not enough memory for output buffer\n");
return(2);
}
return(0);
}
int unpak(char *source,char *to)
{
compress_header header; /* header describing files */
int input_handle;
int output_handle;
long next_file; /* position in input file of next header */
char *name;
int result = 1;
unsigned check = 255;
if ((name = strrchr(to,'\\')) == NULL)
name = to;
else
name++;
if ((result = init_buffers()) !=0)
return(2);
if ((input_handle = open(source, O_RDONLY | O_BINARY)) < 0) {
fprintf(Log_fp,"could not open %s\n",source);
return(1);
}
_fmode = O_BINARY;
next_file = 0; /* start at begining of file */
do {
lseek(input_handle, next_file, SEEK_SET); /* move to next header */
/* read header */
if (read(input_handle,&header, sizeof(header)) < sizeof(header))
break; /* we didn't get a full header, so quit. */
if (header.marker != MARKER_VALUE) /* first byte is always ^Z */
break;
if (header.packtype == 0) /* last header */
break;
/* set position of next file */
next_file = tell(input_handle) + header.size;
if (strcmp(header.name,name) == 0) {
if ((output_handle = creat(to, S_IREAD | S_IWRITE)) < 0) {
fprintf(Log_fp,"Could not create %s\n",to);
return(1);
}
result = 1;
check = expand_file(input_handle, output_handle,
header.size,header.packtype);
close(output_handle);
} /* End of name match */
} while (result == 0); /* until we run out of file, actually. */
close(input_handle);
return(check-1);
}