🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: comp.sources.apple2
1 messages
1 total messages Started by Jonathan A. Chandross Wed, 01 May 1991 22:09
v001SRC033: Nulib - Archive Library Tools (Unix) 02/10
#32
Author: Jonathan A. Chandross
Date: Wed, 01 May 1991 22:09
1582 lines
48495 bytes
Submitted-by: Andy McFadden (fadden@cory.berkeley.edu)
Posting-number: Volume 1, Source:33
Archive-name: archive/unix/nulib/part02.10
Architecture: UNIX
Version-number: 3.03


=nushk.c
-/*
- * nushk.c - P8 ShrinkIt compress/uncompress routines
- *
- * NuLib v3.0  February 1991  Freeware (distribute, don't sell)
- * By Andy McFadden (fadden@cory.berkeley.edu)
- */
-#ifdef APW
-segment "Compress"
-#endif
-
-#include "nudefs.h"
-#include <stdio.h>
-#include <fcntl.h>
-
-#ifdef MSDOS     /* For file IO */
-# include <io.h>
-# include <sys/types.h>
-# include <sys/stat.h>
-# include <errno.h>
-#endif
-
-#include "nuread.h"  /* need CalcCRC() */
-#include "nupak.h"
-#include "nuetc.h"
-
-#define BLKSIZ	4096
-/*#define DEBUG 	/* do verbose debugging output */
-/*#define DEBUG1	/* debugging output in main routine */
-
-static onebyt *ibuf;	/* large buffer (usually set to packBuffer) */
-onebyt lbuf[BLKSIZ+7];	/* temporary buffer for storing data after LZW */
-onebyt rbuf[BLKSIZ+7];	/* temporary buffer for storing data after RLE */
-
-
-/*
- * P8 ShrinkIt compression routines
- * Copyright 1989 Kent Dickey
- *
- * C translation by Kent Dickey / Andy McFadden
- */
-
-#define ESCAPE_CHAR	0xdb
-#define HSIZE 4219		/* Must be prime */
-
-struct ht {
-	int entry;
-	int prefix;
-	unsigned char chr;
-} htab[HSIZE];
-
-int s_at_bit;
-int s_at_byte;
-
-int mask[] = {	0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f,
-		0xff, 0x1ff, 0x3ff, 0x7ff, 0xfff };
-
-int bit_tab[] = { 0,9,10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12 };
-
-
-/*
- * Output code to buffer.
- */
-int put_code(code, ent, bfr)
-int code;
-register int ent;
-char *bfr;
-{
-	int lo_byte;
-	long mycode;
-	int bits;
-
-	bits = bit_tab[(ent >> 8)];
-/*	if (((s_at_bit + bits + 7) / 8) + s_at_byte > BLKSIZ) {*/
-	if (((s_at_bit + bits + 7) >> 3) + s_at_byte > BLKSIZ) {
-		return(-1);
-	}
-	mycode = (long)(code & mask[bits]);
-/*	fprintf(stderr,"Byte: %d, %lx\n", s_at_byte, mycode); */
-	lo_byte = bfr[s_at_byte] & mask[s_at_bit];
-	if (s_at_bit != 0) {
-		mycode <<= s_at_bit;
-	}
-	bfr[s_at_byte++] = (unsigned char)lo_byte | (char)(mycode & 0xff);
-	bfr[s_at_byte] = (unsigned char)((mycode >>= 8) & 0xff);
-	if ((s_at_bit += bits) >= 16) {
-		bfr[++s_at_byte] = (char)((mycode >>= 8) & 0xff);
-	}
-	s_at_bit &= 0x07;
-
-	return(0);
-}
-
-
-/*
- * Try LZW compression on the buffer.
- *
- * Compresses from "buffer" to "outbuf".  "inlen" is the #of bytes of data in
- * "buffer."  Returns the #of bytes of data placed into "outbuf", or -1 on
- * failure.
- */
-int do_LZW(bufr, inlen, outbuf)
-unsigned char *bufr;
-int inlen;
-unsigned char *outbuf;
-{
-	int ent, prefix;
-	register int index;
-	register unsigned char k;
-	register unsigned char *inbuf, *endbuf;
-
-	s_at_byte = 0;
-	s_at_bit =0;
-	ent = 0x101;
-	inbuf = bufr;
-	endbuf = bufr + inlen;
-
-
-	k = ((char)*inbuf++);
-Loop0:
-	prefix = (int)k;
-Loop1:
-	if (inbuf >= endbuf) {
-		if (put_code(prefix, ent, outbuf) < 0) {
-			return(BLKSIZ+2);
-		}
-		if (s_at_bit == 0) return(s_at_byte);
-		else		   return(s_at_byte+1);
-	}
-	k = (unsigned char)*inbuf++;
-	index = (prefix + (k<<4)) & 0xfff;
-
-Check_ent:
-	if (htab[index].entry == 0) {
-		/* Entry is 0... */
-		if (put_code(prefix, ent, outbuf) < 0) {
-			return(-1);	/* failed */
-		}
-		htab[index].entry = ent++;
-		htab[index].prefix = prefix;
-		htab[index].chr = k;
-		goto Loop0;
-	}
-	else if (htab[index].prefix == prefix) {
-		/* Same prefix... */
-		if (htab[index].chr == k) {
-			/* It's HERE!  Yeah! */
-			prefix = htab[index].entry;
-			goto Loop1;
-		}
-		goto Sec_hash;
-	}
-		/* Check for more...secondary hash on index */
-	  else {
-Sec_hash:
-		index = (index + (unsigned int)(k) + 1) % HSIZE;
-	/*	fprintf(stderr,"New ind: %d, k=%d\n", index, (unsigned int)k);  */
-		goto Check_ent;
-	}
-}
-
-
-/*
- * Clear out the hash table.
- */
-void ClearTab()
-{
-	register int i;
-
-	for(i=0; i < HSIZE; i++) {
-		htab[i].entry = 0;
-	}
-}
-
-
-/*
- * Do run-length encoding
- *
- * Takes input from srcptr, and writes to dstptr.  Maximum expansion is
- * (BLKSIZ / 2) + (BLKSIZ / 2) * 3 == 2 * BLKSIZ
- * Output of form  <DLE> char count
- *
- * This really isn't very pretty, but it works.
- */
-int do_RLE(srcptr, dstptr)
-register onebyt *srcptr, *dstptr;
-{
-    int found, scount, dcount;
-    register onebyt c, lastc, tlastc;
-
-    c = *(srcptr++);  scount = 1;
-    dcount = 0;
-    found = 1;  /* one char has been found */
-    lastc = '\0';
-    while (scount < BLKSIZ) {
-	tlastc = lastc;
-	lastc = c;
-	c = *(srcptr++);  scount++;
-
-	if (found == 1) {  /* no run found */
-	    if (c != lastc) {  /* no run starting */
-		if (lastc == ESCAPE_CHAR) {
-		    *(dstptr++) = ESCAPE_CHAR;  dcount++;
-		    *(dstptr++) = lastc;  dcount++;
-		    *(dstptr++) = 0;  dcount++;  /* found one */
-		} else {
-		    *(dstptr++) = lastc;  dcount++;
-		}
-		found = 1;
-	    } else {
-		found = 2;  /* they matched, so two in a row */
-	    }
-
-	} else if (found == 2) {  /* got two, try for three */
-	    if (c != lastc) {  /* only got two in a row */
-		if (lastc == ESCAPE_CHAR) {  /* and tlastc as well */
-		    *(dstptr++) = ESCAPE_CHAR;  dcount++;
-		    *(dstptr++) = lastc;  dcount++;
-		    *(dstptr++) = 1;  dcount++;  /* found two */
-		} else {
-		    *(dstptr++) = tlastc;  dcount++;
-		    *(dstptr++) = lastc;  dcount++;
-		}
-		found = 1;
-	    } else {  /* found 3, got a run going */
-		found = 3;
-	    }
-
-	} else {  /* (found >= 3), got a run going */
-	    if (c == lastc) {  /* found another */
-		found++;
-	    }
-	    if ((c != lastc) || (found > 256)) {  /* end, or too many */
-		*(dstptr++) = ESCAPE_CHAR;  dcount++;
-		*(dstptr++) = lastc;  dcount++;
-		*(dstptr++) = (found > 256) ? 255 : found-1;
-		dcount++;
-		found = 1;  /* c has something other than the run char	*/
-			    /* or found is 257-256 = 1		 	*/
-	    }
-	}
-    }  /* while */
-
-    /* reached end of buffer; flush what was left */
-    if (found == 1) {
-	if (c == ESCAPE_CHAR) {
-	    *(dstptr++) = ESCAPE_CHAR;  dcount++;
-	    *(dstptr++) = c;  dcount++;
-	    *(dstptr++) = 0;  dcount++;
-	} else {
-	    *(dstptr++) = c;  dcount++;
-	}
-
-    } else if (found == 2) {
-	/* maybe have if lastc == c == ESCAPE_CHAR? */
-	if (lastc == ESCAPE_CHAR) {
-	    *(dstptr++) = ESCAPE_CHAR;  dcount++;
-	    *(dstptr++) = lastc;  dcount++;
-	    *(dstptr++) = 0;  dcount++;
-	} else {
-	    *(dstptr++) = lastc;  dcount++;
-	}
-	if (c == ESCAPE_CHAR) {
-	    *(dstptr++) = ESCAPE_CHAR;  dcount++;
-	    *(dstptr++) = c;  dcount++;
-	    *(dstptr++) = 0;  dcount++;
-	} else {
-	    *(dstptr++) = c;  dcount++;
-	}
-
-    } else {  /* found >= 3, in the middle of processing a run */
-	*(dstptr++) = ESCAPE_CHAR;  dcount++;
-	*(dstptr++) = c;  dcount++;
-	*(dstptr++) = found-1;  dcount++;
-    }
-
-    return (dcount);
-}
-
-
-/*
- * Main compression entry point.
- *
- * Returns actual thread_format used.
- *
- * Note that "copybuf" should be at least twice as big as BLKSIZ.
- */
-long pak_SHK(srcfd, dstfd, length, copybuf)
-int srcfd, dstfd;
-long length;		/* uncompressed size */
-onebyt *copybuf;
-{
-    unsigned int partial;   /* size for partial read/write */
-    onebyt *rptr, *out_buf;
-    register int idx;
-    onebyt scratch[8];
-    long srcposn,	/* start in source file */
-	 startposn,	/* start in dest file */
-	 endposn;	/* end in dest file */
-    long unc_len = length,
-	 comp_len = 0L;
-    twobyt CRC;
-    int rlesize, lzwsize, out_size;	/* length after compression */
-    int sc;  /* spin counter */
-    static char *procName = "pak_SHK";
-
-    CRC = 0;
-    if ((srcposn = lseek(srcfd, 0L, S_REL)) < 0)	/* only used if */
-	Fatal("Bad seek (srcposn)", procName);		/* compress fails */
-    if ((startposn = lseek(dstfd, 0L, S_REL)) < 0)
-	Fatal("Bad seek (startposn)", procName);
-    lseek(dstfd, 4L, S_REL);  /* leave room for 4-byte header */
-    comp_len += 4L;
-
-    sc = 0;
-    do {  /* have to handle when length == 0L */
-	if (length > (long) BLKSIZ) {
-	    partial = (unsigned int) BLKSIZ;
-	    length -= (long) BLKSIZ;
-	} else {
-	    partial = (unsigned int) length;
-	    length = 0L;
-	    for (idx = partial; idx < BLKSIZ; idx++)  /* fill in zeroes */
-		*(copybuf + idx) = 0;
-	}
-
-	if (partial > 0) {  /* should work anyway, but let's be careful */
-	    if (read(srcfd, copybuf, partial) != partial)
-		Fatal("Source read failed", procName);
-	}
-	/* calc CRC on all 4096 bytes */
-	CRC = CalcCRC(CRC, (onebyt *) copybuf, BLKSIZ); 
-	rlesize = do_RLE(copybuf, copybuf + BLKSIZ+1);  /* pack 4096 bytes */
-	if (rlesize < 0x1000) {  /* did it pack or expand? */
-	    rptr = copybuf + BLKSIZ+1;  /* use packed version */
-	} else {
-	    rlesize = 0x1000;  /* just store original */
-	    rptr = copybuf;
-	}
-	ClearTab();
-	lzwsize = do_LZW(rptr, rlesize, lbuf);	/* compress from rle to lzw */
-	if ((lzwsize > rlesize) || (lzwsize < 0)) {
-	    /* lzw failed, use rle'd copy */
-	    scratch[2] = 0;
-	    out_size = rlesize;
-	    out_buf = rptr;
-	} else {
-	    /* lzw succeeded, use it */
-	    scratch[2] = 1;		/* LZW on */
-	    out_size = lzwsize;
-	    out_buf = lbuf;
-	}
-	scratch[0] = (onebyt) (rlesize & 0x00ff);	/* NOT out_size */
-	scratch[1] = (onebyt) ((rlesize >> 8) & 0x00ff);
-	if (write(dstfd, scratch, 3) != 3)
-	    Fatal("Dest hdr write failed", procName);
-	comp_len += 3;
-	comp_len += out_size;
-	if (comp_len > unc_len)
-	    goto bad_compress;		/* you didn't see this */
-	if (write(dstfd, out_buf, out_size) != out_size)  /* need to do CRLF */
-	    Fatal("Dest write failed", procName);
-
-	sc++;
-	if (sc == 15) {
-	    sc = 0;
-	    Spin();
-	}
-    } while (length != 0L);
-
-    if ((endposn = lseek(dstfd, 0L, S_REL)) < 0)
-	Fatal("Bad seek (now)", procName);
-    if (lseek(dstfd, startposn, S_ABS) < 0)
-	Fatal("Bad seek (to4)", procName);
-    scratch[0] = (char) CRC;
-    scratch[1] = (char) (CRC >> 8);
-    scratch[2] = 0;
-    scratch[3] = ESCAPE_CHAR;
-    if (write(dstfd, scratch, 4) != 4)
-	Fatal("Dest hdr write failed", procName);
-    if (lseek(dstfd, endposn, S_ABS) < 0)
-	Fatal("Bad seek (last)", procName);
-
-    if (comp_len != endposn - startposn) {
-	printf(
-	    "internal error: comp_len=%ld, endposn=%ld, startposn=%ld (%ld)\n",
-		comp_len, endposn, startposn, endposn - startposn);
-    }
-    packedSize = comp_len;
-    return (0x0002);	/* SHK packing */
-
-bad_compress:	/* I'm too lazy to do a procedure call... */
-
-    if (verbose) { printf("storing...");  fflush(stdout); }
-    if (lseek(srcfd, srcposn, S_ABS) < 0)
-	Fatal("Bad seek (srcposn in bad_compress)", procName);
-    if (lseek(dstfd, startposn, S_ABS) < 0)
-	Fatal("Bad seek (startposn in bad_compress)", procName);
-    FCopy(srcfd, dstfd, unc_len, copybuf, FALSE);
-    packedSize = unc_len;
-    return (0x0000);	/* no compression */
-}
-
-
-/*
- * P8 ShrinkIt uncompression routines
- *
- * Copyright 1989 Kent Dickey
- * C translation by Kent Dickey / Andy McFadden
- * Modifications for LZW-II by Andy Nicholas
- */
-
-static int inf;  /* to make Getc() calls happy */
-static BOOLEAN type2;	/* true if working with LZW-II format */
-
-static onebyt escape_char;
-
-typedef struct {
-    unsigned char chr;
-    int prefix;
-} Table_ent;
-
-static Table_ent Real_tab[BLKSIZ-256];  /* first 256 don't exist */
-static Table_ent *Table;
-
-static int Mask_tab[16] = {
-	0x0000, 0x01ff, 0x03ff, 0x03ff, 0x07ff,
-	0x07ff, 0x07ff, 0x07ff, 0x0fff, 0x0fff,
-	0x0fff, 0x0fff, 0x0fff, 0x0fff, 0x0fff,
-	0x0fff
-};
-static int Number[16] = {
-	0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4 };
-
-static onebyt Stack[100];  /* simulated stack; should be <= 64 */
-static int out_bytes, stack_ptr, entry, at_bit, at_byte;
-static onebyt last_byte;  /* used in get_code */
-
-
-/* fake Getc(); easier to make this a macro than to change the code */
-#ifdef DEBUG
-onebyt Getc(foo)
-int foo;  /* this is ignored */
-{
-    return (*(ibuf++));
-}
-#else  /* if not debugging, use a macro */
-# define Getc(foo) *(ibuf++)
-#endif /* DEBUG */
-
-
-/*
- * Stack operations; used by undo_LZW
- */
-#ifdef DEBUG
-void push(a_byte)
-unsigned char a_byte;
-{
-    if (stack_ptr > 100) {
-	printf("\n*** stack_ptr exceeded 100 in push() [%d]\n", stack_ptr);
-	exit (-1);
-    }
-    Stack[stack_ptr++] = a_byte;
-}
-#else  /* if not debugging, use a macro */
-# define push(a_byte) Stack[stack_ptr++] = a_byte
-#endif /* DEBUG */
-
-
-#ifdef DEBUG
-void dump_stack(buffer)
-unsigned char *buffer;
-{
-    printf("--- Going to dump stack, stack_ptr = %d, out_bytes = %d\n",
-	stack_ptr, out_bytes);
-    while (stack_ptr > 0) {
-	*(buffer + out_bytes++) = Stack[--stack_ptr];
-    }
-}
-#else  /* if not debugging, use a macro */
-# define dump_stack(buffer) while (stack_ptr > 0) { \
-				*( buffer +out_bytes++) = Stack[--stack_ptr];\
-			    }
-#endif /* DEBUG */
-
-
-/*
- * Decipher LZW codes.
- */
-static int get_code(/*Buffer*/)
-/*unsigned char *Buffer;*/
-{
-    register int num_bits, old_bit, last_bit;
-    long value, mask;
-    unsigned char byte1, byte2, byte3;  /* get compressed chars... */
-
-#ifdef DEBUG
-    printf("ENT: bit=%d byte=%-4d last_byte=$%.2x ",
-	at_bit, at_byte, last_byte);
-    printf("Entry: %.4x \n", entry);
-#endif
-
-    num_bits = ((entry+1) >> 8);  /* get hi-byte of entry */
-    last_bit = at_bit + Number[num_bits] + 8;
-    old_bit = at_bit;
-#ifdef DEBUG
-    if (at_byte >= BLKSIZ) {
-	fprintf(stderr, "at_byte exceeded BLKSIZ (4096) in get_code()\n");
-	exit (-1);
-    }
-#endif
-    if (at_bit == 0)
-	last_byte = Getc(inf);
-    byte1 = last_byte;  /* first byte = last one used */
-    byte2 = Getc(inf);
-    if (last_bit > 16) {  /* get 3rd byte if nec. */
-	byte3 = Getc(inf);
-	last_byte = byte3;
-    } else {
-	byte3 = 0;
-	last_byte = byte2;
-    }
-    value = ((((long)byte3 << 8) + (long)byte2) << 8) + (long)byte1;
-/*    value = (((Buffer[at_byte+2] << 8) + Buffer[at_byte+1]) << 8) +	*/
-/*	Buffer[at_byte];						*/
-
-    mask = (long) Mask_tab[num_bits];
-    at_byte += (last_bit >> 3);  /* new byte */
-    at_bit = (last_bit & 0x07);
-
-#ifdef DEBUG
-    printf("| EX: value=$%.6x mask=$%.4x return=$%.3x\n",
-	value, mask, ((value >> old_bit) & mask));
-#endif
-    if (old_bit)
-	return ((value >> old_bit) & mask);
-    else
-	return (value & mask);  /* shifting by zero may be undefined */
-}
-
-
-/*
- * Un-LZW a range of bytes
- *
- * Reads data with get_code (eventually from packBuffer) and stores the
- * output in "buffer".
- */
-static void undo_LZW(buffer, length)
-unsigned char *buffer;  /* where to put output */
-int length;  /* uncompressed length of output */
-{
-    register int oldc, incode, finalc, ptr;
-
-    /* initialize variables */
-    Table = Real_tab-256;
-    entry = 0x101;  /* start at $101 */
-    at_bit = at_byte = 0;
-    out_bytes = 0;
-    stack_ptr = 0;
-
-    last_byte = 0;  /* init last_byte */
-    oldc = incode = get_code(/*buffer*/);
-    finalc = (oldc & 0xff);
-    *(buffer + out_bytes++) = (unsigned char) incode;
-
-    /* main loop */
-    while (out_bytes < length) {
-	incode = ptr = get_code(/*buffer*/);
-	if (ptr >= entry) {
-	    push(finalc);
-	    ptr = oldc;
-	}
-	while (ptr > 0xff) {
-	    push(Table[ptr].chr);
-	    ptr = Table[ptr].prefix;
-	}
-
-	/* ptr is now < 0x100 */
-	finalc = ptr;
-	push(finalc);
-	dump_stack(buffer);
-	Table[entry].chr = (finalc & 0xff);  /* mask to get unsigned?? byte */
-	Table[entry].prefix = oldc;
-	entry++;
-	oldc = incode;
-    }
-}
-
-
-/*
- * Un-LZW-II a range of bytes (someday!)
- *
- * Reads data with get_code (eventually from packBuffer) and stores the
- * output in "buffer".  Has additional code to support LZW-II's table
- * clears.
- */
-static void undo_LZW_2(buffer, length)
-unsigned char *buffer;  /* where to put output */
-int length;  /* uncompressed length of output */
-{
-    register int oldc, incode, finalc, ptr;
-
-    /* initialize variables */
-    Table = Real_tab-256;
-    entry = 0x101;  /* start at $101 */
-    at_bit = at_byte = 0;
-    out_bytes = 0;
-    stack_ptr = 0;
-
-    last_byte = 0;  /* init last_byte */
-    oldc = incode = get_code(/*buffer*/);
-    finalc = (oldc & 0xff);
-    *(buffer + out_bytes++) = (unsigned char) incode;
-
-    /* main loop */
-    while (out_bytes < length) {
-	incode = ptr = get_code(/*buffer*/);
-	if (ptr >= entry) {
-	    push(finalc);
-	    ptr = oldc;
-	}
-	while (ptr > 0xff) {
-	    push(Table[ptr].chr);
-	    ptr = Table[ptr].prefix;
-	}
-
-	/* ptr is now < 0x100 */
-	finalc = ptr;
-	push(finalc);
-	dump_stack(buffer);
-	Table[entry].chr = (finalc & 0xff);  /* mask to get unsigned?? byte */
-	Table[entry].prefix = oldc;
-	entry++;
-	oldc = incode;
-    }
-}
-
-
-/*
- * Second pass... undo the Run Length Encoding.
- *
- * Copy data from inbuffer to outbuffer.  Keep going until we've got
- * exactly BLKSIZ bytes.  Note that this uses codes of the form
- *   <DLE> char count
- * which is different from some other programs.
- */
-static void undo_RLE(inbuffer, outbuffer)
-unsigned char *inbuffer, *outbuffer;
-/*int length;  /* how many bytes from LZW; just to make sure... */
-{
-    register unsigned char c;
-    register int total, count;  /* count is RLE reps */
-
-#ifdef DEBUG
-    /*printf("Starting undo_RLE, length = %d\n", length);*/
-#endif
-    total = 0;
-    while (total < BLKSIZ) {
-	c = *(inbuffer++);  /*length--;*/
-	if (c == (onebyt) escape_char) {
-	    c = *(inbuffer++);  /*length--;*/
-	    count = *(inbuffer++);  /*length--;*/
-	    total += count +1;  /* count of zero -> 1 byte */
-	    while (count-- >= 0) {
-		*(outbuffer++) = c;  /*Putc(c, outf);*/
-	    }
-	} else {
-	    *(outbuffer++) = c;  /*Putc(c, outf);*/
-	    total++;
-	}
-    }
-
-    if (total != 4096)
-	fprintf(stderr, "internal error: bad undo_RLE\n");
-#ifdef DEBUG
-/*    printf("Exiting undo_RLE, length = %d (should be 0), total = %d (4096)\n",
-	length, total);*/
-#endif
-}
-
-
-/*
- * Main entry point.
- *
- * This is among the more hellish things I've written.  Uses
- *   a large buffer for efficiency reasons, and unpacks a stream of bytes
- *   (LZW-II improves things a little).
- * If you find this hard to understand, imagine what it was like to debug.
- *
- * Could use some cleaning up, esp argument list...
- */
-void
-unpak_SHK(srcfd,dstfd,comp_thread_eof,thread_eof,buffer, use_type2, thread_crc)
-int srcfd, dstfd;
-fourbyt comp_thread_eof, thread_eof;
-register onebyt *buffer;
-BOOLEAN use_type2;		/* true if we should expect LZW-II */
-twobyt thread_crc;
-{
-    twobyt CRC, blkCRC;
-    onebyt vol;
-    onebyt *wrbuf;  /* points to buffer we're about to write */
-    short unlen, lzwflag, rleflag, complen;	/* should be short */
-    unsigned int partial, toread, still_in_buf;
-    fourbyt tmp4;  /* temporary 4-byte variable */
-    int cc;
-    static char *procName = "unpak_SHK";
-
-    CRC = 0;
-    type2 = use_type2;
-
-    /* read min(PAKBUFSIZ, comp_thread_eof) bytes into buffer */
-    if (comp_thread_eof > (fourbyt) PAKBUFSIZ) {
-	toread = (unsigned int) PAKBUFSIZ;
-	comp_thread_eof -= (fourbyt) PAKBUFSIZ;
-    } else {
-	toread = (unsigned int) comp_thread_eof;  /* read it all... */
-	comp_thread_eof = (fourbyt) 0;
-    }
-
-    /* do initial read */
-#ifdef DEBUG1
-    printf("initial read = %u\n", toread);
-#endif
-    if ((cc = read(srcfd, buffer, toread)) < toread) {
-#ifdef DEBUG1
-	printf("Only read %d bytes\n", cc);
-#endif
-	Fatal("Bad read during uncompress", procName);
-    }
-    ibuf = buffer;  /* set input pointer to start of buffer */
-
-    /* get header data */
-    if (type2) {
-	blkCRC = thread_crc;
-    } else {
-	blkCRC = Getc(inf);
-	blkCRC += (Getc(inf) << 8);
-    }
-    vol = (char) Getc(inf);  /* disk volume #; not used here */
-    escape_char = (char) Getc(inf);  /* RLE delimiter */
-
-#ifdef DEBUG1
-    printf("vol = %d, escape_char = %x\n", vol, escape_char);
-#endif
-
-    /*
-     * main loop
-     */
-    while (thread_eof != (fourbyt) 0) {
-
-	/* note "unlen" is un-LZWed length (i.e., after RLE) */
-	if (type2) {
-	    unlen = Getc(inf);
-	    unlen += (Getc(inf) << 8);
-	    lzwflag = (unlen & 0x8000) ? 1 : 0;	/* flag is hi bit */
-	    unlen &= 0x1fff;			/* strip extra stuff */
-	    rleflag = (unlen != BLKSIZ);
-	    if (lzwflag) {	/* will the real length bytes please stand up*/
-		complen = Getc(inf);
-		complen += (Getc(inf) << 8);
-	    }
-	} else {
-	    unlen = Getc(inf);
-	    unlen += (Getc(inf) << 8);
-	    lzwflag = Getc(inf);
-	    rleflag = (unlen != BLKSIZ);
-	}
-#ifdef DEBUG1
-	printf("Length after RLE = %d ($%.4x)\n", unlen, unlen);
-	printf("LZW flag = %d, RLE flag = %d\n", lzwflag, rleflag);
-	if (lzwflag != 0 && lzwflag != 1) {  /* this is weird... */
-	    for (lzwflag = -6; lzwflag < 3; lzwflag++) {
-		printf("foo %d: %.2x\n", lzwflag, *(ibuf+lzwflag));
-	    }
-	}
-	if (type2 && lzwflag) {
-	    printf("Length after RLE+LZW = %d ($%.4x)\n", complen, complen);
-	}
-#endif
-
-	/* If it looks like we're going to run out of room, shift & read
-	/* Mostly a guess; LZW length is less than unlen...  This is
-	/* complicated and very prone to errors.
-	/* tmp4 is the number of bytes between the current ptr and the end;
-	/* some (16-bit) compilers yack if it's all one statement.*/
-	tmp4 = (fourbyt) buffer + (fourbyt) PAKBUFSIZ;
-	tmp4 -= (fourbyt) ibuf;
-	if (tmp4 < (unlen + 6)) {  /* 6 = 3/4 byte header + two just in case */
-	    still_in_buf = tmp4;
-
-#ifdef DEBUG1
-	    printf("--- unlen = %d, space left = %d bytes\n",
-		    unlen, still_in_buf);
-#endif
-	    BCopy((onebyt *) ibuf, (onebyt *) buffer, still_in_buf, FALSE);
-	    if (comp_thread_eof != (fourbyt) 0) {  /* no read, just shift */
-		if (comp_thread_eof > ((fourbyt) PAKBUFSIZ - still_in_buf)){
-		    toread = (unsigned int) PAKBUFSIZ - still_in_buf;
-		    comp_thread_eof -= (fourbyt) PAKBUFSIZ - still_in_buf;
-		} else {
-		    toread = (unsigned int) comp_thread_eof;
-		    comp_thread_eof = (fourbyt) 0;
-		}
-#ifdef DEBUG1
-		printf("--- reading another %u bytes\n", toread);
-#endif
-		if (read(srcfd, buffer+still_in_buf, toread) < toread)
-		    Fatal("Unable to read [middle]", procName);
-		if (verbose) Spin();
-	    }
-	    ibuf = buffer;
-	}
-    
-	/* how much of the buffered data do we really need? */
-	if (thread_eof > (fourbyt) BLKSIZ) {
-	    partial = (unsigned int) BLKSIZ;
-	    thread_eof -= (fourbyt) BLKSIZ;
-	} else {
-	    partial = (unsigned int) thread_eof;  /* last block of file */
-	    thread_eof = (fourbyt) 0;
-	}
-
-	/*
-	 * undo_LZW reads from ibuf (using Getc()) and writes to lbuf
-	 * undo_LZW_2 does what undo_LZW does, but for LZW-II.
-	 * undo_RLE reads from where you tell it and writes to rbuf
-	 *
-	 * This is really insane...
-	 */
-	if (lzwflag && rleflag) {
-	    if (type2)
-		undo_LZW_2(lbuf, unlen);  /* from ibuf -> lbuf */
-	    else
-		undo_LZW(lbuf, unlen);  /* from ibuf -> lbuf */
-	    undo_RLE(lbuf, rbuf);  /* from lbuf -> rbuf */
-	    wrbuf = rbuf;  /* write rbuf */
-	    CRC = CalcCRC(CRC, (onebyt *) rbuf, BLKSIZ);  /* always 4K bytes */
-	} else if (lzwflag && !rleflag) {
-	    if (type2)
-		undo_LZW_2(lbuf, unlen);  /* from ibuf -> lbuf */
-	    else
-		undo_LZW(lbuf, unlen);  /* from ibuf -> lbuf */
-	    wrbuf = lbuf;  /* write lbuf */
-	    CRC = CalcCRC(CRC, (onebyt *) lbuf, BLKSIZ);
-	} else if (!lzwflag && rleflag) {
-	    undo_RLE(ibuf, rbuf);  /* from ibuf -> rbuf */
-	    wrbuf = rbuf;  /* write rbuf */
-	    CRC = CalcCRC(CRC, (onebyt *) rbuf, BLKSIZ);
-	    ibuf += unlen;  /* have to skip over RLE-only data */
-			/* normally ibuf is advanced by Getc() calls */
-	} else {
-	    wrbuf = ibuf;  /* write ibuf */
-	    CRC = CalcCRC(CRC, (onebyt *) ibuf, BLKSIZ);
-	    ibuf += partial;  /* skip over uncompressed data */
-			/* normally ibuf is advanced by Getc() calls */
-	}
-#ifdef DEBUG1
-	printf("Writing %d bytes.\n", partial);
-#endif
-	if (crlf(dstfd, wrbuf, partial) < partial)  /* write wrbuf */
-	    Fatal("Bad write", procName);
-    }
-
-    if (CRC != blkCRC) {
-	fprintf(stderr, "WARNING: CRC does not match...");
-	if (verbose) fprintf(stderr, "\n");
-	else fprintf(stderr, "extract with V suboption to see filenames.\n");
-    }
-}
-
=nuadd.c
-/*
- * nuadd.c - operations which add to a NuFX archive
- *
- * NuLib v3.0  February 1991  Freeware (distribute, don't sell)
- * By Andy McFadden (fadden@cory.berkeley.edu)
- */
-#ifdef APW
-segment "NuMain"
-#endif
-
-#include "nudefs.h"
-#include <stdio.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <ctype.h>
-#ifdef BSD43
-# include <strings.h>
-#else
-# include <string.h>
-#endif
-
-#ifdef UNIX
-# include <sys/types.h>
-# include <sys/stat.h>
-# ifdef XENIX386
-#  include <sys/ndir.h>		/* maybe <sys/ndir.h>, <dirent.h>, <dir.h>...*/
-# else
-#  include <sys/dir.h>
-# endif
-#endif
-#ifdef APW
-# include <types.h>
-# include <prodos.h>
-# include <shell.h>
-# include <strings.h>
-#endif
-#ifdef MSDOS
-# include <stdlib.h>
-# include <errno.h>
-# include <time.h>
-# include <io.h>
-# include <sys/types.h>
-# include <sys/stat.h>
-#endif
-
-#include "nuread.h"
-#include "nuadd.h"
-#include "nupak.h"
-#include "nuetc.h"
-
-#ifdef DATAGENERAL					/* BAK */
-# ifdef AOSVS						/* BAK */
-#  define BROKEN_ON_MVs				/* MV/UX is NOT a full UNIX */
-# endif						/* implem. so we just skip */
-#endif						/* the 'UNIX' code on MVs */
-
-#define MAXGSPREFIX 64
-
-static BOOLEAN domove;    /* are we M)oving the files in? */
-static BOOLEAN docreate;  /* using the 'C' option? */
-
-
-/*
- * Expand command args into filenames
- * Stuff number of names into int; build File Information Array.
- * (this routine is heavily implementation-specific, since no two systems
- *  expand wildcards or deal with subdirectories in the same way).
- *
- * Recursively expands subdirectories, unless doSubdir is FALSE.
- */
-int EvalArgs(count, names, FIArray, first)
-int count;	/* #of filenames */
-char **names;	/* array of file names */
-file_info *FIArray[];  /* array to fill with file info */
-BOOLEAN first;	/* first time through? */
-{
-    static char *procName = "EvalArgs";
-#ifdef UNIX
-    /* UNIX shells (sh, csh) won't expand subdirectories, but they do
-     * expand wildcards in arguments before we get them
-     */
-    static int idx;
-    struct stat st;
-    char *cp;  /* temp char pointer */
-    /* dir stuff */
-    int newcount;
-    char **newnames;
-#ifndef BROKEN_ON_MVs
-    DIR *dirp;
-#endif
-    struct direct *dp;
-    int nmlen;
-
-    if (first) idx = 0;
-
-    while (count--) {
-	FIArray[idx] = (file_info *) Malloc(sizeof(file_info));
-
-	if (stat(*names, &st) < 0) {  /* get file info */
-	    if (errno == ENOENT) {
-		fprintf(stderr, "%s: '%s' not found\n", prgName, *names);
-		names++;
-		continue;  /* with while */
-	    }
-	    Fatal("Bad stat()", procName);
-	}
-
-	if ((st.st_mode & S_IFDIR) && doSubdir) {  /* is it a directory? */
-# ifndef BROKEN_ON_MVs
-	    newnames = (char **) Malloc(MAXARGS * sizeof(char *));
-	    strcpy(tmpNameBuf, *names);  /* earlier dir stuff */
-	    strcat(tmpNameBuf, "/");
-	    nmlen = strlen(tmpNameBuf);
-
-	    if ((dirp = opendir(*names)) == NULL)
-		Fatal("Unable to open subdirectory", procName);
-	    for (newcount=0, dp=readdir(dirp); dp != NULL; dp=readdir(dirp)) {
-		if ((!strcmp(dp->d_name, ".")) || (!strcmp(dp->d_name, "..")))
-		    continue;  /* with for */
-		newnames[newcount] = (char *) Malloc(nmlen + dp->d_namlen +1);
-		strcpy(newnames[newcount], tmpNameBuf);
-		strcat(newnames[newcount], dp->d_name);  /* append the name */
-		newcount++;
-	    }
-	    closedir(dirp);
-
-	    EvalArgs(newcount, newnames, FIArray, FALSE);  /* do subdir */
-
-	    while (newcount-- > 0)  /* free up the space we allocated */
-		free(newnames[newcount]);
-	    free(newnames);
-
-	    names++;
-# else								/* BAK */
-	    printf("Help, I ran into a directory and can't handle it!\n");
-# endif								/* BAK */
-	} else if ((st.st_mode & S_IFDIR) && !doSubdir) {
-	    /* maybe print message? */
-	    names++;
-	    continue;	/* with while */
-	} else if (st.st_mode & S_IFREG) {
-	    FIArray[idx]->eof = (long) st.st_size;
-
-	    if (st.st_mode & S_IWRITE)  /* write permission enabled? */
-		FIArray[idx]->fAccess = (fourbyt) 0x00e3;	/* locked */
-	    else
-		FIArray[idx]->fAccess = (fourbyt) 0x0021;	/* unlocked */
-
-	    FIArray[idx]->fileType = defFileType;
-	    FIArray[idx]->auxType = defAuxType;
-	    FIArray[idx]->fileSysID = 0x0001;  /* ProDOS */
-	    FIArray[idx]->fileSysInfo = 0x2f;  /* '/' */
-	    ExpandTime(&st.st_mtime, &FIArray[idx]->create_dt);  /*use mod.. */
-	    ExpandTime(&st.st_mtime, &FIArray[idx]->mod_dt); /*time for both */
-	    FIArray[idx]->marked = FALSE;
-
-	    FIArray[idx]->pathname = (char *) Malloc(strlen(*names)+1);
-	    strcpy(FIArray[idx]->pathname, *names);
-	    FIArray[idx]->store_name = (char *) Malloc(strlen(*names)+1);
-	    cp = *names;
-	    while (*cp == '/') cp++;  /* advance past leading '/' */
-	    strcpy(FIArray[idx]->store_name, cp);  /* can't otherwise fix */
-
-	    names++;
-	    idx++;
-	} else {
-	    printf("Unknown storage type for '%s'\n", *names);
-	    names++;
-	    continue;	/* with while */
-	}
-
-    }
-    return (idx);
-
-#else /* UNIX */
-# ifdef APW
-    static int idx;  /* will eventually hold the total #of filenames */
-    char *nextname = (char *) Malloc(MAXFILENAME);  /* for subdir expand */
-    char prefix[MAXGSPREFIX+1];  /* Max ProDOS prefix size; now 64 */
-    char *fnptr;
-    FileRec finfo_p;
-    PrefixRec prefix_p;
-    OpenRec open_p;
-    EOFRec eof_p;
-
-    if (first) idx = 0;
-
-    prefix_p.prefixNum = 0;  /* current dir */
-    prefix_p.prefix = prefix;  /* prefix buffer */
-    GET_PREFIX( &prefix_p );
-    ToolErrChk();
-    p2cstr(prefix);
-
-    while (count) {
-	strcpy(tmpNameBuf, *names);
-	c2pstr(tmpNameBuf);
-	INIT_WILDCARD(tmpNameBuf, 0);
-	ToolErrChk();
-
-	while (*NEXT_WILDCARD(tmpNameBuf)) {
-	    if (idx >= MAXARGS) {
-		fprintf(stderr, "Too many files (%d, %d max)\n", idx, MAXARGS);
-		Quit (-1);
-	    }
-
-	    finfo_p.pathname = tmpNameBuf;
-	    GET_FILE_INFO( &finfo_p );
-	    ToolErrChk();
-
-	    open_p.openPathname = tmpNameBuf;
-	    OPEN( &open_p );
-	    ToolErrChk();
-
-	    eof_p.eofRefNum = open_p.openRefNum;
-	    GET_EOF( &eof_p );
-	    ToolErrChk();
-
-	    CLOSE( &open_p );
-	    ToolErrChk();
-
-	    p2cstr(tmpNameBuf);  /* also does p2cstr(finfo_p.pathname) */
-	    switch (finfo_p.storageType) {
-	    case 0x00:	/* standard ProDOS storage types */
-	    case 0x01:
-	    case 0x02:
-	    case 0x03:
-		FIArray[idx] = (file_info *) Malloc(sizeof(file_info));
-
-		FIArray[idx]->eof = eof_p.eofPosition;
-		FIArray[idx]->fAccess = finfo_p.fAccess;
-		FIArray[idx]->fileType = (fourbyt) finfo_p.fileType;
-		FIArray[idx]->auxType = (fourbyt) finfo_p.auxType;
-		FIArray[idx]->storageType = finfo_p.storageType;
-		FIArray[idx]->fileSysID = 0x0001;  /* ProDOS */
-		FIArray[idx]->fileSysInfo = 0x2f;  /* '/' */
-		ExpandTime(&finfo_p.createDate, &FIArray[idx]->create_dt);
-		ExpandTime(&finfo_p.modDate, &FIArray[idx]->mod_dt);
-		FIArray[idx]->marked = FALSE;
-
-		FIArray[idx]->pathname = (char *) Malloc(strlen(tmpNameBuf)+1);
-		strcpy(FIArray[idx]->pathname, tmpNameBuf);
-
-		/* are we adding from current directory? */
-		if (!strncmp(tmpNameBuf, prefix, strlen(prefix))) {
-		    FIArray[idx]->store_name =			      /* yes */
-		       (char *) Malloc(strlen(tmpNameBuf) - strlen(prefix) +1);
-		  strcpy(FIArray[idx]->store_name, tmpNameBuf+ strlen(prefix));
-		} else {
-		    fnptr = RINDEX(tmpNameBuf, '/') + 1;	      /* no  */
-		    FIArray[idx]->store_name = (char *)Malloc(strlen(fnptr)+1);
-		    strcpy(FIArray[idx]->store_name, fnptr);
-		}
-		idx++;
-		break;
-
-	    case 0x05:
-		printf("Can't handle Extended file '%s'\n", tmpNameBuf);
-		break;
-	    case 0x0d:
-		if (doSubdir) {
-		    strcpy(nextname, tmpNameBuf);  /* make new copy */
-		    strcat(nextname, "/=");  /* APW-only wildcard */
-		    EvalArgs(1, &nextname, FIArray, FALSE);  /* read subdir */
-		}
-		break;
-	    default:
-		printf("Unknown storage type for '%s'\n", tmpNameBuf);
-		break;
-	    }
-
-	} /* inner while */
-
-	names++, count--;
-    }  /* outer while */
-    free (nextname);
-    return (idx);
-# endif /* APW */
-
-# ifdef MSDOS
-    /* MS-DOS or other shell wildcard expansion here */
-    int idx, error;
-    struct stat fStat;
-
-    idx = 0;
-
-    while (count--) {
-
-	error = stat (*names, &fStat);
-
-	/* If the filename is a directory, we need to expand that too! */
-
-	if (!error) {
-	    FIArray[idx]              = (file_info *) Malloc(sizeof(file_info));
-	    FIArray[idx]->pathname    = (char *) Malloc(strlen(*names)+1);
-	    strcpy(FIArray[idx]->pathname, *names);
-	    FIArray[idx]->store_name  = (char *) Malloc(strlen(*names)+1);
-	    strcpy(FIArray[idx]->store_name, *names);
-	    FIArray[idx]->fAccess     = 0x00e3L;  /* unlocked */
-	    FIArray[idx]->fileType    = defFileType;
-	    FIArray[idx]->auxType     = defAuxType;
-	    FIArray[idx]->storageType = 0x0000;
-	    FIArray[idx]->fileSysID   = 0x0001;  /* ProDOS */
-	    FIArray[idx]->fileSysInfo = 0x1c;  /* '\' */
-	    ExpandTime(&fStat.st_ctime, &FIArray[idx]->create_dt);
-	    ExpandTime(&fStat.st_mtime, &FIArray[idx]->mod_dt);
-	    FIArray[idx]->eof = fStat.st_size;
-
-	    FIArray[idx]->marked = FALSE;
-	    idx++;
-	}
-	names++;
-    }
-    return (idx);
-# endif /* MDOS */
-
-# ifndef APW
-# ifndef MSDOS
-    /* nothing else defined */
-
-    /* +PORT+ */
-    printf("\n[other] wildcard expansion/file info needs work\n");
-    while (count--) {
-	FIArray[count] = (file_info *) Malloc(sizeof(file_info));
-
-	FIArray[count]->pathname = (char *) Malloc(strlen(*names)+1);
-	strcpy(FIArray[count]->pathname, *names);
-	FIArray[count]->store_name = (char *) Malloc(strlen(*names)+1);
-	strcpy(FIArray[count]->store_name, *names);
-	FIArray[count]->fAccess = 0x00e3L;  /* unlocked */
-	FIArray[count]->fileType = 0x0006L;  /* BIN */
-	FIArray[count]->auxType = 0L;
-	FIArray[count]->storageType = 0x0000;
-	FIArray[count]->fileSysID = 0x0001;  /* ProDOS */
-	FIArray[count]->fileSysInfo = 0x1c;  /* '\' */
-	ExpandTime((char *) NULL, &FIArray[count]->create_dt);
-	ExpandTime((char *) NULL, &FIArray[count]->mod_dt);
-	FIArray[count]->marked = FALSE;
-
-	names++;
-    }
-    return (count);
-# endif /* none2 */
-# endif /* none1 */
-#endif /* UNIX */
-}
-
-
-/*
- * Add a file onto the end of an archive; does not check to see if an entry
- * already exists.
- *
- * This creates the record entry, and calls subroutines to add the various
- * threads.  The archive fd should be open, the file fd should not.  Returns
- * the size of the record added.
- */
-long AddFile(arcfd, infoptr)
-int arcfd;
-file_info *infoptr;
-{
-    int srcfd;	/* file to add */
-    onebyt *recBuf;  /* record header block */
-    twobyt *twoptr;
-    THblock thread[1];	/* thread block */
-    twobyt CRC;
-    int idx;
-    fourbyt total_threads;
-    long recposn;  /* file posn for record entry */
-    long thposn;   /* file posn for last thread */
-    long tmpposn;  /* temporary file posn */
-    static char *procName = "AddFile";
-
-    if (verbose) {
-	printf("Adding '%s' (data)...",
-					  infoptr->store_name, infoptr->eof);
-	fflush(stdout);
-    }
-
-    recBuf = (onebyt *) Malloc(ATTSIZE);
-    for (idx = 0; idx < ATTSIZE; idx++)  /* zero the buffer */
-	*(recBuf+idx) = 0;
-
-    total_threads = 0;
-
-    strncpy((char *) recBuf+0, (char *) RecordID, 4);
-    twoptr = (twobyt *) (recBuf+6);
-    *twoptr = ATTSIZE;	/* don't have an attrib_count... */
-    HiSwap((onebyt *) recBuf, 6, 7);
-    twoptr = (twobyt *) (recBuf+8);
-    *twoptr = OURVERS;	/* store new record with our rec vers */
-    HiSwap((onebyt *) recBuf, 8, 9);
-    /* total_threads */
-/*    BCopy((onebyt *) &total_threads, (onebyt *) recBuf+10, 2, TRUE); */
-    *(recBuf+12) = 0;  /* reserved1 */
-    *(recBuf+13) = 0;
-    BCopy((onebyt *) &infoptr->fileSysID, (onebyt *) recBuf+14, 2, TRUE);
-    BCopy((onebyt *) &infoptr->fileSysInfo, (onebyt *) recBuf+16, 1, TRUE);
-    *(recBuf+17) = 0;  /* reserved2 */
-    BCopy((onebyt *) &infoptr->fAccess, (onebyt *) recBuf+18, 4, TRUE);
-    BCopy((onebyt *) &infoptr->fileType, (onebyt *) recBuf+22, 4, TRUE);
-    BCopy((onebyt *) &infoptr->auxType, (onebyt *) recBuf+26, 4, TRUE);
-    BCopy((onebyt *) &infoptr->create_dt, (onebyt *) recBuf+32,
-	sizeof(Time), FALSE);
-    BCopy((onebyt *) &infoptr->mod_dt, (onebyt *) recBuf+40, sizeof(Time),
-	FALSE);
-    BCopy((onebyt *) GetTime(), (onebyt *) recBuf+48, sizeof(Time), FALSE);
-    twoptr = (twobyt *) (recBuf + (ATTSIZE - 2));
-    *twoptr = strlen(infoptr->store_name);
-
-    /* correct strlen ordering */
-    HiSwap((onebyt *) recBuf, ATTSIZE-2, ATTSIZE-1);
-
-    thread[0].thread_class = 0x0002;  /* data */
-    HiSwap((onebyt *) &thread[0].thread_class, 0, 1);
-    thread[0].thread_kind = 0x0000;  /* data fork */
-    HiSwap((onebyt *) &thread[0].thread_kind, 0, 1);
-    thread[0].thread_format = 0x0000;  /* filled in later */
-    thread[0].thread_crc = 0x0000;  /* not supported yet */
-    /* so I don't forget if I support these */
-    HiSwap((onebyt *) &thread[0].thread_crc, 0, 1); 
-    thread[0].thread_eof = infoptr->eof;
-    HiSwap((onebyt *) &thread[0].thread_eof, 0, 3);
-    HiSwap((onebyt *) &thread[0].thread_eof, 1, 2);
-    thread[0].comp_thread_eof = -1L;  /* filled in later */
-    total_threads++;
-
-    BCopy((onebyt *) &total_threads, (onebyt *) recBuf+10, 4, TRUE);
-
-    /*
-     * Because we don't know CRCs or compressed size yet, we must:
-     * skip record entry and filename.
-     * for each thread:
-     *	 skip thread entry, write data, move back, write thread entry.
-     * move back, write record entry and filename.
-     * move forward to next position.
-     */
-    if ((srcfd = open(infoptr->pathname, O_RDONLY | O_BINARY)) < 0)
-	Fatal("Unable to open file", procName);
-
-    recposn = lseek(arcfd, 0L, S_REL);	/* save record posn */
-    if (lseek(arcfd, (long) (ATTSIZE + strlen(infoptr->store_name)), S_REL)<0)
-	Fatal("Bad seek (R.rel)", procName);
-
-    /* loop... */
-    thposn = lseek(arcfd, 0L, S_REL);  /* save thread posn */
-    if (lseek(arcfd, (long) THsize, S_REL) < 0)
-	Fatal("Bad seek (Th)", procName);
-
-    /*
-     * since we can store files as being packed without actually packing them,
-     * we need to check "dopack" to see if we want packMethod or zero.  Note
-     * that packing can fail for various reasons; the value returned by
-     * PackFile() is the actual algorithm used to pack the file.
-     *
-     * NuLib uses version 0 records; thread_crcs are not stored.
-     */
-
-    thread[0].thread_format = 
-	    PackFile(srcfd,arcfd, infoptr->eof, dopack ? packMethod:0, pakbuf);
-    if (!dopack) thread[0].thread_format = packMethod;  /* for S subopt */
-    HiSwap((onebyt *) &thread[0].thread_format, 0, 1);
-    thread[0].comp_thread_eof = (fourbyt) packedSize;
-    HiSwap((onebyt *) &thread[0].comp_thread_eof, 0, 3);  /* correct ordering*/
-    HiSwap((onebyt *) &thread[0].comp_thread_eof, 1, 2);
-    tmpposn = lseek(arcfd, 0L, S_REL);
-
-    if (lseek(arcfd, thposn, S_ABS) < 0)  /* seek back to thread posn */
-	Fatal("Bad seek (Th2)", procName);
-    if (write(arcfd, &thread[0], THsize) < THsize)  /* write updated thread */
-	Fatal("Unable to write thread", procName);
-    if (lseek(arcfd, tmpposn, S_ABS) < 0)  /* seek back to where we were */
-	Fatal("Bad seek (TmpA)", procName);
-    /* ...loop end */
-
-    if (close(srcfd) < 0)
-	Fatal("Unable to close file", procName);
-
-    CRC = CalcCRC(0, (onebyt *) recBuf+6, ATTSIZE-6);
-    CRC = CalcCRC(CRC, (onebyt *) infoptr->store_name,
-	strlen(infoptr->store_name));
-    CRC = CalcCRC(CRC, (onebyt *) &thread[0], THsize);
-    twoptr = (twobyt *) (recBuf+4);
-    *twoptr = CRC;
-    HiSwap((onebyt *) recBuf, 4, 5);
-
-    tmpposn = lseek(arcfd, 0L, S_REL);	   /* record posn (next posn) */
-    if (lseek(arcfd, recposn, S_ABS) < 0)  /* seek back to record entry */
-	Fatal("Bad seek (R.abs)", procName);
-    if (write(arcfd, recBuf, ATTSIZE) < ATTSIZE)
-	Fatal("Unable to write record", procName);
-    if (write(arcfd, infoptr->store_name, strlen(infoptr->store_name))
-				     < strlen(infoptr->store_name))
-	Fatal("Unable to store filename", procName);
-    if (lseek(arcfd, tmpposn, S_ABS) < 0)  /* seek back to where we were */
-	Fatal("Bad seek (TmpB)", procName);
-
-    if (verbose) printf("done.\n");
-    free(recBuf);
-
-    /* switch ordering back */
-    HiSwap((onebyt *) &thread[0].comp_thread_eof, 0, 3);
-    HiSwap((onebyt *) &thread[0].comp_thread_eof, 1, 2);
-    return ( (long) (THsize * total_threads) + (long) ATTSIZE +
-	  (long) strlen(infoptr->store_name) + thread[0].comp_thread_eof);
-}
-
-
-/*
- * Certain options can cause an archive to be created (add, create, move).
- * If the archive does not already exist, then an empty file is created (of
- * type $e0/8002 under ProDOS) and an empty archive struct is built.
- *
- * Note that this requires certain options to deal with archive structures that
- * do not have any records, and archive files that are empty.
- *
- * If the file exists, this will call NuRead() to read it; otherwise, it will
- * create it.
- */
-static ListHdr *CreateMaybe(filename)
-char *filename;
-{
-    ListHdr *archive;
-    MHblock *MHptr;
-    onebyt *bufPtr;
-    twobyt *twoptr;
-    fourbyt *fourptr;
-    int idx;
-#ifdef APW
-    FileRec create_p;
-#endif
-    static char *procName = "CreateMaybe";
-
-    if (Exists(filename)) {
-	archive = NuRead(filename);
-	return (archive);
-    }
-
-    if (!docreate)
-	printf("Archive does not exist; creating archive file...\n");
-
-    archive = (ListHdr *) Malloc(sizeof(ListHdr));
-    archive->arc_name = (char *) Malloc(strlen(filename)+1);
-    strcpy(archive->arc_name, filename);
-    archive->MHptr = (MHblock *) Malloc(sizeof(MHblock));
-    archive->RNodePtr = (RNode *) NULL;
-    archive->nextposn = (long) MHsize;
-
-    bufPtr = (onebyt *) archive->MHptr;
-    for (idx = 0; idx < MHsize; idx++)
-	*(bufPtr+idx) = '\0';
-
-    /* total_records -> zero */
-    MHptr = archive->MHptr;
-    strncpy((char *) MHptr->ID, (char *) MasterID, 6);
-    BCopy((onebyt *) GetTime(), (onebyt *) &(MHptr->arc_create_when),8, FALSE);
-    BCopy((onebyt *) bufPtr+12, (onebyt *) &(MHptr->arc_mod_when), 8, FALSE);
-    fourptr = (fourbyt *) (&(MHptr->master_eof));
-    *fourptr = (fourbyt) MHsize;
-
-/*    twoptr = (twobyt *) (&(MHptr->master_crc));
-    *twoptr = CalcCRC(0, (onebyt *) bufPtr+8, MHsize-8); */
-
-    ArcfiCreate(filename);  /* create SHK file */
-    return (archive);
-}
-
-
-/*
- * Return a pointer to a valid Master Header block
- * Anything that isn't set to a default value needs to be passed as a
- * parameter [ right now I can't remember why ].
- */
-onebyt *MakeMHblock(archive, total_records, master_eof)
-ListHdr *archive;
-fourbyt total_records;
-fourbyt master_eof;
-{
-    static onebyt buf[MHsize];  /* must be static */
-    twobyt *twoptr;
-    fourbyt *fourptr;
-    int idx;
-    static char *procName = "MakeMHblock";
-
-    for (idx = 0; idx < MHsize ; idx++)
-	buf[idx] = '\0';
-
-    /* messy... should've used MHptr->thing here, but if it ain't broke... */
-    strncpy((char *) buf, (char *) MasterID, 6);
-    BCopy((onebyt *) &total_records, (onebyt *) &buf[8], 4, TRUE);
-    BCopy((onebyt *) &archive->MHptr->arc_create_when, (onebyt *) &buf[12],
-	sizeof(Time), FALSE);
-    BCopy((onebyt *) GetTime(), (onebyt *) &buf[20], sizeof(Time), FALSE);
-    twoptr = (twobyt *) &buf[28];  /* master version */
-    *twoptr = OURMVERS;
-    HiSwap((onebyt *) buf, 28, 29);  /* correct byte ordering */
-    BCopy((onebyt *) &master_eof, (onebyt *) &buf[38], 4, TRUE);
-    twoptr = (twobyt *) &buf[6];
-    *twoptr = CalcCRC(0, (onebyt *) &buf[8], MHsize-8);
-    HiSwap((onebyt *) buf, 6, 7);
-
-    return (buf);
-}
-
-
-/*
- * Add files to archive
- *
- * Read files from disk, adding them to the end of the archive as we go.
- * Update the master header block after all files have been added.
- */
-static void Add(filename, namecount, names)
-char *filename;
-int namecount;
-char **names;
-{
-    ListHdr *archive;
-    int arcfd;
-    file_info *FIArray[MAXARGS];  /* entries malloc()ed by EvalArgs */
-    int idx;
-    onebyt *mptr;  /* points to a MHblock suitable for writing */
-    long addSize;
-    static char *procName = "Add";
-
-    /* expand wildcards/subdirectories, and get file info */
-    namecount = EvalArgs(namecount, names, FIArray, TRUE);
-    if (!namecount) {
-	if (verbose) printf("No files selected.\n");
-	Quit (0);
-    }
-
-    archive = CreateMaybe(filename);
-    if ((arcfd = open(archive->arc_name, O_RDWR | O_BINARY)) < 0)
-	Fatal("Unable to open archive", procName);
-    if (lseek(arcfd, archive->nextposn, S_ABS) < 0)  /* seek to end */
-	Fatal("Unable to seek in archive", procName);
-
-    for (idx = 0 ; idx < namecount; idx++) {
-#ifdef APW
-	if (STOP()) Quit(1);  /* check for OA-. */
-#endif
-	addSize = AddFile(arcfd, FIArray[idx]);
-	archive->MHptr->master_eof += addSize;
-	archive->nextposn += addSize;
-	archive->MHptr->total_records++;
-    }
-
-    mptr = MakeMHblock(archive, archive->MHptr->total_records,
-		archive->MHptr->master_eof);
-    if (lseek(arcfd, 0L, S_ABS) < 0)
-	Fatal("Unable to rewind archive for master header", procName);
-
-    if (write(arcfd, mptr, MHsize) < MHsize)
-	Fatal("Unable to update master header", procName);
-    if (close(arcfd) < 0)
-	Fatal("Unable to close archive", procName);
-
-    if (domove) {
-	if (verbose) printf("Deleteing files...\n");
-	for (idx = 0; idx < namecount; idx++) {
-	    if (verbose) {
-		printf("%s...", FIArray[idx]->pathname);
-		fflush(stdout);
-	    }
-	    if (unlink(FIArray[idx]->pathname) < 0) {
-		if (verbose) printf("failed.\n");
-	    } else {
-		if (verbose) printf("done.\n");
-	    }
-	}
-    }
-}
-
-
-/*
- * Main entry point for adding files.
- */
-void NuAdd(filename, namecount, names, options)
-char *filename;
-int namecount;
-char **names;
-char *options;
-{
-    char *optr;
-    int idx;
-    char type[5];
-    static char *procName = "NuAdd";
-
-    if (*options == 'm')
-	domove = TRUE;
-
-    if (*options == 'c')
-	docreate = TRUE;
-
-    /* change T subopt to convert FROM current system TO <subopt> */
-    if (transfrom >= 0) {
-	transto = transfrom;
-	transfrom = -1;
-    }
-
-    Add(filename, namecount, names);  /* do main processing */
-}
-
+ END OF ARCHIVE
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads