AUSAM/source/S/unpack.c
#
#include <local-system>
/* Expand Huffman coded input to
* Input file format:
* PACKED flag defined below (integer)
* Number of chars in expanded file (float or long)
* Number of words in expanded tree (integer)
* Tree in 'compressed' form:
* If 0<=byte<=0376, expand by zero padding to left
* If byte=0377, next two bytes for one word
* Terminal nodes: First word is zero; second is character
* Non-terminal nodes: Incremental 0/1 pointers
* Code string for number of characters in expanded file
*/
#define SUF0 '.'
#define SUF1 'z'
struct iobuf
{
int fildes;
int nleft;
char *nextp;
char buf[512];
} buf, obuf;
struct
{
char minor;
char major;
int inumber;
int flags;
#ifdef AUSAM
unsigned uid;
#endif AUSAM
char nlinks;
#ifndef AUSAM
char uid;
char gid;
#endif AUSAM
char size0;
int size1;
int addr[8];
long actime;
long modtime;
} status;
#define LNAME 80
#define PACKED 017437 /* <US><US> - Unlikely value */
long size;
long size;
union
{
int hilo[2];
float fsize;
long lsize;
} q;
struct {int hi, lo;};
int tree[1024];
main(argc, argv)
int argc; char *argv[];
{
register int i, k, *t;
int sep, keysize;
char filename[LNAME], *cp;
/**/ int *u;
for (k = 1; k<argc; k++)
{
sep = -1; cp = filename;
for (i=0; i < (LNAME-3) && (*cp = argv[k][i]); i++)
if (*cp++ == '/') sep = i;
sep = i - sep - 1; /* nr of chars in name */
if (i >= (LNAME-3) || sep > 14)
{
namerr: printf ("File name too long -- %s\n", argv[k]);
continue;
}
if (cp[-1] == SUF1 && cp[-2] == SUF0 && fopen(filename, &buf) >= 0) argv[k][i - 2] = '\0';
else
{
if (sep > 12) goto namerr;
*cp++ = SUF0; *cp++ = SUF1; *cp = '\0';
if (fopen(filename, &buf) < 0)
{
printf ("Unable to open %s\n", filename);
continue;
}
}
if (getw(&buf) != PACKED)
{
printf ("Unable to unpack %s\n", filename);
close(buf.fildes);
continue;
}
if( stat(argv[k], &status) != -1 )
{
printf("%s: Already exists\n", argv[k]);
close(buf.fildes);
continue;
}
#ifdef AUSAM
newfstat(buf.fildes, &status);
#endif AUSAM
#ifndef AUSAM
fstat(buf.fildes, &status);
#endif AUSAM
if ( status.nlinks != 1)
printf("Warning: '%s' has links\n", filename);
if (fcreat(argv[k], &obuf) == -1)
{
printf ("Unable to create %s\n", argv[k]);
close(buf.fildes);
continue;
}
chmod(argv[k], status.flags&07777);
#ifdef AUSAM
chown( argv[k], status.uid); /* IAN J Jan '77 */
#endif AUSAM
q.hilo[0] = getw(&buf);
q.hilo[1] = getw(&buf);
if( q.hilo[0] > 040000) /* a float */
size = q.fsize;
else
size = q.lsize; /* a long */
t = tree;
for (keysize = getw(&buf); keysize--; )
{
if ((i = getc(&buf)) == 0377)
*t++ = getw(&buf);
else
*t++ = i;
}
/**//* for (u=tree; u<t; u++ ) printf("%4d: %6d <%3o> %c\n", */
/**//* u-tree, *u, *u&0377, *u); */
if ( expand() == 0 )
{
fflush(&obuf);
unlink(filename);
smdate( argv[k] , status.modtime ); /* preserve modified date */
}
else
{
perror( argv[k] );
printf( "%s: I/O Error - File unchanged\n", filename );
unlink( argv[k] );
}
close(buf.fildes);
close(obuf.fildes);
}
}
expand()
{
register int tp, bit, word;
extern errno;
bit = tp = 0;
for (;;)
{
if (bit == 0)
{
word = getw(&buf);
bit = 16;
}
tp =+ tree[tp + (word<0)];
word =<< 1; bit--;
if (tree[tp] == 0)
{
putc(tree[tp+1], &obuf);
if ( errno )
return( 1 );
tp = 0;
if ((size =- 1) == 0) return( 0 );
}
}
}