Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!tut.cis.ohio-state.edu!gem.mps.ohio-state.edu!usc!ucsd!ucbvax!pasteur!cory.Berkeley.EDU!fadden From: fadden@cory.Berkeley.EDU (Andy McFadden) Newsgroups: comp.binaries.apple2 Subject: NuLib v2.1.1 NuFX archiver (UNIX/APW) shar format 4/5 Message-ID: <19360@pasteur.Berkeley.EDU> Date: 9 Nov 89 09:22:10 GMT Sender: news@pasteur.Berkeley.EDU Reply-To: fadden@cory.Berkeley.EDU (Andy McFadden) Organization: University of California, Berkeley Lines: 1547 NuLib part 4/5 ----- #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # nupdel.c # nuread.c # nushk.c # This archive created: Thu Nov 9 01:07:41 1989 # By: Andy McFadden () export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'nupdel.c'" '(13337 characters)' if test -f 'nupdel.c' then echo shar: "will not over-write existing file 'nupdel.c'" else cat << \!Funky!Stuff! > 'nupdel.c' /* * nudel.c - operations which delete from a NuFX archive * nuupd.c - update/freshen a NuFX archive * * By Andy McFadden (fadden@cory.berkeley.edu) * NuLib v2.1 November 1989 Freeware (distribute, don't sell) */ #include "nudefs.h" #include #include #ifdef BSD43 # include #else /* SYSV, APW, MSC */ # include #endif #ifdef UNIX # include #endif #ifdef APW # include # include /* ? */ # include # include /* APW string ops */ #endif #ifdef MSDOS # include # include # include # include #endif #include "nuread.h" #include "nuadd.h" /* AddFile(), etc. */ #include "nupak.h" /* uses PAKBUFSIZ */ #include "nupdel.h" #include "nuetc.h" static BOOLEAN dofreshen; /* do freshen instead of update? */ /* delete routines */ /* * Rebuild an archive, excluding files marked as deleted. * Does not use absolute position values; just seeks along. The archive * should be seeked just beyond the master header block. */ static void RebuildArchive(arcfd, archive, tmpname, remaining) int arcfd; ListHdr *archive; char *tmpname; long remaining; { int dstfd; /* destination filename */ onebyt *mptr; RNode *RNodePtr; TNode *TNodePtr; int rec, thread; long size; #ifdef APW FileRec create_p; #endif static char *procName = "RebuildArchive"; if (verbose) { printf("Building new archive file..."); fflush(stdout); } mptr = MakeMHblock(archive, remaining); /* build master header */ ArcfiCreate(tmpname); /* create file */ if ((dstfd = open(tmpname, O_WRONLY | O_TRUNC | O_BINARY, WPERMS)) < 0) Fatal("Unable to open dest file", procName); if (write(dstfd, mptr, MHsize) < MHsize) Fatal("Unable to write master header", procName); RNodePtr = archive->RNodePtr; /* copy the surviving records to the destination file */ for (rec = 0; rec < archive->MHptr->total_records; rec++) { #ifdef APW if (STOP()) { printf("aborting.\n"); Quit(1); } #endif size = (long) RNodePtr->RHptr->attrib_count; size += (long) RNodePtr->namelen; 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); } size += (long) THsize; size += TNodePtr->THptr->comp_thread_eof; TNodePtr = TNodePtr->TNext; } if (!RNodePtr->filename[0]) { if (lseek(arcfd, size, S_REL) < 0) Fatal("Unable to seek past deleted record", procName); } else { FCopy(arcfd, dstfd, size, pakbuf, FALSE); } RNodePtr = RNodePtr->RNext; /* move on to next record */ } if (close(dstfd) < 0) Fatal("Unable to close archive", procName); if (verbose) printf("done.\n"); } /* * Delete files from archive * * Scan archive, deleting files which start with the strings in "names". */ static void Delete(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 */ int len, *lentab; /* hold strlen() of all names */ char *pn; /* archived pathname */ long remaining; char *tmpname = (char *) Malloc(MAXFILENAME); static char *procName = "Delete"; archive = NuRead(filename); if ((arcfd = open(archive->arc_name, O_RDONLY | O_BINARY)) < 0) Fatal("Unable to open archive", procName); 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; remaining = MHptr->total_records; /* 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("WARNING: '%s' has unknown record version_number\n", pn); for (idx = 0; idx < namecount; idx++) { /* find file in archive */ /* try to match argument with first few chars of stored filename */ /* or the entire filename, depending on EXPAND flag */ if ((len >= lentab[idx]) && doExpand ? (!strncasecmp(pn, names[idx], lentab[idx])) : (!strcasecmp(pn, names[idx])) ) { if (verbose) printf("Marking '%s' as deleted.\n", pn); RNodePtr->filename[0] = '\0'; /* mark as deleted */ remaining--; break; /* out of filename matching for-loop */ } } RNodePtr = RNodePtr->RNext; /* move on to next record */ } if (remaining == MHptr->total_records) { if (verbose) printf("No files selected; archive not modified\n"); if (close(arcfd) < 0) Fatal("Source (archive) close failed", procName); Quit (0); } if (remaining == 0L) { printf("All files in archive marked for deletion..."); fflush(stdout); if (close(arcfd) < 0) Fatal("Source (archive) close failed", procName); #ifdef APW if (STOP()) { printf("aborting.\n"); Quit (1); } #endif printf(" deleteing archive file.\n"); if (unlink(archive->arc_name) < 0) Fatal("Unable to delete archive", procName); } else { tmpname = MakeTemp(tmpname); #ifdef APW if (STOP()) { printf("aborting.\n"); Quit (1); } #endif if (lseek(arcfd, (long) MHsize, S_ABS) < 0) Fatal("Unable to seek past master block", procName); RebuildArchive(arcfd, archive, tmpname, remaining); if (close(arcfd) < 0) Fatal("Source (archive) close failed", procName); if (verbose) { printf("Deleteing old archive file..."); fflush(stdout); } if (unlink(archive->arc_name) < 0) Fatal("Unable to delete original archive", procName); Rename(tmpname, archive->arc_name); if (verbose) printf("done.\n"); } free (tmpname); free (lentab); } /* * Entry point for deleteing files from archive. */ void NuDelete(filename, namecount, names, options) char *filename; int namecount; char **names; char *options; { static char *procName = "NuDelete"; /* presently does nothing */ Delete(filename, namecount, names); } /********** update routines **********/ /* * Updates the archive. * * Evaluate the command line arguments and compare them with the files in * the archive. Put the most recent copy of the file in a new archive file. * Essentially a combination of add and delete. * * This procedure is huge. Someday I may clean this up a bit... */ static void Update(archive, namecount, names) ListHdr *archive; int namecount; char **names; { int arcfd, dstfd; /* archive file descriptor */ static file_info *FIArray[MAXARGS]; /* entries malloc()ed by EvalArgs */ unsigned int rec; int idx, thread; MHblock *MHptr; /* Master Header block */ RNode *RNodePtr; /* Record Node */ TNode *TNodePtr; /* Thread block */ char *pn; /* archived pathname */ BOOLEAN keeparc, gotone; char *tmpname = (char *) Malloc(MAXFILENAME); Time *atptr, *ftptr; long a_dt, f_dt; long size; fourbyt totalrecs; onebyt *mptr; twobyt *twoptr; static char *procName = "Update"; if ((arcfd = open(archive->arc_name, O_RDONLY | O_BINARY)) < 0) Fatal("Unable to open archive", procName); /* expand wildcards/subdirectories, and get info */ namecount = EvalArgs(namecount, names, FIArray, TRUE); if (!namecount) { if (verbose) printf("No files selected; archive not modified.\n"); Quit (0); } /* * For each file in the archive, check for an *exact* match with the * store_names in FIArray (case independent). If a match is found, * compare the dates, and copy/add the most recent file. If no match * is found, copy the file. After all archived files have been processed, * add all remaining files specified on the command line (unless the * F)reshen option is used, in which case this exits). */ MHptr = archive->MHptr; RNodePtr = archive->RNodePtr; gotone = FALSE; /* mark files that will be replaced */ for (rec = 0; rec < MHptr->total_records; rec++) { #ifdef APW if (STOP()) { printf("aborting.\n"); Quit (1); } #endif pn = RNodePtr->filename; if (RNodePtr->RHptr->version_number > MAXVERS) printf("WARNING: '%s' has unknown record version_number\n", pn); for (idx = 0; idx < namecount; idx++) { /* find file in archive */ /* try to match argument with first few chars of stored filename */ if (!strcasecmp(pn, FIArray[idx]->store_name)) { atptr = &RNodePtr->RHptr->mod_when; ftptr = &FIArray[idx]->mod_dt; /* compare dates; avoid month/year stuff by straight compare */ if ((atptr->year > ftptr->year) || (atptr->month > ftptr->month)) keeparc = TRUE; else if ((atptr->year < ftptr->year) || (atptr->month < atptr->month)) keeparc = FALSE; else { /* year & month match, check rest */ a_dt = (atptr->day * 86400L) + (atptr->hour * 3600) + (atptr->minute * 60) + (atptr->second); f_dt = (ftptr->day * 86400L) + (ftptr->hour * 3600) + (ftptr->minute * 60) + (ftptr->second); if (a_dt < f_dt) keeparc = FALSE; else /* (a_dt >= f_dt) */ keeparc = TRUE; } if (!keeparc) { /* not keeping; mark as being replaced */ #ifndef APW /* APW uses actual filetype; other systems keep old */ FIArray[idx]->fileType = RNodePtr->RHptr->file_type; FIArray[idx]->auxType = RNodePtr->RHptr->extra_type; #endif RNodePtr->RHptr->version_number = 65535; /*can't do fname*/ twoptr = (twobyt *) RNodePtr->filename; *twoptr = idx; /* null filename -> problems */ gotone = TRUE; } FIArray[idx]->marked = TRUE; /* MARK as processed */ } } RNodePtr = RNodePtr->RNext; /* move on to next record */ } totalrecs = MHptr->total_records; /* none will be deleted */ if (!dofreshen) { /* add new files? */ for (idx = 0; idx < namecount; idx++) { /* handle unmatched args */ if (!FIArray[idx]->marked) { gotone = TRUE; totalrecs++; /* count new ones too */ } } } if (!gotone) { if (verbose) printf("No files need updating; archive not modified\n"); if (close(arcfd) < 0) Fatal("Source (archive) close failed", procName); Quit (0); } /* * Rebuild archive file */ if (verbose) printf("Building new archive file...\n"); tmpname = MakeTemp(tmpname); ArcfiCreate(tmpname); /* build master header */ mptr = MakeMHblock(archive, totalrecs); if (lseek(arcfd, (long) MHsize, S_ABS) < 0) Fatal("Bad archive seek", procName); if ((dstfd = open(tmpname, O_RDWR | O_TRUNC | O_BINARY)) < 0) Fatal("Unable to open dest file", procName); if (write(dstfd, mptr, MHsize) < MHsize) Fatal("Unable to write master header", procName); RNodePtr = archive->RNodePtr; for (rec = 0; rec < MHptr->total_records; rec++) { size = (long) RNodePtr->RHptr->attrib_count; size += (long) RNodePtr->namelen; 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); } size += (long) THsize; size += TNodePtr->THptr->comp_thread_eof; TNodePtr = TNodePtr->TNext; } /* we now know the size; either copy the old or replace with new */ if (RNodePtr->RHptr->version_number != 65535) { /* file not replaced */ /* if (verbose) { * printf("Copying '%s'...", RNodePtr->filename); * fflush(stdout); * } */ FCopy(arcfd, dstfd, size, pakbuf, FALSE); /* if (verbose) printf("done.\n"); */ } else { /* file replaced; skip orig and add new */ if (lseek(arcfd, size, S_REL) < 0) Fatal("Bad skip seek", procName); twoptr = (twobyt *) RNodePtr->filename; idx = *twoptr; if (verbose) printf("Replacing/"); /* +"Adding 'filename'..." */ AddFile(dstfd, FIArray[idx]); } RNodePtr = RNodePtr->RNext; /* move on to next record */ } if (!dofreshen) { for (idx = 0 ; idx < namecount; idx++) { #ifdef APW if (STOP()) Quit(1); /* check for OA-. */ #endif if (!FIArray[idx]->marked) { AddFile(dstfd, FIArray[idx]); } } } if (close(arcfd) < 0) Fatal("Source (old archive) close failed", procName); if (close(dstfd) < 0) Fatal("Destination (new archive) close failed", procName); if (verbose) { printf("Deleteing old archive file..."); fflush(stdout); } if (unlink(archive->arc_name) < 0) Fatal("Unable to delete original archive", procName); Rename(tmpname, archive->arc_name); if (verbose) printf("done.\n"); free (tmpname); } /* * Update files in archive * * This part just evaluates the options, sets parms, and calls Update(). */ void NuUpdate(filename, namecount, names, options) char *filename; int namecount; char **names; char *options; { ListHdr *archive; static char *procName = "NuUpdate"; if (*options == 'f') dofreshen = TRUE; else dofreshen = FALSE; /* change T subopt to convert FROM current system TO */ if (transfrom >= 0) { transto = transfrom; transfrom = -1; } archive = NuRead(filename); Update(archive, namecount, names); } !Funky!Stuff! fi # end of overwriting check echo shar: "extracting 'nuread.c'" '(14376 characters)' if test -f 'nuread.c' then echo shar: "will not over-write existing file 'nuread.c'" else cat << \!Funky!Stuff! > 'nuread.c' /* * nuread.c - read NuFX archives (header info only) into structures * * By Andy McFadden (fadden@cory.berkeley.edu) * NuLib v2.1 November 1989 Freeware (distribute, don't sell) */ #include "nudefs.h" #include #include #include #ifdef MSDOS /* For file IO */ # include # include # include # include #endif #ifdef CRC_TAB # include "crc.h" /* fast CRC lookup */ #endif #include "nuread.h" #include "nupak.h" /* uses PAKBUFSIZ */ #include "nuetc.h" /* 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. * * If the verbose setting is used, it prints CRCs for entire records (headers, * threads, etc). */ 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 size; int srcfd; /* file descriptor */ int thread; twobyt CRC; long CRCsum = 0L; static char *procName = "NuTest"; printf("Testing %s", filename); if (verbose) printf("\n"); else { printf("..."); fflush(stdout); } archive = NuRead(filename); /* major glitches cause this to fail */ 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); size = (long) RNodePtr->RHptr->attrib_count; size += (long) RNodePtr->namelen; 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); } size += (long) THsize; size += TNodePtr->THptr->comp_thread_eof; TNodePtr = TNodePtr->TNext; } if (verbose) { printf("record size = %ld, ", size); fflush(stdout); } CRC = 0; while (size != 0L) { if (size > (long) PAKBUFSIZ) { partial = (unsigned int) PAKBUFSIZ; size -= (long) PAKBUFSIZ; } else { partial = (unsigned int) size; 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) CRC = CalcCRC(CRC, copybuf, partial); if (verbose) printf("CRC = $%.4x\n", CRC); if (verbose) CRCsum += CRC; } 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, tu_ptr, tc_ptr, CRC_ptr) int fd; RHblock *RHptr; fourbyt *tu_ptr, /* pointer to int holding len of uncomp. threads */ *tc_ptr; /* same for sum of comp_thread_eof */ 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"; *tu_ptr = 0L, *tc_ptr = 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); perror("ReadThread (THblock)"); } CRC = CalcCRC(CRC, filebuf, 16); /* rec 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->reserved, 2, TRUE); BCopy(filebuf+8, (onebyt *) &THptr->thread_eof, 4, TRUE); BCopy(filebuf+12, (onebyt *) &THptr->comp_thread_eof, 4, TRUE); /* update pointers and skip the actual data */ *tu_ptr += THptr->thread_eof; *tc_ptr += THptr->comp_thread_eof; if ((TNodePtr->fileposn = lseek(fd, 0L, S_REL)) < 0) Fatal("Bad thread posn lseek()", procName); if (THptr->comp_thread_eof > 2097152L) /* SANITY CHECK */ fprintf(stderr, "Sanity check: found comp_thread_eof > 2MB\n"); if (lseek(fd, (long) THptr->comp_thread_eof, S_REL) < 0) Fatal("Bad seek", procName); } *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, filebuf+8, MHsize-8); /* calc 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->reserved, 20, 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, "SIT!", 4)) /* StuffIt */ OtherArc("a StuffIt archive", "StuffIt (Macintosh)"); if (!strncmp((char *) filebuf, "", 4)) /* system V arch */ OtherArc("a library archive (Sys V)", "ar"); if (!strncmp((char *) filebuf, "!", 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 ARC and ZOO */ Quit (-1); } if (CRC != MHptr->master_crc) printf("WARNING: Master Header block may be corrupted (bad CRC)\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 */ 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); } CRC = CalcCRC(0, filebuf+6, RHsize-6); /* rec hdr CRC part 1/5 */ 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, 4, TRUE); BCopy(filebuf+14, (onebyt *) &RHptr->file_sys_id, 2, TRUE); BCopy(filebuf+16, (onebyt *) &RHptr->file_sys_info, 2, 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); if (strncmp(RHptr->ID, RecordID, 4)) { fprintf(stderr, "Found bad record ID (#%d)\n", 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, filebuf, num); /* rec 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(&namelen, 0, 1); /* read filename, and store in struct */ if (namelen > MAXFILENAME) { fprintf(stderr, "ERROR: namelen > MAXFILENAME\n"); Quit (-1); } RNodePtr->namelen = namelen; if (read(fd, namebuf, namelen) < namelen) Fatal("Bad namebuf read", procName); CRC = CalcCRC(CRC, namebuf, namelen); /* rec hdr CRC part 4/5 */ RNodePtr->filename = (char *) Malloc(namelen+1); /* store fname */ BCopy(namebuf, (onebyt *) RNodePtr->filename, namelen, FALSE); RNodePtr->filename[namelen] = '\0'; RNodePtr->TNodePtr = ReadThreads(fd, RHptr, &RNodePtr->unc_len, &RNodePtr->comp_len, &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); } return (ListPtr); } !Funky!Stuff! fi # end of overwriting check echo shar: "extracting 'nushk.c'" '(16430 characters)' if test -f 'nushk.c' then echo shar: "will not over-write existing file 'nushk.c'" else cat << \!Funky!Stuff! > 'nushk.c' /* * nushk.c - P8 ShrinkIt compress/uncompress routines * * By Andy McFadden (fadden@cory.berkeley.edu) * NuLib v2.1 November 1989 Freeware (distribute, don't sell) */ #include "nudefs.h" #include #include #ifdef MSDOS /* For file IO */ # include # include # include # include #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+1]; /* temporary buffer for storing data after LZW */ onebyt rbuf[BLKSIZ+1]; /* temporary buffer for storing data after RLE */ /* * Fake ShrinkIt compression routines. * * Only removes repeated characters; doesn't actually do the LZW. This * means that the compression achieved will not be all that great (if it * compresses at all). */ #define ESCAPE_CHAR 0xdb /* * 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 char count */ int do_RLE(srcptr, dstptr) onebyt *srcptr, *dstptr; { int found, scount, dcount; 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 entry point. */ long pak_SHK(srcfd, dstfd, length, copybuf) int srcfd, dstfd; long length; onebyt *copybuf; { unsigned int partial; /* size for partial read/write */ onebyt *rptr; register int idx; onebyt scratch[8]; long startposn, endposn; long comp_len = 0L; twobyt CRC; int rlesize; /* length after RLE */ int sc; /* spin counter */ static char *procName = "pak_SHK"; CRC = 0; if ((startposn = lseek(dstfd, 0L, S_REL)) < 0) Fatal("Bad seek (first)", 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); } CRC = CalcCRC(CRC, copybuf, BLKSIZ); /* calc on all 4096 bytes */ 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; } scratch[0] = (onebyt) (rlesize & 0x00ff); scratch[1] = (onebyt) ((rlesize >> 8) & 0x00ff); scratch[2] = 0; /* LZW off */ if (write(dstfd, scratch, 3) != 3) Fatal("Dest hdr write failed", procName); comp_len += 3; if (write(dstfd, rptr, rlesize) != rlesize) /* need to do CRLF */ Fatal("Dest write failed", procName); comp_len += rlesize; 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 */ } /* * P8 ShrinkIt uncompression routines * * Copyright 1989 Kent Dickey * C translation by Kent Dickey / Andy McFadden */ static int inf; /* to make Getc() calls happy */ 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;*/ { 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 */ { 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 * char count * which is different from the norm. */ static void undo_RLE(inbuffer, outbuffer) unsigned char *inbuffer, *outbuffer; /*int length; /* how many bytes from LZW; just to make sure... */ { int total, count; /* count is RLE reps */ unsigned char c; #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. * */ void unpak_SHK(srcfd, dstfd, comp_thread_eof, thread_eof, buffer) int srcfd, dstfd; fourbyt comp_thread_eof, thread_eof; onebyt *buffer; { twobyt CRC, blkCRC; onebyt vol; onebyt *wrbuf; /* points to buffer we're about to write */ int unlen, lzwflag, rleflag; unsigned int partial, toread, still_in_buf; fourbyt tmp4; /* temporary 4-byte variable */ static char *procName = "unpak_SHK"; CRC = 0; /* 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 (read(srcfd, buffer, toread) < toread) Fatal("Bad read", procName); ibuf = buffer; /* set input pointer to start of buffer */ /* get header data */ 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) { unlen = Getc(inf); unlen += (Getc(inf) << 8); #ifdef DEBUG1 printf("Length after compression = %d ($%.4x)\n", unlen, unlen); #endif lzwflag = Getc(inf); rleflag = (unlen != BLKSIZ); #ifdef DEBUG1 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)); } } #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 + 5)) { /* 5 = 3 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(ibuf, 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_RLE reads from where you tell it and writes to rbuf */ if (lzwflag && rleflag) { undo_LZW(lbuf, unlen); /* from ibuf -> lbuf */ undo_RLE(lbuf, rbuf); /* from lbuf -> rbuf */ wrbuf = rbuf; /* write rbuf */ CRC = CalcCRC(CRC, rbuf, BLKSIZ); /* always 4K bytes */ } else if (lzwflag && !rleflag) { undo_LZW(lbuf, unlen); /* from ibuf -> lbuf */ wrbuf = lbuf; /* write lbuf */ CRC = CalcCRC(CRC, lbuf, BLKSIZ); } else if (!lzwflag && rleflag) { undo_RLE(ibuf, rbuf); /* from ibuf -> rbuf */ wrbuf = rbuf; /* write rbuf */ CRC = CalcCRC(CRC, 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, 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"); } } !Funky!Stuff! fi # end of overwriting check exit 0 # End of shell archive