jac@yoko.rutgers.edu (Jonathan A. Chandross) (05/02/91)
Submitted-by: Andy McFadden (fadden@cory.berkeley.edu)
Posting-number: Volume 1, Source:37
Archive-name: archive/unix/nulib/part06.10
Architecture: UNIX
Version-number: 3.03
=nupdel.c
-/*
- * nudel.c - operations which delete from a NuFX archive
- * nuupd.c - update/freshen 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>
-#ifdef BSD43
-# include <strings.h>
-#else /* SYSV, APW, MSC */
-# include <string.h>
-#endif
-
-#ifdef UNIX
-# include <errno.h>
-#endif
-#ifdef APW
-# include <types.h>
-# include <prodos.h> /* ? */
-# include <shell.h>
-# include <strings.h> /* APW string ops */
-#endif
-#ifdef MSDOS
-# include <io.h>
-# include <sys/types.h>
-# include <sys/stat.h>
-# include <errno.h>
-#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;
- long master_eof;
-#ifdef APW
- FileRec create_p;
-#endif
- static char *procName = "RebuildArchive";
-
- if (verbose) { printf("Building new archive file..."); fflush(stdout); }
-
- ArcfiCreate(tmpname); /* create file */
- master_eof = (long) MHsize;
-
- if ((dstfd = open(tmpname, O_WRONLY | O_TRUNC | O_BINARY, WPERMS)) < 0)
- Fatal("Unable to open dest file", procName);
- if (lseek(dstfd, (long) MHsize, S_ABS) < 0)
- Fatal("Unable to lseek past dest mhblock", 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->filename_length;
- 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);
- master_eof += size;
- }
-
- RNodePtr = RNodePtr->RNext; /* move on to next record */
- }
-
- mptr = MakeMHblock(archive, remaining, master_eof); /* build mheader */
- if (lseek(dstfd, 0L, S_ABS) < 0)
- Fatal("Unable to seek back in dest file", procName);
- if (write(dstfd, mptr, MHsize) < MHsize)
- Fatal("Unable to write master header", procName);
-
- if (close(dstfd) < 0)
- Fatal("Unable to close archive", procName);
- if (verbose) printf("done.\n");
-}
-
-
-/*
- * Delete files from archive
- *
- * Scan archive, deleting files which match 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, master_eof;
- 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 month/year [ I think it's best-case faster... ] */
- a_dt = (atptr->year * 12) + atptr->month;
- f_dt = (ftptr->year * 12) + ftptr->month;
- if (a_dt > f_dt) /* archive is more recent? */
- keeparc = TRUE;
- else if (a_dt < f_dt) /* file is more recent? */
- 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);
-
- master_eof = (long) MHsize;
-
- 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 (lseek(dstfd, (long) MHsize, S_ABS) < 0)
- Fatal("Bad dest seek", procName); /* leave space for later */
-
- RNodePtr = archive->RNodePtr;
- for (rec = 0; rec < MHptr->total_records; rec++) {
- size = (long) RNodePtr->RHptr->attrib_count;
- size += (long) RNodePtr->filename_length;
- 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);
- master_eof += (fourbyt) size;
-/* 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'..." */
- master_eof += 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) {
- master_eof += AddFile(dstfd, FIArray[idx]);
- }
- }
- }
-
- /* build master header */
- mptr = MakeMHblock(archive, totalrecs, master_eof);
- if (lseek(dstfd, 0L, S_ABS) < 0)
- Fatal("Bad lseek for master header", procName);
- if (write(dstfd, mptr, MHsize) < MHsize)
- Fatal("Unable to write master header", procName);
-
- 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 <subopt> */
- if (transfrom >= 0) {
- transto = transfrom;
- transfrom = -1;
- }
-
- archive = NuRead(filename);
- Update(archive, namecount, names);
-}
-
=nublu.c
-/*
- * nublu.c - operations on Binary II archives
- *
- * NuLib v3.0 February 1991 Freeware (distribute, don't sell)
- * By Andy McFadden (fadden@cory.berkeley.edu)
- */
-#ifdef APW
-segment "Compress"
-#endif
-
-#ifndef NO_BLU /***********************************/
-
-#include "nudefs.h"
-#include <stdio.h>
-#include <fcntl.h>
-
-#ifdef UNIX
-# include <errno.h>
-# include <sys/types.h>
-# include <sys/stat.h>
-#endif
-#ifdef APW
-# include <prodos.h>
-#endif
-#ifdef MSDOS
-# include <stdlib.h>
-# include <io.h>
-# include <string.h>
-# include <sys/types.h>
-# include <sys/stat.h>
-#endif
-
-#include "nuview.h" /* file types for BLU */
-#include "nuadd.h" /* need OptNum() */
-#include "nupak.h" /* need unpak_SQU */
-#include "nuetc.h"
-
-/* Binary II extraction routines are adapted from: */
-/*************************************************************************
- ** **
- ** Name : unblu **
- ** Author : Marcel J.E. Mol **
- ** Date : 10/05/88 (first release) **
- ** Version : 2.20 **
- ** Files : unblu.c Main source file **
- ** **
- ** ------------------------- Revision List ------------------------- **
- ** Ver Date Name Remarks **
- ** 1.00 10/05/88 Marcel Mol Raw copy of a basic program**
- ** 2.00 03/06/88 Marcel Mol Rewrite after blu info **
- ** was send to the net **
- ** 2.10 18/06/88 Marcel Mol Added filetype texts **
- ** 2.20 23/09/88 Marcel Mol Show mod and creation time **
- ** **
- ************************************************************************/
-
-
-/*char * copyright = "@(#) unblu.c 2.1 18/06/88 (c) M.J.E. Mol";*/
-#define BUFSIZE 128 /* Blu block length */
-
-/* global variables */
-static char *progname;
-static char *blufile;
-static BOOLEAN extract = FALSE; /* extract (as opposed to just listing) */
-
-
-/*
- * extract_file -- extract file fname from the archive fd. Fname
- * contains filelen bytes.
- *
- * If the first block has the .QQ magic numbers, go ahead and try to
- * unsqueeze it. Not the best way to go about it, but it works.
- */
-static void extract_file(fd, fname, filelen)
-int fd;
-char *fname; /* 64 bytes */
-long filelen;
-{
- int ofd;
- int n, i;
- int j, len;
- onebyt buf[BUFSIZE];
- long full_len;
- int offset;
- static char *procName = "extract_file";
-
- /*n = */ read(fd, buf, 70); /* read first few bytes */
- lseek(fd, -70L, S_REL); /* back up */
- if ((buf[0] == 0x76) && (buf[1] == 0xff)) { /* is it squeezed? */
- i = 0; /* get the original file name */
- while ((fname[i] = buf[4+i]) != '\0')
- i++;
- offset = 5+i; /* how far into file is end of filename? */
- if (verbose) { printf("(as %s)...", fname); fflush(stdout); }
- }
-
- len = strlen(fname);
- for (j = 0; j < len; j++)
- fname[j] &= 0x7f; /* clear hi bits */
-
- if (Exists(fname)) {
- if (interact) {
- if (verbose) printf("file exists, overwite");
- else printf("%s exists, overwite", fname);
- if (!AskYesNo()) { /* return w/o overwriting */
- full_len = ( (filelen / 128L) +1 ) * 128L;
- lseek(fd, full_len, S_REL);
- return;
- }
- }
- if (verbose) { printf("overwriting..."); fflush(stdout); }
- if (unlink(fname) < 0)
- Fatal("Unable to remove existing file", procName);
- }
-
- if ((ofd = open(fname, O_BINARY|O_CREAT|O_WRONLY|O_TRUNC, 0644)) < 0) {
- Fatal("Can't open destination file", "extract_file");
- }
-
- if ((buf[0] == 0x76) && (buf[1] == 0xff)) { /* is it squeezed? */
- if (verbose) { printf("unsqueezing..."); fflush(stdout); }
- full_len = ( (filelen / 128L) +1 ) * 128L;
- lseek(fd, (long) offset, S_REL);
- full_len -= offset; /* send unpak_SQU everything past fname */
-
- unpak_SQU(fd, ofd, full_len); /* unsqueeze it */
-
- } else { /* extract uncompressed */
-
- lastseen = '\0'; /* used by crlf() translator */
- while (filelen > 0L) {
- n = read(fd, buf, BUFSIZE); /* Read 128 bytes */
- if (n != BUFSIZE) {
- fprintf(stderr, "Extract_BNY: %s file size broken\n", blufile);
- Quit(-1);
- }
- if (crlf(ofd, buf, (filelen >= BUFSIZE ? BUFSIZE : filelen)) !=
- (filelen >= BUFSIZE ? BUFSIZE : filelen))
- Fatal("Bad write", procName);
-
- filelen -= (long) BUFSIZE;
- }
- }
- close(ofd); /* Close destination file */
-}
-
-
-/*
- * print_header -- print global information of the binary II file
- */
-static void print_header(buf)
-onebyt *buf;
-{
- long disk_blocks;
-
- disk_blocks = buf[117] + (buf[118]<<8) + (buf[119]<<16) + (buf[120]<<24);
- printf("Listing %-40.40s ", blufile);
- printf("Blocks used: %-5ld", disk_blocks);
- printf("Files: %d\n", buf[127]+1);
- printf("\nFilename Type Blocks Modified ");
- printf("Created Length Subtype\n\n");
-}
-
-
-/*
- * want -- return TRUE if name exists in array wantlist,
- * else return FALSE
- */
-static BOOLEAN want(name, wantlist)
-char *name;
-char **wantlist;
-{
- while (*wantlist != NULL) {
- if (strcasecmp(name, *wantlist++) == NULL)
- return (TRUE);
- }
- return (FALSE);
-
-}
-
-
-/*
- * process_file -- retrieve or print file information of file given
- * in buf
- */
-static void process_file(fd, buf, count, wanted)
-int fd;
-onebyt *buf;
-int count;
-char **wanted;
-{
- int ftype, auxtype;
- int fnamelen;
- long filelen;
- char fname[64];
- char outbuf[16]; /* temp for sprintf */
- int nblocks, problocks;
- Time create_dt;
- Time mod_dt;
-#ifdef APW
- FileRec frec;
-#endif
-#ifdef UNIX
- struct stat st;
-#endif
-#ifdef MSDOS
- struct stat st;
-#endif
-/* +PORT+ */
-/* int tf;
- * int dflags;
- */
- static char *procName = "process_file";
-
- /* Get file info */
- ftype = buf[4]; /* File type */
- auxtype = (int) buf[5] + ((int)buf[6] << 8);
- fnamelen = buf[23]; /* filename */
- strncpy(fname, &buf[24], fnamelen);
- fname[fnamelen] = '\0';
- /* dflags = buf[125]; /* Data flags */
- /* tf = buf[127]; /* Number of files to follow */
- filelen = (long) buf[20] + ((long) buf[21] << 8) +
- ((long) buf[22] << 16); /* calculate file len */
- nblocks = (filelen + BUFSIZE-1) / BUFSIZE; /* #of BNY blocks */
- problocks = buf[8] + ((int) buf[9] << 8);
-
- mod_dt.second = 0;
- mod_dt.minute = buf[12] & 0x3f;
- mod_dt.hour = buf[13] & 0x1f;
- mod_dt.day = (buf[10] & 0x1f) -1;
- mod_dt.month = (((buf[11] & 0x01) << 3) + (buf[10] >> 5)) -1;
- mod_dt.year = buf[11] >> 1;
- mod_dt.weekDay= 0;
- create_dt.second = 0;
- create_dt.minute = buf[16] & 0x3f;
- create_dt.hour = buf[17] & 0x1f;
- create_dt.day = (buf[14] & 0x1f) -1;
- create_dt.month = (((buf[15] & 0x01) << 3) + (buf[14] >> 5)) -1;
- create_dt.year = buf[15] >> 1;
- create_dt.weekDay= 0;
-
- if (!count || want(fname, wanted)) {
- if (!extract) { /* print file information ONLY */
- printf("%-15.15s %-3.3s ", fname, FT[ftype]);
- printf("%6d ", problocks);
- printf("%-16.16s ", PrintDate(&mod_dt, TRUE));
- printf("%-16.16s ", PrintDate(&create_dt, TRUE));
- if (filelen < 0x100L)
- sprintf(outbuf, "$%.2lx", filelen);
- else if (filelen < 0x10000L)
- sprintf(outbuf, "$%.4lx", filelen);
- else sprintf(outbuf, "$%.6lx", filelen);
- printf("%7s ", outbuf);
- printf("$%.4x\n", auxtype);
-
-/* if (dflags == 0)
- * printf("stored");
- * else {
- * if (dflags & 128) {
- * printf("squeezed");
- * }
- * if (dflags & 64) {
- * printf("encrypted");
- * }
- * if (dflags & 1)
- * printf("packed");
- * }
- * putchar('\n');
- */
- if (ftype != 15) { /* If not a directory */
- lseek(fd, (long) BUFSIZE*nblocks, S_REL); /*Seek to next file*/
- }
-
- } else { /* extract is TRUE */
-
- if (verbose) { printf("Extracting %s...", fname); fflush(stdout); }
-#ifdef UNIX
- if (ftype != 15)
- extract_file(fd, fname, filelen); /* note dates etc not set */
- else {
- /* if no directory exists, then make one */
- if (stat(fname, &st) < 0)
- if (errno == ENOENT) {
- sprintf(tmpNameBuf, "mkdir %s", fname);
- if (system(tmpNameBuf) != 0) /* call UNIX mkdir */
- Fatal("Unable to create subdir", procName);
- } else {
- Fatal("Unable to create dir", procName);
- }
- }
-#else
-# ifdef APW
- /* create file/directory , with appropriate type/auxtype stuff */
- c2pstr(fname);
- frec.pathname = fname;
- frec.fAccess = 0x00e3; /* unlocked */
- frec.fileType = ftype;
- frec.auxType = (unsigned long) auxtype;
- frec.storageType = (int) buf[7];
- frec.createDate = 0x0000; /* set later */
- frec.createTime = 0x0000;
-
- CREATE( &frec );
- ToolErrChk();
- p2cstr(fname);
-
- extract_file(fd, fname, filelen);
-
- /* set file attributes */
- c2pstr(fname);
- frec.fAccess = (word) buf[3];
- frec.modDate = (word) buf[10] + ((word)buf[11] << 8);
- frec.modTime = (word) buf[12] + ((word)buf[13] << 8);
- frec.createDate = (word) buf[14] + ((word)buf[15] << 8);
- frec.createTime = (word) buf[16] + ((word)buf[17] << 8);
- SET_FILE_INFO( &frec );
- ToolErrChk();
- p2cstr(fname);
-# else
- if (ftype != 15)
- extract_file(fd, fname, filelen);
- else /* +PORT+ */
- printf("[ need [other] subdir create for UnBNY ]\n");
-# endif /* APW */
-#endif /* UNIX */
- if (verbose) printf("done.\n");
- }
- } else if (ftype != 15) { /* This file not wanted; if not a directory */
- lseek(fd, (long) BUFSIZE*nblocks, S_REL); /* Seek to next file */
- }
-}
-
-
-/*
- * unblu -- process a binary II file fd, and process the filenames
- * listed in wanted. If wanted is \0, all files are processed.
- */
-static void unblu(fd, count, wanted)
-int fd;
-int count;
-char **wanted;
-{
- onebyt buf[BUFSIZE];
- int firstblock = 1; /* First block needs special processing */
- int tofollow = 1; /* Files to follow in the archive */
- int n;
-
- while (tofollow && ((n = read(fd, buf, BUFSIZE)) > 0)) {
- /* If there is a header block */
-
- if (n != BUFSIZE) {
- fprintf(stderr, "UnBNY: %s file size is broken\n", blufile);
- Quit(-1);
- }
- if ((buf[0] != 10) || (buf[1] != 71) ||
- (buf[2] != 76) || (buf[18] != 2)) {
- fprintf(stderr,
- "UnBNY: %s not a Binary II file or bad record\n", blufile);
- Quit(-1);
- }
-
- tofollow = buf[127]; /* How many files to follow */
- if (firstblock && !extract) {
- print_header(buf);
- }
- firstblock = 0;
- process_file(fd, buf, count, wanted); /* process the file for it */
-
- }
- if (firstblock && (n < 0)) /* length < 128 */
- fprintf(stderr, "UnBNY: Not a Binary II file");
-}
-
-
-/*
- * Main entry point from CShrink
- */
-void NuBNY(filename, argc, argv, options)
-char *filename;
-int argc;
-char **argv;
-char *options;
-{
- int bfd; /* File descriptor for blu file */
- char *optr;
-
- /* process X subopt ourselves */
- if (INDEX(options+1, 'x')) extract = TRUE;
- else extract = FALSE;
-
- blufile = filename; /* Make it global */
- if ((bfd = open(filename, O_RDONLY | O_BINARY)) < 0)
- Fatal("Unable to open Binary II archive", "NuBNY");
-
- unblu(bfd, argc, argv); /* Process wanted files */
-
- close(bfd);
- Quit(0);
-}
-
-#endif /*NO_BLU*/ /***********************************/
-
=nusq.c
-/*
- * nusq.c - Huffman squeeze/unsqueeze routines
- * Based on sq3/usq2 by Don Elton
- *
- * 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 "nuetc.h"
-
-/*
- * usq.c - undo Huffman coding
- * Adapated from code By Marcel J.E. Mol
- *
- * Squeezed file format:
- * 2 bytes MAGIC
- * 2 bytes dummy ??? (maybe CRC or checksum; not checked)
- * filename ended by \0
- *
- * 2 bytes node count
- * node count node values, each 2 bytes
- * squeezed data per byte
- *
- * NuFX SQueezed format includes only the node count, node values, and
- * the data. The BLU routines are expected to strip off the MAGIC,
- * checksum, and filename before calling this.
- */
-
-/*char *copyright = "@(#) usq.c 2.1 18/06/88 (c) M.J.E. Mol";*/
-#define BUFSIZE 128
-#define MAGIC 0xff76 /* Squeezed file magic */
-#define DLE 0x90 /* repeat byte flag */
-#define NOHIST 0 /* no relevant history */
-#define INREP 1 /* sending a repeated value */
-#define SPEOF 256 /* special endfile token */
-#define NUMVALS 257 /* 256 data values plus SPEOF */
-
-/* global variable declarations */
-char *sfn; /* squeezed file name */
-struct nd { /* decoding tree */
- int child[2]; /* left, right */
-} node[NUMVALS]; /* use large buffer */
-int state; /* repeat unpacking state */
-int bpos; /* last bit position read */
-int curin; /* last byte value read */
-int numnodes; /* number of nodes in decode tree */
-
-static unsigned char fromc; /* for use in text translation */
-static BOOLEAN trbool; /* BOOLEAN version of transfrom */
-
-
-/* Get an integer from the input stream */
-static twobyt get_int(f)
-FILE *f;
-{
- twobyt val;
-
- val = (twobyt)getc(f);
- val += (twobyt)getc(f) << 8;
- return (val);
-}
-
-
-static int getc_usq(f) /* get byte from squeezed file */
-FILE *f; /* file containing squeezed data */
-{
- register short i; /* tree index */
-
- /* follow bit stream in tree to a leaf */
- for (i=0; (i <= 0x7fff) && (i>=0); )/* work down(up?) from root */
- {
- if (++bpos > 7) {
- if ((curin=getc(f)) == EOF)
- return(EOF);
- bpos = 0;
-
- /* move a level deeper in tree */
- i = node[i].child[1 & curin];
- }
- else i = node[i].child[1 & (curin >>= 1)];
- }
-
- /* decode fake node index to original data value */
- i = -(i + 1);
-
- /* decode special endfile token to normal EOF */
- return ((i==SPEOF) ? EOF : i);
-}
-
-
-/* putc-ncr -- decode non-repeat compression. Bytes are passed one
- * at a time in coded format, and are written out uncoded.
- * The data is stored normally, except that runs of more
- * than two characters are represented as:
- *
- * <char> <DLE> <count>
- *
- * With a special case that a count of zero indicates a DLE
- * as data, not as a repeat marker.
- */
-static void putc_ncr(c, t) /* put NCR coded bytes */
-unsigned char c; /* next byte of stream */
-FILE *t; /* file to receive data */
-{
- static int lastc; /* last character seen */
-
- /* if converting line terminators, do so now */
- if (trbool && (c == fromc))
-#ifdef UNIX
- c = 0x0a;
-#else
-# ifdef APW
- c = 0x0d;
-# else
- c = 0x0d; /* No CRLF stuff in unSQueeze... sorry */
-# endif
-#endif
-
- switch (state) { /* action depends on our state */
- case NOHIST: /* no previous history */
- if (c==DLE) /* if starting a series */
- state = INREP; /* then remember it next time */
- else putc(lastc=c, t); /* else nothing unusual */
- return;
-
- case INREP: /* in a repeat */
- if (c) /* if count is nonzero */
- while (--c) /* then repeatedly ... */
- putc(lastc, t); /* ... output the byte */
- else putc(DLE, t); /* else output DLE as data */
- state = NOHIST; /* back to no history */
- return;
-
- default:
- fprintf(stderr, "%s: bad NCR unpacking state (%d)",
- prgName, state);
- }
-}
-
-
-static int init_usq(f) /* initialize Huffman unsqueezing */
-FILE *f; /* file containing squeezed data */
-{
- register int i; /* node index */
-
- switch (transfrom) {
- case -1: /* no translation */
- trbool = 0;
- break;
- case 0: /* from ProDOS */
- trbool = 1;
- fromc = 0x0d;
- break;
- case 1: /* from UNIX */
- trbool = 1;
- fromc = 0x0a;
- break;
- case 2: /* from MS-DOS... this needs fixing */
- trbool = 1;
- fromc = 0x0a; /* just turn LFs into whatever... */
- break;
- default: /* unknown */
- fprintf(stderr, "%s: unknown translation type %d\n", prgName, trbool);
- fprintf(stderr, "%s: assuming conversion from CR\n", prgName);
- trbool = 1; /* should just ignore flag, but other procs do this */
- fromc = 0x0d;
- break;
- }
-
- bpos = 99; /* force initial read */
- numnodes = get_int(f); /* get number of nodes */
-
- if (numnodes<0 || numnodes>=NUMVALS) {
- fprintf(stderr, "%s: usq: archived file has invalid decode tree\n",
- prgName);
- return (-1);
- }
-
- /* initialize for possible empty tree (SPEOF only) */
- node[0].child[0] = -(SPEOF + 1);
- node[0].child[1] = -(SPEOF + 1);
-
- for (i=0; i<numnodes; ++i) { /* get decoding tree from file */
- node[i].child[0] = get_int(f);
- node[i].child[1] = get_int(f);
- }
-
- return (0);
-}
-
-
-/*
- * Unsqueeze a file
- */
-static int unsqueeze(sfp, dfp)
-FILE *sfp, *dfp;
-{
- register int i;
- register int c; /* one char of stream */
-
- state = NOHIST; /* initial repeat unpacking state */
-
- if (init_usq(sfp)) /* init unsqueeze algorithm */
- return 1;
- while ((c=getc_usq(sfp)) != EOF) /* and unsqueeze file */
- putc_ncr(c, dfp);
-
- return (0); /* file is okay */
-}
-
-
-/*
- * main entrance to unsqueeze
- *
- * We reset the file posn to where it should be according to "length"; note
- * that "length" is not actually used by the unsqueeze routines. We have
- * do to this because fdopen() sticks about 8K or so in a buffer...
- *
- * Note also that we dup() the file descriptors before starting. This
- * is so that we can cleanly fclose() the file descriptors when we're done,
- * but still keep the file open.
- */
-void unpak_SQU(srcfd, dstfd, length)
-int srcfd, dstfd;
-long length; /* #of bytes we're expected to read */
-{
- FILE *srcfp, *dstfp; /* File pointers for squ/dest file */
- int srcfd2, dstfd2;
- long finalposn;
- static char *procName = "unpak_SQU";
-
- finalposn = lseek(srcfd, 0L, S_REL) + length; /* where we should end up */
- srcfd2 = dup(srcfd);
- dstfd2 = dup(dstfd);
- if ((srcfp = fdopen(srcfd2, FREAD_STR)) == NULL)
- Fatal("Can't fdopen() archive", procName);
- if ((dstfp = fdopen(dstfd2, FWRITE_STR)) == NULL)
- Fatal("Can't fdopen() dest file", procName);
-
- unsqueeze(srcfp, dstfp); /* unsqueeze the file */
- fclose(srcfp); /* (was fflush) (this isn't really necessary) */
- fclose(dstfp); /* (was fflush) This is *very* necessary */
-
- if (lseek(srcfd, finalposn, S_ABS) < 0) /* set file posn back */
- Fatal("Can't reset final posn", procName);
- /* note that this lets things continue even if unSQueezing failed */
-}
-
=apwerr.h
-/*
- * apwerr.h - text versions of APW and ProDOS 16 error codes
- * ERROR() didn't cut it, and I'm trying to separate things from the shell.
- *
- * NuLib v3.0 February 1991 Freeware (distribute, don't sell)
- * By Andy McFadden (fadden@cory.berkeley.edu)
- */
-
-/* APW-specific UNIX-like errors */
-
-/*
- [ this is derived from: ]
- errno.h -- error return codes
-
- Copyright American Telephone & Telegraph
- Modified and used with permission, Apple Computer Inc.
- Copyright Apple Computer Inc. 1985, 1986, 1987
- All rights reserved.
-*/
-/* @(#)errno.h 2.1 */
-/* 3.0 SID # 1.3 */
-
-#define sys_nerr 35 /* err must be < Max APW Err */
-static char *sys_errlist[sys_nerr] = {
- /* 0 (no err) */ "[ call successful ]",
- /* 1 EPERM */ "permission denied",
- /* 2 ENOENT */ "no such file or directory",
- /* 3 ENORSRC */ "no such resource",
- /* 4 EINTR */ "interrupted system call",
- /* 5 EIO */ "I/O error",
- /* 6 ENXIO */ "no such device or address",
- /* 7 E2BIG */ "insufficient space for return argument",
- /* 8 ENOEXEC */ "exec format error",
- /* 9 EBADF */ "bad file number",
- /* 10 ECHILD */ "no children",
- /* 11 EAGAIN */ "no more processes",
- /* 12 ENOMEM */ "not enough memory",
- /* 13 EACCES */ "permission denied",
- /* 14 EFAULT */ "bad address",
- /* 15 ENOTBLK */ "block device required",
- /* 16 EBUSY */ "mount device busy",
- /* 17 EEXIST */ "file exists",
- /* 18 EXDEV */ "cross-device link",
- /* 19 ENODEV */ "no such device",
- /* 20 ENOTDIR */ "not a directory",
- /* 21 EISDIR */ "is a directory",
- /* 22 EINVAL */ "invalid argument",
- /* 23 ENFILE */ "file table overflow",
- /* 24 EMFILE */ "too many open files",
- /* 25 ENOTTY */ "not a typewriter (sorry)",
- /* 26 ETXTBSY */ "text file busy",
- /* 27 EFBIG */ "file too large",
- /* 28 ENOSPC */ "no space left on device",
- /* 29 ESPIPE */ "illegal seek",
- /* 30 EROFS */ "read only file system",
- /* 31 EMLINK */ "too many links",
- /* 32 EPIPE */ "broken pipe",
- /* 33 EDOM */ "math arg out of domain of func",
- /* 34 ERANGE */ "math result not representable"
-};
-
-
-/* ProDOS errors */
-
-/* [ This is derived from: ]
-/********************************************
-; File: ProDos.h
-;
-;
-; Copyright Apple Computer, Inc. 1986, 1987
-; All Rights Reserved
-;
-********************************************/
-
-#define MPErr 0x61 /* err must be < Max ProDOS Err # */
-static char *ProDOSErr[MPErr] = {
- /* 00 (no error) */ "[ ProDOS call successful ]",
- /* 01 invalidCallNum */ "invalid call number / (fatal) unclaimed intr",
- /* 02 */ "",
- /* 03 */ "",
- /* 04 */ "(ProDOS 8 invalid parameter count)",
- /* 05 badPBlockPtr */ "call pointer out of bounds",
- /* 06 pdosActiveErr */ "ProDOS is active",
- /* 07 pdosBusyErr */ "ProDOS is busy",
- /* 08 */ "",
- /* 09 */ "",
- /* 0a vcbUnusable */ "(fatal) VCB is unusable",
- /* 0b fcbUnusable */ "(fatal) FCB is unusable",
- /* 0c badBlockZero */ "(fatal) block zero allocated illegally",
- /* 0d shdwInterruptErr */ "(fatal) interrupt occurred while I/O shadowing off",
- /* 0e */ "",
- /* 0f */ "",
- /* 10 devNotFound */ "device not found",
- /* 11 badDevRefNum */ "invalid device ref# / (fatal) wrong OS version",
- /* 12 */ "",
- /* 13 */ "",
- /* 14 */ "",
- /* 15 */ "",
- /* 16 */ "",
- /* 17 */ "",
- /* 18 */ "",
- /* 19 */ "",
- /* 1a */ "",
- /* 1b */ "",
- /* 1c */ "",
- /* 1d */ "",
- /* 1e */ "",
- /* 1f */ "",
- /* 20 badReqCode */ "invalid request code",
- /* 21 */ "",
- /* 22 */ "",
- /* 23 */ "",
- /* 24 */ "",
- /* 25 intTableFull */ "interrupt table full",
- /* 26 invalidOperation */ "invalid operation",
- /* 27 ioError */ "I/O error",
- /* 28 noDevConnect */ "no device connected",
- /* 29 */ "",
- /* 2a */ "",
- /* 2b writeProtectErr */ "write protect error",
- /* 2c */ "",
- /* 2d */ "",
- /* 2e diskSwitchErr */ "disk switched error",
- /* 2f */ "device not online",
- /* 30 */ "device-specific err $30",
- /* 31 */ "device-specific err $31",
- /* 32 */ "device-specific err $32",
- /* 33 */ "device-specific err $33",
- /* 34 */ "device-specific err $34",
- /* 35 */ "device-specific err $35",
- /* 36 */ "device-specific err $36",
- /* 37 */ "device-specific err $37",
- /* 38 */ "device-specific err $38",
- /* 39 */ "device-specific err $39",
- /* 3a */ "device-specific err $3a",
- /* 3b */ "device-specific err $3b",
- /* 3c */ "device-specific err $3c",
- /* 3d */ "device-specific err $3d",
- /* 3e */ "device-specific err $3e",
- /* 3f */ "device-specific err $3f",
- /* 40 badPathName */ "invalid pathname syntax",
- /* 41 */ "",
- /* 42 fcbFullErr */ "FCB full error (too many files open)",
- /* 43 badFileRefNum */ "invalid file reference number",
- /* 44 pathNotFound */ "path not found",
- /* 45 volumeNotFound */ "volume not found",
- /* 46 fileNotFound */ "file not found",
- /* 47 dupFileName */ "duplicate file name",
- /* 48 volumeFullErr */ "volume full error",
- /* 49 dirFullErr */ "directory full error",
- /* 4a versionErr */ "version error (incompatible file format)",
- /* 4b badStoreType */ "unsupported (or incorrect) storage type",
- /* 4c eofEncountered */ "end-of-file encountered",
- /* 4d positionRangeErr */ "position out of range",
- /* 4e accessErr */ "access not allowed",
- /* 4f */ "",
- /* 50 fileOpenErr */ "file already open",
- /* 51 dirDamaged */ "directory structure is damaged (file count?)",
- /* 52 badVolType */ "unsupported volume type",
- /* 53 paramRangeErr */ "parameter out of range",
- /* 54 memoryFullErr */ "out of memory",
- /* 55 vcbFullErr */ "VCB full error",
- /* 56 */ "(ProDOS 8 bad buffer address)",
- /* 57 dupVolumeErr */ "duplicate volume error",
- /* 58 notBlkDevErr */ "not a block device",
- /* 59 invalidLevel */ "invalid level",
-
- /* 5a */ "block number out of range (bad vol bitmap?)",
- /* 5b */ "illegal pathname change",
- /* 5c */ "not an executable file",
- /* 5d */ "file system not available",
- /* 5e */ "cannot deallocate /RAM",
- /* 5f */ "return stack overflow",
- /* 60 */ "data unavailable"
-};
+ END OF ARCHIVE