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