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