|
|
1.1 root 1: # include <stdio.h>
2: # include <ingres.h>
3: # include <aux.h>
4: # include <catalog.h>
5: # include <access.h>
6: # include <batch.h>
7: # include <opsys.h>
8: # include <lock.h>
9: # include <symbol.h>
10: # include <resp.h>
11: # include <sys/dir.h>
12: # include <sccs.h>
13: # include <signal.h>
14:
15: SCCSID(@(#)restore.c 7.5 7/7/83)
16:
17: /*
18: ** INGRES crash recovery processor
19: ** to recover a database you must be the dba or the ingres superuser
20: ** RESTORE attempts to complete updates from batch files left in a
21: ** database. After finishing all the batch files it calls PURGE.
22: */
23:
24: # ifndef PURGE
25: # ifdef xV7_UNIX
26: # define PURGE "purge"
27: # else xV7_UNIX
28: # define PURGE "/usr/bin/purge"
29: # endif xV7_UNIX
30: # endif PURGE
31:
32: /* first file to close on error */
33: # define CLOSEFILES 3
34:
35: extern int Status;
36: extern char *Usercode;
37: char Utemp[2];
38: char *Fileset;
39: char Berror; /* batch error */
40: char Error;
41: extern char Ask;
42: extern char Superuser;
43: extern char All;
44: extern char Qrymod;
45: int Direc = CLOSEFILES - 1;
46: extern int Wait_action;
47: short tTvect[100];
48: short tTdbu[100];
49: struct resp Resp;
50:
51:
52: #ifndef DIRBLKSIZ
53: typedef DIR FILE;
54: #endif
55: extern DIR *opendir();
56: extern struct direct *readdir();
57:
58: main(argc, argv)
59: int argc;
60: char *argv[];
61: {
62: register int fd;
63: register int i;
64: register char *dbname;
65: extern char *Proc_name;
66: auto int stat;
67: extern (*ExitFn)();
68: extern rubproc(), exit();
69: char *nargv[20];
70: char **avp;
71: char **fvp;
72: extern char *Flagvect[];
73: extern char *getnxtdb();
74: char *lookucode();
75:
76: Proc_name = "RESTORE";
77:
78: /* check param list */
79: argv[argc] = NULL;
80: # ifdef xTTR1
81: tTrace(argv, 'T', tTvect, 100);
82: tTrace(argv, 'Z', tTdbu, 100);
83: # endif
84:
85: initialize(argc, argv);
86:
87: /* do it to it */
88: ExitFn = rubproc;
89: signal(SIGQUIT, exit);
90: while (dbname = getnxtdb())
91: {
92: Berror = Error = 0;
93:
94: /* first restart point for this database */
95: setexit();
96: if (Error) /* if set, will cause skip to next database */
97: continue;
98: printf("\nRestoring database: %s\t", dbname);
99:
100: acc_init();
101: printf("owner: %s\n", lookucode(Admin.adhdr.adowner));
102:
103: /* set exclusive lock on data base */
104: db_lock(M_EXCL);
105:
106: restore(); /* recover batch update and modify files */
107: printf("\tRecovery of batch files complete.\n");
108:
109: /*
110: ** second restart point for this database
111: ** the batch files are completed and now the system
112: ** relations need checking
113: */
114: setexit();
115: if (Error) /* again, may cause skipping to next database */
116: continue;
117: printf("\tChecking system relations\n");
118:
119:
120: /*
121: ** check the relation relation
122: ** this will mean checking for file existence,
123: ** and whether the relstat bits are supported by
124: ** the information in the other catalogs.
125: */
126: checkrel();
127:
128: /*
129: ** check the attribute relation
130: ** for each tuple in the attribute relation, there must
131: ** be a tuple in the relation relation.
132: ** the indexes relation doesn't need to be reverse checked
133: ** into the relation relation since the order things are
134: ** handled else where in the system is in the correct
135: ** order. All the other catalogs need to be reverse checked.
136: */
137: checkatts();
138:
139: /* only check the qrymod catalogs if qrymod is turned on */
140: if (Qrymod)
141: {
142: /* check the protect relation */
143: checkprotect();
144:
145: /* check the integrities relation */
146: checkinteg();
147:
148: /*
149: ** check the tree relation
150: ** must be done last since it depends upon
151: ** a state of the system relations provided
152: ** by the other check... routines.
153: */
154: checktree();
155: }
156:
157: /* finished, close up the database and go on to the next */
158: closecatalog(TRUE);
159: unldb();
160: acc_close();
161:
162: /* call PURGE if no errors */
163: if (!Berror && !Error)
164: {
165: printf("\tCalling purge: ");
166: fflush(stdout);
167: if ((i = fork()) == -1)
168: printf("Can't fork\n");
169: else if (!i)
170: {
171: avp = nargv;
172: *avp++ = "Purge";
173: for (fvp = Flagvect; *fvp != NULL; )
174: *avp++ = *fvp++;
175: *avp++ = dbname;
176: *avp++ = 0;
177: # ifdef xTTR2
178: if (tTf(0, 1))
179: for (avp = nargv, i = 0; *avp != NULL; avp++, i++)
180: printf("%d %s\n", i, *avp);
181: # endif
182: for (i=3; i <= NOFILE; i++)
183: close(i);
184: execv(ztack(Pathname, "/bin/purge"), nargv);
185: # ifdef xV7_UNIX
186: execvp(PURGE, nargv);
187: # else xV7_UNIX
188: execv(PURGE, nargv);
189: # endif xV7_UNIX
190: printf("Cannot exec %s\n", PURGE);
191: exit(-1);
192: }
193: else
194: wait(&stat);
195: }
196: }
197: }
198: /*
199: ** RESTORE -- find the batch files and process them
200: */
201: restore()
202: {
203: DESC descr;
204: register DIR *dirp;
205: register struct direct *dp;
206: register int i;
207: extern char *Fileset;
208: extern uperr(), (*ExitFn)();
209: int (*tmpfn)();
210: char *lookucode();
211: char *fname;
212: # ifndef DIRBLKSIZ
213: char fnambuf[DIRSIZ+1];
214: # endif
215:
216: if ( (dirp = opendir(".")) == NULL )
217: syserr("Can't open data base directory");
218: bmove(Usercode, Utemp, 2);
219: Batch_recovery = 1;
220: tmpfn = ExitFn;
221: ExitFn = uperr;
222:
223: /* restart point */
224: setexit();
225: for ( dp = readdir(dirp) ; dp != NULL ; dp = readdir(dirp) )
226: {
227: # ifdef DIRBLKSIZ
228: fname = dp->d_name;
229: # else
230: strncpy(fnambuf, dp->d_name, DIRSIZ);
231: fnamebuf[DIRSIZ] = '\0';
232: fname = fnamebuf;
233: # endif
234: if ( !strcmp(".",fname) || !strcmp("..",fname) )
235: continue;
236: if (bequal("_SYSbatch", fname, 9))
237: {
238: Fileset = &fname[9];
239: Batch_fp = open(batchname(), 0);
240: Batch_cnt = BATCHSIZE;
241: getbatch(&Batchhd, sizeof(Batchhd));
242: printf("\tFound batch file: %s\n", fname);
243: printf("\tRelation: %s\tUser: %s\n", Batchhd.rel_name,
244: lookucode(Batchhd.userid));
245: close(Batch_fp);
246: bmove(Batchhd.userid, Usercode, 2);
247: if(ask("\tUpdate? "))
248: update();
249: }
250: if (bequal(MODBATCH, fname, sizeof(MODBATCH) - 1))
251: {
252: Fileset = &fname[sizeof(MODBATCH) - 1];
253: if ((Batch_fp = open(dp->d_name, 0)) < 0)
254: syserr("Can't open %s", dp->d_name);
255: Batch_cnt = 0;
256: if((i = getbatch(&descr, sizeof(descr))) != sizeof(descr))
257: syserr(" cant read %d",i);
258: printf("\tFound incomplete modify of %.12s, user = %s\n",
259: descr.reldum.relid, lookucode(descr.reldum.relowner));
260:
261: bmove(descr.reldum.relowner, Usercode, sizeof(descr.reldum.relowner));
262: close(Batch_fp);
263: if (ask("\tComplete? "))
264: modupdate();
265: }
266: }
267: bmove(Utemp, Usercode, 2);
268: ExitFn = tmpfn;
269: closedir(dirp);
270: }
271: /*
272: ** handles syserr's in the update processor
273: */
274: uperr()
275: {
276:
277: if (Batch_fp)
278: close(Batch_fp);
279: Berror++;
280: reset();
281: }
282:
283:
284:
285: /*
286: ** Catch errors in other places
287: */
288: rubproc()
289: {
290: register int i;
291: register struct desxx *p;
292: extern struct desxx Desxx[];
293: extern int Acc_init;
294:
295: Error++;
296: printf("Unable to restore!\n");
297:
298: /* restore user code */
299: bmove(Utemp, Usercode, sizeof Utemp);
300:
301: /* close all possible files */
302: if (Acc_init)
303: {
304: closecatalog(TRUE);
305: unldb();
306: acc_close();
307: }
308:
309: /* close users file */
310: getuser(0);
311:
312: /* get everything else */
313: for (i = Direc + 1; i <= NOFILE; i++)
314: close(i);
315: }
316: /*
317: ** looks up user by usercode in users file
318: */
319: char *
320: lookucode(ucode)
321: char ucode[2];
322: {
323: static char buf[MAXLINE + 1];
324: register char *p;
325:
326: if (getuser(ucode, buf))
327: syserr("cannot identify user %.2s", ucode);
328: for (p = buf; *p != ':'; p++);
329: *p = 0;
330: return (buf);
331: }
332: /*
333: ** CHECKATTS
334: ** Checks that all attributes are in a relation
335: */
336: checkatts()
337: {
338: extern DESC Reldes, Attdes;
339: register int i;
340: register int once;
341: TID tid, limtid, reltid;
342: char key[MAXTUP];
343: struct attribute atttup;
344: struct relation reltup;
345: char lastrel[MAXNAME + 2];
346:
347: once = 0;
348: opencatalog("relation", 2);
349: opencatalog("attribute", 2);
350: clearkeys(&Attdes);
351: lastrel[0] = '\0';
352: if (find(&Attdes, NOKEY, &tid, &limtid))
353: syserr("CHECKATT: find");
354:
355: while (!(i = get(&Attdes, &tid, &limtid, &atttup, TRUE)))
356: {
357: if (bequal(atttup.attrelid, lastrel, MAXNAME + 2))
358: continue;
359:
360: clearkeys(&Reldes);
361: setkey(&Reldes, key, atttup.attrelid, ATTRELID);
362: setkey(&Reldes, key, atttup.attowner, ATTOWNER);
363:
364: if (i = getequal(&Reldes, key, &reltup, &reltid))
365: {
366: if (i < 0)
367: syserr("ATTCHECK: getequal");
368: if (!once++)
369: printf("\tNo relation for attribute(s):\n");
370: printf("\t");
371: printup(&Attdes, &atttup);
372: if (ask("\tDelete?"))
373: if (i = delete(&Attdes, &tid))
374: syserr("ATTCHECK: delete=%d", i);
375: }
376: else
377: bmove(atttup.attrelid, lastrel, MAXNAME + 2);
378: }
379:
380: if (i < 0)
381: syserr("ATTCHECK: get=%d", i);
382: }
383: /*
384: ** CHECKREL -- check relation relation against every thing else
385: **
386: ** Each tuple in the relation relation is read and each verifiable
387: ** characteristic is checked for accuracy. Including the existence
388: ** of the physical file (if not a view), the qrymod definition if
389: ** appropriate and the secondary indexing.
390: */
391:
392: checkrel()
393: {
394: extern DESC Reldes;
395: register int i, j;
396: struct relation rel;
397: TID rtid, limtid;
398: char fname[MAXNAME + 3];
399:
400: /* setup for search of entire relation */
401: opencatalog("relation", 2);
402: clearkeys(&Reldes);
403: if (find(&Reldes, NOKEY, &rtid, &limtid))
404: syserr("CHECKREL: find");
405:
406: /* loop until all tuples checked */
407: for (;;)
408: {
409: /* for each tuple in the rel-rel */
410: i = get(&Reldes, &rtid, &limtid, &rel, TRUE);
411: if (i > 0)
412: break; /* have finished */
413: if (i < 0)
414: syserr("CHECKREL: get=%d", i);
415:
416: /* if not a view, check for the file */
417: if ((rel.relstat & S_VIEW) != S_VIEW)
418: {
419: ingresname(rel.relid, rel.relowner, fname);
420: if ((j = open(fname, 2)) == -1)
421: {
422: printf("\tNo file for:\n\t");
423: printup(&Reldes, &rel);
424: if (ask("\tDelete tuple? "))
425: {
426: if(j = delete(&Reldes, &rtid))
427: syserr("CHECKREL: delete=%d", j);
428: continue;
429: }
430: else
431: /* don't call purge the file might still be there */
432: Error++;
433: }
434: else
435: close(j);
436: }
437:
438: /* does it think that it has a secondary index */
439: if (rel.relindxd > 0)
440: {
441: /* does it really have an index? */
442: if (!hasndx(rel.relid, rel.relowner))
443: {
444: /* no, should it be fixed */
445: printf("\tNo indexes entry for primary relation:\n\t");
446: printup(&Reldes, &rel);
447: if (ask("\tAdjust? "))
448: {
449: /* fix up relation relation entry */
450: rel.relindxd = 0;
451: if (i = replace(&Reldes, &rtid, &rel, FALSE))
452: syserr("CHECKREL: replace=%d", i);
453: }
454: }
455: }
456:
457: /* does it think that it is a secondary index */
458: if (rel.relindxd < 0)
459: {
460: /* check to make sure */
461: if (!isndx(rel.relid, rel.relowner))
462: {
463: /* none, what should be done? */
464: printf("\tNo indexes entry for index:\n\t");
465: printup(&Reldes, &rel);
466: if(ask("\tDelete? "))
467: {
468: /*
469: ** get rid of rel-rel tuple for
470: ** secondary index,
471: ** purge will do rest of
472: ** removal if necessary
473: */
474: if (i = delete(&Reldes, &rtid))
475: syserr("CHECKREL: delete=%d", i);
476: continue; /* go on to next tuple */
477: }
478: }
479: }
480:
481: /* if qrymod on in the database, check those catalogs too */
482: if (Qrymod)
483: {
484: /*
485: ** cannot deal with S_VBASE since there is no way to
486: ** find the tree catalog entries without decoding the
487: ** 'treetree' fields.
488: **
489: ** check to see if this is a view
490: */
491: if ((rel.relstat & S_VIEW) && !havetree(rel.relid, rel.relowner, mdVIEW))
492: {
493: /* no entry, should it be fixed? */
494: printf("\tNo tree entry for this view:\n\t");
495: printup(&Reldes, &rel);
496: if (ask("\tDelete tuple? "))
497: {
498: /* delete relation entry */
499: if (i = delete(&Reldes, &rtid))
500: syserr("CHECKREL: delete=%d", i);
501: continue; /* skip to next entry in rel-rel */
502: }
503: }
504:
505: /* check to see if has 'protect' entry */
506: if ((rel.relstat & S_PROTUPS) && !isprot(rel.relid, rel.relowner, -1))
507: {
508: /* no entry, should the bit be reset */
509: printf("\tNo protect entry for:\n\t");
510: printup(&Reldes, &rel);
511: if (ask("\tAdjust? "))
512: {
513: /* fix the bit */
514: rel.relstat &= ~S_PROTUPS;
515: if (i = replace(&Reldes, &rtid, &rel, FALSE))
516: syserr("CHECKREL: replace=%d", i);
517: }
518: }
519:
520: /* check to see if has 'integrities entry */
521: if ((rel.relstat & S_INTEG) && !isinteg(rel.relid, rel.relowner, -1))
522: {
523: /* no entry, should bit be reset */
524: printf("\tNo integrities entry for:\n\t");
525: printup(&Reldes, &rel);
526: if (ask("\tAdjust? "))
527: {
528: /* fix up the bit */
529: rel.relstat &= ~S_INTEG;
530: if (i = replace(&Reldes, &rtid, &rel, FALSE))
531: syserr("CHECKREL: replace=%d", i);
532: }
533: }
534: }
535: }
536: }
537: /*
538: ** HASNDX -- the relation indicated an index, check it out
539: **
540: ** will search the index relation for all secondary indexes
541: ** and check to see that each secondary index named has an
542: ** entry in the relation relation.
543: */
544: hasndx(id, own)
545: char id[MAXNAME];
546: char own[2];
547: {
548: register int hasindexes;
549: register int i, j;
550: extern DESC Reldes, Inddes;
551: TID rtid;
552: struct relation rkey, rel;
553: TID itid, ihitid;
554: struct index ikey, ind;
555:
556: /* presume that answer is negative */
557: hasindexes = FALSE;
558:
559: /* set search for all tuples with 'id' and 'own' in indexes */
560: opencatalog("indexes", 2);
561: clearkeys(&Inddes);
562: setkey(&Inddes, &ikey, id, IRELIDP);
563: setkey(&Inddes, &ikey, own, IOWNERP);
564: if (find(&Inddes, EXACTKEY, &itid, &ihitid, &ikey))
565: syserr("HASNDX: find");
566:
567: /* for each possible tuple in the indexes relation */
568: for (;;)
569: {
570: i = get(&Inddes, &itid, &ihitid, &ind, TRUE);
571:
572: /* check return values */
573: if (i < 0)
574: syserr("HASNDX: get=%d\n", i);
575: if (i > 0)
576: break; /* finished */
577:
578: /* if key doesn't match, skip to next tuple */
579: if(kcompare(&Inddes, &ikey, &ind))
580: continue;
581: hasindexes = TRUE;
582:
583: /* verify that primary entry for sec index exists */
584: opencatalog("relation", 2);
585: clearkeys(&Reldes);
586: setkey(&Reldes, &rkey, ind.irelidi, RELID);
587: setkey(&Reldes, &rkey, ind.iownerp, RELOWNER);
588: if (j = getequal(&Reldes, &rkey, &rel, &rtid, FALSE))
589: {
590: /* one doesn't exist, should we ignore it */
591: if (j < 0)
592: syserr("HASNDX: getequal=%d", j);
593: printf("\tNo secondary index for indexes entry:\n\t");
594: printup(&Inddes, &ind);
595: if (ask("\tDelete? "))
596: {
597: /* get rid of bad entry in indexes relation */
598: if (j = delete(&Inddes, &itid))
599: syserr("HASNDX: delete=%d", j);
600: hasindexes = FALSE;
601: }
602: }
603: }
604: return (hasindexes);
605: }
606: /*
607: ** ISNDX -- so you think that you're a secondary index, I'll check it out.
608: **
609: ** searches the indexes relation for the name of the primary relation
610: ** and check to see if the primary is real. Will also update the
611: ** 'relindxd' field of the primary if it isn't correct.
612: */
613: isndx(id, own)
614: char id[MAXNAME];
615: char own[2];
616: {
617: register int isindex;
618: register int i;
619: extern DESC Inddes;
620: TID itid;
621: struct index ind, ikey;
622: extern DESC Reldes;
623: TID rtid;
624: struct relation rel, rkey;
625:
626: /* search for tuple in index relation, should only be one */
627: opencatalog("indexes", 2);
628: clearkeys(&Inddes);
629: setkey(&Inddes, &ikey, id, IRELIDI);
630: setkey(&Inddes, &ikey, own, IOWNERP);
631: if (i = getequal(&Inddes, &ikey, &ind, &itid))
632: {
633: /* there isn't a tuple in the indexes relation */
634: if (i < 0)
635: syserr("ISNDX: getequal=%d", i);
636: isindex = FALSE;
637: }
638: else
639: {
640: isindex = TRUE;
641:
642: /* there is a tuple in the indexes relation */
643: opencatalog("relation", 2);
644: clearkeys(&Reldes);
645: setkey(&Reldes, &rkey, ind.irelidp, RELID);
646: setkey(&Reldes, &rkey, ind.iownerp, RELOWNER);
647:
648: /* see if the primary relation exists */
649: if (i = getequal(&Reldes, &rkey, &rel, &rtid))
650: {
651: /* no it doesn't */
652: if (i < 0)
653: syserr("ISNDX: getequal=%d", i);
654:
655: /* what should be done about it */
656: printf("\tNo primary relation for index:\n\t");
657: printup(&Inddes, &ind);
658: if (ask("\tDelete?"))
659: {
660: /*
661: ** get rid of indexes tuple,
662: ** a FALSE return will also get rid
663: ** of the relation tuple
664: */
665: if (i = delete(&Inddes, &itid))
666: syserr("ISNDX: delete=%d", i);
667: isindex = FALSE;
668: }
669: }
670: else if (!(rel.relindxd > 0) || (rel.relstat & S_INDEX) == S_INDEX)
671: {
672: /*
673: ** the primary tuple exists but isn't marked correctly
674: */
675: printf("\t%.12s is index for:\n\t", rel.relid);
676: printup(&Reldes, &rel);
677: if (ask("\tMark as indexed? "))
678: {
679: rel.relstat |= S_INDEX;
680: rel.relindxd = SECBASE;
681: if (i = replace(&Reldes, &rtid, &rel, FALSE))
682: syserr("ISNDX: replace=%d", i);
683: }
684: }
685: }
686: return (isindex);
687: }
688: /*
689: ** HAVETREE -- check tree catalog for an entry with right name and owner
690: **
691: ** The 'id' and 'own' parameters are used to look in the tree catalog
692: ** for at least on tuple that also has a 'treetype' of 'mdvalue'.
693: **
694: ** If any tuples are found, havetree returns TRUE, else FALSE
695: */
696:
697: havetree(id, own, mdvalue)
698: char id[MAXNAME];
699: char own[2];
700: int mdvalue;
701: {
702: extern DESC Treedes;
703: register int i;
704: struct tree tkey, trent;
705: TID ttid, thitid;
706:
707: /* search tree relation for tuple that matches */
708: opencatalog("tree", 2);
709: clearkeys(&Treedes);
710: setkey(&Treedes, &tkey, id, TREERELID);
711: setkey(&Treedes, &tkey, own, TREEOWNER);
712: setkey(&Treedes, &tkey, &mdvalue, TREETYPE);
713:
714: /* set search limit tids from the key */
715: if (i = find(&Treedes, EXACTKEY, &ttid, &thitid, &tkey))
716: syserr("HAVETREE: find=%d", i);
717:
718: for (;;)
719: {
720: i = get(&Treedes, &ttid, &thitid, &trent, TRUE);
721:
722: if (i < 0)
723: syserr("HAVETREE: get=%d", i);
724: if (i > 0)
725: break; /* finished, didn't find one */
726:
727: if (kcompare(&Treedes, &tkey, &trent) == 0)
728: return (TRUE);
729: }
730: return (FALSE);
731: }
732: /*
733: ** ISPROT -- check in the 'protect' catalog for a tuple with right name, owner
734: **
735: ** search the 'protect' catalog for at least on tuple with matches the
736: ** values in the parameters. If 'treeid' is >= 0 then it is not used as
737: ** a key.
738: **
739: ** if one is found, returns TRUE, otherwise, returns FALSE
740: */
741:
742: isprot(id, own, treeid)
743: char id[MAXNAME];
744: char own[2];
745: int treeid;
746: {
747: extern DESC Prodes;
748: register int i;
749: struct protect pkey, pent;
750: TID ptid, phitid;
751:
752: /* search the protect relation for at least on matching tuple */
753: opencatalog("protect", 2);
754: clearkeys(&Prodes);
755: setkey(&Prodes, &pkey, id, PRORELID);
756: setkey(&Prodes, &pkey, own, PRORELOWN);
757: if (treeid >= 0)
758: setkey(&Prodes, &pkey, &treeid, PROTREE);
759:
760: /* set search limit tids from the keys */
761: if (i = find(&Prodes, EXACTKEY, &ptid, &phitid, &pkey))
762: syserr("ISPROT: find=%d", i);
763:
764: for (;;)
765: {
766: i = get(&Prodes, &ptid, &phitid, &pent, TRUE);
767:
768: if (i < 0)
769: syserr("ISPROT: get=%d", i);
770: if (i > 0)
771: break; /* finished, didn't find one */
772:
773: if (kcompare(&Prodes, &pkey, &pent) == 0)
774: return (TRUE);
775: }
776: return (FALSE);
777: }
778: /*
779: ** ISINTEG -- check for a tuple in 'integrities'
780: **
781: ** searches the integrities relation for 'id' and 'own'.
782: **
783: ** returns TRUE if one is found, else FALSE
784: */
785:
786: isinteg(id, own, treeid)
787: char id[MAXNAME];
788: char own[2];
789: int treeid;
790: {
791: extern DESC Intdes;
792: register int i;
793: struct integrity inkey, integ;
794: TID intid, inhitid;
795:
796: /* search the entire relation for a tuple that matches */
797: opencatalog("integrities", 2);
798: clearkeys(&Intdes);
799: setkey(&Intdes, &inkey, id, INTRELID);
800: setkey(&Intdes, &inkey, own, INTRELOWNER);
801: if (treeid >= 0)
802: setkey(&Intdes, &inkey, &treeid, INTTREE);
803:
804: /* set the search limit tids from the key */
805: if (i = find(&Intdes, EXACTKEY, &intid, &inhitid, &inkey))
806: syserr("ISINTEG: find=%d", i);
807:
808: for (;;)
809: {
810: i = get(&Intdes, &intid, &inhitid, &integ, TRUE);
811:
812: if (i < 0)
813: syserr("ISINTEG: get=%d", i);
814: if (i > 0)
815: break; /* finished, didn't find one */
816:
817: if (kcompare(&Intdes, &inkey, &integ) == 0)
818: return (TRUE);
819: }
820: return (FALSE);
821: }
822: /*
823: ** CHECKTREE -- check the tree catalog against the others
824: */
825:
826: checktree()
827: {
828: extern DESC Treedes, Reldes;
829: register int i;
830: struct tree tkey, trent;
831: TID ttid, thitid;
832: struct relation rkey, rel;
833: TID rtid;
834:
835: /* search the entire tree catalog */
836: opencatalog("tree", 2);
837: clearkeys(&Treedes);
838: if (i = find(&Treedes, NOKEY, &ttid, &thitid))
839: syserr("CHECKTREE: find=%d", i);
840:
841: /* for each tuple in 'tree' */
842: for (;;)
843: {
844: i = get(&Treedes, &ttid, &thitid, &trent, TRUE);
845: if (i > 0)
846: break; /* finished */
847: if (i < 0)
848: syserr("CHECKTREE: get=%d", i);
849:
850: /* verify that a tuple exists in the relation relation */
851: opencatalog("relation", 2);
852: clearkeys(&Reldes);
853: setkey(&Reldes, &rkey, trent.treerelid, RELID);
854: setkey(&Reldes, &rkey, trent.treeowner, RELOWNER);
855:
856: /* fetch the tuple */
857: if (i = getequal(&Reldes, &rkey, &rel, &rtid))
858: {
859: /*
860: ** Oops, a tuple doesn't exist in the relation
861: ** relation.
862: **
863: ** maybe it's just a fatal error
864: */
865: if (i < 0)
866: syserr("CHECKTREE: getequal=%d", i);
867:
868: /* not a fatal error, what to do about it? */
869: printf("\tNo relation tuple for:\n\t");
870: printup(&Treedes, &trent);
871: if (ask("\tDelete? "))
872: {
873: if (i = delete(&Treedes, &ttid))
874: syserr("CHECKTREE: delete=%d", i);
875: continue; /* go on to next tuple */
876: }
877: }
878: else
879: {
880: /*
881: ** Ah. A tuple does exist.
882: **
883: ** If the relstat bits are correct then we can stop
884: ** here since elsewhere the 'protect' and 'integrity'
885: ** entries were verified.
886: */
887: switch (trent.treetype)
888: {
889: case mdVIEW:
890: /* mere existence is sufficient */
891: break;
892:
893: case mdPROT:
894: if ((rel.relstat & S_PROTUPS) != S_PROTUPS)
895: {
896: printf("\tNo 'protect' entry for:\n\t");
897: deltup:
898: printup(&Treedes, &trent);
899: if (ask("\tDelete? "))
900: {
901: if (i = delete(&Treedes, &ttid))
902: syserr("CHECKTREE: delete=%d", i);
903: continue;
904: }
905: }
906: break;
907:
908: case mdINTEG:
909: if ((rel.relstat & S_INTEG) != S_INTEG)
910: {
911: printf("\tNo 'integrities' entry for:\n\t");
912: goto deltup;
913: }
914: break;
915:
916: default:
917: syserr("Unknown treetype: %d\n", trent.treetype);
918: }
919: }
920: }
921: }
922: /*
923: ** CHECKPROTECT
924: */
925:
926: checkprotect()
927: {
928: register int i;
929: extern DESC Reldes, Prodes;
930: struct protect pkey, pent;
931: TID ptid, phitid;
932: struct relation rkey, rel;
933: TID rtid;
934:
935: /* for each entry in the 'protect' relation */
936: opencatalog("protect", 2);
937: clearkeys(&Prodes);
938: if (i = find(&Prodes, NOKEY, &ptid, &phitid))
939: syserr("CHECKPROTECT: find=%d", i);
940:
941: for (;;)
942: {
943: i = get(&Prodes, &ptid, &phitid, &pent, TRUE);
944: if (i > 0)
945: break; /* finished */
946: if (i < 0)
947: syserr("CHECKPROTECT: get=%d", i);
948:
949: /* verify that a tuple exists in 'relation' */
950: opencatalog("relation", 2);
951: clearkeys(&Reldes);
952: setkey(&Reldes, &rkey, pent.prorelid, RELID);
953: setkey(&Reldes, &rkey, pent.prorelown, RELOWNER);
954:
955: /* fetch the tuple if possible */
956: if (i = getequal(&Reldes, &rkey, &rel, &rtid))
957: {
958: /*
959: ** Oops. A tuple doesn't exits in 'relation'
960: **
961: ** Maybe it's just a fatal error.
962: */
963: if (i < 0)
964: syserr("CHECKPROTECT: getequal=%d", i);
965:
966: /* not a fatal error, what to do? */
967: printf("\tNo relation for 'protect' entry:\n\t");
968: printup(&Prodes, &pent);
969: if (ask("\tRemove 'protect' entry? "))
970: {
971: if (i = delete(&Prodes, &ptid))
972: syserr("CHECKPROTECT: delete=%d", i);
973: continue; /* go on to next tuple */
974: }
975: }
976: else
977: {
978: /* 'relation' entry exists, check for the tree entry */
979: if (pent.protree >= 0)
980: {
981: if (!havetree(pent.prorelid, pent.prorelown, mdPROT))
982: {
983: /* no tuples in 'tree' */
984: printf("\tNo tree for:\n\t");
985: printup(&Prodes, &pent);
986: if (ask("\tDelete entry and fix relation status bits? "))
987: {
988: if (i = delete(&Prodes, &pent))
989: syserr("CHECKPROTECT: delete=%d", i);
990: rel.relstat &= ~S_PROTUPS;
991: if (i = replace(&Reldes, &rtid, &rel, FALSE))
992: syserr("CHECKPROTECT: replace=%d", i);
993: continue; /* go on to next tuple */
994: }
995: }
996: }
997: if ((rel.relstat & S_PROTUPS) != S_PROTUPS)
998: {
999: /* bits not set correctly */
1000: printf("\tIncorrect relation status bits for:\n\t");
1001: printup(&Reldes, &rel);
1002: if (ask("\tAdjust? "))
1003: {
1004: rel.relstat |= S_PROTUPS;
1005: if (i = replace(&Reldes, &rtid, &rel, FALSE))
1006: syserr("CHECKPROTECT: replace=%d", i);
1007: continue; /* go on to next tuple */
1008: }
1009: }
1010: }
1011: }
1012: }
1013: /*
1014: ** CHECKINTEG
1015: */
1016:
1017: checkinteg()
1018: {
1019: register int i;
1020: extern DESC Reldes, Intdes;
1021: struct integrity inkey, inent;
1022: TID intid, inhitid;
1023: struct relation rkey, rel;
1024: TID rtid;
1025:
1026: /* for each entry in 'integrities' */
1027: opencatalog("integrities", 2);
1028: clearkeys(&Intdes);
1029: if (i = find(&Intdes, NOKEY, &intid, &inhitid))
1030: syserr("CHECKINTEG: find=%d", i);
1031:
1032: for (;;)
1033: {
1034: i = get(&Intdes, &intid, &inhitid, &inent, TRUE);
1035: if (i > 0)
1036: break; /* finished */
1037: if (i < 0)
1038: syserr("CHECKINTEG: get=%d", i);
1039:
1040: /* verify that a tuple exists in 'relation' */
1041: opencatalog("relation", 2);
1042: clearkeys(&Reldes);
1043: setkey(&Reldes, &rkey, inent.intrelid, RELID);
1044: setkey(&Reldes, &rkey, inent.intrelowner, RELOWNER);
1045:
1046: /* fetch the tuple if possible */
1047: if (i = getequal(&Reldes, &rkey, &rel, &rtid))
1048: {
1049: /*
1050: ** Oops. A tuple doesn't exits in 'relation'
1051: **
1052: ** Maybe it's just a fatal error.
1053: */
1054: if (i < 0)
1055: syserr("CHECKINTEG: getequal=%d", i);
1056:
1057: /* not a fatal error, what to do? */
1058: printf("\tNo relation for 'integrities' entry:\n\t");
1059: printup(&Intdes, &inent);
1060: if (ask("\tRemove 'integrities' entry? "))
1061: {
1062: if (i = delete(&Intdes, &intid))
1063: syserr("CHECKINTEG: delete=%d", i);
1064: continue; /* go on to next tuple */
1065: }
1066: }
1067: else
1068: {
1069: /* 'relation' entry exists, check for the tree entry */
1070: if (inent.inttree >= 0)
1071: {
1072: if (!havetree(inent.intrelid, inent.intrelowner, mdINTEG))
1073: {
1074: /* no tuples in 'tree' */
1075: printf("\tNo tree for:\n\t");
1076: printup(&Intdes, &inent);
1077: if (ask("\tDelete entry and fix relation status bits? "))
1078: {
1079: if (i = delete(&Intdes, &inent))
1080: syserr("CHECKINTEG: delete=%d", i);
1081: rel.relstat &= ~S_INTEG;
1082: if (i = replace(&Reldes, &rtid, &rel, FALSE))
1083: syserr("CHECKINTEG: replace=%d", i);
1084: continue; /* go on to next tuple */
1085: }
1086: }
1087: }
1088: if ((rel.relstat & S_INTEG) != S_INTEG)
1089: {
1090: /* bits not set correctly */
1091: printf("\tIncorrect relation status bits for:\n\t");
1092: printup(&Reldes, &rel);
1093: if (ask("\tAdjust? "))
1094: {
1095: rel.relstat |= S_INTEG;
1096: if (i = replace(&Reldes, &rtid, &rel, FALSE))
1097: syserr("CHECKINTEG: replace=%d", i);
1098: continue; /* go on to next tuple */
1099: }
1100: }
1101: }
1102: }
1103: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.