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