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: }