home *** CD-ROM | disk | FTP | other *** search
- From: jac@yoko.rutgers.edu (Jonathan A. Chandross)
- Newsgroups: comp.sources.apple2
- Subject: v001SRC034: Nulib - Archive Library Tools (Unix) 03/10
- Message-ID: <May.1.18.09.53.1991.23482@yoko.rutgers.edu>
- Date: 1 May 91 22:09:55 GMT
- Approved: jac@paul.rutgers.edu
-
-
- Submitted-by: Andy McFadden (fadden@cory.berkeley.edu)
- Posting-number: Volume 1, Source:34
- Archive-name: archive/unix/nulib/part03.10
- Architecture: UNIX
- Version-number: 3.03
-
-
- =nuread.c
- -/*
- - * nuread.c - read NuFX archives (header info only) into structures
- - *
- - * 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>
- -
- -#ifdef MSDOS /* For file IO */
- -# include <stdlib.h> /* errno, among others */
- -# include <string.h>
- -# include <io.h>
- -# include <sys/types.h>
- -# include <sys/stat.h>
- -#endif
- -
- -#ifdef CRC_TAB
- -# include "crc.h" /* fast CRC lookup */
- -#endif
- -#include "nuread.h"
- -#include "nupak.h" /* uses PAKBUFSIZ */
- -#include "nuetc.h"
- -
- -#define UNKNOWN_FN "<No Filename>"
- -
- -/* quick proc to save x00 bytes of static storage */
- -void OtherArc(str1, str2)
- -{
- - fprintf(stderr, "File may be %s; try \"%s\".\n", str1, str2);
- -}
- -
- -/* swap two bytes if HiLo is TRUE */
- -void HiSwap(ptr, a, b)
- -onebyt *ptr;
- -register onebyt a, b;
- -{
- - register onebyt tmp;
- -
- - if (HiLo) {
- - tmp = ptr[a], ptr[a] = ptr[b], ptr[b] = tmp;
- - }
- -}
- -
- -
- -/* copy bytes from buffer to buffer, reversing byte order if necessary */
- -void BCopy(srcptr, destptr, num, order)
- -onebyt *srcptr, *destptr;
- -register int num;
- -BOOLEAN order; /* true if byte ordering is important */
- -{
- - register int i = num--;
- -
- - if (order && HiLo) {
- - while (i--) { /* copy & reverse */
- - *(destptr+i) = *(srcptr + num - i); /* dest+3 = src + 3 - 3 .. */
- - }
- - } else if (order) {
- - while (i--) { /* copy only */
- - *(destptr+i) = *(srcptr + i);
- - }
- - } else {
- - while (i--) { /* byte ordering not important; just copy */
- - *(destptr+i) = *(srcptr+i);
- - }
- - }
- -}
- -
- -
- -/*
- - * Calculate CRC on a region
- - *
- - * A CRC is the result of a mathematical operation based on the
- - * coefficients of a polynomial when multiplied by X^16 then divided by
- - * the generator polynomial (X^16 + X^12 + X^5 + 1) using modulo two
- - * arithmetic.
- - *
- - * This routine is a slightly modified verison of one found in:
- - * _Advanced Programming Techniques for the Apple //gs Toolbox_
- - * By Morgan Davis and Dan Gookin (Compute! Publications, Inc.)
- - * It can either calculate the CRC bit-by-bit or use a table.
- - * [ one of the few //gs books worth the money +atm ]
- - */
- -twobyt CalcCRC(seed, ptr, count)
- -twobyt seed; /* initial value for CRC */
- -onebyt *ptr; /* pointer to start of data buffer */
- -int count; /* number of bytes to scan through - note 64K max */
- -{
- - register int x;
- - register twobyt CRC = seed;
- -
- - do {
- -#ifndef CRC_TAB
- - CRC ^= *ptr++ << 8; /* XOR hi-byte of CRC w/data */
- - for (x = 8; x; --x) /* Then, for 8 bit shifts... */
- - if (CRC & 0x8000) /* Test hi order bit of CRC */
- - CRC = CRC << 1 ^ 0x1021; /* if set, shift & XOR w/$1021 */
- - else
- - CRC <<= 1; /* Else, just shift left once. */
- -#else
- - CRC = updcrc(*ptr++, CRC); /* look up new value in table */
- -#endif
- - } while (--count);
- - return (CRC);
- -}
- -
- -
- -/*
- - * Test an archive's integrity.
- - *
- - * Reads the entire file, and checks CRCs for certain things.
- - */
- -void NuTest(filename, options)
- -char *filename;
- -char *options;
- -{
- - ListHdr *archive;
- - onebyt *copybuf; /* buffer for reading record */
- - int partial; /* size for partial read */
- - unsigned int rec;
- - RNode *RNodePtr;
- - MHblock *MHptr;
- - TNode *TNodePtr;
- - long hdr_size, total_size, thread_size;
- - int srcfd; /* file descriptor */
- - int thread;
- - twobyt CRC, RecordCRC;
- - long CRCsum = 0L; /* sum of CRCs for all records */
- - BOOLEAN check_thread_crc; /* TRUE if we want to check a give thread */
- - static char *procName = "NuTest";
- -
- - printf("Testing %s", filename);
- - if (verbose) printf("\n");
- - else { printf("..."); fflush(stdout); }
- -
- - archive = NuRead(filename); /* this catches most errors... */
- -
- - MHptr = archive->MHptr;
- - RNodePtr = archive->RNodePtr;
- - copybuf = (onebyt *) Malloc(PAKBUFSIZ);
- - if ((srcfd = open(filename, O_RDONLY | O_BINARY)) < 0)
- - Fatal("Unable to close archive", procName);
- - if (lseek(srcfd, (long) MHsize, S_ABS) < 0) /* seek past master block */
- - Fatal("Bad seek (MH)", procName);
- -
- - for (rec = 0; rec < (unsigned int) MHptr->total_records; rec++) {
- - if (verbose) printf("Record %d (%s): ", rec, RNodePtr->filename);
- - hdr_size = (long) RNodePtr->RHptr->attrib_count;
- - hdr_size += (long) RNodePtr->filename_length;
- - total_size = hdr_size;
- - TNodePtr = RNodePtr->TNodePtr;
- - for (thread=0; thread < (int)RNodePtr->RHptr->total_threads; thread++){
- - if (TNodePtr == (TNode *) NULL) {
- - fprintf(stderr, "Internal error: Bad thread structure\n");
- - Quit(-1);
- - }
- - hdr_size += (long) THsize;
- - total_size += (long) THsize;
- - total_size += TNodePtr->THptr->comp_thread_eof;
- - TNodePtr = TNodePtr->TNext;
- - }
- - if (verbose) {
- - printf("total record size = %ld (%d threads)\n", total_size,
- - (int) RNodePtr->RHptr->total_threads);
- - fflush(stdout);
- - }
- -
- - /* read record header */
- - RecordCRC = 0;
- - while (hdr_size != 0L) {
- - if (hdr_size > (long) PAKBUFSIZ) {
- - partial = (unsigned int) PAKBUFSIZ;
- - hdr_size -= (long) PAKBUFSIZ;
- - } else {
- - partial = (unsigned int) hdr_size;
- - hdr_size = 0L;
- - }
- -
- - if (read(srcfd, copybuf, partial) != partial) {
- - fprintf(stderr, ">>> Read error");
- - if (verbose) fprintf(stderr, "\n");
- - else fprintf(stderr,
- - " - record %d (%s)\n", rec, RNodePtr->filename);
- - fprintf(stderr, "Operation aborted.\n");
- - Quit(-1);
- - }
- - if (verbose) RecordCRC = CalcCRC(CRC, (onebyt *) copybuf, partial);
- - }
- -
- - TNodePtr = RNodePtr->TNodePtr;
- - for (thread=0; thread < (int)RNodePtr->RHptr->total_threads; thread++){
- - if (lseek(srcfd, (long) TNodePtr->fileposn, S_ABS) < 0)
- - Fatal("whoops!", procName);
- - thread_size = TNodePtr->THptr->comp_thread_eof;
- -
- - /* decide whether or not to check thread CRCs */
- - check_thread_crc = FALSE;
- - if (RNodePtr->RHptr->version_number >= 2) /* valid CRCs */
- - if (TNodePtr->THptr->thread_class == 2) /* data_thread */
- - check_thread_crc = TRUE;
- - if (RNodePtr->RHptr->version_number == 3) /* CRC of uncom data */
- - if (TNodePtr->THptr->thread_format != 0x0000)
- - check_thread_crc = FALSE; /* can't check comp */
- -
- - if (check_thread_crc) CRC = 0xffff;
- - while (thread_size != 0L) {
- - if (thread_size > (long) PAKBUFSIZ) {
- - partial = (unsigned int) PAKBUFSIZ;
- - thread_size -= (long) PAKBUFSIZ;
- - } else {
- - partial = (unsigned int) thread_size;
- - thread_size = 0L;
- - }
- -
- - if (read(srcfd, copybuf, partial) != partial) {
- - fprintf(stderr, ">>> Read error in thread");
- - if (verbose) fprintf(stderr, " %d\n", thread);
- - else fprintf(stderr, " - record %d (%s), thread %d\n",
- - rec, RNodePtr->filename, thread);
- - fprintf(stderr, "Operation aborted.\n");
- - Quit(-1);
- - }
- -
- - if (verbose)
- - RecordCRC = CalcCRC(RecordCRC, (onebyt *)copybuf, partial);
- -
- - /* calculate CRC for thread, and compare with thread_crc */
- - if (check_thread_crc)
- - CRC = CalcCRC(CRC, (onebyt *) copybuf, partial);
- -#ifdef DEBUG
- - printf(
- -"At posn %ld: rec %d/thread %d (%ld bytes) CalcCRC = 0x%.4x (0x%.4x)\n",
- -TNodePtr->fileposn, rec, thread, thread_size, CRC, TNodePtr->THptr->thread_crc
- - );
- -#endif
- - }
- -
- - /* check and see if CRC matches */
- - if (check_thread_crc) {
- - if (CRC != TNodePtr->THptr->thread_crc) {
- - fprintf(stderr, ">>> Bad CRC for thread %d",
- - thread);
- - if (verbose) fprintf(stderr, "\n");
- - else fprintf(stderr, " in record %d\n", rec);
- - } else {
- - if (verbose) printf("--- CRC matched for thread %d\n",
- - thread);
- - }
- - }
- - TNodePtr = TNodePtr->TNext;
- - }
- -
- - if (verbose) {
- - printf("--- CRC for entire record was $%.4x\n", RecordCRC);
- - CRCsum += RecordCRC;
- - }
- - RNodePtr = RNodePtr->RNext;
- - }
- - if (close(srcfd) < 0)
- - Fatal("Unable to close archive", procName);
- -
- - free(copybuf);
- - if (verbose) printf("Sum of CRCs = $%.8lx\n", CRCsum);
- - printf("done.\n");
- -}
- -
- -
- -/*
- - * Read thread header data, and skip data fields
- - */
- -
- -static TNode *ReadThreads(fd, RHptr, RNodePtr, CRC_ptr)
- -int fd;
- -RHblock *RHptr;
- -RNode *RNodePtr;
- -twobyt *CRC_ptr; /* CRC seed; result is returned thru this */
- -{
- - int i;
- - unsigned int size;
- - BOOLEAN first;
- - TNode *TNodePtr, *THeadPtr = (TNode *) NULL;
- - THblock *THptr;
- - char filebuf[THsize];
- - twobyt CRC = *CRC_ptr;
- - static char *procName = "ReadThreads";
- -
- - RNodePtr->unc_len = 0L;
- - RNodePtr->comp_len = 0L;
- - first = TRUE;
- - for (i = 0; i < RHptr->total_threads; i++) {
- - if (first) { /* create first block, or... */
- - TNodePtr = (TNode *) Malloc(sizeof(TNode));
- - THeadPtr = TNodePtr;
- - first = FALSE;
- - } else { /* create next block and go on */
- - TNodePtr->TNext = (TNode *) Malloc(sizeof(TNode));
- - TNodePtr = TNodePtr->TNext;
- - }
- - TNodePtr->TNext = (TNode *) NULL;
- -
- - /* Create the thread header block, and read it in */
- - TNodePtr->THptr = (THblock *) Malloc(sizeof(THblock));
- - THptr = TNodePtr->THptr;
- -
- - if (size = read(fd, filebuf, THsize) < THsize) { /* should be 16 */
- - printf("read size = %d, THsize = %d\n", size, THsize);
- - Fatal("ReadThread (THblock)", procName);
- - }
- - CRC = CalcCRC(CRC, (onebyt *) filebuf, 16); /* hdr CRC part(s) 5/5 */
- -
- - /* copy all fields... */
- - BCopy(filebuf+0, (onebyt *) &THptr->thread_class, 2, TRUE);
- - BCopy(filebuf+2, (onebyt *) &THptr->thread_format, 2, TRUE);
- - BCopy(filebuf+4, (onebyt *) &THptr->thread_kind, 2, TRUE);
- - BCopy(filebuf+6, (onebyt *) &THptr->thread_crc, 2, TRUE);
- - BCopy(filebuf+8, (onebyt *) &THptr->thread_eof, 4, TRUE);
- - BCopy(filebuf+12, (onebyt *) &THptr->comp_thread_eof, 4, TRUE);
- -
- - RNodePtr->unc_len += THptr->thread_eof;
- - RNodePtr->comp_len += THptr->comp_thread_eof;
- - if (THptr->comp_thread_eof > 2097152L) /* SANITY CHECK */
- - fprintf(stderr, "Sanity check: found comp_thread_eof > 2MB\n");
- - }
- -
- - /* skip the actual data */
- - TNodePtr = THeadPtr;
- - for (i = 0; i < RHptr->total_threads; i++) {
- - THptr = TNodePtr->THptr;
- - if ((TNodePtr->fileposn = lseek(fd, 0L, S_REL)) < 0)
- - Fatal("Bad thread posn lseek()", procName);
- -
- - /* pull filenames out of threads, if present */
- - if (THptr->thread_class == 0x0003) { /* filename thread */
- - RNodePtr->filename = (char *) Malloc(THptr->thread_eof +1);
- - if (read(fd, RNodePtr->filename, THptr->thread_eof) < 0) {
- - fprintf(stderr, "Error on thread %d\n", i);
- - Fatal("Unable to read filename", procName);
- - }
- - RNodePtr->filename[THptr->thread_eof] = '\0';
- - RNodePtr->real_fn_length = THptr->thread_eof;
- -
- - { /* patch to fix bug in ShrinkIt v3.0.0 */
- - int j, name_len = strlen(RNodePtr->filename);
- -
- - for (j = 0; j < name_len; j++) {
- - RNodePtr->filename[j] &= 0x7f; /* clear hi bit */
- - }
- - }
- -
- - if (lseek(fd, TNodePtr->fileposn, S_ABS) < 0)
- - Fatal("Unable to seek back after fn", procName);
- - }
- - if (lseek(fd, THptr->comp_thread_eof, S_REL) < 0)
- - Fatal("Bad skip-thread seek", procName);
- - TNodePtr = TNodePtr->TNext;
- - }
- - *CRC_ptr = CRC;
- - return (THeadPtr);
- -}
- -
- -
- -/*
- - * Read header data from a NuFX archive into memory
- - */
- -ListHdr *NuRead(filename)
- -char *filename;
- -{
- - int fd; /* archive file descriptor */
- - char namebuf[MAXFILENAME];
- - int rec, num;
- - BOOLEAN first;
- - twobyt namelen;
- - twobyt CRC;
- - ListHdr *ListPtr; /* List Header struct */
- - MHblock *MHptr; /* Master Header block */
- - RNode *RNodePtr; /* Record Node */
- - RHblock *RHptr; /* Record Header block */
- - onebyt filebuf[RECBUFSIZ]; /* must be > RH, MH, or atts-RH size */
- - static char *procName = "NuRead";
- -
- - ListPtr = (ListHdr *) Malloc(sizeof(ListHdr)); /* create head of list */
- - ListPtr->arc_name = (char *) Malloc(strlen(filename)+1); /* archive fnam */
- - strcpy(ListPtr->arc_name, filename);
- - ListPtr->MHptr = (MHblock *) Malloc(sizeof(MHblock)); /* master block */
- -
- - if ((fd = open(filename, O_RDONLY | O_BINARY)) < 0) {
- - if (errno == ENOENT) {
- - fprintf(stderr, "%s: can't find file '%s'\n", prgName, filename);
- - Quit (-1);
- - } else
- - Fatal("Unable to open archive", procName);
- - }
- -
- - /* create and read the master header block */
- - MHptr = ListPtr->MHptr;
- - if (read(fd, filebuf, MHsize) < MHsize) {
- - fprintf(stderr, "File '%s' may not be a NuFX archive\n", filename);
- - Fatal("Unable to read Master Header Block", procName);
- - }
- -
- - CRC = CalcCRC(0, (onebyt *) filebuf+8, MHsize-8); /* master header CRC */
- -
- - /* Copy data to structs, correcting byte ordering if necessary */
- - BCopy(filebuf+0, (onebyt *) MHptr->ID, 6, FALSE);
- - BCopy(filebuf+6, (onebyt *) &MHptr->master_crc, 2, TRUE);
- - BCopy(filebuf+8, (onebyt *) &MHptr->total_records, 4, TRUE);
- - BCopy(filebuf+12, (onebyt *) &MHptr->arc_create_when, sizeof(Time), FALSE);
- - BCopy(filebuf+20, (onebyt *) &MHptr->arc_mod_when, sizeof(Time), FALSE);
- - BCopy(filebuf+28, (onebyt *) &MHptr->master_version, 2, TRUE);
- - BCopy(filebuf+30, (onebyt *) MHptr->reserved1, 8, FALSE);
- - BCopy(filebuf+38, (onebyt *) &MHptr->master_eof, 4, TRUE); /* m_v $0001 */
- - BCopy(filebuf+42, (onebyt *) MHptr->reserved2, 6, FALSE);
- -
- - if (strncmp(MHptr->ID, MasterID, 6)) {
- - fprintf(stderr, "\nFile '%s' is not a NuFX archive\n", filename);
- - if ((filebuf[0] == 10) && (filebuf[1] == 71) &&
- - (filebuf[2] == 76) && (filebuf[18] == 2))
- -#ifdef NO_BLU
- - OtherArc("Binary II", "unblu");
- -#else
- - fprintf(stderr, "File may be Binary II; try 'B' option\n");
- -#endif
- - if ((filebuf[0] == '\037') && (filebuf[1] == '\036'))
- - OtherArc("packed", "unpack");
- - if ((filebuf[0] == (onebyt)'\377') && (filebuf[1] == '\037'))
- - OtherArc("compacted", "uncompact");
- - if ((filebuf[0] == '\037') && (filebuf[1] == (onebyt)'\235'))
- - OtherArc("compressed", "uncompress");
- - if ((filebuf[0] == 0x76) && (filebuf[1] == 0xff))
- - OtherArc("SQueezed", "usq");
- - if ((filebuf[0] == 0x04) && (filebuf[1] == 0x03) &&
- - (filebuf[2] == 0x4b) && (filebuf[3] == 0x50))
- - OtherArc("a ZIP archive", "UnZip");
- - if (!strncmp((char *) filebuf, "ZOO", 3)) /* zoo */
- - OtherArc("a ZOO archive", "zoo");
- - if ((filebuf[0] == 0x1a) && (filebuf[1] == 0x08)) /* arc */
- - OtherArc("an ARC archive", "arc");
- - if (!strncmp((char *) filebuf, "SIT!", 4)) /* StuffIt */
- - OtherArc("a StuffIt archive", "StuffIt (Macintosh)");
- - if (!strncmp((char *) filebuf, "<ar>", 4)) /* system V arch */
- - OtherArc("a library archive (Sys V)", "ar");
- - if (!strncmp((char *) filebuf, "!<arch>", 7))
- - OtherArc("a library archive", "ar");
- - if (!strncmp((char *) filebuf, "#! /bin/sh", 10) ||
- - !strncmp((char *) filebuf, "#!/bin/sh", 9))
- - OtherArc("a shar archive", "/bin/sh");
- - if (!strncmp((char *) filebuf, "GIF87a", 6))
- - OtherArc("a GIF picture", "?!?");
- - /* still need ZIP */
- -
- - Quit (-1);
- - }
- -
- - if (CRC != MHptr->master_crc)
- - printf("WARNING: Master Header block may be corrupted (bad CRC)\n");
- -
- - if (MHptr->master_version > MAXMVERS)
- - printf("WARNING: unknown Master Header version, trying to continue\n");
- -
- - /* main record read loop */
- - first = TRUE;
- - for (rec = 0; rec < (unsigned int) MHptr->total_records; rec++) {
- - if (first) { /* allocate first, or... */
- - ListPtr->RNodePtr = (RNode *) Malloc(sizeof(RNode));
- - RNodePtr = ListPtr->RNodePtr;
- - first = FALSE;
- - } else { /* allocate next, and go on */
- - RNodePtr->RNext = (RNode *) Malloc(sizeof(RNode)); /* next Rnode */
- - RNodePtr = RNodePtr->RNext; /* move on to next record */
- - }
- - RNodePtr->RNext = (RNode *) NULL;
- -
- - RNodePtr->RHptr = (RHblock *) Malloc(sizeof(RHblock)); /* alloc blk */
- - /* expansion here */
- - RHptr = RNodePtr->RHptr;
- - if (read(fd, filebuf, RHsize) < RHsize) { /* get known stuff */
- - fprintf(stderr,"%s: error in record %d (at EOF?)\n", prgName, rec);
- - Fatal("Bad RHblock read", procName);
- - }
- -
- - /* rec hdr CRC part 1/5 */
- - CRC = CalcCRC(0, (onebyt *) filebuf+6, RHsize-6);
- -
- - BCopy(filebuf+0, (onebyt *) RHptr->ID, 4, FALSE);
- - BCopy(filebuf+4, (onebyt *) &RHptr->header_crc, 2, TRUE);
- - BCopy(filebuf+6, (onebyt *) &RHptr->attrib_count, 2, TRUE);
- - BCopy(filebuf+8, (onebyt *) &RHptr->version_number, 2, TRUE);
- - BCopy(filebuf+10, (onebyt *) &RHptr->total_threads, 2, TRUE);
- - BCopy(filebuf+12, (onebyt *) &RHptr->reserved1, 2, TRUE);
- - BCopy(filebuf+14, (onebyt *) &RHptr->file_sys_id, 2, TRUE);
- - BCopy(filebuf+16, (onebyt *) &RHptr->file_sys_info, 1, TRUE);
- - BCopy(filebuf+17, (onebyt *) &RHptr->reserved2, 1, TRUE);
- - BCopy(filebuf+18, (onebyt *) &RHptr->access, 4, TRUE);
- - BCopy(filebuf+22, (onebyt *) &RHptr->file_type, 4, TRUE);
- - BCopy(filebuf+26, (onebyt *) &RHptr->extra_type, 4, TRUE);
- - BCopy(filebuf+30, (onebyt *) &RHptr->storage_type, 2, TRUE);
- - BCopy(filebuf+32, (onebyt *) &RHptr->create_when, sizeof(Time), FALSE);
- - BCopy(filebuf+40, (onebyt *) &RHptr->mod_when, sizeof(Time), FALSE);
- - BCopy(filebuf+48, (onebyt *) &RHptr->archive_when, sizeof(Time), FALSE);
- - BCopy(filebuf+56, (onebyt *) &RHptr->option_size, 2, TRUE);
- - /* expansion here */
- -
- - if (strncmp(RHptr->ID, RecordID, 4)) {
- - fprintf(stderr, "%s: Found bad record ID (#%d) -- exiting\n",
- - prgName, rec);
- - Quit (-1);
- - }
- -
- - /* read remaining (unknown) attributes into buffer, if any */
- - num = RHptr->attrib_count - RHsize - 2;
- - if (num > RECBUFSIZ) {
- - fprintf(stderr, "ERROR: attrib_count > RECBUFSIZ\n");
- - Quit (-1);
- - }
- - if (num > 0) {
- - if (read(fd, filebuf, num) < num)
- - Fatal("Bad xtra attr read", procName);
- - CRC = CalcCRC(CRC, (onebyt *) filebuf, num); /* hdr CRC part 2/5 */
- - }
- -
- - if (read(fd, (char *) &namelen, 2) < 2) /* read filename len */
- - Fatal("Bad namelen read", procName);
- - CRC = CalcCRC(CRC, (onebyt *) &namelen, 2); /* rec hdr CRC part 3/5 */
- -
- - HiSwap((onebyt *) &namelen, 0, 1);
- - /* read filename, and store in struct */
- - if (namelen > MAXFILENAME) {
- - fprintf(stderr, "ERROR: namelen > MAXFILENAME\n");
- - Quit (-1);
- - }
- - RNodePtr->filename_length = namelen;
- -
- - if (namelen > 0) {
- - RNodePtr->real_fn_length = namelen;
- - if (read(fd, namebuf, namelen) < namelen)
- - Fatal("Bad namebuf read", procName);
- - /* rec hdr CRC part 4/5 */
- - CRC = CalcCRC(CRC, (onebyt *) namebuf, namelen);
- -
- - RNodePtr->filename = (char *) Malloc(namelen+1); /* store fname */
- - BCopy(namebuf, (onebyt *) RNodePtr->filename, namelen, FALSE);
- - RNodePtr->filename[namelen] = '\0';
- - } else {
- - RNodePtr->filename = UNKNOWN_FN;
- - RNodePtr->real_fn_length = strlen(UNKNOWN_FN);
- - }
- -
- - RNodePtr->TNodePtr = ReadThreads(fd, RHptr, RNodePtr, &CRC);
- - /* rec hdr CRC part 5/5 calculated by ReadThreads */
- -
- - if (CRC != RHptr->header_crc) {
- - printf("WARNING: Detected a bad record header CRC\n");
- - printf(" Rec %d in file '%.60s'\n",rec,RNodePtr->filename);
- - }
- - }
- -
- - /* begin adding new files at this point */
- - if ((ListPtr->nextposn = lseek(fd, 0L, S_REL)) < 0)
- - Fatal("Bad final lseek()", procName);
- -
- - if (close(fd) < 0) {
- - Fatal("Bad close", procName);
- - }
- -
- - if (MHptr->master_version > 0x0000) {
- - if (MHptr->master_eof != ListPtr->nextposn) {
- - printf("WARNING: master_eof (stored)=%ld, nextposn (actual)=%ld\n",
- - MHptr->master_eof, ListPtr->nextposn);
- - printf(
- - " (master_eof will be fixed if archive is changed)\n");
- - }
- - }
- -
- - return (ListPtr);
- -}
- -
- =nuext.c
- -/*
- - * nuext.c - operations which extract from 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>
- -#ifdef BSD43
- -# include <strings.h>
- -#else /* SYSV, APW, MSC */
- -# include <string.h>
- -#endif
- -#include <fcntl.h>
- -
- -#ifdef UNIX
- -# include <errno.h>
- -# include <time.h>
- -# include <sys/types.h>
- -# include <sys/stat.h>
- -#endif
- -#ifdef APW
- -# include <types.h>
- -# include <prodos.h>
- -# include <shell.h>
- -# include <strings.h>
- -#endif
- -#ifdef MSDOS
- -# include <io.h>
- -# include <time.h>
- -# include <stdlib.h>
- -# include <errno.h>
- -# include <direct.h>
- -# include <utime.h>
- -# include <sys/types.h>
- -# include <sys/stat.h>
- -#endif
- -
- -#include "nuread.h"
- -#include "nuext.h"
- -#include "nupak.h"
- -#include "nuetc.h"
- -
- -static BOOLEAN extall; /* extract all files? */
- -static BOOLEAN print; /* extract to screen rather than file? */
- -
- -
- -/*
- - * Get the answer to a yes/no question.
- - *
- - * Returns TRUE for yes, FALSE for no. May return additional things in the
- - * future... (y/n/q)?
- - */
- -int AskYesNo()
- -{
- - char buf[16]; /* if user answers with >16 chars, bad things happen */
- - char c;
- -
- - printf(" (y/n)? ");
- - fflush(stdout);
- - gets(buf);
- - c = *buf;
- - if ((c == 'y') || (c == 'Y'))
- - return (TRUE);
- - else
- - return (FALSE);
- -}
- -
- -
- -/*
- - * Convert a filename to one legal in the present file system.
- - *
- - * Does not allocate new space; alters string in place (so original string
- - * will be "corrupted"). Assumes that it has been passed a filename without
- - * the filename separators.
- - */
- -void ConvFileName(str)
- -char *str;
- -{
- - int idx = 0;
- -#ifdef UNIX
- -
- - while (*str != '\0') {
- - if ((*str > 127) || (*str < 0)) *str &= 0x7f; /* clear hi bit */
- - if (*str == '/') *str = '.';
- - if (++idx > 255) { *str = '\0'; break; }
- - str++;
- - }
- -#else
- -# ifdef APW
- - static char *legal =
- - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.";
- -
- - /* assumes ProDOS limits, not GS/OS */
- - if ( ((*str < 'A') && (*str > 'Z')) || ((*str < 'a') && (*str > 'z')) )
- - *str = 'X'; /* must start with alpha char */
- - while (*str != '\0') {
- - if (!INDEX(legal, *str)) *str = '.';
- - if (++idx > 15) { *str = '\0'; break; }
- - str++;
- - }
- -# endif /* APW */
- -# ifdef MSDOS
- - while (*str != '\0') {
- - if ((*str > 127) || (*str < 0)) *str &= 0x7f; /* clear hi bit */
- - if (*str == '/') *str = '_';
- - if (*str == '\\') *str = '_';
- - if (*str == '!') *str = '_';
- - if (*str == ':') *str = '_';
- - if (++idx > 255) { *str = '\0'; break; }
- - str++;
- - }
- -# endif /* MSDOS */
- -
- -# ifndef APW
- -# ifndef MSDOS
- - printf("Need [other] filename converter\n"); /* +PORT+ */
- -# endif /* none2 */
- -# endif /* none1 */
- -#endif /*UNIX*/
- -}
- -
- -/*
- - * Set a file's attributes according to info in a record structure.
- - */
- -void SetFInfo(filename, RHptr)
- -char *filename;
- -RHblock *RHptr;
- -{
- - static char *procName = "SetFInfo";
- -#ifdef UNIX
- - long ltime;
- - time_t timep[2];
- -
- - ltime = ReduceTime(&RHptr->mod_when); /* set both to mod time */
- - timep[0] = ltime; /* accessed */
- - timep[1] = ltime; /* modified */
- - utime(filename, timep);
- -
- - if ((RHptr->access == 0xe3L) || (RHptr->access == 0xc3L)) /* unlocked */
- - chmod(filename, S_IREAD | S_IWRITE | 044);
- - if ((RHptr->access == 0x21L) || (RHptr->access == 0x01L)) /* locked */
- - chmod(filename, S_IREAD | 044);
- -
- -#else /* UNIX */
- -# ifdef APW
- - /*
- - * Call ProDOS SET_FILE_INFO to set attributes for a file.
- - * Uses the information in the record header block.
- - */
- - FileRec finfo;
- - OpenRec oinfo;
- - twobyt date, time;
- - long ltime;
- -
- - finfo.pathname = c2pstr(filename); /* temp storage...? */
- - finfo.fAccess = (twobyt) RHptr->access;
- - finfo.fileType = (twobyt) RHptr->file_type;
- - finfo.auxType = RHptr->extra_type;
- - finfo.storageType = 0; /* RHptr->storage_type otherwise */
- - ltime = ReduceTime(&RHptr->create_when);
- - date = (twobyt) ltime; /* date is lower 16 */
- - time = (twobyt) (ltime >> 16); /* time is upper */
- - finfo.createDate = date;
- - finfo.createTime = time;
- - ltime = ReduceTime(&RHptr->mod_when);
- - date = (twobyt) ltime; /* date is lower 16 */
- - time = (twobyt) (ltime >> 16); /* time is upper */
- - finfo.modDate = date;
- - finfo.modTime = time;
- -
- - SET_FILE_INFO( &finfo );
- - ToolErrChk();
- -# endif /* APW */
- -# ifdef MSDOS
- - long ltime;
- - time_t timep[2];
- -
- - ltime = ReduceTime(&RHptr->mod_when);
- - timep[0] = ltime; /* accessed */
- - timep[1] = ltime; /* modified */
- - utime(filename, timep);
- -
- - if ((RHptr->access == 0xe3L) || (RHptr->access == 0xc3L)) /* unlocked */
- - chmod(filename, S_IREAD | S_IWRITE | 044);
- - if ((RHptr->access == 0x21L) || (RHptr->access == 0x01L)) /* locked */
- - chmod(filename, S_IREAD | 044);
- -# endif /* MSDOS */
- -
- -# ifndef APW
- -# ifndef MSDOS
- - printf("need [other] SetFInfo stuff\n"); /* +PORT+ */
- -# endif /* none2 */
- -# endif /* none1 */
- -#endif /* APW */
- -}
- -
- -
- -/*
- - * Create a subdirectory
- - *
- - * This routine will exit on most errors, since generally more than one file
- - * will be unpacked to a given subdirectory, and we don't want it charging
- - * bravely onward if it's going to run into the same problem every time.
- - */
- -void CreateSubdir(pathname)
- -char *pathname;
- -{
- - char *buffer = (char *) Malloc(MAXFILENAME+6);
- - static char *procName = "CreateSubdir";
- -#ifdef UNIX
- - struct stat st;
- -
- - /* if no directory exists, then make one */
- - if (stat(pathname, &st) < 0)
- - if (errno == ENOENT) {
- - sprintf(buffer, "mkdir %s", pathname);
- - if (system(buffer) != 0) /* call UNIX mkdir to create subdir */
- - Fatal("Unable to create subdir", procName);
- - } else {
- - Fatal("Unable to create dir", procName);
- - }
- -#else
- -# ifdef APW
- - static FileRec create_p = { "", 0x00e3, 0x000f, 0L, 0x000d, 0, 0 }; /*dir*/
- - FileRec info_p; /* check if file exists, is dir */
- - int err; /* holds _toolErr */
- -
- - strcpy(buffer, pathname);
- - c2pstr(buffer);
- - info_p.pathname = buffer;
- - GET_FILE_INFO( &info_p );
- -
- - switch (_toolErr) {
- - case 0x0000: /* no error */
- - if (info_p.storageType != 0x000d) /* not a DIR? */
- - Fatal("File in path exists, is not a directory.", procName);
- - return; /* file exists, is directory, no need to create */
- -
- - case fileNotFound:
- - create_p.pathname = buffer;
- - CREATE( &create_p );
- - if (!_toolErr) return; /* created okay? */
- - else ToolErrChk();
- -
- - default: /* unknown error */
- - ToolErrChk();
- - Fatal("whoops!", procName); /* shouldn't get here */
- - }
- -# endif /* APW */
- -# ifdef MSDOS
- - struct stat st;
- -
- - /* if no directory exists, then make one */
- - if (stat(pathname, &st) < 0)
- - if (errno == ENOENT) {
- - if (mkdir(pathname) != 0)
- - Fatal("Unable to create subdir", procName);
- - } else {
- - Fatal("Unable to create dir", procName);
- - }
- -# endif /* MSDOS */
- -
- -# ifndef APW
- -# ifndef MSDOS
- -
- - /* don't forget to check if it exists first... */ /* +PORT+ */
- - printf("don't know how to create [other] subdirectories\n"); /* mkdir() */
- -# endif /* none2 */
- -# endif /* none1 */
- -#endif /* UNIX */
- - free(buffer);
- -}
- -
- -
- -/*
- - * Given a pathname, create subdirectories as needed. All file names are run
- - * through a system-dependent filename filter, which means that the pathname
- - * has to be broken down, the subdirectory created, and then the pathname
- - * reconstructed with the "legal" pathname. The converted filename is held
- - * in a static buffer; subsequent calls will overwrite the previous string.
- - *
- - * This is useful when unpacking "dir1/dir2/fubar" and dir1 and dir2 don't
- - * necessarily exist.
- - *
- - * It is assumed that all filenames are relative to the current directory.
- - * According to the NuFX docs (revision 3 2/3/89), initial separators (like
- - * "/", "\", or ":") should NOT be included. If they are, this routine may
- - * break.
- - */
- -static char *CreatePath(pathname, fssep)
- -char *pathname; /* full pathname; should not include ProDOS volume name */
- -onebyt fssep; /* file system pathname separator, usually "/" or "\" */
- -{
- - int idx;
- - char *ptr;
- - static char workbuf[MAXFILENAME]; /* work buffer; must be static */
- - static char *procName = "CreatePath";
- -
- - idx = 0;
- - while (TRUE) { /* move through string */
- - ptr = INDEX(pathname, fssep); /* find break */
- - if (ptr) /* down to actual filename? */
- - *ptr = '\0'; /* no, isolate this part of the string */
- -
- - strcpy(&workbuf[idx], pathname); /* copy component to buf */
- - ConvFileName(&workbuf[idx]); /* convert to legal str; may be shorter */
- - idx += strlen(&workbuf[idx]); /* advance index to end of string */
- - if (!ptr) { /* down to actual filename? */
- - workbuf[idx] = '\0'; /* yes, clean up */
- - break; /* out of while */
- - }
- - workbuf[idx] = '\0';
- -
- - CreateSubdir(workbuf); /* system-dependent dir create */
- -
- -#ifdef UNIX
- - workbuf[idx++] = '/'; /* tack a filename separator on, and advance */
- - *ptr = '/'; /* be nice */
- -#else
- -# ifdef APW
- - workbuf[idx++] = '/';
- - *ptr = '/';
- -# endif
- -# ifdef MSDOS
- - workbuf[idx++] = '\';
- - *ptr = '\';
- -# endif
- -# ifndef APW /* +PORT+ */
- -# ifndef MSDOS
- - workbuf[idx++] = '/';
- - *ptr = '/';
- -# endif
- -# endif
- -#endif /*UNIX*/
- -
- -/* was: workbuf[idx++] = fssep; /* tack an fssep on the end, and advance */
- -/* was: *ptr = fssep; /* be nice */
- -
- - pathname = ptr+1; /* go again with next component */
- - }
- -
- - return (workbuf);
- -}
- -
- -
- -/*
- - * Extract a thread, and place in a file.
- - *
- - * Returns TRUE if the extract was successful, FALSE otherwise. The most
- - * common reason for a FALSE return value is a "no" answer when asked about
- - * overwriting an existing file.
- - */
- -static BOOLEAN ExtractThread(arcfd, fileposn, destpn, THptr)
- -int arcfd; /* source file descriptor (must be open) */
- -long fileposn; /* position of data in source file */
- -char *destpn; /* destination filename */
- -THblock *THptr; /* pointer to thread info */
- -{
- - int dstfd; /* destination file descriptor */
- - static char *procName = "ExtractThread";
- -
- - if (!print) {
- - if (Exists(destpn)) {
- - if (interact) {
- - if (verbose) printf("file exists, overwite");
- - else printf("%s exists, overwite", destpn);
- - if (!AskYesNo()) { /* return w/o overwriting */
- - return (FALSE);
- - }
- - }
- - if (verbose) { printf("overwriting..."); fflush(stdout); }
- - if (unlink(destpn) < 0)
- - Fatal("Unable to remove existing file", procName);
- - }
- -
- - if ((dstfd =
- - open(destpn, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, WPERMS)) < 0)
- - Fatal("Unable to open target path", procName);
- -
- - if (lseek(arcfd, fileposn, S_ABS) < 0)
- - Fatal("Seek failed", procName);
- -
- - if (!UnpackFile(arcfd, dstfd, THptr,
- - dopack ? THptr->thread_format : 0, pakbuf)) {
- - if (close(dstfd) < 0)
- - Fatal("Dest close failed", procName);
- - unlink(destpn); /* some sys can't delete while file open */
- - } else {
- - if (close(dstfd) < 0)
- - Fatal("Dest close failed", procName);
- - }
- -
- - } else { /* print */
- - if ((dstfd = fileno(stdout)) < 0)
- - Fatal("Unable to get file for stdout", procName);
- - if (lseek(arcfd, fileposn, S_ABS) < 0)
- - Fatal("Seek failed", procName);
- -
- - if (!UnpackFile(arcfd, dstfd, THptr,
- - dopack ? THptr->thread_format : 0, pakbuf)) {
- - printf("Unpack failed.\n");
- - return (FALSE);
- - }
- - fflush(stdout);
- - }
- -
- - return (TRUE);
- -}
- -
- -
- -/*
- - * Handle message_threads
- - */
- -static void message_thread(arcfd, RNodePtr, TNodePtr)
- -int arcfd;
- -RNode *RNodePtr;
- -TNode *TNodePtr;
- -{
- - int i;
- - int oldTo, oldFrom;
- - static char *procName = "message_thread";
- -
- - switch (TNodePtr->THptr->thread_kind) {
- - case 0x0000: /* ASCII text */
- - printf("Found ASCII text thread\n");
- - break;
- - case 0x0001: /* ASCII text, predefined size */
- - if (verbose && !print && TNodePtr->THptr->thread_eof) {
- - printf("\n--- Comment for file '%s':\n", RNodePtr->filename);
- - fflush(stdout);
- - if (lseek(arcfd, TNodePtr->fileposn, S_ABS) < 0)
- - Fatal("unable to seek to comment", procName);
- - oldTo = transto;
- - oldFrom = transfrom;
- - transto = -1; /* switch to CR -> current mode */
- - transfrom = 0; /* (assumes created under ProDOS) */
- - /* may need to fix this later (but how?) */
- - FCopy(arcfd, fileno(stdout), TNodePtr->THptr->thread_eof,
- - pakbuf, TRUE);
- -#ifdef FUBAR
- - print = TRUE;
- - verbose = FALSE; /* turn off "unshrinking..." messages */
- - ExtractThread(arcfd,TNodePtr->fileposn, "stdout", TNodePtr->THptr);
- - print = FALSE;
- - verbose = TRUE;
- -#endif
- - transto = oldTo;
- - transfrom = oldFrom;
- - putchar('\n');
- - }
- - break;
- - default:
- - printf("Found unknown message_thread %.4x in '%s'\n",
- - TNodePtr->THptr->thread_kind, RNodePtr->filename);
- - break;
- - }
- -}
- -
- -/*
- - * Handle control_threads
- - */
- -static void control_thread(arcfd, RNodePtr, TNodePtr)
- -int arcfd;
- -RNode *RNodePtr;
- -TNode *TNodePtr;
- -{
- - switch (TNodePtr->THptr->thread_kind) {
- - case 0x000: /* create dir */
- - printf("Found create directory control thread\n");
- - break;
- - default:
- - printf("Found unknown control_thread %.4x in '%s'\n",
- - TNodePtr->THptr->thread_kind, RNodePtr->filename);
- - break;
- - }
- -}
- -
- -
- -/*
- - * Handle data_threads
- - *
- - * Does not guarantee that the archive file position is anything rational;
- - * the TNode's fileposn should be (and is) used here.
- - */
- -static void data_thread(arcfd, RNodePtr, TNodePtr)
- -int arcfd;
- -RNode *RNodePtr;
- -TNode *TNodePtr;
- -{
- - long fileposn; /* absolute position of thread in file */
- - long old_eof;
- - char *fn;
- - int ov;
- -
- - if (print) /* this is something of a hack... */
- - if (TNodePtr->THptr->thread_kind != 0x0000) { /* not a data fork? */
- - fprintf(stderr, "Can't print non-data fork for '%s'.\n",
- - RNodePtr->filename);
- - return; /* this hoses the file posn... */
- - } else {
- - if (verbose) printf("\n***** %s *****\n", RNodePtr->filename);
- - fflush(stdout);
- - ov = verbose;
- - verbose = FALSE; /* turn off "unshrinking..." messages */
- - fileposn = TNodePtr->fileposn;
- - ExtractThread(arcfd,fileposn, "stdout", TNodePtr->THptr);
- - verbose = ov;
- - return;
- - }
- -
- - switch (TNodePtr->THptr->thread_kind) {
- - case 0x0000: /* data fork */
- - if (verbose) {
- - printf("Extracting '%s' (data)...", RNodePtr->filename);
- - fflush(stdout);
- - }
- -
- - /* create any needed subdirs */
- - fn = CreatePath(RNodePtr->filename, RNodePtr->RHptr->file_sys_info);
- -
- - /* extract the file */
- - if (ExtractThread(arcfd, TNodePtr->fileposn, fn, TNodePtr->THptr)) {
- - SetFInfo(fn, RNodePtr->RHptr); /* set file attributes, dates... */
- - if (verbose) printf("done.\n");
- - }
- - break;
- -
- - case 0x0001: /* disk image */
- -/* printf("Found disk image (not extracted)\n");*/
- -
- - if (verbose) {
- - printf("Extracting '%s' (disk image)...", RNodePtr->filename);
- - fflush(stdout);
- - }
- -
- - /* setup path (normalize file name) */
- - fn = CreatePath(RNodePtr->filename, RNodePtr->RHptr->file_sys_info);
- -
- - /* thread_eof is invalid for disks, so figure it out */
- - old_eof = TNodePtr->THptr->thread_eof;
- - if (RNodePtr->RHptr->storage_type <= 3) { /* should be block */
- - TNodePtr->THptr->thread_eof = /* size, but shk301 */
- - RNodePtr->RHptr->extra_type * 512; /* stored it wrong */
- - } else {
- - TNodePtr->THptr->thread_eof =
- - RNodePtr->RHptr->extra_type * RNodePtr->RHptr->storage_type;
- - }
- -
- - /* extract the disk into a file */
- - if (ExtractThread(arcfd, TNodePtr->fileposn, fn, TNodePtr->THptr)) {
- - /*SetFInfo(fn, RNodePtr->RHptr);/* set file attributes, dates... */
- - if (verbose) printf("done.\n");
- - }
- -
- - TNodePtr->THptr->thread_eof = old_eof;
- - break;
- -
- - case 0x0002: /* resource_fork */
- - printf("Found resource_fork (not extracted)\n");
- - break;
- - default:
- - printf("Found unknown data_thread %.4x in '%s'\n",
- - TNodePtr->THptr->thread_kind, RNodePtr->filename);
- - break;
- - }
- -}
- -
- -
- -/*
- - * Extract files from archive
- - *
- - * Scan archive, extracting files which start with the strings in "names".
- - * Calls subroutines to handle the various thread_class types.
- - */
- -static void Extract(filename, namecount, names)
- -char *filename;
- -int namecount;
- -char **names;
- -{
- - ListHdr *archive;
- - int arcfd; /* archive file descriptor */
- - int rec, idx;
- - MHblock *MHptr; /* Master Header block */
- - RNode *RNodePtr; /* Record Node */
- - TNode *TNodePtr; /* Thread block */
- - int len, *lentab; /* hold strlen() of all names */
- - char *pn; /* archived pathname */
- - int thread; /* current thread #; max 65535 threads */
- - BOOLEAN gotone = FALSE;
- - static char *procName = "Extract";
- -
- - archive = NuRead(filename);
- - if ((arcfd = open(archive->arc_name, O_RDONLY | O_BINARY)) < 0)
- - Fatal("Unable to open archive", procName);
- -
- - pakbuf = (onebyt *) Malloc(PAKBUFSIZ); /* allocate unpack buffer */
- -
- - lentab = (int *) Malloc( sizeof(int) * namecount ); /* calloc() is nicer */
- - for (idx = 0; idx < namecount; idx++) /* calc. once (for efficiency) */
- - lentab[idx] = strlen(names[idx]);
- -
- - MHptr = archive->MHptr;
- - RNodePtr = archive->RNodePtr;
- -
- - if (!namecount)
- - extall = TRUE;
- -
- - /* main record read loop */
- - for (rec = 0; rec < MHptr->total_records; rec++) {
- - pn = RNodePtr->filename;
- - len = strlen(pn);
- - if (RNodePtr->RHptr->version_number > MAXVERS) {
- - printf("Unable to extract '%s': unknown record version_number\n",
- - pn);
- - continue; /* with for */
- - }
- -
- - for (idx = 0; extall || idx < namecount; idx++) { /* find arced file */
- - /* try to match argument with first few chars of stored filename */
- - /* or the entire filename, depending on EXPAND flag */
- - if (extall || ((len >= lentab[idx]) && doExpand ?
- - (!strncasecmp(pn, names[idx], lentab[idx])) :
- - (!strcasecmp(pn, names[idx])) )) {
- -
- - gotone = TRUE;
- - /* go through all threads */
- - TNodePtr = RNodePtr->TNodePtr;
- - for (thread = 0; thread < (int) RNodePtr->RHptr->total_threads;
- - thread++) {
- - switch(TNodePtr->THptr->thread_class) {
- - case 0x0000:
- - message_thread(arcfd, RNodePtr, TNodePtr);
- - break;
- - case 0x0001:
- - control_thread(arcfd, RNodePtr, TNodePtr);
- - break;
- - case 0x0002:
- - /* don't extract if doMessages is set */
- - if (!doMessages)
- - data_thread(arcfd, RNodePtr, TNodePtr);
- - break;
- - case 0x0003:
- - /* filename_thread; ignore */
- - break;
- - default:
- - printf("Unknown thread_class %.4x for '%s'\n",
- - TNodePtr->THptr->thread_class, RNodePtr->filename);
- - break;
- - }
- - TNodePtr = TNodePtr->TNext;
- - }
- - break; /* out of filename matching (inner) FOR loop */
- - }
- - }
- -
- - RNodePtr = RNodePtr->RNext; /* move on to next record */
- - }
- - if (!gotone && verbose)
- - printf("None selected\n");
- - if (close(arcfd) < 0)
- - Fatal("Source (archive) close failed", procName);
- -
- -}
- -
- -/*
- - * Entry point to extract routines.
- - */
- -void NuExtract(filename, namecount, names, options)
- -char *filename;
- -int namecount;
- -char **names;
- -char *options;
- -{
- - static char *procName = "NuExtract";
- -
- - if (*options == 'p') { /* printing rather then extracting to file */
- - print = TRUE;
- - dopack = TRUE; /* no extract uncompressed! */
- - } else print = FALSE;
- -
- - Extract(filename, namecount, names); /* do stuff */
- -}
- -
- + END OF ARCHIVE
-