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