rsalz@uunet.uu.net (Rich Salz) (06/07/89)
Submitted-by: Axel Mahler <unido!coma!axel> Posting-number: Volume 19, Issue 39 Archive-name: shape/part26 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 26 (of 33)." # Contents: src/afs/afsrepair.c # Wrapped by rsalz@papaya.bbn.com on Thu Jun 1 19:27:17 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'src/afs/afsrepair.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/afs/afsrepair.c'\" else echo shar: Extracting \"'src/afs/afsrepair.c'\" \(30386 characters\) sed "s/^X//" >'src/afs/afsrepair.c' <<'END_OF_FILE' X/* X * Copyright (C) 1989, 1990 W. Koch, A. Lampen, A. Mahler, W. Obst, X * and U. Pralle X * X * This software is published on an as-is basis. There is ABSOLUTELY NO X * WARRANTY for any part of this software to work correctly or as described X * in the manuals. We do not accept any liability for any kind of damage X * caused by use of this software, such as loss of data, time, money, or X * effort. X * X * Permission is granted to use, copy, modify, or distribute any part of X * this software as long as this is done without asking for charge, and X * provided that this copyright notice is retained as part of the source X * files. You may charge a distribution fee for the physical act of X * transferring a copy, and you may at your option offer warranty X * protection in exchange for a fee. X * X * Direct questions to: Tech. Univ. Berlin X * Wilfried Koch X * Sekr. FR 5-6 X * Franklinstr. 28/29 X * D-1000 Berlin 10, West Germany X * X * Tel: +49-30-314-22972 X * E-mail: shape@coma.uucp or shape@db0tui62.bitnet X */ X/* X * X * AFS-test -- try to repair corrupted archive X * X * $Header: afsrepair.c[1.4] Wed Feb 22 16:28:01 1989 andy@coma published $ X */ X X#include <stdio.h> X#include <string.h> X#ifdef SUNOS_4_0 X#include <strings.h> X#endif X#include <setjmp.h> X#include <signal.h> X#include <sys/types.h> X#include <sys/stat.h> X X#include "typeconv.h" X#include "afs.h" X#include "afarchive.h" X#include "afsrepair.h" X Xint givenVLevel = NORMAL; XInput attrIn, dataIn; XConstAttrs cAttrs; XRevision revList[MAXREVS]; XUdas udaList[MAXREVS]; XNote noteList[MAXREVS]; XData dataList[MAXREVS]; Xint curRev, curUda, curNote, curData; X Xchar *malloc(), *verifyString(), *complainString(); Xextern char *optarg; Xextern int optind; X Xjmp_buf env; X Xmain (argc, argv) X int argc; X char **argv; X{ X int cleanup(), getopt(); X short c, i, nfiles; X X if (argc < 2) X { usage (); exit (-1); } X X while ((c = getopt (argc, argv, "l:v")) != EOF) X { X switch (c) X { X case 'l': /* level */ X givenVLevel = atoi (optarg); X if ((givenVLevel < 0) || (givenVLevel > 3)) X { X fprintf (stderr, "illegal level of verbosity (%s)\n", X "must be 0, 1, 2 or 3"); X exit (-1); X } X break; X case 'v': /* print current version of this program */ X printf ("This is %s version %s.\n", argv[0], af_version()); X exit (0); X default: X usage (); X exit (-1); X } X } /* end of command line parsing */ X X (void) signal (SIGINT, cleanup); X X nfiles = argc - optind; X for (i = 0; i < nfiles; i++) X { X if (setjmp (env) == 0) X (void) repair (argv[i+optind]); X } X} /* end of main */ X Xusage () X{ X fprintf (stderr, "Usage: afsrepair [-l level] [-v] files\n"); X} X Xchar lckFilename[4*MAXNAMLEN]; X Xcleanup () X{ X fprintf (stderr, "abort processing of this file\n"); X (void) af_unlink (lckFilename); X longjmp (env, 1); X} X Xrepair (filename) X char *filename; X{ X char *fullname = af_uniqpath (filename), *sPtr, commandLine[1024]; X char *arFilename, datFilename[4*MAXNAMLEN]; X char arTmpFilename[4*MAXNAMLEN], datTmpFilename[4*MAXNAMLEN]; X int size, i, j; X Af_user *owner, *af_garown(); X bool error, writeOk, confirm, busyEx = FALSE; X FILE *inFile, *tmpFile, *lckFile; X struct stat ibuf; X X if (!strcmp (filename, "binary_pool")) X { X fprintf (stdout, "cannot repair binary pools yet -- \nthe only way "); X fprintf (stdout, "to fix a binary pool is to clear it ! (y/n) ? "); X if (askConfirm ("y")) X { X fprintf (stdout, "clearing binary pool...\n", filename); X (void) sprintf (commandLine, "rm -f AFS/%s*\0", AF_BPFILEID); X (void) system (commandLine); X } X exit (0); X } X X cAttrs.host = af_gethostname (); X cAttrs.syspath = af_afpath (fullname); X cAttrs.name = af_afname (fullname); X cAttrs.type = af_aftype (fullname); X X fprintf (stdout, "%s:\n", af_unixname ((char *)0, cAttrs.name, cAttrs.type)); X X arFilename = af_garname (cAttrs.syspath, cAttrs.name, cAttrs.type); X X if ((owner = af_garown (arFilename, &writeOk)) == (Af_user *)0) X { X fprintf (stdout, "cannot determine owner of AFS subdirectory !!\n"); X owner = af_getuser (getuid()); X } X cAttrs.ownerName = af_entersym (owner->af_username); X cAttrs.ownerHost = af_enterhost (owner->af_userhost); X X /* look for Lockfile */ X (void) strcpy (lckFilename, arFilename); X lckFilename [strlen (lckFilename) - sizeof (char)] = AF_LCKEXT; X if (stat (lckFilename, &ibuf) != ERROR) /* lock file present */ X { X fprintf (stdout, "Archive file is locked!\n"); X fprintf (stdout, " There might be a spurious lockfile,\n"); X fprintf (stdout, " or another application is currently modifying the archive file.\n"); X fprintf (stdout, " Ignore the lock (y/n) ? "); X if (!askConfirm ("y")) X exit (0); X else /* create lockfile */ X { X lckFile = fopen (lckFilename, "w"); X (void) fclose (lckFile); X } X } X X /* read the two archive files (if present) */ X if (inFile = fopen (arFilename, "r")) X { X attrIn.length = af_retfsize (arFilename); X if ((attrIn.string = malloc ((unsigned) attrIn.length)) == (char *)0) X { X fprintf (stdout, "repair (malloc): not enough memory\n"); X cleanup (); X } X (void) fread (attrIn.string, sizeof (char), (Size_t) attrIn.length, inFile); X (void) fclose (inFile); X attrIn.curPos = 0; X } X X (void) strcpy (datFilename, arFilename); X datFilename[strlen(datFilename)-sizeof(char)] = AF_DATAEXT; X if (inFile = fopen (datFilename, "r")) X { X dataIn.length = af_retfsize (datFilename); X if ((dataIn.string = malloc ((unsigned) dataIn.length)) == (char *)0) X { X fprintf (stdout, "repair (malloc): not enough memory\n"); X cleanup (); X } X (void) fread (dataIn.string, sizeof (char), (Size_t) dataIn.length, inFile); X (void) fclose (inFile); X } X else X { X if (attrIn.string == (char *)0) X { X fprintf (stdout, "repair: no archive files for %s\n", X af_unixname ((char *)0, cAttrs.name, cAttrs.type)); X cleanup (); X } X } X X /* test existence of busy file */ X if (access (fullname, 0) == 0) X busyEx = TRUE; X X /*========= X * Phase 1 X *=========*/ X fprintf (stdout, "*** Phase 1 (check version independent attributes) ***\n"); X X (void) lookup (&attrIn, AF_NAMEID, 0); X X (void) nextItem (&attrIn); /* host */ X sPtr = verifyString ("hostname", attrIn, VERBOSE); X if (strcmp (sPtr, cAttrs.host)) X sPtr = complainString ("hostname", sPtr, cAttrs.host, NORMAL); X cAttrs.host = af_entersym (sPtr); X X (void) nextItem (&attrIn); /* syspath */ X sPtr = verifyString ("syspath", attrIn, VERBOSE); X if (strcmp (sPtr, cAttrs.syspath)) X sPtr = complainString ("syspath", sPtr, cAttrs.syspath, NORMAL); X cAttrs.syspath = af_entersym (sPtr); X X (void) nextItem (&attrIn); /* name */ X sPtr = verifyString ("name", attrIn, VERBOSE); X if (strcmp (sPtr, cAttrs.name)) X sPtr = complainString ("name", sPtr, cAttrs.name, NORMAL); X cAttrs.name = af_entersym (sPtr); X X (void) nextItem (&attrIn); /* type */ X sPtr = verifyString ("type", attrIn, VERBOSE); X if (strcmp (sPtr, cAttrs.type)) X sPtr = complainString ("type", sPtr, cAttrs.type, NORMAL); X cAttrs.type = af_entersym (sPtr); X X (void) lookup (&attrIn, AF_OWNID, 0); X X (void) nextItem (&attrIn); /* owner's name */ X sPtr = verifyString ("owner's name", attrIn, VERBOSE); X if (strcmp (sPtr, cAttrs.ownerName)) X sPtr = complainString ("owner's name", sPtr, cAttrs.ownerName, NORMAL); X cAttrs.ownerName = af_entersym (sPtr); X X (void) nextItem (&attrIn); /* owner's host */ X sPtr = verifyString ("owner's host", attrIn, VERBOSE); X if (strcmp (sPtr, cAttrs.ownerHost)) X sPtr = complainString ("owner's host", sPtr, cAttrs.ownerHost, NORMAL); X cAttrs.ownerHost = af_entersym (sPtr); X X /*========= X * Phase 2 X *=========*/ X fprintf (stdout, "*** Phase 2 (check version attributes) ***\n"); X X /* initialize busy version --- not *all* attributes get initialized !!! */ X revList[0].generation = AF_BUSYVERS; X revList[0].revision = AF_BUSYVERS; X (void) lookup (&attrIn, AF_NAMEID, 0); X (void) nextItem (&attrIn); (void) nextItem (&attrIn); X (void) nextItem (&attrIn); (void) nextItem (&attrIn); X (void) nextItem (&attrIn); X sPtr = verifyString ("variant", attrIn, VERBOSE); X revList[0].variant = af_entersym (sPtr); X X (void) lookup (&attrIn, AF_LOCKID, 0); X (void) nextItem (&attrIn); X sPtr = verifyString ("locker's name", attrIn, VERBOSE); X revList[0].lockerName = af_entersym (sPtr); X (void) nextItem (&attrIn); X sPtr = verifyString ("locker's host", attrIn, VERBOSE); X revList[0].lockerHost = af_entersym (sPtr); X X if ((revList[0].lockerName == (char *)0) && revList[0].lockerHost) X { X fprintf (stdout, "Warning: lockerID inconsistent -- lock cancelled\n"); X revList[0].lockerName = (char *)0; X revList[0].lockerHost = (char *)0; X } X if (revList[0].lockerName && (revList[0].lockerHost == (char *)0)) X { X fprintf (stdout,"locker's host missing - inserting author's host\n"); X revList[0].lockerHost = revList[0].authorHost; X } X X (void) nextItem (&attrIn); X revList[0].lockTime = verifyDate ("locking date", attrIn, EVERYTHING); X if (revList[0].lockerName && (revList[0].lockTime == AF_NOTIME)) X { X fprintf (stdout, "Warning: locking date inconsistent -- %s\n", X "setting actual date"); X revList[0].lockTime = (time_t) af_acttime(); X } X X (void) lookup (&attrIn, AF_PRDID, 0); X (void) nextItem (&attrIn); X revList[0].predGen = X verifyInt ("pred(gen) of busy version", attrIn, EVERYTHING); X (void) nextItem (&attrIn); X revList[0].predRev = X verifyInt ("pred(rev) of busy version", attrIn, EVERYTHING); X X attrIn.curPos = 0; X curRev = 0; X while (lookup (&attrIn, AF_REVID, 1) != -1) X { X curRev++; X (void) nextItem (&attrIn); X revList[curRev].generation = verifyInt ("gen", attrIn, EVERYTHING); X (void) nextItem (&attrIn); X revList[curRev].revision = verifyInt ("rev", attrIn, EVERYTHING); X (void) nextItem (&attrIn); X revList[curRev].state = verifyInt ("state", attrIn, EVERYTHING); X (void) nextItem (&attrIn); X revList[curRev].mode = (u_short) verifyOct ("mode", attrIn, EVERYTHING); X (void) nextItem (&attrIn); X sPtr = verifyString ("variant", attrIn, VERBOSE); X revList[curRev].variant = af_entersym (sPtr); X X (void) lookup (&attrIn, AF_AUTHORID, 1); X (void) nextItem (&attrIn); /* author's name */ X sPtr = verifyString ("author's name", attrIn, VERBOSE); X if (sPtr == (char *)0) X { X fprintf (stdout,"author's name missing -- inserting owner's name\n"); X revList[curRev].authorName = cAttrs.ownerName; X } X else X revList[curRev].authorName = af_entersym (sPtr); X X (void) nextItem (&attrIn); /* authort's host */ X sPtr = verifyString ("author's host", attrIn, VERBOSE); X if (sPtr == (char *)0) X { X fprintf (stdout,"author's host missing -- inserting owner's host\n"); X revList[curRev].authorHost = cAttrs.ownerHost; X } X else X revList[curRev].authorHost = af_entersym (sPtr); X X (void) nextItem (&attrIn); /* locker's name */ X sPtr = verifyString ("locker's name", attrIn, VERBOSE); X revList[curRev].lockerName = af_entersym (sPtr); X X (void) nextItem (&attrIn); /* locker's host */ X sPtr = verifyString ("locker's host", attrIn, VERBOSE); X if ((sPtr == (char *)0) && (revList[curRev].lockerName != (char *)0)) X { X fprintf (stdout,"locker's host missing - inserting author's host\n"); X revList[curRev].lockerHost = revList[curRev].authorHost; X } X else X revList[curRev].lockerHost = af_entersym (sPtr); X X (void) lookup (&attrIn, AF_DATEID, 1); X (void) nextItem (&attrIn); X revList[curRev].modTime = verifyDate ("mod. date", attrIn, EVERYTHING); X if (revList[curRev].modTime == AF_NOTIME) X { X fprintf (stdout, "Warning: modification date missing -- %s\n", X "inserting actual date"); X revList[curRev].modTime = (time_t) af_acttime(); X } X (void) nextItem (&attrIn); X revList[curRev].accessTime = verifyDate ("acc. date", attrIn,EVERYTHING); X if (revList[curRev].accessTime == AF_NOTIME) X { X fprintf (stdout, "Warning: access date missing -- %s\n", X "inserting actual date"); X revList[curRev].accessTime = (time_t) af_acttime(); X } X (void) nextItem (&attrIn); X revList[curRev].statChangeTime = X verifyDate ("status change date", attrIn, EVERYTHING); X if (revList[curRev].statChangeTime == AF_NOTIME) X { X fprintf (stdout, "Warning: status change date missing -- %s\n", X "inserting actual date"); X revList[curRev].statChangeTime = (time_t) af_acttime(); X } X (void) nextItem (&attrIn); X revList[curRev].saveTime = verifyDate ("save date", attrIn, EVERYTHING); X if (revList[curRev].saveTime == AF_NOTIME) X { X fprintf (stdout, "Warning: save date missing -- %s\n", X "inserting actual date"); X revList[curRev].saveTime = (time_t) af_acttime(); X } X (void) nextItem (&attrIn); X revList[curRev].lockTime = verifyDate ("lock date", attrIn, EVERYTHING); X if ((revList[curRev].lockTime == AF_NOTIME) && X (revList[curRev].lockerName != (char *)0)) X { X fprintf (stdout, "Warning: locking date missing -- %s\n", X "inserting actual date"); X revList[curRev].lockTime = (time_t) af_acttime(); X } X X (void) lookup (&attrIn, AF_REPRID, 1); X (void) nextItem (&attrIn); X revList[curRev].representation = verifyInt ("repr", attrIn, EVERYTHING); X (void) nextItem (&attrIn); X revList[curRev].fileSize = verifyInt ("filesize", attrIn, EVERYTHING); X (void) nextItem (&attrIn); X revList[curRev].deltaSize = verifyInt ("deltasize", attrIn, EVERYTHING); X (void) nextItem (&attrIn); X revList[curRev].succGen = verifyInt ("succ. gen", attrIn, EVERYTHING); X (void) nextItem (&attrIn); X revList[curRev].succRev = verifyInt ("succ. rev", attrIn, EVERYTHING); X (void) nextItem (&attrIn); X revList[curRev].predGen = verifyInt ("pred. gen", attrIn, EVERYTHING); X (void) nextItem (&attrIn); X revList[curRev].predRev = verifyInt ("pred. rev", attrIn, EVERYTHING); X } /* revision loop */ X X /*========= X * Phase 3 X *=========*/ X fprintf (stdout, "*** Phase 3 (check user defined attributes) ***\n"); X X attrIn.curPos = 0; X curUda = 0; X while (lookup (&attrIn, AF_UDAID, 1) != -1) X { X (void) nextItem (&attrIn); X udaList[curUda].generation = verifyInt ("gen", attrIn, EVERYTHING); X (void) nextItem (&attrIn); X udaList[curUda].revision = verifyInt ("rev", attrIn, EVERYTHING); X (void) nextItem (&attrIn); X i = 0; X size = 0; X while (i < MAXUDAS) X { X udaList[curUda].uda[i] = &attrIn.string[attrIn.curPos]; X udaList[curUda].size = udaList[curUda].size + X (strlen (udaList[curUda].uda[i]) + sizeof (char)); X while (attrIn.string[attrIn.curPos] != '\0') X attrIn.curPos++; X attrIn.curPos++; X i++; X if (!strcmp (&attrIn.string[attrIn.curPos], AF_UDAID)) X break; X if (attrIn.string[attrIn.curPos] == '\0') X { X udaList[curUda].size++; X break; X } X } /* uda loop */ X udaList[curUda].uda[i] = (char *)0; X curUda++; X } /* revision loop */ X X /*========= X * Phase 4 X *=========*/ X fprintf (stdout, "*** Phase 4 (check notes) ***\n"); X X dataIn.curPos = 0; X curNote = 0; X while (lookup (&dataIn, AF_NOTEID, 1) != -1) X { X (void) nextItem (&dataIn); X noteList[curNote].generation = verifyInt ("gen", dataIn, EVERYTHING); X (void) nextItem (&dataIn); X noteList[curNote].revision = verifyInt ("rev", dataIn, EVERYTHING); X (void) nextItem (&dataIn); X (void) nextLine (&dataIn); /* skip size */ X size = 0; X noteList[curNote].contents = &dataIn.string[dataIn.curPos]; X while (((noteList[curNote].contents)[size] != AF_DATAID[0]) && X ((noteList[curNote].contents)[size] != '\0')) X size++; X if (size == 0) X { X noteList[curNote].contents = (char *)0; X size = 1; X } X else X (noteList[curNote].contents)[size-1] = '\0'; X noteList[curNote].size = size; X curNote++; X } /* revision loop */ X X /*========= X * Phase 5 X *=========*/ X fprintf (stdout, "*** Phase 5 (check data) ***\n"); X X dataIn.curPos = 0; X curData = 0; X while (lookup (&dataIn, AF_DATAID, 1) != -1) X { X (void) nextItem (&dataIn); X dataList[curData].generation = verifyInt ("gen", dataIn, EVERYTHING); X (void) nextItem (&dataIn); X dataList[curData].revision = verifyInt ("rev", dataIn, EVERYTHING); X (void) nextItem (&dataIn); X dataList[curData].representation = verifyInt ("repr",dataIn, EVERYTHING); X (void) nextItem (&dataIn); X (void) nextLine (&dataIn); /* skip size */ X size = 0; X dataList[curData].contents = &dataIn.string[dataIn.curPos]; X while (itemCmp (&(dataList[curData].contents)[size], X AF_NOTEID, AF_IDSTRLEN) && X itemCmp (&(dataList[curData].contents)[size], X AF_DATAID, AF_IDSTRLEN)) X { X size++; X while ((dataList[curData].contents)[size] != AF_NOTEID[0]) X { X size++; X if ((dataIn.curPos + size) == dataIn.length) X goto loopexit; X } X } X loopexit: X if (size == 0) X dataList[curData].contents = (char *)0; X dataList[curData].size = size; X curData++; X } /* revision loop */ X X /*========= X * Phase 6 X *=========*/ X fprintf (stdout, "*** Phase 6 (check connectivity) ***\n"); X X /* test order of revisions -- not yet implemented */ X /* test existence on successors and predecessors -- not yet implemented */ X X /* calculate number of revisions and size of data */ X cAttrs.noOfRevisions = curRev; X X cAttrs.datasize = 0; X for (i=0; i<curRev; i++) X cAttrs.datasize = cAttrs.datasize + noteList[i].size; X for (i=0; i<curRev; i++) X cAttrs.datasize = cAttrs.datasize + dataList[i].size; X X /* test integrity of attr and data file */ X error = FALSE; X for (i=0; i<=cAttrs.noOfRevisions; i++) X { X if ((udaList[i].generation != revList[i].generation) || X (udaList[i].revision != revList[i].revision)) X { X error = TRUE; X udaList[i].generation = revList[i].generation; X udaList[i].revision = revList[i].revision; X } X } X X for (i=0; i<cAttrs.noOfRevisions; i++) X { X if ((noteList[i].generation != revList[i+1].generation) || X (noteList[i].revision != revList[i+1].revision)) X { X error = TRUE; X noteList[i].generation = revList[i+1].generation; X noteList[i].revision = revList[i+1].revision; X } X if ((dataList[i].generation != revList[i+1].generation) || X (dataList[i].revision != revList[i+1].revision)) X { X error = TRUE; X dataList[i].generation = revList[i+1].generation; X dataList[i].revision = revList[i+1].revision; X } X } X if (error) X fprintf (stderr, "version numbering inconsistent -- fixed !\n"); X X X X /*============================== X * Write temporary archive files X *==============================*/ X X /* if all revisions have been removed */ X if (!busyEx && (cAttrs.noOfRevisions == 0)) X { X fprintf (stdout, "no revisions found\n"); X cleanup (); X } X X /* open tmpfile */ X (void) strcpy (arTmpFilename, arFilename); X arTmpFilename[strlen(arTmpFilename)-sizeof(char)] = AF_ARCHTMP; X if ((tmpFile = fopen (arTmpFilename, "w")) == (FILE *)0) X { X fprintf (stderr, "cannot open tmp file\n"); X cleanup (); X } X X /* write header */ X fprintf (tmpFile, "%s %d %d %ld\n", AF_ARHEADER, AF_ARCURVERS, X cAttrs.noOfRevisions + 1, cAttrs.datasize); X X /* write constant attributes */ X if (busyEx) X { X fprintf (tmpFile, "%s %s %s %s %s %s\n", AF_NAMEID, X cAttrs.host, cAttrs.syspath, cAttrs.name, NOTMT (cAttrs.type), X NOTMT (revList[0].variant)); X } X else X { X fprintf (tmpFile, "%s %s %s %s %s %s\n", AF_NAMEID, cAttrs.host, X cAttrs.syspath, cAttrs.name, NOTMT (cAttrs.type), AF_NOSTRING); X } X X /* write owner */ X fprintf (tmpFile, X "%s %s %s\n", AF_OWNID, cAttrs.ownerName, cAttrs.ownerHost); X X /* write predecessor of busy version */ X if (busyEx) X { X fprintf (tmpFile, "%s %d %d\n", AF_PRDID, X revList[0].predGen, revList[0].predRev); X } X else X fprintf (tmpFile, "%s %d %d\n", AF_PRDID, AF_NOVNUM, AF_NOVNUM); X X /* write locker of busy version */ X fprintf (tmpFile, "%s %s %s %d\n", AF_LOCKID, X NOTMT (revList[0].lockerName), NOTMT (revList[0].lockerHost), X revList[0].lockTime); X X X /* write list of version attributes */ X for (i=1; i <= cAttrs.noOfRevisions; i++) X { X /* write revision ID */ X fprintf (tmpFile, "%s %d %d %d %o %s\n", AF_REVID, X revList[i].generation, revList[i].revision, revList[i].state, X revList[i].mode, NOTMT (revList[i].variant)); X X /* write author */ X fprintf (tmpFile, "\t%s %s %s %s %s\n", AF_AUTHORID, X revList[i].authorName, revList[i].authorHost, X NOTMT (revList[i].lockerName), NOTMT (revList[i].lockerHost)); X X /* write dates */ X fprintf (tmpFile, "\t%s %ld %ld %ld %ld %ld\n", AF_DATEID, X revList[i].modTime, revList[i].accessTime, X revList[i].statChangeTime, revList[i].saveTime, X revList[i].lockTime); X X /* write kind of representation and tree connects */ X fprintf (tmpFile, "\t%s %d %ld %ld %d %d %d %d\n", AF_REPRID, X revList[i].representation, revList[i].fileSize, X revList[i].deltaSize, revList[i].succGen, revList[i].succRev, X revList[i].predGen, revList[i].predRev); X } X X /* write user defined attributes */ X fprintf (tmpFile, "%s\n", AF_UDASEG); X X for (i=0; i <= cAttrs.noOfRevisions; i++) X { X fprintf (tmpFile, "%s %d %d\n", AF_UDAID, X udaList[i].generation, udaList[i].revision); X j=0; X while (udaList[i].uda[j]) X fprintf (tmpFile, "%s%c", udaList[i].uda[j++], '\0'); X if (j==0) /* if no user defined attribute has been written */ X (void) putc ('\0', tmpFile); X (void) putc ('\0', tmpFile); X (void) putc ('\n', tmpFile); X } X (void) fclose (tmpFile); X /* release attrIn */ X (void) free (attrIn.string); X attrIn.string = (char *)0; X attrIn.length = 0; X attrIn.curPos = 0; X X X /* open datatmpfile */ X (void) strcpy (datTmpFilename, arFilename); X datTmpFilename[strlen(datTmpFilename)-sizeof(char)] = AF_DATATMP; X if ((tmpFile = fopen (datTmpFilename, "w")) == (FILE *)0) X { X fprintf (stderr, "cannot open tmp file\n"); X cleanup (); X } X X fprintf (tmpFile, "%s %d\n", AF_DATAHEADER, AF_ARCURVERS); X X for (i=0; i < cAttrs.noOfRevisions; i++) X { X fprintf (tmpFile, "%s %d %d %ld\n", AF_NOTEID, X noteList[i].generation, noteList[i].revision, noteList[i].size); X (void) fwrite (noteList[i].contents, sizeof(char), (Size_t)(noteList[i].size - sizeof(char)), tmpFile); X (void) putc ('\n', tmpFile); X X fprintf (tmpFile, "%s %d %d %d %ld\n", AF_DATAID, X dataList[i].generation, dataList[i].revision, X dataList[i].representation, dataList[i].size); X X (void) fwrite (dataList[i].contents, sizeof(char), (Size_t)dataList[i].size, tmpFile); X } X (void) fclose (tmpFile); X /* release dataIn */ X (void) free (dataIn.string); X dataIn.string = (char *)0; X dataIn.length = 0; X dataIn.curPos = 0; X X X /* test, if archive files are changed -- if not, exit */ X (void) sprintf (commandLine, "cmp -s %s %s\0", arFilename, arTmpFilename); X if (system (commandLine) == 0) /* if files are identical */ X { X (void) sprintf (commandLine, "cmp -s %s %s\0", datFilename, datTmpFilename); X if (system (commandLine) == 0) X { X (void) af_unlink (arTmpFilename); X (void) af_unlink (datTmpFilename); X (void) af_unlink (lckFilename); X fprintf (stdout, "*** archive files ok ! -- unchanged ***\n"); X return (AF_OK); X } X } X if (NORMAL <= givenVLevel) X { X fprintf (stdout, "archive files for %s inconsistent - fix ? (y/n) ", X af_unixname ((char *)0, cAttrs.name, cAttrs.type)); X confirm = askConfirm ("y"); X } X else X confirm = TRUE; X X if (!confirm) X { X (void) af_unlink (arTmpFilename); X (void) af_unlink (datTmpFilename); X (void) af_unlink (lckFilename); X fprintf (stdout, "*** No archive files written ***\n"); X return (AF_OK); X } X X fprintf (stdout, "*** Write new archive files ***\n"); X X (void) af_unlink (arFilename); X if (af_syslink (arTmpFilename, arFilename) == ERROR) X fprintf (stderr,"cannot create new archive file -- preserving tmp file\n"); X X (void) af_uchmod (arFilename, AF_ARCHMODE); X (void) af_unlink (arTmpFilename); X X (void) af_unlink (datFilename); X if (af_syslink (datTmpFilename, datFilename) == ERROR) X fprintf (stderr,"cannot create new archive file -- preserving tmp file\n"); X (void) af_uchmod (datFilename, AF_ARCHMODE); X (void) af_unlink (datTmpFilename); X (void) af_unlink (lckFilename); X X return (AF_OK); X} X X/*=========================================================================== X * askConfirm -- ask for confirmation X * X *==========================================================================*/ X XLOCAL askConfirm (expAnswer) X char *expAnswer; X{ X char strBuf[256], answer[10], *cp; X X (void) fflush (stdin); X printf ("[%s] ", expAnswer); X strBuf[0] = '\0'; X answer[0] = '\0'; X (void) gets (strBuf); X (void) sscanf (strBuf, "%s", answer); X if (answer[0] == '\0') return TRUE; /* assumption acknowledged */ X cp = answer; X while (*cp ? (*cp++ |= ' ') : 0); /* make sure answer is lowercase */ X return !strncmp (expAnswer, answer, strlen (expAnswer)); X} X X/*=========================================================================== X * lookup, netItem, itemCmp X * Functions for random positioning in input stream X * X *==========================================================================*/ X Xlookup (input, searchStr, pos) X Input *input; X char *searchStr; X int pos; X{ X if (pos == 0) X input->curPos = 0; X if (input->curPos == input->length) X return (-1); X X while (itemCmp (&(input->string[input->curPos]), X searchStr, strlen (searchStr))) X { X input->curPos++; X while (input->string[input->curPos] != searchStr[0]) X { X input->curPos++; X if (input->curPos == input->length) X return (-1); X } X } X return (input->curPos); X} X XnextItem (input) X Input *input; X{ X if (input->curPos == input->length) X return (-1); X /* search next white space */ X while ((input->string[input->curPos] != ' ') && X (input->string[input->curPos] != '\t') && X (input->string[input->curPos] != '\n')) X if (++input->curPos == input->length) X return (-1); X X /* skip white spaces */ X while ((input->string[input->curPos] == ' ') || X (input->string[input->curPos] == '\t') || X (input->string[input->curPos] == '\n')) X if (++input->curPos == input->length) X return (-1); X X return (input->curPos); X} X XnextLine(input) X Input *input; X{ X if (input->curPos == input->length) X return (-1); X /* search beginning of next line */ X while (input->string[input->curPos] != '\n') X if (++input->curPos == input->length) X return (-1); X X /* skip newline */ X if (++input->curPos == input->length) X return (-1); X X return (input->curPos); X} X Xchar *itemCopy (str1, str2) X char *str1, *str2; X{ X if (!strncmp (str2, AF_NOSTRING, 2)) X { X str1[0] = '\0'; X return (str1); X } X X while (*str1 = *str2) X { X if ((*str2 ==' ') || (*str2 =='\t') || (*str2 =='\n')) X { *str1 = '\0'; return (str1); } X str1++; X str2++; X } X return (str1); X} X XitemCmp (baseStr, searchStr, len) X char *baseStr, *searchStr; X int len; X{ X int i=0; X while (baseStr[i] == searchStr[i]) X { X i++; X if (i == len) X { X if ((baseStr[i] == ' ') || (baseStr[i] == '\t') || X (baseStr[i] == '\0') || (baseStr[i] == '\n')) X return (0); X else X return (1); X } X } X return (1); X} X X/*========================================================================= X * verifyString, verifyInt, verifyDate X * complainString X * X *=========================================================================*/ X Xchar *verifyString (name, input, level) X char *name; X Input input; X int level; X{ X static char value[256]; X X (void) itemCopy (value, &input.string[input.curPos]); X X if (level <= givenVLevel) X { X fprintf (stdout, "assume %s to be: ->%s<-, ok ? (y/n) ", name, value); X if (askConfirm ("y")) X goto exit; X fprintf (stdout, "enter new %s (*0* for empty string): ", name); X (void) fscanf (stdin, "%s", value); X if (!strncmp (value, "*0*", 3)) X return ((char *)0); X } X exit: X if (value[0]) X return (value); X else X return ((char *)0); X} X Xchar *complainString (name, string1, string2, level) X char *name, *string1, *string2; X int level; X{ X if (level <= givenVLevel) X { X fprintf (stdout, X "Inconsistency: value for %s is ->%s<- (should be ->%s<-), %s", X name, string1, string2, "fix ? (y/n) "); X if (askConfirm ("y")) X return (string1); X } X return (string2); X} X XverifyInt (name, input, level) X char *name; X Input input; X int level; X{ X int value; X X value = atoi (&input.string[input.curPos]); X X if (level <= givenVLevel) X { X fprintf (stdout, "assume %s to be: ->%d<-, ok ? (y/n) ", name, value); X if (askConfirm ("y")) X return (value); X fprintf (stdout, "enter new %s: ", name); X (void) fscanf (stdin, "%d", value); X } X return (value); X} X XverifyOct (name, input, level) X char *name; X Input input; X int level; X{ X int value; X X (void) sscanf (&input.string[input.curPos], "%o", &value); X X if (level <= givenVLevel) X { X fprintf (stdout, "assume %s to be: ->%o<-, ok ? (y/n) ", name, value); X if (askConfirm ("y")) X return (value); X fprintf (stdout, "enter new %s: ", name); X (void) fscanf (stdin, "%o", value); X } X return (value); X} X XverifyDate (name, input, level) X char *name; X Input input; X int level; X{ X int value; X X value = atoi (&input.string[input.curPos]); X X if (level <= givenVLevel) X { X fprintf (stdout, "assume %s to be: ->%d<-, ok ? (y/n) ", name, value); X if (askConfirm ("y")) X return (value); X fprintf (stdout, "enter new date: "); X (void) fscanf (stdin, "%d", value); X } X return (value); X} X END_OF_FILE if test 30386 -ne `wc -c <'src/afs/afsrepair.c'`; then echo shar: \"'src/afs/afsrepair.c'\" unpacked with wrong size! fi # end of 'src/afs/afsrepair.c' fi echo shar: End of archive 26 \(of 33\). cp /dev/null ark26isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 33 archives. rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.