Path: ns-mx!hobbes.physics.uiowa.edu!zaphod.mps.ohio-state.edu!qt.cs.utexas.edu!cs.utexas.edu!sun-barr!newstop!sun!amdahl!fadden From: fadden@uts.amdahl.com (Andy McFadden) Newsgroups: comp.binaries.apple2 Subject: NuLib v3.10 (UNIX) nulib.06 Message-ID: <5bTM02R409.C00@amdahl.uts.amdahl.com> Date: 1 Nov 91 04:13:06 GMT Reply-To: fadden@amdahl.uts.amdahl.com (Andy McFadden) Organization: Amdahl Corporation, Sunnyvale CA Lines: 1627 NuLib v3.10 - nulib.06 ---- Cut Here and feed the following to sh ---- #!/bin/sh # This is part 06 of a multipart archive # ============= numain.c ============== if test -f 'numain.c' -a X"$1" != X"-c"; then echo 'x - skipping numain.c (File already exists)' else echo 'x - extracting numain.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'numain.c' && /* X * numain.c - shell-based front end for NuLib X * X * NuLib v3.1 October 1991 Freeware (distribute, don't sell) X * By Andy McFadden (fadden@cory.berkeley.edu) X */ #ifdef APW segment "main" #endif X static char *header = X "NuLib v3.1 October 1991 Freeware Copyright 1989-91 By Andy McFadden"; X #include "nudefs.h" /* system-dependent defines */ #include /* standard I/O library */ #include #include #include /* C type stuff, like tolower() */ #ifdef BSD43 # include #else /* SYSV, APW, MSC */ # include /* string stuff */ #endif X #ifdef APW # include # include # include # include #endif X #include "nuread.h" /* structs for archive info, archive read routines */ #include "nuview.h" /* archive listing functions */ #include "nuadd.h" /* archive operations (add, create, move) */ #include "nuext.h" /* archive operations (extract) */ #include "nupdel.h" /* archive operations (delete, update, freshen) */ #include "nublu.h" /* Binary II archive operations */ #include "nupak.h" /* need PAKBUFSIZ */ #include "nuetc.h" /* Malloc(), Fatal(), etc. */ X extern char *getenv(); /* +PORT+ */ X #define Whoops(str) printf("WARNING: typedef %s may be set incorrectly\n",str); #define ENVAR "NULIBOPT" /* environment variable with options in it */ X /* X * global to entire program X */ int HiLo; /* byte ordering; FALSE on low-first (65816) */ int verbose; /* print verbose? */ int interact; /* interactive overwrite mode? */ int dopack; /* do we want to pack/unpack? */ int doExpand; /* do we want to expand archive filenames? */ int doSubdir; /* process subdirectories at all? */ int doMessages; /* do comments instead of data */ int transfrom; /* how to do CR<->LF translation (from what?) (-1 = off) */ int transto; /* translate to ? */ int packMethod; /* how to pack a file */ fourbyt defFileType; /* default file type */ fourbyt defAuxType; /* default aux type */ onebyt *pakbuf; /* used by compression routines; created once to reduce */ X /* overhead involved in malloc()ing a 64K buffer */ char *prgName = "NuLib"; /* for error messages; don't like argv[0] */ X /* besides, the name changes every 3 weeks */ X /* X * Print simple usage info X */ static void Usage(argv0) char *argv0; { X printf("\nUsage: %s option[suboptions] archive-name [filespec]\n", argv0); X printf("\nType \"%s h\" for help.\n", argv0); } X X /* X * Print usage info X */ static void Help(argv0, options) char *argv0, *options; { X if (INDEX(options+1, 'n')) { /* using 'n' suboption? */ X printf("%s\n", header); X printf("\nCompression methods:\n"); X printf(" # Name Abbr Pack? Unpack?\n"); X printf(" 0: Uncompressed unc Y Y\n"); X printf(" 1: SQueezed (sq/usq) squ N Y\n"); X printf(" 2: Dynamic LZW-I (ShrinkIt) shk Y Y\n"); X printf(" 3: Dynamic LZW-II (ShrinkIt) sh2 N Y\n"); X printf(" 4: UNIX 12-bit compress u12 Y Y\n"); X printf(" 5: UNIX 16-bit compress u16 Y Y\n"); X printf("The default is #2\n"); X printf("\nText conversion methods (during extraction):\n"); X printf(" 0: Convert from CR to this system (ProDOS files)\n"); X printf(" 1: Convert from LF to this system (UNIX files)\n"); X printf(" 2: Convert from CRLF to this system (MS-DOS files)\n"); X X } else if (INDEX(options+1, 'w')) { /* print author info */ X X printf("%s\n", header); X printf( X "Internet: fadden@cory.berkeley.edu Usenet: ...!ucbvax!cory!fadden\n"); X printf("\nShrinkIt and NuFX standard by Andy Nicholas.\n"); X printf( X "ShrinkIt LZW compression by Kent Dickey. LZW-II (a modified version of\n"); X printf( X " Kent's algorithm) designed by Andy Nicholas. C LZW-II decoder by Kent\n"); X printf( X " Dickey and Frank Petroski (independently and simultaneously).\n"); X printf("\nUNIX compress code adapted from COMPRESS v4.3.\n"); X printf( "\nBinary II unpack and unsqueeze C code adapted from unblu.c and usq.c by\n"); X printf(" Marcel J.E. Mol (usq.c based on usq2/sq3 by Don Elton).\n"); X printf("\nMS-DOS port by Robert B. Hess and Bruce Kahn.\n"); X printf( "\nThis program is Freeware. Please distribute as widely as possible, but\n"); X printf( X " don't sell it. Source code is available via e-mail upon request.\n"); X printf( X "\nUsers without Usenet/Internet access may send mail to me at:\n"); X printf(" 1474 Saskatchewan Drive\n"); X printf(" Sunnyvale, CA 94087\n"); X X } else if (INDEX(options+1, 's')) { /* suboption info */ X printf("%s\n", header); X printf("\nUsual meaning of suboptions:\n"); X printf(" c - compression type, followed by a number\n"); X printf( X " f - file/aux type to add, followed by file/aux type spec\n"); X printf(" i - interactive; prompt before overwriting file\n"); X printf(" m - messages (add/extract comments instead of data)\n"); X printf(" r - don't recursively descend subdirectories\n"); X printf(" s - storage type (store as compressed w/o compressing), "); X printf("followed by number\n"); X printf( X " t - text translation (CR<->LF), followed by conversion mode\n"); X printf(" u - store as uncompressed (same as c0)\n"); X printf(" v - verbose mode\n"); #ifndef NO_BLU X printf(" x - extract during Binary II operations\n"); #endif X printf(" + - match partial pathnames for extract and delete\n"); X printf("\nTable of contents suboptions:\n"); X printf(" v - verbose output (same as V option)\n"); X printf(" a - ARC/ZOO style format\n"); X printf(" z - full output, prints all aspects of archive\n"); X X printf("\nSample shell variable command (csh):\n"); X printf( X " setenv NULIBOPT=verbose,interactive,type=SRC,aux=000a,compress=5\n"); X printf(" (default is non-verbose, non-interactive, type=NON, "); X printf( "aux=0000, compress=2)\n"); X X } else { /* default help screen */ X X printf("%s\n", header); X printf( X "\nUsage: %s option[suboptions] archive-name [filespec]\n", argv0); X printf("Option must be one of:\n"); X printf(" a[vucsrf] add to archive\n"); #ifndef NO_BLU X printf(" b[xvti] Binary II archive operations\n"); #endif X printf( X " c[vucsrf] create archive (add, but suppress 'create' message)\n"); X printf(" d[v+] delete file from archive\n"); X printf(" f[vucsrf] freshen files in archive\n"); X printf(" h[snw] show help screen (subopt/numbers/who's who)\n"); X printf(" i[v] verify archive integrity\n"); X printf(" m[vucsrf] move files to archive (add, delete original)\n"); X printf(" p[vmt+] print archived file to stdout\n"); X printf(" t[vaz] display table of contents\n"); X printf(" u[vucsrf] update files in archive\n"); X printf(" v verbose listing (ProDOS 8 ShrinkIt format)\n"); X printf(" x,e[vumti+] extract from archive\n"); X } } X X /* X * Check machine dependencies X */ static void CheckMach() { X onebyt one; X onebyt *oneptr; X twobyt two; X fourbyt four; X #ifdef UNIX # ifdef APW X ^^ "ERROR: You have both APW and UNIX defined" ^^ # endif # ifdef MSDOS X ^^ "ERROR: You have both MSDOS and UNIX defined" ^^ # endif #endif /*UNIX*/ #ifdef APW # ifdef MSDOS X ^^ "ERROR: You have both APW and MSDOS defined" ^^ # endif #endif X X /* some compilers complain about (unsigned) -1 , so I'm doing it this */ X /* way to keep everybody quiet. */ X X one = 0x100; X if (one) X Whoops("onebyt"); /* one > 1 */ X two = 0x10000; X if (two) X Whoops("twobyt"); /* two > 2 */ X two = 0x1000; X if (!two) X Whoops("twobyt"); /* two < 2 */ X four = 0xffffffff; X four++; X if (four) X Whoops("fourbyt"); /* four > 4 */ X four = 0x10000; X if (!four) X Whoops("fourbyt"); /* four < 4 */ X X /* check byte ordering */ X two = 0x1122; X oneptr = (onebyt *) &two; X if (*oneptr == 0x11) X HiLo = TRUE; X else if (*oneptr == 0x22) X HiLo = FALSE; X else { X printf("WARNING: Unable to determine a value for HiLo\n"); X HiLo = FALSE; X } X X /* check some other stuff... compilers may (should?) give warnings here */ X if (ATTSIZE < MHsize) X printf("WARNING: ATTSIZE must be >= than MHsize\n"); X if (RECBUFSIZ < ATTSIZE) X printf("WARNING: RECBUFSIZ should be larger than ATTSIZE\n"); X if (MHsize != 48 || THsize != 16) X printf("WARNING: Bad MHsize or THsize\n"); X if (sizeof(Time) != 8) X printf("WARNING: struct Time not 8 bytes\n"); } X X /* X * Check to see if string 2 is in string 1. X * X * Returns the position of string 2 within string 1; -1 if not found. X */ static int strc(host, sub) char *host, *sub; { X int hlen = strlen(host); X int slen = strlen(sub); X int i; X X if (slen > hlen) /* substring longer than host string */ X return (-1); X X /* generic linear search... */ X for (i = 0; i <= (hlen - slen); i++) X if ((*(host+i) == *sub) && (!strncmp(host+i, sub, slen))) X return (i); X X return (-1); } X X /* X * Yank a number from a character string. X */ int OptNum(ptr) char *ptr; { X int val = 0; X X while (*ptr && isdigit(*ptr)) { X val *= 10; X val += (*ptr - '0'); X ptr++; X } X return (val); } X X /* X * Set default values for globals. X * X * Should be of form "NULIBOPT=..." X * verbose : default to verbose output X * interactive : default to interactive mode when overwriting X * type=xxx : set storage type to ProDOS type "xxx" X * aux=xxxx : set aux storage type to 4-byte hex number "xxxx" X */ void GetDefaults(options) char *options; { X char *envptr; X int off, idx, pt; X int len = strlen(options); X char type[5]; X X /* set program default values */ X verbose = FALSE; /* silent mode */ X interact = FALSE; /* don't ask questions */ X doSubdir = TRUE; /* process subdirectories unless told not to */ X dopack = TRUE; /* don't pack unless told to */ X doExpand = FALSE; /* don't expand archived filenames */ X doMessages = FALSE; /* do comments instead of data */ X packMethod = 0x0002;/* ShrinkIt LZW */ X transfrom = -1; /* no text translation */ X transto = -1; X defFileType = (fourbyt) 0; /* NON */ X defAuxType = (fourbyt) 0; /* $0000 */ X X /* read from global envir var */ X if (envptr = getenv(ENVAR)) { X if (strc(envptr, "verbose") >= 0) { X verbose = TRUE; X } X if (strc(envptr, "interactive") >= 0) { X interact = TRUE; X } X if ((off = strc(envptr, "compress=")) >= 0) { X off += 9; X if (off+1 > strlen(envptr)) { X fprintf(stderr, "Error with 'compress=n' in NULIBOPT var\n"); X Quit (-1); X } X packMethod = atoi(envptr+off); X } X if ((off = strc(envptr, "type=")) >= 0) { X off += 5; X if (off+3 > strlen(envptr)) { X fprintf(stderr, "Error with 'type=xxx' in NULIBOPT var\n"); X Quit (-1); X } X strncpy(type, envptr+off, 3); X type[3] = '\0'; X for (idx = 0; idx < 256; idx++) /* scan for file type */ X if (!strcasecmp(FT[idx], type)) { X defFileType = (fourbyt) idx; X break; /* out of for */ X } X } X if ((off = strc(envptr, "aux=")) >= 0) { X off += 4; X if (off+4 > strlen(envptr)) { X fprintf(stderr, "Error with 'aux=$xxxx' in NULIBOPT var\n"); X Quit (-1); X } X strncpy(type, envptr+off, 4); X type[4] = '\0'; X sscanf(type, "%x", &defAuxType); X } X } X X /* handle command line suboption string */ X for (pt = 1; pt < len; pt++) { /* skip option char */ X switch(options[pt]) { X case '+': /* expand */ X doExpand = TRUE; X break; X case 'a': /* ARC/ZOO output format */ X /* do nothing */ X break; X case 'c': /* compress method */ X packMethod = OptNum(&options[pt+1]); X while (pt < len && isdigit(options[pt+1])) /* advance to next */ X pt++; X dopack = TRUE; X break; X case 'f': /* filetype specified */ X strncpy(type, &options[pt+1], 3); X type[3] = '\0'; X for (idx = 0; idx < 256; idx++) /* scan for file type */ X if (!strcasecmp(FT[idx], type)) { X defFileType = (fourbyt) idx; X break; /* out of for */ X } X X pt += strlen(type); X if (options[pt+1] == '/') { /* auxtype specification */ X pt++; X strncpy(type, &options[pt+1], 4); X type[4] = '\0'; X sscanf(type, "%lx", &defAuxType); X pt += strlen(type); X } X break; X case 'i': /* interactive overwrites */ X interact = TRUE; X break; X case 'm': /* do messages instead of data */ X doMessages = TRUE; X break; X case 'n': /* help with numbers */ X /* do nothing */ X break; X case 'r': /* don't recursively descend subdir */ X doSubdir = FALSE; X break; X case 's': /* store method */ X packMethod = OptNum(&options[pt+1]); X while (pt < len && isdigit(options[pt+1])) /* advance to next */ X pt++; X dopack = FALSE; X break; X case 't': /* how to translate text? */ X transfrom = OptNum(&options[pt+1]); X while (pt < len && isdigit(options[pt+1])) X pt++; X break; X case 'u': /* don't use compression */ X dopack = FALSE; /* this doesn't matter, but FALSE may be faster */ X packMethod = 0x0000; /* archive w/o compression */ X break; X case 'v': /* verbose mode */ X verbose = TRUE; X break; X case 'w': /* help on people */ X /* do nothing */ X break; X case 'x': /* extract BLU files */ X /* do nothing */ X break; X case 'z': /* in view files */ X /* do nothing */ X break; X default: /* unknown */ X fprintf(stderr, "%s: unknown subopt '%c'\n", prgName, options[pt]); X break; /* do nothing */ X } X } /* for */ } X X #ifdef APW /* X * Expand a ProDOS filename using APW wildcard calls (even if the file doesn't X * exist). X * X * Returns a pointer to a buffer holding the filename. X */ char * ExpandFilename(filename) char *filename; { X char *ptr; X X c2pstr(filename); X if (!(*filename)) { X printf("Internal error: can't expand null filename\n"); X Quit (-1); X } X X INIT_WILDCARD(filename, 0); X ToolErrChk(); X p2cstr(filename); X X NEXT_WILDCARD(tmpNameBuf); X p2cstr(tmpNameBuf); X if (strlen(tmpNameBuf)) /* found it */ X return(tmpNameBuf); X else { X /* file does not exist; expand path */ X strcpy(tmpNameBuf, filename); X ptr = RINDEX(tmpNameBuf, '/'); /* remove filename */ X if (!ptr) /* filename only */ X return (filename); X X *ptr = '\0'; X if (!strlen(tmpNameBuf)) { /* something weird... */ X printf("Unable to expand '%s'\n", filename); X Quit (-1); X } X X c2pstr(tmpNameBuf); X INIT_WILDCARD(tmpNameBuf, 0); X ToolErrChk(); X X NEXT_WILDCARD(tmpNameBuf); X p2cstr(tmpNameBuf); X if (!strlen(tmpNameBuf)) { X printf("Unable to fully expand '%s'\n", filename); X Quit (-1); X } X X strcat(tmpNameBuf, RINDEX(filename, '/')); X return (tmpNameBuf); X } } #endif /* APW */ X X /* X * Parse args, call functions. X */ main(argc, argv) int argc; char **argv; { X char *filename; /* hold expanded archive file name */ X int idx; X X filename = (char *) Malloc(MAXFILENAME); X CheckMach(); /* check compiler options, and set HiLo */ X X if (argc < 2) { /* no arguments supplied */ X Usage(argv[0]); X Quit (0); X } X X if (argv[1][0] == '-') { /* skip initial dashes */ X argv[1]++; X } X for (idx = 0; argv[1][idx]; idx++) /* conv opts to lower case */ X if (isupper(argv[1][idx])) X argv[1][idx] = tolower(argv[1][idx]); X X if (argc < 3) { /* no archive file specified; show help screen */ X if (argv[1][0] == 'h') /* could be HS, HN, or HW */ X Help(argv[0], argv[1]); X else /* not 'H' option; show generic help scrn */ X Help(argv[0], "h"); X Quit (0); X } X #ifdef APW X strcpy(filename, ExpandFilename(argv[2])); #else X strcpy(filename, argv[2]); #endif X GetDefaults(argv[1]); /* get defaults, process suboption string */ X X pakbuf = (onebyt *) Malloc(PAKBUFSIZ); /* allocate global pack buf */ X switch (argv[1][0]) { X case 'a': /* add */ X case 'c': /* create */ X case 'm': /* move */ X NuAdd(filename, argc-3, argv+3, argv[1]); /* NuAdd will read */ X break; #ifndef NO_BLU X case 'b': /* Binary II operations */ X NuBNY(filename, argc-3, argv+3, argv[1]); X break; #endif X case 'd': /* delete */ X NuDelete(filename, argc-3, argv+3, argv[1]); X break; X case 'f': /* freshen */ X case 'u': /* update */ X NuUpdate(filename, argc-3, argv+3, argv[1]); X break; X case 'i': /* verify integrity */ X NuTest(filename, argv[1]); X break; X case 't': /* table of contents */ X case 'v': /* verbose output */ X NuView(filename, argv[1]); X break; X case 'e': /* extract */ X case 'x': X case 'p': X NuExtract(filename, argc-3, argv+3, argv[1]); X break; X default: /* need help */ X fprintf(stderr, "%s: unknown option '%c'\n", argv[0], argv[1][0]); X break; X } X X free (filename); X free (pakbuf); X Quit (0); } X SHAR_EOF chmod 0644 numain.c || echo 'restore of numain.c failed' Wc_c="`wc -c < 'numain.c'`" test 16586 -eq "$Wc_c" || echo 'numain.c: original size 16586, current size' "$Wc_c" fi # ============= nupak.c ============== if test -f 'nupak.c' -a X"$1" != X"-c"; then echo 'x - skipping nupak.c (File already exists)' else echo 'x - extracting nupak.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'nupak.c' && /* X * nupak.c - interface to the compression routines X * X * NuLib v3.1 October 1991 Freeware (distribute, don't sell) X * By Andy McFadden (fadden@cory.berkeley.edu) X */ #define TRY_II #ifdef APW segment "Compress" #endif X #include "nudefs.h" #include /*#include */ /* "nucomp.h" includes for us */ #include "nuread.h" /* need THblock */ #include "nucomp.h" /* includes "nucompfn.h" + "types.h" */ X #ifdef MSDOS /* for file I/O */ # include # include # include # include #endif X #include "nupak.h" #include "nuetc.h" X #define CONVSIZ 1024 X long packedSize; /* global - size of file after packing */ onebyt lastseen; /* used in crlf(); must be set by caller */ X X /* X * Make a little spinning thing. X * X * This just lets the user know that the whole thing hasn't stalled on him. X * Prints a character, then backspaces so that the next thing will overwrite X * it. X * X * Currently called by FCopy(), unpak_SHK(), pak_SHK() X */ void Spin() { X static char *sp = "/-\\|"; X static int posn = 0; X X posn++; X if ((posn < 0) || (posn > 3)) X posn = 0; X putchar(sp[posn]); X putchar('\b'); X fflush(stdout); } X X /* X * Convert the end-of-line terminator between systems. X * X * Compile-time defines determine the value that things are translated to; X * the value of "translate" determines what they are translated from. This X * will write the contents of the buffer to the passed file descriptor, X * altering bytes as necessary. Max buffer size is 64K. Note that the X * syntax is the same as for write(); X * X * This would have been a lot easier without IBM... lastseen is the last X * character seen (used only in CRLF translations). This needs to be set X * by the caller (FCopy(), extract_files()). X * X * The putc_ncr() procedure in nusq.c does its own processing; this was X * somewhat unavoidable. X * X * BUGS: This proc will have to be re-written. It would be nice to be X * able to pack files with a CRLF translation, not just unpack... but you X * can't just do buffer writes for that. It'll take some work, and will X * probably appear in the next version. X */ unsigned int crlf(dstfd, buffer, length) int dstfd; onebyt *buffer; unsigned int length; { X register BOOLEAN doconv; X register onebyt *bptr = buffer; X register unsigned int idx; X static char *procName = "crlf"; X unsigned int partial; /* size for partial read/write */ X onebyt tobuf[2048]; X onebyt *toptr; X int conv; X unsigned int origlength = length; X X if ((transfrom == -1) && (transto == -1)) { /* no translation necessary */ X return (write(dstfd, buffer, length)); X } X if (transfrom < -1 || transfrom > 2) { X fprintf(stderr, "%s: unknown translation type %d\n", X prgName, transfrom); X fprintf(stderr, "%s: assuming conversion 0 (from CR)\n", prgName); X transfrom = 0; X } X if (transto < -1 || transto > 2) { X fprintf(stderr, "%s: unknown translation type %d\n", X prgName, transto); X fprintf(stderr, "%s: assuming conversion 0 (to CR)\n", prgName); X transto = 0; X } X X /* macro defs for system-dependent actions */ #ifdef UNIX # define DEFCONVFROM if (*bptr == 0x0a) /* LF */ \ X doconv = TRUE # define DEFCONVTO *(toptr++) = 0x0a #else # ifdef APW # define DEFCONVFROM if (*bptr == 0x0d) /* CR */ \ X doconv = TRUE # define DEFCONVTO *(toptr++) = 0x0d # endif # ifdef MSDOS # define DEFCONVFROM if ((*bptr == 0x0a) && (lastseen == 0x0d)) { \ X doconv = TRUE; \ X toptr--; /*already put CR; back up over it*/ \ X } \ X lastseen = *bptr # define DEFCONVTO *(toptr++) = 0x0d; \ X *(toptr++) = 0x0a # endif # ifndef APW # ifndef MSDOS # define DEFCONVFROM if (*bptr == 0x0a) /* LF */ \ X doconv = TRUE # endif /* none2 */ # endif /* none1 */ #endif /* UNIX */ X X while (length != 0) { X if (length > CONVSIZ) { X partial = CONVSIZ; X length -= CONVSIZ; X } else { X partial = length; X length = 0; X } X X /* uses an explicit flag rather than "continue" for clarity... */ X toptr = tobuf; X for (idx = partial; idx > 0; idx--, bptr++) { X doconv = FALSE; X switch (transfrom) { X case -1: /* convert from current system's terminator */ X DEFCONVFROM; X break; X case 0: X if (*bptr == 0x0d) /* CR */ X doconv = TRUE; X break; X case 1: X if (*bptr == 0x0a) /* LF */ X doconv = TRUE; X break; X case 2: X if ((*bptr == 0x0a) && (lastseen == 0x0d)) { X doconv = TRUE; X toptr--; /*already outputed CR; back up over it*/ X } X lastseen = *bptr; X break; X } X X X if (doconv) { X switch (transto) { X case -1: /* convert to current system's terminator */ X DEFCONVTO; X break; X case 0: X *(toptr++) = 0x0d; X break; X case 1: X *(toptr++) = 0x0a; X break; X case 2: X *(toptr++) = 0x0d; X *(toptr++) = 0x0a; X break; X } X } else { X *(toptr++) = *bptr; X } X } /* for loop */ X X if (write(dstfd, tobuf, (toptr-tobuf)) != (toptr-tobuf)) X Fatal("Dest write failed", procName); X } /* while loop */ X return (origlength); } X X /* X * Read a file, and place in another file at current posn. We can't read more X * than PAKBUFSIZ at a time, so for some files it will have to be broken down X * into pieces. Note PAKBUFSIZ is expected to be an int (defined in nupak.h), X * and can't be any larger than read() can handle (64K... unsigned 16-bit int). X * X * The transl option is present for NuUpdate and NuDelete, which have to X * copy old records to a new archive w/o performing translation. X */ void FCopy(srcfd, dstfd, length, copybuf, transl) int srcfd; /* source file descriptor (must be open & seek()ed) */ int dstfd; /* destination file descriptor (must be open & seek()ed) */ fourbyt length; /* number of bytes to copy */ onebyt *copybuf; BOOLEAN transl; /* maybe do text translation? */ { X unsigned int partial; /* size for partial read/write */ X static char *procName = "FCopy"; X X if (transl) lastseen = '\0'; X while (length != 0L) { X if (length > (long) PAKBUFSIZ) { X partial = (unsigned int) PAKBUFSIZ; X length -= (long) PAKBUFSIZ; X if (verbose) Spin(); X } else { X partial = (unsigned int) length; X length = 0L; X } X X if (read(srcfd, copybuf, partial) != partial) X Fatal("Source read failed", procName); X if (transl) { /* do text translation if user wants it */ X if (crlf(dstfd, copybuf, partial) != partial) X Fatal("Dest write failed (c)", procName); X } else { /* NEVER do translation */ X if (write(dstfd, copybuf, partial) != partial) X Fatal("Dest write failed (w)", procName); X } X } } X X /* X * Add a range of bytes from one file into another, packing them. X * X * Set up stuff, then call the appropriate pack routine. Returns the actual X * algorithm used (thread_format), since the compression algorithm could X * fail, storing the file in uncompressed format instead. The packed length X * is stored in a global variable. X * X * Since we're only using version 0 records, we don't need to propagate the X * thread_crc. X * X * Compression routines must do the following: X * - compress data from one file descriptor to another, given two seeked X * file descriptors and a length value. They may not rely on EOF conditions X * for either file. X * - return the packing method actually used. If they cope with failure X * by starting over with something different, the successful method should X * be returned. Failure may be handled in the switch statement below. X */ twobyt PackFile(srcfd, dstfd, thread_eof, thread_format, buffer) int srcfd; /* source file descriptor (must be open & seek()ed) */ int dstfd; /* destination file descriptor (must be open & seek()ed) */ fourbyt thread_eof; /* size of input */ int thread_format; /* how to pack the bytes */ onebyt *buffer; /* alloc in main prog so we don't have to each time */ { X long length = (long) thread_eof; X twobyt retval = thread_format; /* default = successful pack */ X long srcposn, dstposn; X static char *procName = "PackFile"; X X switch (thread_format) { X case 0x0000: /* uncompressed */ X if (verbose) { printf("storing...", thread_format); fflush(stdout); } X FCopy(srcfd, dstfd, length, buffer, TRUE); X packedSize = length; X break; X X case 0x0001: /* SQUeeze */ X if (verbose) { X printf("[can't squeeze; storing]..."); X fflush(stdout); X } else { X printf("WARNING: can't squeeze; files stored uncompressed\n"); X } X FCopy(srcfd, dstfd, length, buffer, TRUE); X packedSize = length; X retval = 0x0000; /* uncompressed */ X break; X X case 0x0002: /* LZW (ShrinkIt) */ X if (verbose) { printf("shrinking..."); fflush(stdout); } X /* packedSize set by pak_SHK */ X retval = pak_SHK(srcfd, dstfd, length, buffer); X break; X case 0x0003: /* LZW II (ShrinkIt) */ X if (verbose) { X printf("[can't do LZW II; storing]..."); X fflush(stdout); X } else { X printf("WARNING: can't do LZW II; files stored uncompressed\n"); X } X FCopy(srcfd, dstfd, length, buffer, TRUE); X packedSize = length; X retval = 0x0000; /* uncompressed */ X break; X case 0x0004: /* UNIX 12-bit compress */ #ifdef NO_UCOMP X if (verbose) { X printf("[can't do 12-bit UNIX compress; storing]..."); X fflush(stdout); X } else { X printf( X "WARNING: can't do 12-bit compress; files stored uncompressed\n"); X } X FCopy(srcfd, dstfd, length, buffer, TRUE); X packedSize = length; X retval = 0x0000; /* uncompressed */ #else X maxbits = 12; /* global compress parameter */ X if (verbose) { printf("compressing..."); fflush(stdout); } X /* packedSize set by compress() */ X if (u_compress(srcfd, dstfd, length) == OK) X retval = 0x0004; X else X retval = 0x0004; /* FIX this */ #endif X break; X X case 0x0005: /* UNIX 16-bit compress */ #ifdef NO_UCOMP X if (verbose) { X printf("[can't do 16-bit UNIX compress; storing]..."); X fflush(stdout); X } else { X printf( X "WARNING: can't do 16-bit compress; files stored uncompressed\n"); X } X FCopy(srcfd, dstfd, length, buffer, TRUE); X packedSize = length; X retval = 0x0000; /* uncompressed */ #else X maxbits = 16; /* global compress parameter */ X if (verbose) { printf("compressing..."); fflush(stdout); } X /* packedSize set by compress() */ X srcposn = lseek(srcfd, 0L, S_REL); /* save posn */ X dstposn = lseek(dstfd, 0L, S_REL); X if (u_compress(srcfd, dstfd, length) == OK) { X /* compress succeeded */ X retval = 0x0005; X } else { X /* compression failed */ X if (verbose) { printf("storing..."); fflush(stdout); } X lseek(srcfd, srcposn, S_ABS); /* reposn files */ X lseek(dstfd, dstposn, S_ABS); X FCopy(srcfd, dstfd, length, buffer, TRUE); X packedSize = length; X retval = 0x0000; X } #endif X break; X X default: X fprintf(stderr, "\nUnknown compression method %d\n", thread_format); X fprintf(stderr, "Aborting.\n"); X Quit(-1); X } X X return (retval); } X X /* X * Extract a range of bytes from one file into another, unpacking them. X * X * (hacked to unpack disks, also. Forces the thread_eof to be the total X * size of the disk, since ShrinkIt doesn't really define it, esp for DOS 3.3 X * disks). X * X * Set up stuff, then call the appropriate unpack routine. Leaves the srcfd X * positioned past the data to be unpacked; the calling routine should not X * have to do any seeks. X * X * Returns TRUE if able to unpack, FALSE if not able to. Note that srcfd X * WILL be seeked even if the compression method is not handled. X * X * New uncompression routines should have the following characteristics: X * - they should be able to uncompress a range of bytes from one file X * to another given two seeked file descriptors and a length parameter. X * - they should return TRUE if they succeed and FALSE otherwise. Special X * condition codes can be handled in the switch statement below. X */ int UnpackFile(srcfd, dstfd, THptr, thread_format, buffer) int srcfd; /* source file descriptor (must be open & lseek()ed) */ int dstfd; /* destination file descriptor (must be open & lseek()ed) */ THblock *THptr; /* pointer to thread structure */ int thread_format; /* how to unpack the bytes (NOT THptr->thread_format) */ onebyt *buffer; { X long length; X fourbyt thread_eof, /* #of bytes to output */ X comp_thread_eof; /* #of bytes in source */ X twobyt thread_crc; X BOOLEAN retval = TRUE; /* default to success */ X static char *procName = "UnpackFile"; X X thread_eof = THptr->thread_eof; X comp_thread_eof = THptr->comp_thread_eof; X thread_crc = THptr->thread_crc; X length = (long) comp_thread_eof; /* type checking goes easier */ X X switch (thread_format) { X case 0x0000: /* uncompressed */ X if (verbose) { printf("extracting...", thread_format); fflush(stdout);} X FCopy(srcfd, dstfd, length, buffer, TRUE); X break; X X case 0x0001: /* unSQUeeze */ #ifdef NO_BLU X if (verbose) { X printf("[can't unsqueeze - aborting]..."); X fflush(stdout); X } else { X printf("ERROR: can't unsqueeze; 'squ' files not extracted\n"); X } X lseek(srcfd, length, S_REL); /* set file posn */ X retval = FALSE; #else X if (verbose) { printf("unsqueezing..."); fflush(stdout); } X unpak_SQU(srcfd, dstfd, length); /* thread_eof not needed */ #endif X break; X X case 0x0002: /* LZW (ShrinkIt) */ X if (verbose) { printf("unshrinking (I)..."); fflush(stdout); } X unpak_SHK(srcfd, dstfd, comp_thread_eof, thread_eof, buffer, FALSE, X thread_crc); X break; X X case 0x0003: /* LZW II (ShrinkIt) */ #ifdef TRY_II X if (verbose) { printf("unshrinking (II)..."); fflush(stdout); } X unpak_SHK(srcfd, dstfd, comp_thread_eof, thread_eof, buffer, TRUE, X thread_crc); #else X if (verbose) { X printf("[can't unshrink type II - aborting]..."); X fflush(stdout); X } else { X printf( X "ERROR: can't unshrink type II; 'sh2' files not extracted\n"); X } X lseek(srcfd, length, S_REL); /* set file posn */ X retval = FALSE; #endif X break; X X case 0x0004: /* 12-bit UNIX compress */ #ifdef NO_UCOMP X if (verbose) { X printf("[can't undo 12-bit UNIX compress - aborting]..."); X fflush(stdout); X } else { X printf( X "ERROR: can't undo 12-bit UNIX compress; 'u12' files not extracted\n"); X } X lseek(srcfd, length, S_REL); /* set file posn */ X retval = FALSE; #else X if (verbose) { printf("uncompressing..."); fflush(stdout); } X if (u_decompress(srcfd, dstfd, (long) comp_thread_eof) != OK) X retval = FALSE; #endif X break; X X case 0x0005: /* 16-bit UNIX compress */ #ifdef NO_UCOMP X if (verbose) { X printf("[can't undo 16-bit UNIX compress - aborting]..."); X fflush(stdout); X } else { X printf( X "ERROR: can't undo 16-bit UNIX compress; 'u16' files not extracted\n"); X } X lseek(srcfd, length, S_REL); /* set file posn */ X retval = FALSE; #else X if (verbose) { printf("uncompressing..."); fflush(stdout); } X if (u_decompress(srcfd, dstfd, (long) comp_thread_eof) != OK) X retval = FALSE; #endif X break; X X default: X fprintf(stderr, "Unknown uncompression method %d\n", thread_format); X lseek(srcfd, length, S_REL); /* set file posn */ X retval = FALSE; X break; X } X X return (retval); } X SHAR_EOF chmod 0644 nupak.c || echo 'restore of nupak.c failed' Wc_c="`wc -c < 'nupak.c'`" test 15017 -eq "$Wc_c" || echo 'nupak.c: original size 15017, current size' "$Wc_c" fi # ============= nupdel.c ============== if test -f 'nupdel.c' -a X"$1" != X"-c"; then echo 'x - skipping nupdel.c (File already exists)' else echo 'x - extracting nupdel.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'nupdel.c' && /* X * nudel.c/nuupd.c - operations which delete/update/freshen 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 #ifdef BSD43 # include #else /* SYSV, APW, MSC */ # include #endif X #ifdef UNIX # include #endif #ifdef APW # include # include /* ? */ # include # include /* APW string ops */ #endif #ifdef MSDOS # include # include # include # include #endif X #include "nuread.h" #include "nuadd.h" /* AddFile(), etc. */ #include "nupak.h" /* uses PAKBUFSIZ */ #include "nupdel.h" #include "nuetc.h" X static BOOLEAN dofreshen; /* do freshen instead of update? */ X /* delete routines */ X /* X * Rebuild an archive, excluding files marked as deleted. X * Does not use absolute position values; just seeks along. The archive X * should be seeked just beyond the master header block. X */ static void RebuildArchive(arcfd, archive, tmpname, remaining) int arcfd; ListHdr *archive; char *tmpname; long remaining; { X int dstfd; /* destination filename */ X onebyt *mptr; X RNode *RNodePtr; X TNode *TNodePtr; X int rec, thread; X long size; X long master_eof; #ifdef APW X FileRec create_p; #endif X static char *procName = "RebuildArchive"; X X if (verbose) { printf("Building new archive file..."); fflush(stdout); } X X ArcfiCreate(tmpname); /* create file */ X master_eof = (long) MHsize; X X if ((dstfd = open(tmpname, O_WRONLY | O_TRUNC | O_BINARY, WPERMS)) < 0) X Fatal("Unable to open dest file", procName); X if (lseek(dstfd, (long) MHsize, S_ABS) < 0) X Fatal("Unable to lseek past dest mhblock", procName); X X RNodePtr = archive->RNodePtr; X X /* copy the surviving records to the destination file */ X for (rec = 0; rec < archive->MHptr->total_records; rec++) { #ifdef APW X if (STOP()) { printf("aborting.\n"); Quit(1); } #endif X size = (long) RNodePtr->RHptr->attrib_count; X size += (long) RNodePtr->filename_length; X TNodePtr = RNodePtr->TNodePtr; X for (thread=0; thread < (int)RNodePtr->RHptr->total_threads; thread++){ X if (TNodePtr == (TNode *) NULL) { X fprintf(stderr, "Internal error: Bad thread structure\n"); X Quit(-1); X } X size += (long) THsize; X size += TNodePtr->THptr->comp_thread_eof; X TNodePtr = TNodePtr->TNext; X } X X if (!RNodePtr->filename[0]) { X if (lseek(arcfd, size, S_REL) < 0) X Fatal("Unable to seek past deleted record", procName); X } else { X FCopy(arcfd, dstfd, size, pakbuf, FALSE); X master_eof += size; X } X X RNodePtr = RNodePtr->RNext; /* move on to next record */ X } X X mptr = MakeMHblock(archive, remaining, master_eof); /* build mheader */ X if (lseek(dstfd, 0L, S_ABS) < 0) X Fatal("Unable to seek back in dest file", procName); X if (write(dstfd, mptr, MHsize) < MHsize) X Fatal("Unable to write master header", procName); X X if (close(dstfd) < 0) X Fatal("Unable to close archive", procName); X if (verbose) printf("done.\n"); } X X /* X * Delete files from archive X * X * Scan archive, deleting files which match the strings in "names". X */ static void Delete(filename, namecount, names) char *filename; int namecount; char **names; { X ListHdr *archive; X int arcfd; /* archive file descriptor */ X int rec, idx; X MHblock *MHptr; /* Master Header block */ X RNode *RNodePtr; /* Record Node */ X int len, *lentab; /* hold strlen() of all names */ X char *pn; /* archived pathname */ X long remaining; X char *tmpname = (char *) Malloc(MAXFILENAME); X static char *procName = "Delete"; X X archive = NuRead(filename); X if ((arcfd = open(archive->arc_name, O_RDONLY | O_BINARY)) < 0) X Fatal("Unable to open archive", procName); X X lentab = (int *) Malloc( sizeof(int) * namecount ); /* calloc() is nicer */ X for (idx = 0; idx < namecount; idx++) /* calc. once (for efficiency) */ X lentab[idx] = strlen(names[idx]); X X MHptr = archive->MHptr; X RNodePtr = archive->RNodePtr; X remaining = MHptr->total_records; X X /* main record read loop */ X for (rec = 0; rec < MHptr->total_records; rec++) { X X pn = RNodePtr->filename; X len = strlen(pn); X if (RNodePtr->RHptr->version_number > MAXVERS) X printf("WARNING: '%s' has unknown record version_number\n", pn); X X for (idx = 0; idx < namecount; idx++) { /* find file in archive */ X /* try to match argument with first few chars of stored filename */ X /* or the entire filename, depending on EXPAND flag */ X if ((len >= lentab[idx]) && doExpand ? X (!strncasecmp(pn, names[idx], lentab[idx])) : X (!strcasecmp(pn, names[idx])) ) { X X if (verbose) printf("Marking '%s' as deleted.\n", pn); X RNodePtr->filename[0] = '\0'; /* mark as deleted */ X remaining--; X break; /* out of filename matching for-loop */ X } X } X X RNodePtr = RNodePtr->RNext; /* move on to next record */ X } X X if (remaining == MHptr->total_records) { X if (verbose) printf("No files selected; archive not modified\n"); X if (close(arcfd) < 0) X Fatal("Source (archive) close failed", procName); X Quit (0); X } X if (remaining == 0L) { X printf("All files in archive marked for deletion..."); fflush(stdout); X if (close(arcfd) < 0) X Fatal("Source (archive) close failed", procName); #ifdef APW X if (STOP()) { printf("aborting.\n"); Quit (1); } #endif X printf(" deleteing archive file.\n"); X X if (unlink(archive->arc_name) < 0) X Fatal("Unable to delete archive", procName); X } else { X tmpname = MakeTemp(tmpname); #ifdef APW X if (STOP()) { printf("aborting.\n"); Quit (1); } #endif X if (lseek(arcfd, (long) MHsize, S_ABS) < 0) X Fatal("Unable to seek past master block", procName); X RebuildArchive(arcfd, archive, tmpname, remaining); X X if (close(arcfd) < 0) X Fatal("Source (archive) close failed", procName); X if (verbose) { X printf("Deleteing old archive file..."); X fflush(stdout); X } X if (unlink(archive->arc_name) < 0) X Fatal("Unable to delete original archive", procName); X Rename(tmpname, archive->arc_name); X if (verbose) printf("done.\n"); X X } X free (tmpname); X free (lentab); } X X /* X * Entry point for deleteing files from archive. X */ void NuDelete(filename, namecount, names, options) char *filename; int namecount; char **names; char *options; { X static char *procName = "NuDelete"; X X /* presently does nothing */ X X Delete(filename, namecount, names); } X X /********** update routines **********/ X /* X * Updates the archive. X * X * Evaluate the command line arguments and compare them with the files in X * the archive. Put the most recent copy of the file in a new archive file. X * Essentially a combination of add and delete. X * X * This procedure is huge. Someday I may clean this up a bit... X */ static void Update(archive, namecount, names) ListHdr *archive; int namecount; char **names; { X int arcfd, dstfd; /* archive file descriptor */ X static file_info *FIArray[MAXARGS]; /* entries malloc()ed by EvalArgs */ X unsigned int rec; X int idx, thread; X MHblock *MHptr; /* Master Header block */ X RNode *RNodePtr; /* Record Node */ X TNode *TNodePtr; /* Thread block */ X char *pn; /* archived pathname */ X BOOLEAN keeparc, gotone; X char *tmpname = (char *) Malloc(MAXFILENAME); X Time *atptr, *ftptr; X long a_dt, f_dt; X long size; X fourbyt totalrecs, master_eof; X onebyt *mptr; X twobyt *twoptr; X static char *procName = "Update"; X X if ((arcfd = open(archive->arc_name, O_RDONLY | O_BINARY)) < 0) X Fatal("Unable to open archive", procName); X X /* expand wildcards/subdirectories, and get info */ X namecount = EvalArgs(namecount, names, FIArray, TRUE); X if (!namecount) { X if (verbose) printf("No files selected; archive not modified.\n"); X Quit (0); X } X X /* X * For each file in the archive, check for an *exact* match with the X * store_names in FIArray (case independent). If a match is found, X * compare the dates, and copy/add the most recent file. If no match X * is found, copy the file. After all archived files have been processed, X * add all remaining files specified on the command line (unless the X * F)reshen option is used, in which case this exits). X */ X X MHptr = archive->MHptr; X RNodePtr = archive->RNodePtr; X gotone = FALSE; X X /* mark files that will be replaced */ X for (rec = 0; rec < MHptr->total_records; rec++) { #ifdef APW X if (STOP()) { printf("aborting.\n"); Quit (1); } #endif X pn = RNodePtr->filename; X if (RNodePtr->RHptr->version_number > MAXVERS) X printf("WARNING: '%s' has unknown record version_number\n", pn); X X for (idx = 0; idx < namecount; idx++) { /* find file in archive */ X /* try to match argument with first few chars of stored filename */ X if (!strcasecmp(pn, FIArray[idx]->store_name)) { X atptr = &RNodePtr->RHptr->mod_when; X ftptr = &FIArray[idx]->mod_dt; X X /* compare month/year [ I think it's best-case faster... ] */ X a_dt = (atptr->year * 12) + atptr->month; X f_dt = (ftptr->year * 12) + ftptr->month; X if (a_dt > f_dt) /* archive is more recent? */ X keeparc = TRUE; X else if (a_dt < f_dt) /* file is more recent? */ X keeparc = FALSE; X else { /* year & month match, check rest */ X a_dt = (atptr->day * 86400L) + (atptr->hour * 3600) + X (atptr->minute * 60) + (atptr->second); X f_dt = (ftptr->day * 86400L) + (ftptr->hour * 3600) + X (ftptr->minute * 60) + (ftptr->second); X if (a_dt < f_dt) X keeparc = FALSE; X else /* (a_dt >= f_dt) */ X keeparc = TRUE; X } X X if (!keeparc) { /* not keeping; mark as being replaced */ #ifndef APW /* APW uses actual filetype; other systems keep old */ X FIArray[idx]->fileType = RNodePtr->RHptr->file_type; X FIArray[idx]->auxType = RNodePtr->RHptr->extra_type; #endif X RNodePtr->RHptr->version_number = 65535; /*can't do fname*/ X twoptr = (twobyt *) RNodePtr->filename; X *twoptr = idx; /* null filename -> problems */ X gotone = TRUE; X } X FIArray[idx]->marked = TRUE; /* MARK as processed */ X } X } X X RNodePtr = RNodePtr->RNext; /* move on to next record */ X } X X totalrecs = MHptr->total_records; /* none will be deleted */ X if (!dofreshen) { /* add new files? */ X for (idx = 0; idx < namecount; idx++) { /* handle unmatched args */ X if (!FIArray[idx]->marked) { X gotone = TRUE; X totalrecs++; /* count new ones too */ X } X } X } X if (!gotone) { X if (verbose) printf("No files need updating; archive not modified\n"); X if (close(arcfd) < 0) X Fatal("Source (archive) close failed", procName); X Quit (0); X } X X /* X * Rebuild archive file X */ X if (verbose) printf("Building new archive file...\n"); X tmpname = MakeTemp(tmpname); X ArcfiCreate(tmpname); X X master_eof = (long) MHsize; X X if (lseek(arcfd, (long) MHsize, S_ABS) < 0) X Fatal("Bad archive seek", procName); X X if ((dstfd = open(tmpname, O_RDWR | O_TRUNC | O_BINARY)) < 0) X Fatal("Unable to open dest file", procName); X if (lseek(dstfd, (long) MHsize, S_ABS) < 0) X Fatal("Bad dest seek", procName); /* leave space for later */ X X RNodePtr = archive->RNodePtr; X for (rec = 0; rec < MHptr->total_records; rec++) { X size = (long) RNodePtr->RHptr->attrib_count; X size += (long) RNodePtr->filename_length; X TNodePtr = RNodePtr->TNodePtr; X for (thread=0; thread < (int)RNodePtr->RHptr->total_threads; thread++){ X if (TNodePtr == (TNode *) NULL) { X fprintf(stderr, "Internal error: Bad thread structure\n"); X Quit (-1); X } X size += (long) THsize; X size += TNodePtr->THptr->comp_thread_eof; X TNodePtr = TNodePtr->TNext; X } X /* we now know the size; either copy the old or replace with new */ X if (RNodePtr->RHptr->version_number != 65535) { /* file not replaced */ /* if (verbose) { X * printf("Copying '%s'...", RNodePtr->filename); X * fflush(stdout); X * } X */ X FCopy(arcfd, dstfd, size, pakbuf, FALSE); X master_eof += (fourbyt) size; /* if (verbose) printf("done.\n"); X */ X } else { /* file replaced; skip orig and add new */ X if (lseek(arcfd, size, S_REL) < 0) X Fatal("Bad skip seek", procName); X twoptr = (twobyt *) RNodePtr->filename; X idx = *twoptr; X if (verbose) printf("Replacing/"); /* +"Adding 'filename'..." */ X master_eof += AddFile(dstfd, FIArray[idx]); X } X X RNodePtr = RNodePtr->RNext; /* move on to next record */ X } X X if (!dofreshen) { X for (idx = 0 ; idx < namecount; idx++) { #ifdef APW X if (STOP()) Quit(1); /* check for OA-. */ #endif X if (!FIArray[idx]->marked) { X master_eof += AddFile(dstfd, FIArray[idx]); X } X } X } X X /* build master header */ X mptr = MakeMHblock(archive, totalrecs, master_eof); X if (lseek(dstfd, 0L, S_ABS) < 0) X Fatal("Bad lseek for master header", procName); X if (write(dstfd, mptr, MHsize) < MHsize) X Fatal("Unable to write master header", procName); X X if (close(arcfd) < 0) X Fatal("Source (old archive) close failed", procName); X if (close(dstfd) < 0) X Fatal("Destination (new archive) close failed", procName); X X if (verbose) { printf("Deleteing old archive file..."); fflush(stdout); } X if (unlink(archive->arc_name) < 0) X Fatal("Unable to delete original archive", procName); X Rename(tmpname, archive->arc_name); X if (verbose) printf("done.\n"); X X free (tmpname); } X X /* X * Update files in archive X * X * This part just evaluates the options, sets parms, and calls Update(). X */ void NuUpdate(filename, namecount, names, options) char *filename; int namecount; char **names; char *options; { X ListHdr *archive; X static char *procName = "NuUpdate"; X X if (*options == 'f') dofreshen = TRUE; X else dofreshen = FALSE; X X /* change T subopt to convert FROM current system TO */ X if (transfrom >= 0) { X transto = transfrom; X transfrom = -1; X } X X archive = NuRead(filename); X Update(archive, namecount, names); } X SHAR_EOF chmod 0644 nupdel.c || echo 'restore of nupdel.c failed' Wc_c="`wc -c < 'nupdel.c'`" test 13985 -eq "$Wc_c" || echo 'nupdel.c: original size 13985, current size' "$Wc_c" fi true || echo 'restore of nuread.c failed' echo End of part 6, continue with part 7 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. ]