Received: by NDSUVM1 (Mailer R2.07) id 6575; Tue, 22 May 90 21:40:31 CDT Date: Tue, 22 May 90 22:22:28 EDT Reply-To: Apple II List Sender: Apple II List From: Grant Delaney Subject: NuLib v2.2 (C NuFX archiver) source (UNIX/IIgs/MS-DOS) [02/06] To: "Steven E. Nelson" ---- Cut Here and unpack ---- #!/bin/sh # This is part 02 of a multipart archive if touch 2>&1 | fgrep '[-amc]' > /dev/null then TOUCH=touch else TOUCH=true fi # ============= nuadd.c ============== if test X"$1" != X"-c" -a -f 'nuadd.c'; then echo "File already exists: skipping 'nuadd.c'" else echo "x - extracting nuadd.c (Text)" sed 's/^X//' << 'SHAR_EOF' > nuadd.c && X/* X * nuadd.c - operations which add to a NuFX archive (add) X * X * By Andy McFadden (fadden@cory.berkeley.edu) X * NuLib v2.2 April 1990 Freeware (distribute, don't sell) X */ X X#include "nudefs.h" X#include X#include X#include X#include X#ifdef BSD43 X# include X#else X# include X#endif X X#ifdef UNIX X# include X# include X# include X#endif X#ifdef APW X# include X# include X# include X# include X#endif X#ifdef MSDOS X# include X# include X# include X# include X# include X# include X#endif X X#include "nuread.h" X#include "nuadd.h" X#include "nupak.h" X#include "nuetc.h" X X#ifdef DATAGENERAL /* BAK */ X# ifdef AOSVS /* BAK */ X# define BROKEN_ON_MVs /* MV/UX is NOT a full UNIX */ X# endif /* implem. so we just skip */ X#endif /* the 'UNIX' code on MVs */ X X#define MAXGSPREFIX 64 X Xstatic BOOLEAN domove; /* are we M)oving the files in? */ Xstatic BOOLEAN docreate; /* using the 'C' option? */ X X X/* X * Expand command args into filenames X * Stuff number of names into int; build File Information Array. X * (this routine is heavily implementation-specific, since no two systems X * expand wildcards or deal with subdirectories in the same way). X * X * Recursively expands subdirectories, unless doSubdir is FALSE. X */ Xint EvalArgs(count, names, FIArray, first) Xint count; /* #of filenames */ Xchar **names; /* array of file names */ Xfile_info *FIArray[]; /* array to fill with file info */ XBOOLEAN first; /* first time through? */ X{ X static char *procName = "EvalArgs"; X#ifdef UNIX X /* UNIX shells (sh, csh) won't expand subdirectories, but they do X * expand wildcards in arguments before we get them X */ X static int idx; X struct stat st; X char *cp; /* temp char pointer */ X /* dir stuff */ X int newcount; X char **newnames; X#ifndef BROKEN_ON_MVs X DIR *dirp; X#endif X struct direct *dp; X int nmlen; X X if (first) idx = 0; X X while (count--) { X FIArray[idx] = (file_info *) Malloc(sizeof(file_info)); X X if (stat(*names, &st) < 0) { /* get file info */ X if (errno == ENOENT) { X fprintf(stderr, "%s: '%s' not found\n", prgName, *names); X names++; X continue; /* with while */ X } X Fatal("Bad stat()", procName); X } X X if ((st.st_mode & S_IFDIR) && doSubdir) { /* is it a directory? */ X# ifndef BROKEN_ON_MVs X newnames = (char **) Malloc(MAXARGS * sizeof(char *)); X strcpy(tmpNameBuf, *names); /* earlier dir stuff */ X strcat(tmpNameBuf, "/"); X nmlen = strlen(tmpNameBuf); X X if ((dirp = opendir(*names)) == NULL) X Fatal("Unable to open subdirectory", procName); X for (newcount=0, dp=readdir(dirp); dp != NULL; dp=readdir(dirp)) { X if ((!strcmp(dp->d_name, ".")) || (!strcmp(dp->d_name, ".."))) X continue; /* with for */ X newnames[newcount] = (char *) Malloc(nmlen + dp->d_namlen +1); X strcpy(newnames[newcount], tmpNameBuf); X strcat(newnames[newcount], dp->d_name); /* append the name */ X newcount++; X } X closedir(dirp); X X EvalArgs(newcount, newnames, FIArray, FALSE); /* do subdir */ X X while (newcount-- > 0) /* free up the space we allocated */ X free(newnames[newcount]); X free(newnames); X X names++; X# else /* BAK */ X printf("Help, I ran into a directory and can't handle it!\n"); X# endif /* BAK */ X } else if ((st.st_mode & S_IFDIR) && !doSubdir) { X /* maybe print message? */ X names++; X continue; /* with while */ X } else if (st.st_mode & S_IFREG) { X FIArray[idx]->eof = (long) st.st_size; X X if (st.st_mode & S_IWRITE) /* write permission enabled? */ X FIArray[idx]->fAccess = (fourbyt) 0x00e3; /* locked */ X else X FIArray[idx]->fAccess = (fourbyt) 0x0021; /* unlocked */ X X FIArray[idx]->fileType = defFileType; X FIArray[idx]->auxType = defAuxType; X FIArray[idx]->fileSysID = 0x0001; /* ProDOS */ X FIArray[idx]->fileSysInfo = 0x2f; /* '/' */ X ExpandTime(&st.st_mtime, &FIArray[idx]->create_dt); /*use mod.. */ X ExpandTime(&st.st_mtime, &FIArray[idx]->mod_dt); /*time for both */ X FIArray[idx]->marked = FALSE; X X FIArray[idx]->pathname = (char *) Malloc(strlen(*names)+1); X strcpy(FIArray[idx]->pathname, *names); X FIArray[idx]->store_name = (char *) Malloc(strlen(*names)+1); X cp = *names; X while (*cp == '/') cp++; /* advance past leading '/' */ X strcpy(FIArray[idx]->store_name, cp); /* can't otherwise fix */ X X names++; X idx++; X } else { X printf("Unknown storage type for '%s'\n", *names); X names++; X continue; /* with while */ X } X X } X return (idx); X X#else /* UNIX */ X# ifdef APW X static int idx; /* will eventually hold the total #of filenames */ X char *nextname = (char *) Malloc(MAXFILENAME); /* for subdir expand */ X char prefix[MAXGSPREFIX+1]; /* Max ProDOS prefix size; now 64 */ X char *fnptr; X FileRec finfo_p; X PrefixRec prefix_p; X OpenRec open_p; X EOFRec eof_p; X X if (first) idx = 0; X X prefix_p.prefixNum = 0; /* current dir */ X prefix_p.prefix = prefix; /* prefix buffer */ X GET_PREFIX( &prefix_p ); X ToolErrChk(); X p2cstr(prefix); X X while (count) { X strcpy(tmpNameBuf, *names); X c2pstr(tmpNameBuf); X INIT_WILDCARD(tmpNameBuf, 0); X ToolErrChk(); X X while (*NEXT_WILDCARD(tmpNameBuf)) { X if (idx >= MAXARGS) { X fprintf(stderr, "Too many files (%d, %d max)\n", idx, MAXARGS); X Quit (-1); X } X X finfo_p.pathname = tmpNameBuf; X GET_FILE_INFO( &finfo_p ); X ToolErrChk(); X X open_p.openPathname = tmpNameBuf; X OPEN( &open_p ); X ToolErrChk(); X X eof_p.eofRefNum = open_p.openRefNum; X GET_EOF( &eof_p ); X ToolErrChk(); X X CLOSE( &open_p ); X ToolErrChk(); X X p2cstr(tmpNameBuf); /* also does p2cstr(finfo_p.pathname) */ X switch (finfo_p.storageType) { X case 0x00: /* standard ProDOS storage types */ X case 0x01: X case 0x02: X case 0x03: X FIArray[idx] = (file_info *) Malloc(sizeof(file_info)); X X FIArray[idx]->eof = eof_p.eofPosition; X FIArray[idx]->fAccess = finfo_p.fAccess; X FIArray[idx]->fileType = (fourbyt) finfo_p.fileType; X FIArray[idx]->auxType = (fourbyt) finfo_p.auxType; X FIArray[idx]->storageType = finfo_p.storageType; X FIArray[idx]->fileSysID = 0x0001; /* ProDOS */ X FIArray[idx]->fileSysInfo = 0x2f; /* '/' */ X ExpandTime(&finfo_p.createDate, &FIArray[idx]->create_dt); X ExpandTime(&finfo_p.modDate, &FIArray[idx]->mod_dt); X FIArray[idx]->marked = FALSE; X X FIArray[idx]->pathname = (char *) Malloc(strlen(tmpNameBuf)+1); X strcpy(FIArray[idx]->pathname, tmpNameBuf); X X /* are we adding from current directory? */ X if (!strncmp(tmpNameBuf, prefix, strlen(prefix))) { X FIArray[idx]->store_name = /* yes */ X (char *) Malloc(strlen(tmpNameBuf) - strlen(prefix) +1); X strcpy(FIArray[idx]->store_name, tmpNameBuf+ strlen(prefix)); X } else { X fnptr = RINDEX(tmpNameBuf, '/') + 1; /* no */ X FIArray[idx]->store_name = (char *)Malloc(strlen(fnptr)+1); X strcpy(FIArray[idx]->store_name, fnptr); X } X idx++; X break; X X case 0x05: X printf("Can't handle Extended file '%s'\n", tmpNameBuf); X break; X case 0x0d: X if (doSubdir) { X strcpy(nextname, tmpNameBuf); /* make new copy */ X strcat(nextname, "/="); /* APW-only wildcard */ X EvalArgs(1, &nextname, FIArray, FALSE); /* read subdir */ X } X break; X default: X printf("Unknown storage type for '%s'\n", tmpNameBuf); X break; X } X X } /* inner while */ X X names++, count--; X } /* outer while */ X free (nextname); X return (idx); X# endif /* APW */ X X# ifdef MSDOS X /* MS-DOS or other shell wildcard expansion here */ X int idx, error; X struct stat fStat; X X idx = 0; X X while (count--) { X X error = stat (*names, &fStat); X X /* If the filename is a directory, we need to expand that too! */ X X if (!error) { X FIArray[idx] = (file_info *) Malloc(sizeof(file_info)); X FIArray[idx]->pathname = (char *) Malloc(strlen(*names)+1); X strcpy(FIArray[idx]->pathname, *names); X FIArray[idx]->store_name = (char *) Malloc(strlen(*names)+1); X strcpy(FIArray[idx]->store_name, *names); X FIArray[idx]->fAccess = 0x00e3L; /* unlocked */ X FIArray[idx]->fileType = defFileType; X FIArray[idx]->auxType = defAuxType; X FIArray[idx]->storageType = 0x0000; X FIArray[idx]->fileSysID = 0x0001; /* ProDOS */ X FIArray[idx]->fileSysInfo = 0x1c; /* '\' */ X ExpandTime(&fStat.st_ctime, &FIArray[idx]->create_dt); X ExpandTime(&fStat.st_mtime, &FIArray[idx]->mod_dt); X FIArray[idx]->eof = fStat.st_size; X X FIArray[idx]->marked = FALSE; X idx++; X } X names++; X } X return (idx); X# endif /* MDOS */ X X# ifndef APW X# ifndef MSDOS X /* nothing else defined */ X X /* +PORT+ */ X printf("\n[other] wildcard expansion/file info needs work\n"); X while (count--) { X FIArray[count] = (file_info *) Malloc(sizeof(file_info)); X X FIArray[count]->pathname = (char *) Malloc(strlen(*names)+1); X strcpy(FIArray[count]->pathname, *names); X FIArray[count]->store_name = (char *) Malloc(strlen(*names)+1); X strcpy(FIArray[count]->store_name, *names); X FIArray[count]->fAccess = 0x00e3L; /* unlocked */ X FIArray[count]->fileType = 0x0006L; /* BIN */ X FIArray[count]->auxType = 0L; X FIArray[count]->storageType = 0x0000; X FIArray[count]->fileSysID = 0x0001; /* ProDOS */ X FIArray[count]->fileSysInfo = 0x1c; /* '\' */ X ExpandTime((char *) NULL, &FIArray[count]->create_dt); X ExpandTime((char *) NULL, &FIArray[count]->mod_dt); X FIArray[count]->marked = FALSE; X X names++; X } X return (count); X# endif /* none2 */ X# endif /* none1 */ X#endif /* UNIX */ X} X X X/* X * Add a file onto the end of an archive; does not check to see if an entry X * already exists. X * X * This creates the record entry, and calls subroutines to add the various X * threads. The archive fd should be open, the file fd should not. Returns X * the size of the record added. X */ Xlong AddFile(arcfd, infoptr) Xint arcfd; Xfile_info *infoptr; X{ X int srcfd; /* file to add */ X onebyt *recBuf; /* record header block */ X twobyt *twoptr; X THblock thread[1]; /* thread block */ X twobyt CRC; X int idx; X fourbyt total_threads; X long recposn; /* file posn for record entry */ X long thposn; /* file posn for last thread */ X long tmpposn; /* temporary file posn */ X static char *procName = "AddFile"; X X if (verbose) { X printf("Adding '%s' (data)...", X infoptr->store_name, infoptr->eof); X fflush(stdout); X } X X recBuf = (onebyt *) Malloc(ATTSIZE); X for (idx = 0; idx < ATTSIZE; idx++) /* zero the buffer */ X *(recBuf+idx) = 0; X X total_threads = 0; X X strncpy((char *) recBuf+0, (char *) RecordID, 4); X twoptr = (twobyt *) (recBuf+6); X *twoptr = ATTSIZE; /* don't have an attrib_count... */ X HiSwap((onebyt *) recBuf, 6, 7); X twoptr = (twobyt *) (recBuf+8); X *twoptr = OURVERS; /* store new record with our rec vers */ X HiSwap((onebyt *) recBuf, 8, 9); X /* total_threads */ X/* BCopy((onebyt *) &total_threads, (onebyt *) recBuf+10, 2, TRUE); */ X *(recBuf+12) = 0; /* reserved1 */ X *(recBuf+13) = 0; X BCopy((onebyt *) &infoptr->fileSysID, (onebyt *) recBuf+14, 2, TRUE); X BCopy((onebyt *) &infoptr->fileSysInfo, (onebyt *) recBuf+16, 1, TRUE); X *(recBuf+17) = 0; /* reserved2 */ X BCopy((onebyt *) &infoptr->fAccess, (onebyt *) recBuf+18, 4, TRUE); X BCopy((onebyt *) &infoptr->fileType, (onebyt *) recBuf+22, 4, TRUE); X BCopy((onebyt *) &infoptr->auxType, (onebyt *) recBuf+26, 4, TRUE); X BCopy((onebyt *) &infoptr->create_dt, (onebyt *) recBuf+32, X sizeof(Time), FALSE); X BCopy((onebyt *) &infoptr->mod_dt, (onebyt *) recBuf+40, sizeof(Time), X FALSE); X BCopy((onebyt *) GetTime(), (onebyt *) recBuf+48, sizeof(Time), FALSE); X twoptr = (twobyt *) (recBuf + (ATTSIZE - 2)); X *twoptr = strlen(infoptr->store_name); X X /* correct strlen ordering */ X HiSwap((onebyt *) recBuf, ATTSIZE-2, ATTSIZE-1); X X thread[0].thread_class = 0x0002; /* data */ X HiSwap((onebyt *) &thread[0].thread_class, 0, 1); X thread[0].thread_kind = 0x0000; /* data fork */ X HiSwap((onebyt *) &thread[0].thread_kind, 0, 1); X thread[0].thread_format = 0x0000; /* filled in later */ X thread[0].thread_crc = 0x0000; /* not supported yet */ X /* so I don't forget if I support these */ X HiSwap((onebyt *) &thread[0].thread_crc, 0, 1); X thread[0].thread_eof = infoptr->eof; X HiSwap((onebyt *) &thread[0].thread_eof, 0, 3); X HiSwap((onebyt *) &thread[0].thread_eof, 1, 2); X thread[0].comp_thread_eof = -1L; /* filled in later */ X total_threads++; X X BCopy((onebyt *) &total_threads, (onebyt *) recBuf+10, 4, TRUE); X X /* X * Because we don't know CRCs or compressed size yet, we must: X * skip record entry and filename. X * for each thread: X * skip thread entry, write data, move back, write thread entry. X * move back, write record entry and filename. X * move forward to next position. X */ X if ((srcfd = open(infoptr->pathname, O_RDONLY | O_BINARY)) < 0) X Fatal("Unable to open file", procName); X X recposn = lseek(arcfd, 0L, S_REL); /* save record posn */ X if (lseek(arcfd, (long) (ATTSIZE + strlen(infoptr->store_name)), S_REL)<0) X Fatal("Bad seek (R.rel)", procName); X X /* loop... */ X thposn = lseek(arcfd, 0L, S_REL); /* save thread posn */ X if (lseek(arcfd, (long) THsize, S_REL) < 0) X Fatal("Bad seek (Th)", procName); X X /* X * since we can store files as being packed without actually packing them, X * we need to check "dopack" to see if we want packMethod or zero. Note X * that packing can fail for various reasons; the value returned by X * PackFile() is the actual algorithm used to pack the file. X * X * NuLib uses version 0 records; thread_crcs are not stored. X */ X X thread[0].thread_format = X PackFile(srcfd,arcfd, infoptr->eof, dopack ? packMethod:0, pakbuf); X if (!dopack) thread[0].thread_format = packMethod; /* for S subopt */ X HiSwap((onebyt *) &thread[0].thread_format, 0, 1); X thread[0].comp_thread_eof = (fourbyt) packedSize; X HiSwap((onebyt *) &thread[0].comp_thread_eof, 0, 3); /* correct ordering* / X HiSwap((onebyt *) &thread[0].comp_thread_eof, 1, 2); X tmpposn = lseek(arcfd, 0L, S_REL); X X if (lseek(arcfd, thposn, S_ABS) < 0) /* seek back to thread posn */ X Fatal("Bad seek (Th2)", procName); X if (write(arcfd, &thread[0], THsize) < THsize) /* write updated thread */ X Fatal("Unable to write thread", procName); X if (lseek(arcfd, tmpposn, S_ABS) < 0) /* seek back to where we were */ X Fatal("Bad seek (TmpA)", procName); X /* ...loop end */ X X if (close(srcfd) < 0) X Fatal("Unable to close file", procName); X X CRC = CalcCRC(0, (onebyt *) recBuf+6, ATTSIZE-6); X CRC = CalcCRC(CRC, (onebyt *) infoptr->store_name, X strlen(infoptr->store_name)); X CRC = CalcCRC(CRC, (onebyt *) &thread[0], THsize); X twoptr = (twobyt *) (recBuf+4); X *twoptr = CRC; X HiSwap((onebyt *) recBuf, 4, 5); X X tmpposn = lseek(arcfd, 0L, S_REL); /* record posn (next posn) */ X if (lseek(arcfd, recposn, S_ABS) < 0) /* seek back to record entry */ X Fatal("Bad seek (R.abs)", procName); X if (write(arcfd, recBuf, ATTSIZE) < ATTSIZE) X Fatal("Unable to write record", procName); X if (write(arcfd, infoptr->store_name, strlen(infoptr->store_name)) X < strlen(infoptr->store_name)) X Fatal("Unable to store filename", procName); X if (lseek(arcfd, tmpposn, S_ABS) < 0) /* seek back to where we were */ X Fatal("Bad seek (TmpB)", procName); X X if (verbose) printf("done.\n"); X free(recBuf); X X /* switch ordering back */ X HiSwap((onebyt *) &thread[0].comp_thread_eof, 0, 3); X HiSwap((onebyt *) &thread[0].comp_thread_eof, 1, 2); X return ( (long) (THsize * total_threads) + (long) ATTSIZE + X (long) strlen(infoptr->store_name) + thread[0].comp_thread_eof); X} X X X/* X * Certain options can cause an archive to be created (add, create, move). X * If the archive does not already exist, then an empty file is created (of X * type $e0/8002 under ProDOS) and an empty archive struct is built. X * X * Note that this requires certain options to deal with archive structures tha t X * do not have any records, and archive files that are empty. X * X * If the file exists, this will call NuRead() to read it; otherwise, it will X * create it. X */ Xstatic ListHdr *CreateMaybe(filename) Xchar *filename; X{ X ListHdr *archive; X onebyt *bufPtr; X twobyt *twoptr; X fourbyt *fourptr; X int idx; X#ifdef APW X FileRec create_p; X#endif X static char *procName = "CreateMaybe"; X X if (Exists(filename)) { X archive = NuRead(filename); X return (archive); X } X X if (!docreate) X printf("Archive does not exist; creating archive file...\n"); X X archive = (ListHdr *) Malloc(sizeof(ListHdr)); X archive->arc_name = (char *) Malloc(strlen(filename)+1); X strcpy(archive->arc_name, filename); X archive->MHptr = (MHblock *) Malloc(sizeof(MHblock)); X archive->RNodePtr = (RNode *) NULL; X archive->nextposn = (long) MHsize; X X bufPtr = (onebyt *) archive->MHptr; X for (idx = 0; idx < MHsize; idx++) X *(bufPtr+idx) = '\0'; X X /* total_records -> zero */ X /* (most of this is easier to do w/o using struct definition) */ X strncpy((char *) bufPtr+0, (char *) MasterID, 6); X BCopy((onebyt *) GetTime(), (onebyt *) bufPtr+12, 8, FALSE); X BCopy((onebyt *) bufPtr+12, (onebyt *) bufPtr+20, 8, FALSE); X fourptr = (fourbyt *) (bufPtr+38); X *fourptr = (fourbyt) MHsize; X twoptr = (twobyt *) (bufPtr+6); X *twoptr = CalcCRC(0, (onebyt *) bufPtr+8, MHsize-8); X X ArcfiCreate(filename); /* create SHK file */ X return (archive); X} X X X/* X * Return a pointer to a valid Master Header block X * Anything that isn't set to a default value needs to be passed as a X * parameter [ right now I can't remember why ]. X */ Xonebyt *MakeMHblock(archive, total_records, master_eof) XListHdr *archive; Xfourbyt total_records; Xfourbyt master_eof; X{ X static onebyt buf[MHsize]; /* must be static */ X twobyt *twoptr; X fourbyt *fourptr; X int idx; X static char *procName = "MakeMHblock"; X X for (idx = 0; idx < MHsize ; idx++) X buf[idx] = '\0'; X X /* messy... should've used MHptr->thing here, but if it ain't broke... */ X strncpy((char *) buf, (char *) MasterID, 6); X BCopy((onebyt *) &total_records, (onebyt *) &buf[8], 4, TRUE); X BCopy((onebyt *) &archive->MHptr->arc_create_when, (onebyt *) &buf[12], X sizeof(Time), FALSE); X BCopy((onebyt *) GetTime(), (onebyt *) &buf[20], sizeof(Time), FALSE); X twoptr = (twobyt *) &buf[28]; /* master version */ X *twoptr = OURMVERS; X HiSwap((onebyt *) buf, 28, 29); /* correct byte ordering */ X BCopy((onebyt *) &master_eof, (onebyt *) &buf[38], 4, TRUE); X twoptr = (twobyt *) &buf[6]; X *twoptr = CalcCRC(0, (onebyt *) &buf[8], MHsize-8); X HiSwap((onebyt *) buf, 6, 7); X X return (buf); X} X X X/* X * Add files to archive X * X * Read files from disk, adding them to the end of the archive as we go. X * Update the master header block after all files have been added. X */ Xstatic void Add(filename, namecount, names) Xchar *filename; Xint namecount; Xchar **names; X{ X ListHdr *archive; X int arcfd; X file_info *FIArray[MAXARGS]; /* entries malloc()ed by EvalArgs */ X int idx; X onebyt *mptr; /* points to a MHblock suitable for writing */ X long addSize; X static char *procName = "Add"; X X /* expand wildcards/subdirectories, and get file info */ X namecount = EvalArgs(namecount, names, FIArray, TRUE); X if (!namecount) { X if (verbose) printf("No files selected.\n"); X Quit (0); X } X X archive = CreateMaybe(filename); X if ((arcfd = open(archive->arc_name, O_RDWR | O_BINARY)) < 0) X Fatal("Unable to open archive", procName); X if (lseek(arcfd, archive->nextposn, S_ABS) < 0) /* seek to end */ X Fatal("Unable to seek in archive", procName); X X for (idx = 0 ; idx < namecount; idx++) { X#ifdef APW X if (STOP()) Quit(1); /* check for OA-. */ X#endif X addSize = AddFile(arcfd, FIArray[idx]); X archive->MHptr->master_eof += addSize; X archive->nextposn += addSize; X archive->MHptr->total_records++; X } X X mptr = MakeMHblock(archive, archive->MHptr->total_records, X archive->MHptr->master_eof); X if (lseek(arcfd, 0L, S_ABS) < 0) X Fatal("Unable to rewind archive for master header", procName); X X if (write(arcfd, mptr, MHsize) < MHsize) X Fatal("Unable to update master header", procName); X if (close(arcfd) < 0) X Fatal("Unable to close archive", procName); X X if (domove) { X if (verbose) printf("Deleteing files...\n"); X for (idx = 0; idx < namecount; idx++) { X if (verbose) { X printf("%s...", FIArray[idx]->pathname); X fflush(stdout); X } X if (unlink(FIArray[idx]->pathname) < 0) { X if (verbose) printf("failed.\n"); X } else { X if (verbose) printf("done.\n"); X } X } X } X} X X X/* X * Main entry point for adding files. X */ Xvoid NuAdd(filename, namecount, names, options) Xchar *filename; Xint namecount; Xchar **names; Xchar *options; X{ X char *optr; X int idx; X char type[5]; X static char *procName = "NuAdd"; X X if (*options == 'm') X domove = TRUE; X X if (*options == 'c') X docreate = TRUE; X X /* change T subopt to convert FROM current system TO */ X if (transfrom >= 0) { X transto = transfrom; X transfrom = -1; X } X X Add(filename, namecount, names); /* do main processing */ X} X SHAR_EOF $TOUCH -am 0430215790 nuadd.c && chmod 0644 nuadd.c || echo "restore of nuadd.c failed" set `wc -c nuadd.c`;Wc_c=$1 if test "$Wc_c" != "21530"; then echo original size 21530, current size $Wc_c fi fi # ============= nublu.c ============== if test X"$1" != X"-c" -a -f 'nublu.c'; then echo "File already exists: skipping 'nublu.c'" else echo "x - extracting nublu.c (Text)" sed 's/^X//' << 'SHAR_EOF' > nublu.c && X/* X * nublu.c - operations on Binary II archives X * X * By Andy McFadden (fadden@cory.berkeley.edu) X * NuLib v2.2 April 1990 Freeware (distribute, don't sell) X */ X X#ifndef NO_BLU /***********************************/ X X#include "nudefs.h" X#include X#include X X#ifdef UNIX X# include X# include X# include X#endif X#ifdef APW X# include X#endif X#ifdef MSDOS X# include X# include X# include X# include X# include X#endif X X#include "nuview.h" /* file types for BLU */ X#include "nuadd.h" /* need OptNum() */ X#include "nupak.h" /* need unpak_SQU */ X#include "nuetc.h" X X/* Binary II extraction routines are adapted from: */ X/************************************************************************* X ** ** X ** Name : unblu ** X ** Author : Marcel J.E. Mol ** X ** Date : 10/05/88 (first release) ** X ** Version : 2.20 ** X ** Files : unblu.c Main source file ** X ** ** X ** ------------------------- Revision List ------------------------- ** X ** Ver Date Name Remarks ** X ** 1.00 10/05/88 Marcel Mol Raw copy of a basic program** X ** 2.00 03/06/88 Marcel Mol Rewrite after blu info ** X ** was send to the net ** X ** 2.10 18/06/88 Marcel Mol Added filetype texts ** X ** 2.20 23/09/88 Marcel Mol Show mod and creation time ** X ** ** X ************************************************************************/ X X X/*char * copyright = "@(#) unblu.c 2.1 18/06/88 (c) M.J.E. Mol";*/ X#define BUFSIZE 128 /* Blu block length */ X X/* global variables */ Xstatic char *progname; Xstatic char *blufile; Xstatic BOOLEAN extract = FALSE; /* extract (as opposed to just listing) */ X X X/* X * extract_file -- extract file fname from the archive fd. Fname X * contains filelen bytes. X * X * If the first block has the .QQ magic numbers, go ahead and try to X * unsqueeze it. Not the best way to go about it, but it works. X */ Xstatic void extract_file(fd, fname, filelen) Xint fd; Xchar *fname; /* 64 bytes */ Xlong filelen; X{ X int ofd; X int n, i; X onebyt buf[BUFSIZE]; X long full_len; X int offset; X static char *procName = "extract_file"; X X /*n = */ read(fd, buf, 70); /* read first few bytes */ X lseek(fd, -70L, S_REL); /* back up */ X if ((buf[0] == 0x76) && (buf[1] == 0xff)) { /* is it squeezed? */ X i = 0; /* get the original file name */ X while ((fname[i] = buf[4+i]) != '\0') X i++; X offset = 5+i; /* how far into file is end of filename? */ X if (verbose) { printf("(as %s)...", fname); fflush(stdout); } X } X X if (Exists(fname)) { X if (interact) { X if (verbose) printf("file exists, overwite"); X else printf("%s exists, overwite", fname); X if (!AskYesNo()) { /* return w/o overwriting */ X full_len = ( (filelen / 128L) +1 ) * 128L; X lseek(fd, full_len, S_REL); X return; X } X } X if (verbose) { printf("overwriting..."); fflush(stdout); } X if (unlink(fname) < 0) X Fatal("Unable to remove existing file", procName); X } X X if ((ofd = open(fname, O_BINARY|O_CREAT|O_WRONLY|O_TRUNC, 0644)) < 0) { X Fatal("Can't open destination file", "extract_file"); X } X X if ((buf[0] == 0x76) && (buf[1] == 0xff)) { /* is it squeezed? */ X if (verbose) { printf("unsqueezing..."); fflush(stdout); } X full_len = ( (filelen / 128L) +1 ) * 128L; X lseek(fd, (long) offset, S_REL); X full_len -= offset; /* send unpak_SQU everything past fname */ X X unpak_SQU(fd, ofd, full_len); /* unsqueeze it */ X X } else { /* extract uncompressed */ X X lastseen = '\0'; /* used by crlf() translator */ X while (filelen > 0L) { X n = read(fd, buf, BUFSIZE); /* Read 128 bytes */ X if (n != BUFSIZE) { X fprintf(stderr, "Extract_BNY: %s file size broken\n", blufile); X Quit(-1); X } X if (crlf(ofd, buf, (filelen >= BUFSIZE ? BUFSIZE : filelen)) != X (filelen >= BUFSIZE ? BUFSIZE : filelen)) X Fatal("Bad write", procName); X X filelen -= (long) BUFSIZE; X } X } X close(ofd); /* Close destination file */ X} X X X/* X * print_header -- print global information of the binary II file X */ Xstatic void print_header(buf) Xonebyt *buf; X{ X long disk_blocks; X X disk_blocks = buf[117] + (buf[118]<<8) + (buf[119]<<16) + (buf[120]<<24); X printf("Listing %-40.40s ", blufile); X printf("Blocks used: %-5ld", disk_blocks); X printf("Files: %d\n", buf[127]+1); X printf("\nFilename Type Blocks Modified "); X printf("Created Length Subtype\n\n"); X} X X X/* X * want -- return TRUE if name exists in array wantlist, X * else return FALSE X */ Xstatic BOOLEAN want(name, wantlist) Xchar *name; Xchar **wantlist; X{ X while (*wantlist != NULL) { X if (strcasecmp(name, *wantlist++) == NULL) X return (TRUE); X } X return (FALSE); X X} X X X/* X * process_file -- retrieve or print file information of file given X * in buf X */ Xstatic void process_file(fd, buf, count, wanted) Xint fd; Xonebyt *buf; Xint count; Xchar **wanted; X{ X int ftype, auxtype; X int fnamelen; X long filelen; X char fname[64]; X char outbuf[16]; /* temp for sprintf */ X int nblocks, problocks; X Time create_dt; X Time mod_dt; X#ifdef APW X FileRec frec; X#endif X#ifdef UNIX X struct stat st; X#endif X#ifdef MSDOS X struct stat st; X#endif X/* +PORT+ */ X/* int tf; X * int dflags; X */ X static char *procName = "process_file"; X X /* Get file info */ X ftype = buf[4]; /* File type */ X auxtype = (int) buf[5] + ((int)buf[6] << 8); X fnamelen = buf[23]; /* filename */ X strncpy(fname, &buf[24], fnamelen); X fname[fnamelen] = '\0'; X /* dflags = buf[125]; /* Data flags */ X /* tf = buf[127]; /* Number of files to follow */ X filelen = (long) buf[20] + ((long) buf[21] << 8) + X ((long) buf[22] << 16); /* calculate file len */ X nblocks = (filelen + BUFSIZE-1) / BUFSIZE; /* #of BNY blocks */ X problocks = buf[8] + ((int) buf[9] << 8); X X mod_dt.second = 0; X mod_dt.minute = buf[12] & 0x3f; X mod_dt.hour = buf[13] & 0x1f; X mod_dt.day = (buf[10] & 0x1f) -1; X mod_dt.month = (((buf[11] & 0x01) << 3) + (buf[10] >> 5)) -1; X mod_dt.year = buf[11] >> 1; X mod_dt.weekDay= 0; X create_dt.second = 0; X create_dt.minute = buf[16] & 0x3f; X create_dt.hour = buf[17] & 0x1f; X create_dt.day = (buf[14] & 0x1f) -1; X create_dt.month = (((buf[15] & 0x01) << 3) + (buf[14] >> 5)) -1; X create_dt.year = buf[15] >> 1; X create_dt.weekDay= 0; X X if (!count || want(fname, wanted)) { X if (!extract) { /* print file information ONLY */ X printf("%-15.15s %-3.3s ", fname, FT[ftype]); X printf("%6d ", problocks); X printf("%-16.16s ", PrintDate(&mod_dt, TRUE)); X printf("%-16.16s ", PrintDate(&create_dt, TRUE)); X if (filelen < 0x100L) X sprintf(outbuf, "$%.2lx", filelen); X else if (filelen < 0x10000L) X sprintf(outbuf, "$%.4lx", filelen); X else sprintf(outbuf, "$%.6lx", filelen); X printf("%7s ", outbuf); X printf("$%.4x\n", auxtype); X X/* if (dflags == 0) X * printf("stored"); X * else { X * if (dflags & 128) { X * printf("squeezed"); X * } X * if (dflags & 64) { X * printf("encrypted"); X * } X * if (dflags & 1) X * printf("packed"); X * } X * putchar('\n'); X */ X if (ftype != 15) { /* If not a directory */ X lseek(fd, (long) BUFSIZE*nblocks, S_REL); /*Seek to next file*/ X } X X } else { /* extract is TRUE */ X X if (verbose) { printf("Extracting %s...", fname); fflush(stdout); } X#ifdef UNIX X if (ftype != 15) X extract_file(fd, fname, filelen); /* note dates etc not set */ X else { X /* if no directory exists, then make one */ X if (stat(fname, &st) < 0) X if (errno == ENOENT) { X sprintf(tmpNameBuf, "mkdir %s", fname); X if (system(tmpNameBuf) != 0) /* call UNIX mkdir */ X Fatal("Unable to create subdir", procName); X } else { X Fatal("Unable to create dir", procName); X } X } X#else X# ifdef APW X /* create file/directory , with appropriate type/auxtype stuff */ X c2pstr(fname); X frec.pathname = fname; X frec.fAccess = 0x00e3; /* unlocked */ X frec.fileType = ftype; X frec.auxType = (unsigned long) auxtype; X frec.storageType = (int) buf[7]; X frec.createDate = 0x0000; /* set later */ X frec.createTime = 0x0000; X X CREATE( &frec ); X ToolErrChk(); X p2cstr(fname); X X extract_file(fd, fname, filelen); X X /* set file attributes */ X c2pstr(fname); X frec.fAccess = (word) buf[3]; X frec.modDate = (word) buf[10] + ((word)buf[11] << 8); X frec.modTime = (word) buf[12] + ((word)buf[13] << 8); X frec.createDate = (word) buf[14] + ((word)buf[15] << 8); X frec.createTime = (word) buf[16] + ((word)buf[17] << 8); X SET_FILE_INFO( &frec ); X ToolErrChk(); X p2cstr(fname); X# else X if (ftype != 15) X extract_file(fd, fname, filelen); X else /* +PORT+ */ X printf("[ need [other] subdir create for UnBNY ]\n"); X# endif /* APW */ X#endif /* UNIX */ X if (verbose) printf("done.\n"); X } X } else if (ftype != 15) { /* This file not wanted; if not a directory */ X lseek(fd, (long) BUFSIZE*nblocks, S_REL); /* Seek to next file */ X } X} X X X/* X * unblu -- process a binary II file fd, and process the filenames X * listed in wanted. If wanted is \0, all files are processed. X */ Xstatic void unblu(fd, count, wanted) Xint fd; Xint count; Xchar **wanted; X{ X onebyt buf[BUFSIZE]; X int firstblock = 1; /* First block needs special processing */ X int tofollow = 1; /* Files to follow in the archive */ X int n; X X while (tofollow && ((n = read(fd, buf, BUFSIZE)) > 0)) { X /* If there is a header block */ X X if (n != BUFSIZE) { X fprintf(stderr, "UnBNY: %s file size is broken\n", blufile); X Quit(-1); X } X if ((buf[0] != 10) || (buf[1] != 71) || X (buf[2] != 76) || (buf[18] != 2)) { X fprintf(stderr, X "UnBNY: %s not a Binary II file or bad record\n", blufile); X Quit(-1); X } X X tofollow = buf[127]; /* How many files to follow */ X if (firstblock && !extract) { X print_header(buf); X } X firstblock = 0; X process_file(fd, buf, count, wanted); /* process the file for it */ X X } X if (firstblock && (n < 0)) /* length < 128 */ X fprintf(stderr, "UnBNY: Not a Binary II file"); X} X X X/* X * Main entry point from CShrink X */ Xvoid NuBNY(filename, argc, argv, options) Xchar *filename; Xint argc; Xchar **argv; Xchar *options; X{ X int bfd; /* File descriptor for blu file */ X char *optr; X X /* process X subopt ourselves */ X if (INDEX(options+1, 'x')) extract = TRUE; X else extract = FALSE; X X blufile = filename; /* Make it global */ X if ((bfd = open(filename, O_RDONLY | O_BINARY)) < 0) X Fatal("Unable to open Binary II archive", "NuBNY"); X X unblu(bfd, argc, argv); /* Process wanted files */ X X close(bfd); X Quit(0); X} X X#endif /*NO_BLU*/ /***********************************/ X SHAR_EOF $TOUCH -am 0411221690 nublu.c && chmod 0644 nublu.c || echo "restore of nublu.c failed" set `wc -c nublu.c`;Wc_c=$1 if test "$Wc_c" != "11004"; then echo original size 11004, current size $Wc_c fi fi echo "End of part 2, continue with part 3" exit 0