Path: ns-mx!uunet!sun-barr!newstop!sun!amdahl!fadden From: fadden@uts.amdahl.com (Andy McFadden) Newsgroups: comp.binaries.apple2 Subject: NuLib v3.10 (UNIX) nulib.03 Message-ID: <58Bb02A3098o00@amdahl.uts.amdahl.com> Date: 1 Nov 91 04:11:45 GMT Reply-To: fadden@amdahl.uts.amdahl.com (Andy McFadden) Organization: Amdahl Corporation, Sunnyvale CA Lines: 1168 NuLib v3.10 - nulib.03 ---- Cut Here and feed the following to sh ---- #!/bin/sh # This is part 03 of a multipart archive # ============= nuadd.c ============== if test -f 'nuadd.c' -a X"$1" != X"-c"; then echo 'x - skipping nuadd.c (File already exists)' else echo 'x - extracting nuadd.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'nuadd.c' && /* X * nuadd.c - operations which add to a NuFX archive X * X * NuLib v3.1 October 1991 Freeware (distribute, don't sell) X * By Andy McFadden (fadden@cory.berkeley.edu) X */ #ifdef APW segment "NuMain" #endif X #include "nudefs.h" #include #include #include #include #ifdef BSD43 # include #else # include #endif X #ifdef UNIX # include # include # ifdef XENIX386 # include /* maybe , , ...*/ # endif # ifdef SYSV # include # endif # ifdef BSD43 # include # endif #endif X #ifdef APW # include # include # include # include #endif X #ifdef MSDOS # include # include # include # include # include # include #endif X #include "nuread.h" #include "nuadd.h" #include "nupak.h" #include "nuetc.h" X #ifdef DATAGENERAL /* BAK */ # ifdef AOSVS /* BAK */ # define BROKEN_ON_MVs /* MV/UX is NOT a full UNIX */ # endif /* implem. so we just skip */ #endif /* the 'UNIX' code on MVs */ X #define MAXGSPREFIX 64 X static BOOLEAN domove; /* are we M)oving the files in? */ static BOOLEAN docreate; /* using the 'C' option? */ 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 */ int EvalArgs(count, names, FIArray, first) int count; /* #of filenames */ char **names; /* array of file names */ file_info *FIArray[]; /* array to fill with file info */ BOOLEAN first; /* first time through? */ { X static char *procName = "EvalArgs"; #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; #ifndef BROKEN_ON_MVs X DIR *dirp; #endif #ifdef SYSV X struct dirent *dp; #else X struct direct *dp; #endif 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? */ # 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 */ #ifdef SYSV X newnames[newcount] = (char *)Malloc(nmlen+strlen(dp->d_name)+1); #else X newnames[newcount] = (char *)Malloc(nmlen + dp->d_namlen +1); #endif 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++; # else /* BAK */ X printf("Help, I ran into a directory and can't handle it!\n"); # 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 #else /* UNIX */ # 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); # endif /* APW */ 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); # endif /* MDOS */ X # ifndef APW # 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); # endif /* none2 */ # endif /* none1 */ #endif /* UNIX */ } 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 */ long AddFile(arcfd, infoptr) int arcfd; file_info *infoptr; { 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 */ /* 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 * 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 that 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 */ static ListHdr * CreateMaybe(filename) char *filename; { X ListHdr *archive; X MHblock *MHptr; X onebyt *bufPtr; X twobyt *twoptr; X fourbyt *fourptr; X int idx; #ifdef APW X FileRec create_p; #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 MHptr = archive->MHptr; X strncpy((char *) MHptr->ID, (char *) MasterID, 6); X BCopy((onebyt *) GetTime(), (onebyt *) &(MHptr->arc_create_when),8, FALSE); X BCopy((onebyt *) bufPtr+12, (onebyt *) &(MHptr->arc_mod_when), 8, FALSE); X fourptr = (fourbyt *) (&(MHptr->master_eof)); X *fourptr = (fourbyt) MHsize; X /* twoptr = (twobyt *) (&(MHptr->master_crc)); X *twoptr = CalcCRC(0, (onebyt *) bufPtr+8, MHsize-8); */ X X ArcfiCreate(filename); /* create SHK file */ X return (archive); } 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 */ onebyt * MakeMHblock(archive, total_records, master_eof) ListHdr *archive; fourbyt total_records; fourbyt master_eof; { 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 * 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 */ static void Add(filename, namecount, names) char *filename; int namecount; char **names; { 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++) { #ifdef APW X if (STOP()) Quit(1); /* check for OA-. */ #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 * Main entry point for adding files. X */ void NuAdd(filename, namecount, names, options) char *filename; int namecount; char **names; char *options; { 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 SHAR_EOF chmod 0644 nuadd.c || echo 'restore of nuadd.c failed' Wc_c="`wc -c < 'nuadd.c'`" test 21905 -eq "$Wc_c" || echo 'nuadd.c: original size 21905, current size' "$Wc_c" fi # ============= nublu.c ============== if test -f 'nublu.c' -a X"$1" != X"-c"; then echo 'x - skipping nublu.c (File already exists)' else echo 'x - extracting nublu.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'nublu.c' && /* X * nublu.c - operations on Binary II archives X * X * NuLib v3.1 October 1991 Freeware (distribute, don't sell) X * By Andy McFadden (fadden@cory.berkeley.edu) X */ #ifdef APW segment "Compress" #endif X #ifndef NO_BLU /***********************************/ X #include "nudefs.h" #include #include X #ifdef UNIX # include # include # include #endif #ifdef APW # include #endif #ifdef MSDOS # include # include # include # include # include #endif X #include "nuview.h" /* file types for BLU */ #include "nuadd.h" /* need OptNum() */ #include "nupak.h" /* need unpak_SQU */ #include "nuetc.h" X /* Binary II extraction routines are adapted from: */ /************************************************************************* 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 /*char * copyright = "@(#) unblu.c 2.1 18/06/88 (c) M.J.E. Mol";*/ #define BUFSIZE 128 /* Blu block length */ X /* global variables */ static char *progname; static char *blufile; static BOOLEAN extract = FALSE; /* extract (as opposed to just listing) */ 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 */ static void extract_file(fd, fname, filelen) int fd; char *fname; /* 64 bytes */ long filelen; { X int ofd; X int n, i; X int j, len; 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 len = strlen(fname); X for (j = 0; j < len; j++) X fname[j] &= 0x7f; /* clear hi bits */ 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 * print_header -- print global information of the binary II file X */ static void print_header(buf) onebyt *buf; { 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 * want -- return TRUE if name exists in array wantlist, X * else return FALSE X */ static BOOLEAN want(name, wantlist) char *name; char **wantlist; { X while (*wantlist != NULL) { X if (strcasecmp(name, *wantlist++) == NULL) X return (TRUE); X } X return (FALSE); X } X X /* X * process_file -- retrieve or print file information of file given X * in buf X */ static void process_file(fd, buf, count, wanted) int fd; onebyt *buf; int count; char **wanted; { 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; #ifdef APW X FileRec frec; #endif #ifdef UNIX X struct stat st; #endif #ifdef MSDOS X struct stat st; #endif /* +PORT+ */ /* 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 /* 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); } #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 } #else # 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); # else X if (ftype != 15) X extract_file(fd, fname, filelen); X else /* +PORT+ */ X printf("[ need [other] subdir create for UnBNY ]\n"); # endif /* APW */ #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 * unblu -- process a binary II file fd, and process the filenames X * listed in wanted. If wanted is \0, all files are processed. X */ static void unblu(fd, count, wanted) int fd; int count; char **wanted; { 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 * Main entry point from CShrink X */ void NuBNY(filename, argc, argv, options) char *filename; int argc; char **argv; char *options; { 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 #endif /*NO_BLU*/ /***********************************/ X SHAR_EOF chmod 0644 nublu.c || echo 'restore of nublu.c failed' Wc_c="`wc -c < 'nublu.c'`" test 11154 -eq "$Wc_c" || echo 'nublu.c: original size 11154, current size' "$Wc_c" fi true || echo 'restore of nucomp.c failed' echo End of part 3, continue with part 4 exit 0 -- fadden@uts.amdahl.com (Andy McFadden) fadden@cory.berkeley.edu (expires in December) [ Above opinions are mine, Amdahl has nothing to do with them, etc, etc. ]