v19i039: A software configuration management system, Part26/33
Rich Salz
rsalz at uunet.uu.net
Wed Jun 7 07:48:35 AEST 1989
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 at 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 at coma.uucp or shape at 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 at 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 at uunet.uu.net.
More information about the Comp.sources.unix
mailing list