home *** CD-ROM | disk | FTP | other *** search
- From: jac@yoko.rutgers.edu (Jonathan A. Chandross)
- Newsgroups: comp.sources.apple2
- Subject: v001SRC033: Nulib - Archive Library Tools (Unix) 02/10
- Message-ID: <May.1.18.09.08.1991.23475@yoko.rutgers.edu>
- Date: 1 May 91 22:09:09 GMT
- Approved: jac@paul.rutgers.edu
-
-
- 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
-