1: # include <stdio.h> 2: 3: # include "../ingres.h" 4: # include "../aux.h" 5: # include "../access.h" 6: # include "../pipes.h" 7: # include "../symbol.h" 8: # include "../unix.h" 9: 10: /* 11: ** CREATDB -- create database (or modify database status) 12: ** 13: ** This program creates a new database. It takes the name of 14: ** the new database (syntax defined below) and a series of 15: ** flags (also defined below). 16: ** 17: ** In order to perform this command, you must be enabled by 18: ** having the U_CREATDB bit set in the user status word 19: ** of the users file. 20: ** 21: ** The -m flag specifies that the directory for the database 22: ** already exists. It stands for "mounted-file-system", 23: ** because this is presumably when you might use this feature. 24: ** The directory must be empty. 25: ** 26: ** The -e flag specifies that the database already exists. 27: ** It must be in all ways a valid database. This mode allows 28: ** you to turn flags on and off, as controlled by the other 29: ** flags. 30: ** 31: ** Usage: 32: ** creatdb [flags] databasename 33: ** 34: ** Positional Parameters: 35: ** databasename -- the name of the database to create. 36: ** It must conform to all the usual rules 37: ** about names. Notice that this is more 38: ** restrictive than UNIX usually is: names 39: ** must begin with an alpha, and must be 40: ** composed of alphanumerics. It may be 41: ** at most 14 characters long. Underscore 42: ** counts as an alphabetic. 43: ** 44: ** Flags: 45: ** -m 46: ** This is a mounted filesystem. Actually, 47: ** this just means that the directory in which 48: ** the database is to reside already exists. 49: ** It must be empty. 50: ** -e 51: ** This database exists. When the -e flag is 52: ** specified, the database is brought up to date, 53: ** rather than created. Things which may be 54: ** changed with the -e flag is anything that 55: ** affects the database status or the relation 56: ** status bits. 57: ** -uXX 58: ** Run as user XX (usercode or login name). This 59: ** flag may only be used by the INGRES superuser. 60: ** Normally, the database administrator for the 61: ** new database is the user who performs the 62: ** command, but the -u flag allows INGRES to 63: ** give the database to someone else. Thus, it 64: ** is possible for someone to be a DBA without 65: ** having the U_CREATDB bit set. 66: ** -Fpathname 67: ** Use the named file as the database template. 68: ** This is, of course, for debugging use only. 69: ** +-c 70: ** Turn concurrency control on/off. The default 71: ** for a new database depends on the dbtmplt file, 72: ** but as of this writing it defaults on. 73: ** +-q 74: ** Turn query modification on/off. 75: ** +-l 76: ** Turn protection violation logging on/off. 77: ** 78: ** Files: 79: ** .../files/dbtmplt<VERSION> 80: ** This file drives the entire program. The 81: ** syntax of this file is defined below in 82: ** readdbtemp(). Briefly, it tells the database 83: ** status, the relations in an 'empty' database, 84: ** and the status and format of those relations. 85: ** .../data/base 86: ** This directory is the directory in which all 87: ** databases eventually reside. Each database is 88: ** a subdirectory of this directory. 89: ** 90: ** Return Codes: 91: ** zero -- success 92: ** else -- failure. 93: ** 94: ** Defined Constants: 95: ** MAXRELNS 96: ** This defines the maximum number of relations 97: ** which may be declared in the dbtmplt file. 98: ** MAXDBTEMP 99: ** The maximum size of the dbtmplt file. This 100: ** determines the maximum number of characters 101: ** which may be in the file. 102: ** 103: ** Requires: 104: ** Much. Notably, be careful about changes to any 105: ** access methods, especially automatic references to 106: ** to the 'admin' file or relation relation. 107: ** create() -- to actually create relations. 108: ** 109: ** Compilation Flags: 110: ** xB_UNIX -- if defined, says that we have a "Berkeley 111: ** UNIX" system, with no group id's. If 112: ** undefined, specifies either a version seven 113: ** UNIX (with 16-bit group id's) or version six 114: ** UNIX (with 8-bit group id's); either way, 115: ** "setgid(getgid())" will work. 116: ** 117: ** Trace Flags: 118: ** -Tn, as below: 119: ** 120: ** 1 -- makereln() 121: ** 2 -- create() 122: ** 10 -- makeadmin() 123: ** 12 -- makefile() 124: ** 20 -- makedb() 125: ** 126: ** Diagnostics: 127: ** No database name specified. 128: ** You may not access this database 129: ** Your entry in the users file says this is 130: ** not a valid database for you. 131: ** You are not a valid INGRES user 132: ** You do not have a users file entry, and can 133: ** not do anything with INGRES at all. 134: ** You are not allowed this command 135: ** The U_CREATDB bit is not set in your users 136: ** file entry. 137: ** You may not use the -u flag 138: ** Only the INGRES superuser may say s/he is 139: ** someone else. 140: ** %s does not exist 141: ** With -e or -m, the directory does not exist. 142: ** %s already exists 143: ** Without either -e or -m, the database 144: ** (actually, the directory) already exists. 145: ** %s is not empty 146: ** With the -m flag, the directory you named 147: ** must be empty. 148: ** You are not the DBA for this database 149: ** With the -e flag, you must be the database 150: ** administrator. 151: ** 152: ** Syserrs: 153: ** fork 154: ** A fork request (for the mkdir command) failed; 155: ** probably if you try again later things will 156: ** work 157: ** setuid 158: ** The call to setuid() (to reset the user id 159: ** to that of the actual user) failed. This 160: ** "cannot happen". 161: ** setgid 162: ** Same for setgid(). 163: ** exec /bin/mkdir 164: ** It was not possible to execute the mkdir 165: ** command, used to create a directory for 166: ** the database. 167: ** chmod 168: ** The chmod command on the database (after the 169: ** return from mkdir) failed -- probably due 170: ** to the mkdir command failing somehow before 171: ** creating the directory. Notice that we do 172: ** not check the return from mkdir, since we 173: ** are not sure that it is unpolluted on all 174: ** systems. 175: ** chdir %s 176: ** After creating the database, we could not 177: ** change directory into it. 178: ** open .../files/dbtmplt 179: ** The dbtmplt file does not exist or is not 180: ** readable. 181: ** creatdb: closer(rel) %d 182: ** It was not possible to close the relation 183: ** relation after finishing the bulk of the 184: ** creatdb. 185: ** closer(att) %d 186: ** Ditto for attribute relation. 187: ** main: creat admin 188: ** It was not possible to create the 'admin' 189: ** file in the database. This is, of course, 190: ** a total disaster. 191: ** main: write Admin 192: ** It was not possible to write the admin file 193: ** out -- probably out of disk space. 194: ** 195: ** Compilation Instructions: 196: ** % setup creatdb 197: ** 198: ** - which translates to - 199: ** 200: ** % cc -n -O creatdb.c error.c ../../lib/dbulib \ 201: ** ../../lib/access ../../lib/utility 202: ** % chmod 4711 a.out 203: ** 204: ** History: 205: ** 8/15/79 (eric) (6.2/7) -- changed 'mkdir' stuff to 206: ** change into /mnt/ingres/data/base and then 207: ** mkdir on 'database' instead of 'Dbpath' -- 208: ** to avoid dependence on a mkdir bug on our 209: ** system. Changed to assume that argv[argc] 210: ** is NULL instead of -1 for v7. Added #include 211: ** of unix.h to get unix version flags. 212: ** 10/11/78 (eric) -- -F option added. 213: ** 8/3/78 (eric) -- written. 214: */ 215: 216: 217: 218: 219: # define MAXRELNS 20 220: # define MAXDBTEMP 2000 221: 222: /* relation & attribute reln descriptors used in access methods */ 223: extern struct descriptor Reldes; 224: extern struct descriptor Attdes; 225: 226: extern int Status; /* user status, set by initucode */ 227: int Dbstat; /* database status */ 228: int Dbson, Dbsoff; /* same: bits turned on, bits turned off */ 229: struct reldes 230: { 231: int bitson; 232: int bitsoff; 233: char *parmv[MAXPARMS]; 234: }; 235: struct reldes Rellist[MAXRELNS]; 236: char Delim; 237: extern char *Dbpath; 238: 239: 240: 241: main(argc, argv) 242: int argc; 243: char *argv[]; 244: { 245: register int i; 246: int admin; /* file desc */ 247: char adminbuf[BUFSIZ]; 248: extern struct admin Admin; 249: extern int errno; 250: auto int code; 251: struct relation relk; 252: char *database; 253: char **av; 254: register char *p; 255: char *user_ovrd; 256: int faterr; 257: register int *flagv; 258: char *dbtmpfile; 259: extern char *Parmvect[]; 260: extern char *Flagvect[]; 261: int exists; 262: extern char Version[]; 263: int *flaglkup(); 264: char *ztack(); 265: 266: # ifdef xSTR1 267: tTrace(&argc, argv, 'T'); 268: # endif 269: 270: /* 271: ** Do a lot of magic initialization. 272: */ 273: 274: exists = 0; 275: i = initucode(argc, argv, TRUE, NULL, -1); 276: switch (i) 277: { 278: case 0: 279: case 5: 280: exists = 1; 281: break; 282: 283: case 6: 284: exists = -1; 285: 286: case 1: 287: break; 288: 289: case 2: 290: printf("You are not authorized to create this database\n"); 291: exit(-1); 292: 293: case 3: 294: printf("You are not a valid INGRES user\n"); 295: exit(-1); 296: 297: case 4: 298: printf("No database name specified\n"); 299: usage: 300: printf("Usage: creatdb [-uname] [-e] [-m] [+-c] [+-q] dbname\n"); 301: exit(-1); 302: 303: default: 304: syserr("initucode %d", i); 305: } 306: 307: faterr = 0; 308: dbtmpfile = 0; 309: for (av = Flagvect; (p = *av) != NULL; av++) 310: { 311: if (p[0] != '-' && p[0] != '+') 312: syserr("flag %s", p); 313: switch (database[1]) 314: { 315: case 'F': /* dbtmplt file */ 316: if (p[2] == 0) 317: goto badflag; 318: dbtmpfile = &p[2]; 319: break; 320: 321: default: 322: if (flagv = flaglkup(p[1], p[0])) 323: { 324: if (p[0] == '+') 325: *flagv = 1; 326: else 327: *flagv = -1; 328: continue; 329: } 330: badflag: 331: printf("bad flag %s\n", p); 332: faterr++; 333: continue; 334: 335: } 336: if (p[0] == '+') 337: goto badflag; 338: } 339: 340: /* check for legality of database name */ 341: database = Parmvect[0]; 342: if (Parmvect[1] != NULL) 343: { 344: printf("Too many parameters to creatdb"); 345: goto usage; 346: } 347: if (!check(database)) 348: { 349: printf("Illegal database name %s\n", database); 350: exit(-1); 351: } 352: 353: if ((Status & U_CREATDB) == 0) 354: { 355: printf("You are not allowed this command\n"); 356: exit(-1); 357: } 358: 359: /* end of input checking */ 360: if (faterr != 0) 361: exit(2); 362: 363: /* now see if it should have been there */ 364: if (flagval('m') || flagval('e')) 365: { 366: # ifdef xSTR3 367: if (tTf(1, 14)) 368: printf("Dbpath = '%s'\n", Dbpath); 369: # endif 370: if (flagval('e') && exists <= 0) 371: { 372: printf("Database %s does not exist\n", database); 373: exit(-1); 374: } 375: 376: if (chdir(Dbpath) < 0) 377: { 378: printf("Directory for %s does not exist\n", database); 379: exit(-1); 380: } 381: 382: if (!flagval('e')) 383: { 384: /* make certain that it is empty */ 385: freopen(".", "r", stdin); 386: for (i = 0; i < 16; i++) 387: getw(stdin); 388: while ((i = getw(stdin)) != EOF) 389: { 390: if (i != 0) 391: syserr(0, "%s is not empty", database); 392: for (i = 0; i < 7; i++) 393: getw(stdin); 394: } 395: } 396: else 397: { 398: /* check for correct owner */ 399: acc_init(); 400: if (!bequal(Usercode, Admin.adhdr.adowner, 2)) 401: syserr(0, "You are not the DBA for this database"); 402: } 403: } 404: else 405: { 406: if (exists != 0) 407: { 408: printf("Database %s already exists\n", database); 409: exit(-1); 410: } 411: 412: /* create it */ 413: i = fork(); 414: if (i < 0) 415: syserr("fork err"); 416: if (i == 0) 417: { 418: /* enter database directory */ 419: initdbpath(NULL, adminbuf, FALSE); 420: if (chdir(adminbuf) < 0) 421: syserr("%s: cannot enter", adminbuf); 422: 423: /* arrange for proper permissions */ 424: if (setuid(getuid())) 425: syserr("setuid"); 426: # ifndef xB_UNIX 427: if (setgid(getgid())) 428: syserr("setgid"); 429: # endif 430: execl("/bin/mkdir", "mkdir", database, 0); 431: syserr("exec /bin/mkdir"); 432: } 433: while (wait(&code) != -1) 434: continue; 435: if (chdir(Dbpath) < 0) 436: syserr("could not chdir into %s; probably bad default mode in '/bin/mkdir'", Dbpath); 437: i = fork(); 438: if (i < 0) 439: syserr("fork 2"); 440: if (i == 0) 441: { 442: setuid(getuid()); 443: if (chmod(".", 0777)) 444: syserr("chmod"); 445: exit(0); 446: } 447: 448: while (wait(&code) != -1) 449: ; 450: if ((code & 0377) != 0) 451: exit(code); 452: 453: } 454: 455: /* reset 'errno', set from possibly bad chdir */ 456: errno = 0; 457: 458: /* determine name of dbtmplt file and open */ 459: if (dbtmpfile == NULL) 460: { 461: smove(Version, adminbuf); 462: for (i = 0; adminbuf[i] != 0; i++) 463: if (adminbuf[i] == '/') 464: break; 465: adminbuf[i] = 0; 466: dbtmpfile = ztack(ztack(Pathname, "/files/dbtmplt"), adminbuf); 467: } 468: if (freopen(dbtmpfile, "r", stdin) == NULL) 469: syserr("dbtmplt open %s", dbtmpfile); 470: 471: readdbtemp(); 472: 473: /* check for type -- update database status versus create */ 474: if (flagval('e')) 475: changedb(); 476: else 477: makedb(); 478: 479: /* close the cache descriptors */ 480: # ifdef xSTR3 481: if (tTf(50, 0)) 482: { 483: printf("Attdes.reltid = "); 484: dumptid(&Attdes.reltid); 485: printf("Reldes.reltid = "); 486: dumptid(&Reldes.reltid); 487: } 488: # endif 489: if (i = closer(&Attdes)) 490: syserr("creatdb: closer(att) %d", i); 491: if (i = closer(&Reldes)) 492: syserr("creatdb: closer(rel) %d", i); 493: 494: /* bring tupcount in 'admin' file to date */ 495: bmove(&Reldes.reltups, &Admin.adreld.reltups, sizeof Reldes.reltups); 496: bmove(&Attdes.reltups, &Admin.adattd.reltups, sizeof Attdes.reltups); 497: 498: /* clean up some of the fields to catch problems later */ 499: Admin.adreld.relfp = Admin.adattd.relfp = -1; 500: Admin.adreld.relopn = Admin.adattd.relopn = 0; 501: 502: if ((admin = creat("admin", FILEMODE)) < 0) 503: syserr("main: creat admin"); 504: if (write(admin, &Admin, sizeof Admin) != sizeof Admin) 505: syserr("main: write Admin"); 506: close(admin); 507: 508: /* exit successfully */ 509: exit(0); 510: } 511: 512: 513: 514: 515: /* 516: ** Rubout processing. 517: */ 518: 519: rubproc() 520: { 521: exit(-2); 522: } 523: /* 524: ** READDBTEMP -- read the dbtmplt file and build internal form 525: ** 526: ** This routine reads the dbtmplt file (presumably openned as 527: ** the standard input) and initializes the Dbstat (global database 528: ** status word) and Rellist variables. 529: ** 530: ** Rellist is an array of argument vectors, exactly as passed to 531: ** 'create'. 532: ** 533: ** The syntax of the dbtmplt file is as follows: 534: ** 535: ** The first line is a single status word (syntax defined below) 536: ** which is the database status. 537: ** 538: ** The rest of the file is sets of lines separated by blank lines. 539: ** Each set of lines define one relation. Two blank lines in a 540: ** row or an end-of-file define the end of the file. Each set 541: ** of lines is broken down: 542: ** 543: ** The first line is in the following format: 544: ** relname:status 545: ** which defines the relation name and the relation status for 546: ** this relation (syntax defined in 'getstat' below). Status 547: ** may be omitted, in which case a default status is assumed. 548: ** 549: ** Second through n'th lines of each set define the attributes. 550: ** They are of the form: 551: ** attname format 552: ** separated by a single tab. 'Format' is the same as on a 553: ** 'create' statement in QUEL. 554: ** 555: ** Notice that we force the S_CATALOG bit to be on in any 556: ** case. This is because the changedb() routine will fail 557: ** if the -e flag is ever used on this database if any 558: ** relation appears to be a user relation. 559: ** 560: ** Parameters: 561: ** none 562: ** 563: ** Returns: 564: ** none 565: ** 566: ** Side Effects: 567: ** Dbstat gets the database status. 568: ** Rellist is created with a list of the relations, 569: ** (as parameter vectors -- just as passed to 570: ** create). The entry after the last entry 571: ** has its pv[0] == NULL. 572: ** 573: ** Requires: 574: ** getstat -- to read status words. 575: ** getname -- to read names. 576: ** Delim -- set to the delimiter which terminated getstat 577: ** or getname. 578: ** 579: ** Called By: 580: ** main 581: ** 582: ** Trace Flags: 583: ** none 584: ** 585: ** Diagnostics: 586: ** none 587: ** 588: ** Syserrs: 589: ** readdbtemp: bad Dbstat -- the Dbstat entry was not 590: ** terminated with a newline. 591: ** readdbtemp: bad rel delim -- a relation name entry 592: ** did not terminate with a newline. 593: ** readdbtemp: bad att delim -- an attribute entry 594: ** did not terminate with a colon. 595: ** readdbtemp: bad type delim -- an attribute type entry 596: ** did not end with a newline. 597: */ 598: 599: readdbtemp() 600: { 601: static char buf[MAXDBTEMP]; 602: register struct reldes *r; 603: register char **q; 604: register int i; 605: int j; 606: char *p; 607: int defrstat; 608: auto int bitson, bitsoff; 609: 610: /* read database status */ 611: defrstat = S_CATALOG | S_NOUPDT | S_CONCUR | S_PROTALL; 612: bitson = bitsoff = 0; 613: Dbstat = getstat(A_DBCONCUR, &Dbson, &Dbsoff); 614: if (Delim == ':') 615: defrstat = getstat(defrstat, &bitson, &bitsoff); 616: if (Delim != '\n') 617: syserr("readdbtemp: bad Dbstat %c", Delim); 618: 619: /* compute default relation status */ 620: 621: /* start reading relation info */ 622: p = buf; 623: for (r = Rellist; ; r++) 624: { 625: r->bitson = bitson; 626: r->bitsoff = bitsoff; 627: 628: q = r->parmv; 629: 630: /* get relation name */ 631: q[1] = p; 632: p += getname(p) + 1; 633: 634: /* test for end of dbtmplt file */ 635: if (q[1][0] == 0) 636: break; 637: 638: /* get relation status */ 639: i = getstat(defrstat, &r->bitson, &r->bitsoff); 640: i |= S_CATALOG; /* guarantee system catalog */ 641: *q++ = p; 642: *p++ = ((i >> 15) & 1) + '0'; 643: for (j = 12; j >= 0; j -= 3) 644: *p++ = ((i >> j) & 07) + '0'; 645: *p++ = 0; 646: q++; 647: if (Delim != '\n') 648: syserr("readdbtemp: bad rel %c", Delim); 649: 650: /* read attribute names and formats */ 651: for (;;) 652: { 653: /* get attribute name */ 654: *q++ = p; 655: p += getname(p) + 1; 656: if (q[-1][0] == 0) 657: break; 658: if (Delim != '\t') 659: syserr("readdbtemp: bad att %c", Delim); 660: 661: /* get attribute type */ 662: *q++ = p; 663: p += getname(p) + 1; 664: if (Delim != '\n') 665: syserr("readdbtemp: bad type %c", Delim); 666: } 667: 668: /* insert end of argv signal */ 669: *--q = NULL; 670: 671: /* ad-hoc overflow test */ 672: if (p >= &buf[MAXDBTEMP]) 673: syserr("readdbtemp: overflow"); 674: } 675: /* mark the end of list */ 676: q[1] = NULL; 677: } 678: /* 679: ** GETSTAT -- Get status word 680: ** 681: ** A status word is read from the standard input (presumably 682: ** 'dbtmplt'). The string read is interpreted as an octal 683: ** number. The syntax is: 684: ** N{+c+N[~N]} 685: ** where N is a number, + is a plus or a minus sign, and c is 686: ** a flag. '+c+N1[~N2]' groups are interpreted as follows: 687: ** If flag 'c' is set (assuming the preceeding character is a +, 688: ** clear if it is a -), then set (clear) bits N1. If tilde N2 689: ** is present, then if flag 'c' is unset (called as '-c' ('+c')) 690: ** clear (set) bits N2; if ~N2 is not present, clear (set) 691: ** bits N1. 692: ** 693: ** For example, an entry might be (but probably isn't): 694: ** 1-c-1+q+6~2 695: ** having the following meaning: 696: ** 697: ** 1. Default to the 1 bit set. 698: ** 699: ** 2. If the -c flag is specified, clear the '1' bit. If the 700: ** +c flag is specified, set the '1' bit. If it is unspecified, 701: ** leave the '1' bit alone. 702: ** 703: ** 3. If the +q flag is specified, set the '2' bit and the '4' 704: ** bit. If the -q flag is specified, clear the '2' bit (but leave 705: ** the '4' bit alone). If the +-q flag is unspecified, leave 706: ** those bits alone. 707: ** 708: ** Thus, a database with this entry is initially created with 709: ** the 1 bit on. The '4' bit is a history, which says if the 710: ** 'q' flag has ever been set, while the '2' bit tells if it is 711: ** currently set. 712: ** 713: ** Parameters: 714: ** def -- the default to return if there is no number 715: ** there at all. 716: ** bitson -- a pointer to a word to contain all the 717: ** bits to be turned on -- used for the -e flag. 718: ** bitsoff -- same, for bits turned off. 719: ** 720: ** Returns: 721: ** The value of the status word. 722: ** There are no error returns. 723: ** 724: ** Side Effects: 725: ** File activity. 726: ** 727: ** Requires: 728: ** getchar -- to get input characters 729: ** roctal -- to read an octal number. 730: ** ungetc -- to give a character back during parsing. 731: ** Delim -- set the the terminating delimitor in roctal(). 732: ** flagval() -- to get the value of a flag. 733: ** 734: ** Called By: 735: ** readdbtemp 736: ** 737: ** Trace Flags: 738: ** none 739: ** 740: ** Diagnostics: 741: ** none 742: ** 743: ** Syserrs: 744: ** getstat: bad fmt %c -- a '+' or '-' was expected. 745: */ 746: 747: getstat(def, bitson, bitsoff) 748: int def; 749: int *bitson; 750: int *bitsoff; 751: { 752: register int c; 753: register int stat; 754: register int i; 755: int setbits; 756: int clrbits; 757: char ctlch; 758: 759: /* reset bits being turned on and off */ 760: *bitson = *bitsoff = 0; 761: 762: /* check to see if a base status word is defined */ 763: if (Delim == '\n' || (Delim = c = getchar()) < '0' || c > '7') 764: { 765: /* no, use default */ 766: stat = def; 767: } 768: else 769: { 770: /* read base status field */ 771: ungetc(c, stdin); 772: stat = roctal(); 773: } 774: 775: /* scan '+c+N' entries */ 776: for (;;) 777: { 778: /* check for a flag present */ 779: c = Delim; 780: if (c == '\n' || c == ':') 781: return (stat); 782: if (c != '+' && c != '-') 783: { 784: badfmt: 785: syserr("getstat: bad fmt %c", c); 786: } 787: 788: /* we have some flag -- get it's value */ 789: i = flagval(getchar()); 790: 791: /* save sign char on flag */ 792: ctlch = c; 793: 794: /* get sign on associated number and the number */ 795: c = getchar(); 796: if (c != '+' && c != '-') 797: goto badfmt; 798: setbits = roctal(); 799: 800: /* test whether action on -X same as on +X */ 801: if (Delim == '~') 802: { 803: /* they have different bits (see above) */ 804: clrbits = roctal(); 805: } 806: else 807: { 808: /* on 'creatdb -e -X', use opposite bits of +X */ 809: clrbits = setbits; 810: } 811: 812: /* test for any effect at all */ 813: if (i == 0) 814: continue; 815: 816: /* test whether we should process the '+N' */ 817: if ((ctlch == '-') ? (i < 0) : (i > 0)) 818: i = setbits; 819: else 820: { 821: i = clrbits; 822: 823: /* switch sense of bit action */ 824: if (c == '+') 825: c = '-'; 826: else 827: c = '+'; 828: } 829: 830: if (c == '+') 831: { 832: stat |= i; 833: *bitson |= i; 834: } 835: else 836: { 837: stat &= ~i; 838: *bitsoff |= i; 839: } 840: } 841: } 842: /* 843: ** ROCTAL -- Read an octal number from standard input. 844: ** 845: ** This routine just reads a single octal number from the standard 846: ** input and returns its value. It will only read up to a non- 847: ** octal digit. It will also skip initial and trailing blanks. 848: ** 'Delim' is set to the next character in the input stream. 849: ** 850: ** Parameters: 851: ** none 852: ** 853: ** Returns: 854: ** value of octal number in the input stream. 855: ** 856: ** Side Effects: 857: ** 'Delim' is set to the delimiter which terminated the 858: ** number. 859: ** File activity on stdin. 860: ** 861: ** Requires: 862: ** getchar() -- to get the input characters. 863: ** Delim -- as noted above. 864: ** 865: ** Called By: 866: ** getstat() 867: ** 868: ** Trace Flags: 869: ** none 870: ** 871: ** Diagnostics: 872: ** none 873: ** 874: ** Syserrs: 875: ** none 876: */ 877: 878: roctal() 879: { 880: register int c; 881: register int val; 882: 883: val = 0; 884: 885: /* skip initial blanks */ 886: while ((c = getchar()) == ' ') 887: continue; 888: 889: /* get numeric value */ 890: while (c >= '0' && c <= '7') 891: { 892: val = (val << 3) | (c - '0'); 893: c = getchar(); 894: } 895: 896: /* skip trailing blanks */ 897: while (c == ' ') 898: c = getchar(); 899: 900: /* set Delim and return numeric value */ 901: Delim = c; 902: return (val); 903: } 904: /* 905: ** GETNAME -- get name from standard input 906: ** 907: ** This function reads a name from the standard input. A 908: ** name is defined as a string of letters and digits. 909: ** 910: ** The character which caused the scan to terminate is stored 911: ** into 'Delim'. 912: ** 913: ** Parameters: 914: ** ptr -- a pointer to the buffer in which to dump the 915: ** name. 916: ** 917: ** Returns: 918: ** The length of the string. 919: ** 920: ** Side Effects: 921: ** File activity on standard input. 922: ** 923: ** Requires: 924: ** getchar() 925: ** Delim 926: ** 927: ** Called By: 928: ** readdbtemp 929: ** 930: ** Trace Flags: 931: ** none 932: ** 933: ** Diagnostics: 934: ** none 935: ** 936: ** Syserrs: 937: ** none 938: */ 939: 940: getname(ptr) 941: char *ptr; 942: { 943: register int len; 944: register int c; 945: register char *p; 946: 947: len = 0; 948: 949: for (p = ptr; (c = getchar()) != EOF; len++) 950: { 951: /* check for end of name */ 952: if ((c < 'a' || c > 'z') && 953: (c < '0' || c > '9')) 954: break; 955: 956: /* store character into buffer */ 957: *p++ = c; 958: } 959: 960: /* null-terminate the string */ 961: *p = '\0'; 962: 963: /* store the delimiting character and return length of string */ 964: Delim = c; 965: return (len); 966: } 967: /* 968: ** MAKEDB -- make a database from scratch 969: ** 970: ** This is the code to make a database if the -e flag is off. 971: ** 972: ** The first step is to make a copy of the admin file 973: ** in the internal 'Admin' struct. This is the code which 974: ** subsequently gets used by openr and opencatalog. Notice 975: ** that the admin file is not written out; this happens after 976: ** makedb returns. 977: ** 978: ** Next, the physical files are created with one initial (empty) 979: ** page. This has to happen before the 'create' call so 980: ** that it will be possible to flush 'relation' and 'attribute' 981: ** relation pages during the creates of the 'relation' and 982: ** 'attribute' relations. Other relations don't need this, 983: ** but it is more convenient to be symmetric. 984: ** 985: ** The next step is to create the relations. Of course, all 986: ** this really is is inserting stuff into the system catalogs. 987: ** 988: ** When we are all done we open the relation relation for the 989: ** admin cache (which of course should exist now). Thus, 990: ** the closer's in main (which must be around to update the 991: ** tuple count) will work right. 992: ** 993: ** Parameters: 994: ** none 995: ** 996: ** Returns: 997: ** none 998: ** 999: ** Side Effects: 1000: ** A database is created!! 1001: ** Several files will be created in the current directory, 1002: ** one for each relation mentioned in the 1003: ** 'dbtmplt' file. 1004: ** The 'Admin' struct will be filled in. 1005: ** 1006: ** Requires: 1007: ** makefile -- to create the physical file. 1008: ** makereln -- to create the relations. 1009: ** Rellist -- containing the list of relations to be 1010: ** created with specs. 1011: ** makeadmin -- to initialize the Admin struct. 1012: ** 1013: ** Called By: 1014: ** main 1015: ** 1016: ** Trace Flags: 1017: ** 20 1018: ** 1019: ** Diagnostics: 1020: ** none 1021: ** 1022: ** Syserrs: 1023: ** open(rel) 1024: ** It was not possible to open the relation 1025: ** relation for the Admin.adreld cache. 1026: */ 1027: 1028: makedb() 1029: { 1030: struct descriptor d; 1031: register struct reldes *r; 1032: register int pc; 1033: register char **pv; 1034: 1035: # ifdef xSTR3 1036: if (tTf(51, 0)) 1037: printf(">>makedb, Usercode = %s (%u)\n", Usercode, Usercode); 1038: # endif 1039: 1040: /* create the physical files */ 1041: for (r = Rellist; r->parmv[1] != 0; r++) 1042: { 1043: makefile(r); 1044: } 1045: 1046: /* initialize the admin file internal cache */ 1047: bmove(Usercode, Admin.adhdr.adowner, 2); 1048: Admin.adhdr.adflags = Dbstat; 1049: makeadmin(&Admin.adreld, Rellist[0].parmv); 1050: makeadmin(&Admin.adattd, Rellist[1].parmv); 1051: 1052: /* done with admin initialization */ 1053: 1054: /* initialize relations */ 1055: for (r = Rellist; r->parmv[1] != 0; r++) 1056: { 1057: makereln(r); 1058: } 1059: } 1060: /* 1061: ** MAKEADMIN -- manually initialize descriptor for admin file 1062: ** 1063: ** The relation descriptor pointed to by 'pv' is turned into 1064: ** a descriptor, returned in 'd'. Presumably, this descriptor 1065: ** is later written out to the admin file. 1066: ** 1067: ** Notice that the 'reltid' field is filled in sequentially. 1068: ** This means that the relations put into the admin file 1069: ** must be created in the same order that they are 'made' 1070: ** (by this routine), that the format of tid's must not 1071: ** change, and that there can not be over one page worth of 1072: ** relations in the admin file. Our current system currently 1073: ** handles this easily. 1074: ** 1075: ** Parameters: 1076: ** d -- the descriptor to get the result. 1077: ** pv -- a parm vector in 'create' format, which drives 1078: ** this routine. 1079: ** 1080: ** Returns: 1081: ** none 1082: ** 1083: ** Side Effects: 1084: ** none 1085: ** 1086: ** Requires: 1087: ** ingresname 1088: ** oatoi 1089: ** atoi 1090: ** typeconv 1091: ** 1092: ** Called By: 1093: ** main 1094: ** 1095: ** Trace Flags: 1096: ** 10 1097: ** 1098: ** Diagnostics: 1099: ** none 1100: ** 1101: ** Syserrs: 1102: ** makeadmin: type err %c -- a bad type specifier 1103: ** occured in the dbtmplt file. 1104: ** makeadmin: len err %s -- a length was specified 1105: ** which was not an integer. 1106: */ 1107: 1108: 1109: 1110: makeadmin(d, pv) 1111: struct descriptor *d; 1112: char *pv[]; 1113: { 1114: register struct descriptor *des; 1115: register char **p; 1116: register int i; 1117: auto int len; 1118: static int tid; 1119: char fname[MAXNAME + 3]; 1120: 1121: des = d; 1122: p = pv; 1123: 1124: # ifdef xSTR2 1125: if (tTf(10, -1)) 1126: printf("creating %s in admin\n", p[1]); 1127: # endif 1128: i = oatoi(*p++); 1129: ingresname(*p++, Usercode, fname); 1130: bmove(fname, des->relid, MAXNAME + 2); 1131: des->relstat = i; 1132: des->relatts = 0; 1133: des->relwid = 0; 1134: des->relspec = M_HEAP; 1135: des->reltid = tid++; 1136: des->relfp = open(fname, 2); 1137: if (des->relfp < 0) 1138: syserr("makeadmin: open %s", fname); 1139: des->relopn = (des->relfp + 1) * -5; 1140: 1141: /* initialize domain info */ 1142: for (; *p++ != NULL; p++) 1143: { 1144: i = typeconv(p[0][0]); 1145: if (i < 0) 1146: syserr("dbtmplt: type err %c", p[0][0]); 1147: des->relfrmt[++(des->relatts)] = i; 1148: if (atoi(&p[0][1], &len) != 0) 1149: syserr("makeadmin: len err %s", p[0]); 1150: des->relfrml[des->relatts] = len; 1151: des->reloff[des->relatts] = des->relwid; 1152: des->relwid += len; 1153: } 1154: } 1155: /* 1156: ** MAKEFILE -- make an 'empty' file for a relation 1157: ** 1158: ** This routine creates a file with a single (empty) page 1159: ** on it -- it is part of the 'create' code, essentially. 1160: ** 1161: ** Parameters: 1162: ** rr -- a pointer to the 'reldes' structure for this 1163: ** relation (file). 1164: ** 1165: ** Returns: 1166: ** none 1167: ** 1168: ** Side Effects: 1169: ** A file with one page is created. 1170: ** 1171: ** Requires: 1172: ** ingresname -- to create the actual file name. 1173: ** formatpg -- to put the single page into the relation. 1174: ** creat -- to create the file 1175: ** FILEMODE -- the mode of the created file. 1176: ** 1177: ** Called By: 1178: ** makedb 1179: ** changedb 1180: ** 1181: ** Trace Flags: 1182: ** 12 1183: ** 1184: ** Diagnostics: 1185: ** none 1186: ** 1187: ** Syserrs: 1188: ** creat %s 1189: ** The file named could not be created. 1190: ** formatpg 1191: ** The 'formatpg' call failed; check the 1192: ** access method error for why. 1193: */ 1194: 1195: makefile(rr) 1196: struct reldes *rr; 1197: { 1198: register struct reldes *r; 1199: struct descriptor d; 1200: long npages; 1201: 1202: r = rr; 1203: 1204: ingresname(r->parmv[1], Usercode, d.relid); 1205: # ifdef xSTR1 1206: if (tTf(12, 0)) 1207: printf("creat %s\n", d.relid); 1208: # endif 1209: if ((d.relfp = creat(d.relid, FILEMODE)) < 0) 1210: syserr("creat %s", d.relid); 1211: npages = 1; 1212: if (formatpg(&d, npages)) 1213: syserr("formatpg"); 1214: close(d.relfp); 1215: } 1216: /* 1217: ** MAKERELN -- make a relation 1218: ** 1219: ** This is the second half of the create, started by 'makefile'. 1220: ** 1221: ** This routine just sets up argument vectors and calls create, 1222: ** which does the real work. 1223: ** 1224: ** Parameters: 1225: ** rr -- a pointer to the Rellist entry for the relation 1226: ** to be created. 1227: ** 1228: ** Returns: 1229: ** none 1230: ** 1231: ** Side Effects: 1232: ** Information will be inserted into the 'relation' and 1233: ** 'attribute' relations. 1234: ** 1235: ** Requires: 1236: ** Rellist -- with a list of relations to be created 1237: ** and data descriptions. 1238: ** create -- to actually do the create. 1239: ** 'Admin' must be filled in. Openr must use 'Admin' 1240: ** and never look at the physical 'admin' file. 1241: ** 1242: ** Called By: 1243: ** makedb 1244: ** changedb 1245: ** 1246: ** Trace Flags: 1247: ** 1 1248: ** 1249: ** Diagnostics: 1250: ** none 1251: ** 1252: ** Syserrs: 1253: ** create %d 1254: ** The call to 'create' failed, for reason 1255: ** given. 1256: */ 1257: 1258: makereln(rr) 1259: struct reldes *rr; 1260: { 1261: register struct reldes *r; 1262: register int pc; 1263: register char **pv; 1264: int i; 1265: 1266: r = rr; 1267: 1268: pc = 0; 1269: for (pv = r->parmv; *pv != NULL; pv++) 1270: pc++; 1271: pv = r->parmv; 1272: # ifdef xSTR1 1273: if (tTf(1, 0)) 1274: prargs(pc, pv); 1275: # endif 1276: i = create(pc, pv); 1277: if (i != 0) 1278: syserr("create %d", i); 1279: } 1280: /* 1281: ** CHECK -- check database name syntax 1282: ** 1283: ** The name of a database is checked for validity. A valid 1284: ** database name is not more than 14 characters long, begins 1285: ** with an alphabetic character, and contains only alpha- 1286: ** numerics. Underscore is considered numeric. 1287: ** 1288: ** Parameters: 1289: ** st -- the string to check. 1290: ** 1291: ** Returns: 1292: ** TRUE -- ok. 1293: ** FALSE -- failure. 1294: ** 1295: ** Side Effects: 1296: ** none 1297: ** 1298: ** Requires: 1299: ** length -- to check the length of the string. 1300: ** 1301: ** Called By: 1302: ** main 1303: ** 1304: ** Trace Flags: 1305: ** none 1306: ** 1307: ** Diagnostics: 1308: ** none 1309: ** 1310: ** Syserrs: 1311: ** none 1312: */ 1313: 1314: check(st) 1315: char *st; 1316: { 1317: register char c; 1318: register char *p; 1319: 1320: p = st; 1321: 1322: /* check string length */ 1323: if (length(p) > 14) 1324: return (FALSE); 1325: 1326: /* check the first character of the string for alphabetic */ 1327: c = *p++; 1328: if (c < 'a' || c > 'z') 1329: return (FALSE); 1330: 1331: /* check the rest for alphanumeric */ 1332: while ((c = *p++) != 0) 1333: { 1334: if (c == '_') 1335: continue; 1336: if (c >= '0' && c <= '9') 1337: continue; 1338: if (c >= 'a' && c <= 'z') 1339: continue; 1340: return (FALSE); 1341: } 1342: return (TRUE); 1343: } 1344: /* 1345: ** FLAGLKUP -- look up user flag 1346: ** 1347: ** This routine helps support a variety of user flags. The 1348: ** routine takes a given user flag and looks it up (via a 1349: ** very crude linear search) in the 'Flags' vector, and 1350: ** returns a pointer to the value. 1351: ** 1352: ** The 'flag' struct defines the flags. The 'flagname' field 1353: ** is the character which is the flag id, for example, 'c' 1354: ** in the flag '-c'. The 'flagtype' field defines how the 1355: ** flag may appear; if negative, only '-c' may appear, if 1356: ** positive, only '+c' may appear; if zero, either form may 1357: ** appear. Finally, the 'flagval' field is the value of the 1358: ** flag -- it may default any way the user wishes. 1359: ** 1360: ** Parameters: 1361: ** flagname -- the name (as defined above) of the 1362: ** flag to be looked up. 1363: ** plusminus -- a character, '+' means the '+x' form 1364: ** was issued, '-' means the '-x' form was 1365: ** issued, something else means *don't care*. 1366: ** If an illegal form was issued (that is, 1367: ** that does not match the 'flagtype' field 1368: ** in the structure), the "not found" return 1369: ** is taken. 1370: ** 1371: ** Returns: 1372: ** NULL -- flag not found, or was incorrect type, 1373: ** as when the '+x' form is specified in the 1374: ** parameters, but the 'Flags' struct says 1375: ** that only a '-x' form may appear. 1376: ** else -- pointer to the 'flagval' field of the correct 1377: ** field in the 'Flags' vector. 1378: ** 1379: ** Side Effects: 1380: ** none 1381: ** 1382: ** Requires: 1383: ** Flags vector -- of type 'struct flag', defined below. 1384: ** This vector should be terminated with a 1385: ** zero 'flagname'. 1386: ** 1387: ** Called By: 1388: ** main 1389: ** flagval 1390: ** 1391: ** Trace Flags: 1392: ** none 1393: ** 1394: ** Diagnostics: 1395: ** none 1396: ** 1397: ** Syserrs: 1398: ** none 1399: */ 1400: 1401: struct flag 1402: { 1403: char flagname; /* the name of the flag */ 1404: char flagtype; /* -1: -x form; +1: +x form; 0: both */ 1405: int flagval; /* user-defined value of the flag */ 1406: }; 1407: 1408: struct flag Flags[] = 1409: { 1410: 'q', 0, 0, 1411: 'l', 0, 0, 1412: 'c', 0, 0, 1413: 'e', -1, 0, 1414: 'm', -1, 0, 1415: 0 1416: }; 1417: 1418: int * 1419: flaglkup(flagname, plusminus) 1420: char flagname; 1421: char plusminus; 1422: { 1423: register char f; 1424: register struct flag *p; 1425: register char pm; 1426: 1427: f = flagname; 1428: pm = plusminus; 1429: 1430: /* look up flag in vector */ 1431: for (p = Flags; p->flagname != f; p++) 1432: { 1433: if (p->flagname == 0) 1434: return (NULL); 1435: } 1436: 1437: /* found in list -- check type */ 1438: if ((pm == '+' && p->flagtype < 0) || 1439: (pm == '-' && p->flagtype > 0)) 1440: return (NULL); 1441: 1442: /* type is OK -- return pointer to value */ 1443: return (&p->flagval); 1444: } 1445: /* 1446: ** FLAGVAL -- return value of a flag 1447: ** 1448: ** Similar to 'flaglkup', except that the value is returned 1449: ** instead of the address, and no error return can occur. 1450: ** 1451: ** Parameters: 1452: ** fx -- the flag to look up (see flaglkup). 1453: ** 1454: ** Returns: 1455: ** The value of flag 'fx'. 1456: ** 1457: ** Side Effects: 1458: ** none 1459: ** 1460: ** Requires: 1461: ** flaglkup() 1462: ** 1463: ** Called By: 1464: ** readdbtemp() 1465: ** main() 1466: ** 1467: ** Trace Flags: 1468: ** none 1469: ** 1470: ** Diagnostics: 1471: ** none 1472: ** 1473: ** Syserrs: 1474: ** flagval: flag %c -- the value of a flag which does 1475: ** not exist was asked for. 1476: */ 1477: 1478: flagval(fx) 1479: char fx; 1480: { 1481: register char f; 1482: register char *p; 1483: 1484: f = fx; 1485: 1486: /* get value of flag */ 1487: p = (char *) flaglkup(f, 0); 1488: 1489: /* test for error return, syserr if so */ 1490: if (p == NULL) 1491: syserr("flagval: flag %c", f); 1492: 1493: /* return value */ 1494: return (*p); 1495: } 1496: /* 1497: ** CHANGEDB -- change status bits for database/relations 1498: ** 1499: ** In this function we change the status bits for use with the 1500: ** -e flag. 1501: ** 1502: ** This module always uses the differential status 1503: ** change information, so that existing bits are not touched. 1504: ** 1505: ** We check to see that invalid updates, such as turning off 1506: ** query modification when it is already on, can not occur. 1507: ** This is because of potential syserr's when the system is 1508: ** later run, e.g., because of views without instantiations. 1509: ** 1510: ** In the second step, the database status is updated. This is 1511: ** done strictly in-core, and will be updated in the database 1512: ** after we return. 1513: ** 1514: ** The list of valid relations are then scanned. For each 1515: ** relation listed, a series of steps occurs: 1516: ** 1517: ** (1) The relation is checked for existance. If it does not 1518: ** exist, it is created, and we return to the beginning of the 1519: ** loop. Notice that we don't have to change modes in this 1520: ** case, since it already has been done. 1521: ** 1522: ** (2) If the relation does exist, we check to see that it 1523: ** is a system catalog. If it is not, we have an error, since 1524: ** this is a user relation which just happenned to have the 1525: ** same name. We inform the user and give up. 1526: ** 1527: ** (3) If the relation exists, is a system catalog, and all 1528: ** that, then we check the changes we need to make in the 1529: ** bits. If no change need be made, we continue the loop; 1530: ** otherwise, we change the bits and replace the tuple in 1531: ** the relation relation. 1532: ** 1533: ** (4) If the relation being updated was the "relation" or 1534: ** "attribute" relation, we change the Admin struct accordingly. 1535: ** 1536: ** Notice that the result of all this is that all relations 1537: ** which might ever be used exist and have the correct status. 1538: ** 1539: ** Notice that it is fatal for either the attribute or relation 1540: ** relations to not exist, since the file is created at the 1541: ** same time that relation descriptors are filled in. This 1542: ** should not be a problem, since this is only called on an 1543: ** existing database. 1544: ** 1545: ** As a final note, we open the attribute relation cache not 1546: ** because we use it, but because we want to do a closer 1547: ** in main() to insure that the tupcount is updated in all 1548: ** cases. 1549: ** 1550: ** Parameters: 1551: ** none 1552: ** 1553: ** Returns: 1554: ** none 1555: ** 1556: ** Side Effects: 1557: ** The database is brought up to date, as described 1558: ** above. 1559: ** Tuples may be added or changed in system catalogs. 1560: ** Files may be created. 1561: ** 1562: ** Requires: 1563: ** Dbson, Dbsoff -- bits to set/clear for the database 1564: ** status. 1565: ** opencatalog() -- to open the relation relation. 1566: ** getequal() -- to get the relation relation tuple 1567: ** for specific relations. 1568: ** Rellist -- a list of needed relations and their 1569: ** data description. 1570: ** Reldes -- result of opencatalog() call. 1571: ** replace() -- to update the relstat in the relation 1572: ** relation for entries. 1573: ** Admin struct -- must be filled in with the current 1574: ** contents of the 'admin' file. 1575: ** makefile(), makereln() -- to make the relation 1576: ** if it does not exist at all. 1577: ** 1578: ** Called By: 1579: ** main 1580: ** 1581: ** Trace Flags: 1582: ** 40 1583: ** 1584: ** Diagnostics: 1585: ** Relation %s already exists 1586: ** A system catalog which must be created does 1587: ** already exists as a user relation. 1588: ** I'm sorry, it is not possible to turn query modification off. 1589: ** The user tried to turn query modification off. 1590: ** We can't allow this because it could cause 1591: ** a syserr later; for instance, if the user 1592: ** referenced a view which might still hang around 1593: ** the 'relation' catalog. This would result in 1594: ** an attempt to open the file for the view, which 1595: ** of course does not exist. BANG! 1596: ** 1597: ** Syserrs: 1598: ** getequal 1599: ** getequal() failed. 1600: ** replace %d 1601: ** replace() failed. 1602: */ 1603: 1604: changedb() 1605: { 1606: register struct reldes *r; 1607: struct relation relk, relt; 1608: struct tup_id tid; 1609: register int i; 1610: 1611: # ifdef xSTR1 1612: if (tTf(40, 0)) 1613: printf(">>> changedb: Dbson=%o, Dbsoff=%o\n", Dbson, Dbsoff); 1614: # endif 1615: 1616: /* check to see we aren't doing anything illegal */ 1617: if (flagval('q') < 0) 1618: { 1619: syserr(0, "I'm sorry, it is not possible to turn query modification off"); 1620: } 1621: 1622: /* update the database status field */ 1623: Admin.adhdr.adflags = (Admin.adhdr.adflags | Dbson) & ~Dbsoff; 1624: 1625: /* open the system catalog caches */ 1626: opencatalog("relation", 2); 1627: opencatalog("attribute", 0); 1628: 1629: /* scan the relation list:- Rellist */ 1630: for (r = Rellist; r->parmv[1] != 0; r++) 1631: { 1632: /* see if this relation exists */ 1633: clearkeys(&Reldes); 1634: setkey(&Reldes, &relk, r->parmv[1], RELID); 1635: i = getequal(&Reldes, &relk, &relt, &tid); 1636: 1637: if (i < 0) 1638: syserr("changedb: getequal"); 1639: 1640: if (i > 0) 1641: { 1642: /* doesn't exist, create it */ 1643: printf("Creating relation %s\n", r->parmv[1]); 1644: makefile(r); 1645: makereln(r); 1646: } 1647: else 1648: { 1649: /* exists -- check to make sure it is the right one */ 1650: if ((relt.relstat & S_CATALOG) == 0) 1651: { 1652: /* exists as a user reln -- tough luck buster */ 1653: printf("Relation %s already exists -- I cannot bring this database\n", r->parmv[1]); 1654: printf(" up to date. Sorry.\n"); 1655: exit(3); 1656: } 1657: 1658: /* it exists and is the right one -- update status */ 1659: if (r->bitson == 0 && r->bitsoff == 0) 1660: continue; 1661: 1662: /* actual work need be done */ 1663: relt.relstat = (relt.relstat | r->bitson) & ~r->bitsoff; 1664: 1665: /* replace tuple in relation relation */ 1666: i = replace(&Reldes, &tid, &relt, FALSE); 1667: if (i != 0) 1668: syserr("changedb: replace %d", i); 1669: 1670: /* update Admin struct if "relation" or "attribute" */ 1671: if (sequal(r->parmv[1], "relation")) 1672: Admin.adreld.relstat = relt.relstat; 1673: else if (sequal(r->parmv[1], "attribute")) 1674: Admin.adattd.relstat = relt.relstat; 1675: } 1676: } 1677: } 1678: /* 1679: ** READADMIN -- read the admin file into the 'Admin' cache 1680: ** 1681: ** This routine opens and reads the 'Admin' cache from the 1682: ** 'admin' file in the current directory. 1683: ** 1684: ** This version of the routine is modified for creatdb -- 1685: ** the '-e' flag is checked, and nothing is performed 1686: ** unless it is set. 1687: ** 1688: ** If not set, the 'relation' and 'attribute' relations 1689: ** are opened, and the descriptors for them in the Admin 1690: ** struct are filled in with their file descriptors. 1691: ** 1692: ** Parameters: 1693: ** none 1694: ** 1695: ** Returns: 1696: ** none 1697: ** 1698: ** Side Effects: 1699: ** The 'Admin' struct is filled in. 1700: ** The 'relation...xx' and 'attribute...xx' files are 1701: ** opened. 1702: ** 1703: ** Requires: 1704: ** 'Admin' struct. 1705: ** 'Usercode' must have the user code of the DBA. 1706: ** ingresname() -- to create the physical file name. 1707: ** flagval() -- to test the -e flag. 1708: ** 1709: ** Called By: 1710: ** acc_init (accbuf.c) 1711: ** changedb 1712: ** 1713: ** Trace Flags: 1714: ** none 1715: ** 1716: ** Diagnostics: 1717: ** none 1718: ** 1719: ** Syserrs: 1720: ** adminread: open admin 1721: ** It was not possible to open the admin file. 1722: ** adminread: read admin 1723: ** There was a read error when reading the 'admin' 1724: ** file. 1725: ** adminread: open rel 1726: ** It was not possible to open the 'relation..xx' 1727: ** file. 1728: ** adminread: open att 1729: ** It was not possible to open the 'attribute..xx' 1730: ** file. 1731: */ 1732: 1733: readadmin() 1734: { 1735: register int i; 1736: char relname[MAXNAME + 4]; 1737: 1738: /* read the stuff from the admin file */ 1739: if (flagval('e')) 1740: { 1741: i = open("admin", 0); 1742: if (i < 0) 1743: syserr("readadmin: open admin %d", i); 1744: if (read(i, &Admin, sizeof Admin) != sizeof Admin) 1745: syserr("readadmin: read err admin"); 1746: close(i); 1747: 1748: /* open the physical files for 'relation' and 'attribute' */ 1749: ingresname(Admin.adreld.relid, Admin.adreld.relowner, relname); 1750: if ((Admin.adreld.relfp = open(relname, 2)) < 0) 1751: syserr("readadmin: open rel %d", Admin.adreld.relfp); 1752: ingresname(Admin.adattd.relid, Admin.adattd.relowner, relname); 1753: if ((Admin.adattd.relfp = open(relname, 2)) < 0) 1754: syserr("readadmin: open att %d", Admin.adattd.relfp); 1755: Admin.adreld.relopn = (Admin.adreld.relfp + 1) * -5; 1756: Admin.adattd.relopn = (Admin.adattd.relfp + 1) * 5; 1757: } 1758: 1759: return (0); 1760: }