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 >
Wrap
C/C++ Source or Header
|
1989-05-26
|
16KB
|
570 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 */
/* */
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
/* This is basically UNZIP.C by Samuel H. Smith. There have been several */
/* modifications to meet the needs of FVIEW, as opposed to a stand-alone */
/* program. Who can judge when source code has been so modified as to no */
/* longer belongs to the original person? So you better respect his copy- */
/* right. I still want to do more work on this thing. There's an AWFUL */
/* amount of global data here. */
/* */
/* Copyright 1989, Doug Boone */
/*--------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#ifndef TURBOC
#include <sys\types.h>
#include <malloc.h>
#endif
#include <sys\stat.h>
#include <fcntl.h>
#include <string.h>
#include "archdr.h"
#include "unzip.h"
extern void unpack(int,int,long); /* In Arc_View.C */
int unzip(char *,char *);
int loadup(void);
int read_bytes(unsigned *);
int load_bits(int);
void flushout(void);
void load_follower(void);
void reduced(void);
void clear_part(void);
void shrunk(void);
int get_file(char *);
void do_header(char *);
/* Main entry point for this module */
int unzip(char *in_name,char *out_name)
{
bits_left = 0;
bitbuf = 0;
inpos = 0;
outpos = 0;
zipeof = 0;
insize = INBUF_SIZE;
outsize = OUTBUF_SIZE;
outcnt = 0L;
if ((infile = open(in_name,O_RDONLY|O_BINARY)) < 1) {
free(inbuf);
free(outbuf);
return(1);
}
do_header(out_name);
return(0);
}
int loadup(void)
{
if (packed <= 0)
return inpos = 0;
if (packed < insize)
insize = (int) packed;
inpos = read(infile, inbuf, insize);
packed -= inpos;
inptr = inbuf;
return inpos--;
}
int read_bytes(unsigned *x)
{
if (inpos-- == 0)
if (loadup() == 0)
return 0;
*x = *inptr++;
return 8;
}
int load_bits(register int bits)
{
unsigned temp;
register int result = bitbuf;
int sbits = bits_left;
bits -= bits_left;
bits_left = read_bytes(&bitbuf);
bits_left += read_bytes(&temp);
bitbuf |= (temp << 8);
if (bits_left == 0)
zipeof = 1;
result = result | (int) ((bitbuf & mask_bits[bits]) << sbits);
bitbuf >>= bits;
bits_left -= bits;
return result;
}
void flushout(void)
{
write(outfile, outbuf, outpos);
outcnt += (long) outpos;
outpos = 0;
outptr = outbuf;
}
void load_follower(void)
{
register int x;
register int i;
for (x = 255; x >= 0; x--) {
if (6 <= bits_left) {
Slen[x] = (byte)(bitbuf & mask_bits[6]);
bitbuf >>= 6;
bits_left -= 6;
}
else
Slen[x] = (byte) load_bits(6);
for (i = 0; i < Slen[x]; i++) {
if (8 <= bits_left) {
followers[x][i] = (byte)(bitbuf & mask_bits[8]);
bitbuf >>= 8; bits_left -= 8;
}
else
followers[x][i] = (byte) load_bits(8);
} /* end of for(Slen[x]) loop */
} /* end of for(x) loop */
}
void reduced(void)
{
int lchar;
int i;
int ix;
int nchar;
int ExState;
int V;
int Len;
int offset;
int follower;
int bitsneeded;
int factor;
long op;
factor = method - 1;
ExState = 0;
lchar = 0;
load_follower();
while ((unpacked > (outpos+outcnt)) && (!zipeof)) {
if (Slen[lchar] == 0) {
if (8 <= bits_left) {
nchar = (int)(bitbuf & mask_bits[8]);
bitbuf >>= 8;
bits_left -= 8;
}
else
nchar = load_bits(8);
}
else {
if (1 <= bits_left) {
nchar = (int)(bitbuf & mask_bits[1]);
bitbuf >>= 1;
bits_left -= 1;
}
else
nchar = load_bits(1);
if (nchar != 0) {
if (8 <= bits_left) {
nchar = (int)(bitbuf & mask_bits[8]);
bitbuf >>= 8;
bits_left -= 8;
}
else
nchar = load_bits(8);
}
else {
bitsneeded = B_table[Slen[lchar]];
if (bitsneeded <= bits_left) {
follower = (int)(bitbuf & mask_bits[bitsneeded]);
bitbuf >>= bitsneeded;
bits_left -= bitsneeded;
}
else
follower = load_bits(bitsneeded);
nchar = followers[lchar][follower];
}
} /* This one is questionable! */
switch (ExState) {
case 0:
if (nchar != DLE ) {
*outptr++ = (byte) nchar;
if (++outpos >= outsize)
flushout();
}
else
ExState = 1;
break;
case 1:
if (nchar != 0) {
V = nchar;
Len = V & L_table[factor];
if (Len == L_table[factor])
ExState = 2;
else
ExState = 3;
}
else {
*outptr++ = DLE;
if (++outpos >= outsize)
flushout();
ExState = 0;
}
break;
case 2:
Len += nchar;
ExState = 3;
break;
case 3: i = Len + 3;
offset = (((V >> D_shift[factor]) &
D_mask[factor]) << 8) + nchar + 1;
op = outcnt + outpos - offset;
while ((op < 0L) && (i > 0)) {
*outptr++=0;
if (++outpos >= outsize)
flushout();
op++;
i--;
} /* End of while((op<0L && (i>0)) */
ix = (int) (op % outsize );
if ( (((long)(ix + i)) < outsize ) &&
((outpos+i) < outsize ) ) {
memcpy(outptr,&outbuf[ix],i);
outptr += i;
outpos += i;
}
else {
while (i--) {
*outptr++=outbuf[ix];
if (++outpos==outsize )
flushout();
if (((long)++ix) >= outsize )
ix = 0;
}
}
ExState = 0;
break; /* End of case 3 */
} /* End of Switch statement */
lchar = nchar;
} /* End of WHILE loop */
return;
}
void clear_part(void)
{
register int pr;
register int cd;
for (cd = FIRST ; cd < free_ent; cd++)
prefix[cd] |= 0x8000;
for (cd = FIRST ; cd < free_ent; cd++) {
pr = prefix[cd] & 0x7fff;
if (pr >= FIRST )
prefix[pr] &= 0x7fff;
}
for (cd = FIRST ; cd < free_ent; cd++)
if ((prefix[cd] & 0x8000) != 0)
prefix[cd] = -1;
cd = FIRST ;
while ((cd < maxcodemax) && (prefix[cd] != -1))
cd++;
free_ent = cd;
}
void shrunk(void)
{
register int code;
register int stackp;
int finchar;
int oldcode;
int incode;
maxcodemax = 1 << MAX_BITS ;
codesize = INIT_BITS ;
maxcode = (1 << codesize) - 1;
free_ent = FIRST ;
offset = 0;
for (code = maxcodemax; code > 255; code--)
prefix[code] = -1;
for (code = 255; code >= 0; code--) {
prefix[code] = 0;
suffix[code] = (byte) code;
}
if (codesize <= bits_left) {
oldcode = (int)(bitbuf & mask_bits[codesize]);
bitbuf >>= codesize;
bits_left -= codesize;
}
else
oldcode = load_bits(codesize);
if (zipeof)
return;
finchar = oldcode;
*outptr++ = (byte) finchar;
if (++outpos==outsize )
flushout();
stackp = HSIZE ;
while (!zipeof) {
if (codesize <= bits_left) {
code = (int)(bitbuf & mask_bits[codesize]);
bitbuf >>= codesize;
bits_left -= codesize;
}
else
code = load_bits(codesize);
if (zipeof)
return;
while (code == CLEAR ) {
if (codesize <= bits_left) {
code = (int)(bitbuf & mask_bits[codesize]);
bitbuf >>= codesize;
bits_left -= codesize;
}
else
code = load_bits(codesize);
/*}*/
switch (code) {
case 1:
codesize++;
if (codesize == MAX_BITS )
maxcode = maxcodemax;
else
maxcode = (1 << codesize) - 1;
break;
case 2:
clear_part();
break;
} /* End of switch(code) */
if (codesize <= bits_left) {
code = (int)(bitbuf & mask_bits[codesize]);
bitbuf >>= codesize;
bits_left -= codesize;
}
else
code = load_bits(codesize);
if (zipeof)
return;
} /* End of while(code == CLEAR) */
incode = code;
if (prefix[code] == -1) {
stack[--stackp] = (byte) finchar;
code = oldcode;
}
while (code >= FIRST ) {
stack[--stackp] = suffix[code];
code = prefix[code];
}
finchar = suffix[code];
stack[--stackp] = (byte) finchar;
if ((HSIZE -stackp+outpos) < outsize ) {
memcpy(outptr,&stack[stackp],HSIZE -stackp);
outptr += HSIZE -stackp;
outpos += HSIZE -stackp;
stackp = HSIZE ;
}
else while (stackp < HSIZE ) {
*outptr++=stack[stackp++];
if (++outpos==outsize )
flushout();
}
code = free_ent;
if (code < maxcodemax) {
prefix[code] = oldcode;
suffix[code] = (byte) finchar;
do
code++;
while ((code < maxcodemax) && (prefix[code] != -1));
free_ent = code;
}
oldcode = incode;
} /* End of while(!zipeof) */
}
int get_file(char *dearc)
{
if ((outfile = open(dearc,O_RDWR|O_BINARY|O_CREAT,S_IREAD|S_IWRITE)) < 1 ) {
fprintf(Log_fp,"Can't create output: %s\n", dearc);
return 1;
}
write(outfile, "?", 1);
lseek(outfile, 0L,SEEK_SET);
switch (method) {
case 0: unpack(infile,outfile,outsize);
break;
case 1:
inbuf = (byte *) malloc(insize);
outbuf = (byte *) malloc(outsize);
inptr = inbuf;
outptr = outbuf;
if ((inbuf == 0L ) || (outbuf == 0L )) {
fprintf(Log_fp,"Can't allocate buffers!\n");
return(1);
}
shrunk();
break;
case 2:
case 3:
case 4:
case 5:
inbuf = (byte *) malloc(insize);
outbuf = (byte *) malloc(outsize);
inptr = inbuf;
outptr = outbuf;
if ((inbuf == 0L ) || (outbuf == 0L )) {
fprintf(Log_fp,"Can't allocate buffers!\n");
return(1);
}
reduced();
break;
default:
fprintf(Log_fp,"Unknown compression method.\n");
}
if (outpos > 0)
write(outfile, outbuf, (int) outpos);
close(outfile);
return(0);
}
void do_header(char *dearc)
{
struct ID_Hdr *ID;
struct Local_Hdr *local;
char *mbrname;
int check;
char *test;
if ((test = strrchr(dearc,'\\')) == 0L )
test = dearc;
else
test++;
ID = (struct ID_Hdr *) malloc(sizeof(struct ID_Hdr));
local = (struct Local_Hdr *) malloc(sizeof(struct Local_Hdr));
mbrname = (char *) malloc(80);
do {
check = read(infile,(void *)ID,sizeof(struct ID_Hdr));
if (ID->Head_Type == LOCAL_HEADER) {
if ((check = read(infile,(void *)local,sizeof(struct Local_Hdr))) != -1) {
memset(mbrname,EOS,80);
check = read(infile,mbrname,local->name_length);
lseek(infile,((long)local->Xfield_length),SEEK_CUR);
if (stricmp(test,mbrname) == 0) {
packed = local->size_now;
method = local->compression;
unpacked = local->real_size;
get_file(dearc);
zipeof = 1;
}
else
lseek(infile,local->size_now,SEEK_CUR);
} /* End of one entry */
} /* End of grabbing local directory entries */
else
check = -1;
} while(check >0 && !zipeof); /* End of file */
free(local);
free(mbrname);
free(ID);
close(infile);
free(inbuf);
free(outbuf);
return;
}