1*13305Ssam #ifndef lint 2*13305Ssam static char sccsid[] = "@(#)dbm.c 4.1 (Berkeley) 06/27/83"; 3*13305Ssam #endif 4*13305Ssam 5*13305Ssam #include "dbm.h" 6*13305Ssam #include <sys/types.h> 7*13305Ssam #include <sys/stat.h> 8*13305Ssam 9*13305Ssam dbminit(file) 10*13305Ssam char *file; 11*13305Ssam { 12*13305Ssam struct stat statb; 13*13305Ssam 14*13305Ssam dbrdonly = 0; 15*13305Ssam strcpy(pagbuf, file); 16*13305Ssam strcat(pagbuf, ".pag"); 17*13305Ssam pagf = open(pagbuf, 2); 18*13305Ssam if (pagf < 0) { 19*13305Ssam pagf = open(pagbuf, 0); 20*13305Ssam dbrdonly = 1; 21*13305Ssam } 22*13305Ssam 23*13305Ssam strcpy(pagbuf, file); 24*13305Ssam strcat(pagbuf, ".dir"); 25*13305Ssam dirf = open(pagbuf, 2); 26*13305Ssam if (dirf < 0) { 27*13305Ssam dirf = open(pagbuf, 0); 28*13305Ssam dbrdonly = 1; 29*13305Ssam } 30*13305Ssam if(pagf < 0 || dirf < 0) { 31*13305Ssam printf("cannot open database %s\n", file); 32*13305Ssam return(-1); 33*13305Ssam } 34*13305Ssam fstat(dirf, &statb); 35*13305Ssam maxbno = statb.st_size*BYTESIZ-1; 36*13305Ssam return(0); 37*13305Ssam } 38*13305Ssam 39*13305Ssam long 40*13305Ssam forder(key) 41*13305Ssam datum key; 42*13305Ssam { 43*13305Ssam long hash; 44*13305Ssam 45*13305Ssam hash = calchash(key); 46*13305Ssam for(hmask=0;; hmask=(hmask<<1)+1) { 47*13305Ssam blkno = hash & hmask; 48*13305Ssam bitno = blkno + hmask; 49*13305Ssam if(getbit() == 0) 50*13305Ssam break; 51*13305Ssam } 52*13305Ssam return(blkno); 53*13305Ssam } 54*13305Ssam 55*13305Ssam datum 56*13305Ssam fetch(key) 57*13305Ssam datum key; 58*13305Ssam { 59*13305Ssam register i; 60*13305Ssam datum item; 61*13305Ssam 62*13305Ssam dbm_access(calchash(key)); 63*13305Ssam for(i=0;; i+=2) { 64*13305Ssam item = makdatum(pagbuf, i); 65*13305Ssam if(item.dptr == NULL) 66*13305Ssam return(item); 67*13305Ssam if(cmpdatum(key, item) == 0) { 68*13305Ssam item = makdatum(pagbuf, i+1); 69*13305Ssam if(item.dptr == NULL) 70*13305Ssam printf("items not in pairs\n"); 71*13305Ssam return(item); 72*13305Ssam } 73*13305Ssam } 74*13305Ssam } 75*13305Ssam 76*13305Ssam delete(key) 77*13305Ssam datum key; 78*13305Ssam { 79*13305Ssam register i; 80*13305Ssam datum item; 81*13305Ssam 82*13305Ssam if (dbrdonly) 83*13305Ssam return -1; 84*13305Ssam dbm_access(calchash(key)); 85*13305Ssam for(i=0;; i+=2) { 86*13305Ssam item = makdatum(pagbuf, i); 87*13305Ssam if(item.dptr == NULL) 88*13305Ssam return(-1); 89*13305Ssam if(cmpdatum(key, item) == 0) { 90*13305Ssam delitem(pagbuf, i); 91*13305Ssam delitem(pagbuf, i); 92*13305Ssam break; 93*13305Ssam } 94*13305Ssam } 95*13305Ssam lseek(pagf, blkno*PBLKSIZ, 0); 96*13305Ssam write(pagf, pagbuf, PBLKSIZ); 97*13305Ssam return(0); 98*13305Ssam } 99*13305Ssam 100*13305Ssam store(key, dat) 101*13305Ssam datum key, dat; 102*13305Ssam { 103*13305Ssam register i; 104*13305Ssam datum item; 105*13305Ssam char ovfbuf[PBLKSIZ]; 106*13305Ssam 107*13305Ssam if (dbrdonly) 108*13305Ssam return -1; 109*13305Ssam loop: 110*13305Ssam dbm_access(calchash(key)); 111*13305Ssam for(i=0;; i+=2) { 112*13305Ssam item = makdatum(pagbuf, i); 113*13305Ssam if(item.dptr == NULL) 114*13305Ssam break; 115*13305Ssam if(cmpdatum(key, item) == 0) { 116*13305Ssam delitem(pagbuf, i); 117*13305Ssam delitem(pagbuf, i); 118*13305Ssam break; 119*13305Ssam } 120*13305Ssam } 121*13305Ssam i = additem(pagbuf, key); 122*13305Ssam if(i < 0) 123*13305Ssam goto split; 124*13305Ssam if(additem(pagbuf, dat) < 0) { 125*13305Ssam delitem(pagbuf, i); 126*13305Ssam goto split; 127*13305Ssam } 128*13305Ssam lseek(pagf, blkno*PBLKSIZ, 0); 129*13305Ssam write(pagf, pagbuf, PBLKSIZ); 130*13305Ssam return (0); 131*13305Ssam 132*13305Ssam split: 133*13305Ssam if(key.dsize+dat.dsize+2*sizeof(short) >= PBLKSIZ) { 134*13305Ssam printf("entry too big\n"); 135*13305Ssam return (-1); 136*13305Ssam } 137*13305Ssam clrbuf(ovfbuf, PBLKSIZ); 138*13305Ssam for(i=0;;) { 139*13305Ssam item = makdatum(pagbuf, i); 140*13305Ssam if(item.dptr == NULL) 141*13305Ssam break; 142*13305Ssam if(calchash(item) & (hmask+1)) { 143*13305Ssam additem(ovfbuf, item); 144*13305Ssam delitem(pagbuf, i); 145*13305Ssam item = makdatum(pagbuf, i); 146*13305Ssam if(item.dptr == NULL) { 147*13305Ssam printf("split not paired\n"); 148*13305Ssam break; 149*13305Ssam } 150*13305Ssam additem(ovfbuf, item); 151*13305Ssam delitem(pagbuf, i); 152*13305Ssam continue; 153*13305Ssam } 154*13305Ssam i += 2; 155*13305Ssam } 156*13305Ssam lseek(pagf, blkno*PBLKSIZ, 0); 157*13305Ssam write(pagf, pagbuf, PBLKSIZ); 158*13305Ssam lseek(pagf, (blkno+hmask+1)*PBLKSIZ, 0); 159*13305Ssam write(pagf, ovfbuf, PBLKSIZ); 160*13305Ssam setbit(); 161*13305Ssam goto loop; 162*13305Ssam } 163*13305Ssam 164*13305Ssam datum 165*13305Ssam firstkey() 166*13305Ssam { 167*13305Ssam return(firsthash(0L)); 168*13305Ssam } 169*13305Ssam 170*13305Ssam datum 171*13305Ssam nextkey(key) 172*13305Ssam datum key; 173*13305Ssam { 174*13305Ssam register i; 175*13305Ssam datum item, bitem; 176*13305Ssam long hash; 177*13305Ssam int f; 178*13305Ssam 179*13305Ssam hash = calchash(key); 180*13305Ssam dbm_access(hash); 181*13305Ssam f = 1; 182*13305Ssam for(i=0;; i+=2) { 183*13305Ssam item = makdatum(pagbuf, i); 184*13305Ssam if(item.dptr == NULL) 185*13305Ssam break; 186*13305Ssam if(cmpdatum(key, item) <= 0) 187*13305Ssam continue; 188*13305Ssam if(f || cmpdatum(bitem, item) < 0) { 189*13305Ssam bitem = item; 190*13305Ssam f = 0; 191*13305Ssam } 192*13305Ssam } 193*13305Ssam if(f == 0) 194*13305Ssam return(bitem); 195*13305Ssam hash = hashinc(hash); 196*13305Ssam if(hash == 0) 197*13305Ssam return(item); 198*13305Ssam return(firsthash(hash)); 199*13305Ssam } 200*13305Ssam 201*13305Ssam datum 202*13305Ssam firsthash(hash) 203*13305Ssam long hash; 204*13305Ssam { 205*13305Ssam register i; 206*13305Ssam datum item, bitem; 207*13305Ssam 208*13305Ssam loop: 209*13305Ssam dbm_access(hash); 210*13305Ssam bitem = makdatum(pagbuf, 0); 211*13305Ssam for(i=2;; i+=2) { 212*13305Ssam item = makdatum(pagbuf, i); 213*13305Ssam if(item.dptr == NULL) 214*13305Ssam break; 215*13305Ssam if(cmpdatum(bitem, item) < 0) 216*13305Ssam bitem = item; 217*13305Ssam } 218*13305Ssam if(bitem.dptr != NULL) 219*13305Ssam return(bitem); 220*13305Ssam hash = hashinc(hash); 221*13305Ssam if(hash == 0) 222*13305Ssam return(item); 223*13305Ssam goto loop; 224*13305Ssam } 225*13305Ssam 226*13305Ssam dbm_access(hash) 227*13305Ssam long hash; 228*13305Ssam { 229*13305Ssam static long oldb = -1; 230*13305Ssam 231*13305Ssam for(hmask=0;; hmask=(hmask<<1)+1) { 232*13305Ssam blkno = hash & hmask; 233*13305Ssam bitno = blkno + hmask; 234*13305Ssam if(getbit() == 0) 235*13305Ssam break; 236*13305Ssam } 237*13305Ssam if(blkno != oldb) { 238*13305Ssam clrbuf(pagbuf, PBLKSIZ); 239*13305Ssam lseek(pagf, blkno*PBLKSIZ, 0); 240*13305Ssam read(pagf, pagbuf, PBLKSIZ); 241*13305Ssam chkblk(pagbuf); 242*13305Ssam oldb = blkno; 243*13305Ssam } 244*13305Ssam } 245*13305Ssam 246*13305Ssam getbit() 247*13305Ssam { 248*13305Ssam long bn; 249*13305Ssam register b, i, n; 250*13305Ssam static oldb = -1; 251*13305Ssam 252*13305Ssam if(bitno > maxbno) 253*13305Ssam return(0); 254*13305Ssam n = bitno % BYTESIZ; 255*13305Ssam bn = bitno / BYTESIZ; 256*13305Ssam i = bn % DBLKSIZ; 257*13305Ssam b = bn / DBLKSIZ; 258*13305Ssam if(b != oldb) { 259*13305Ssam clrbuf(dirbuf, DBLKSIZ); 260*13305Ssam lseek(dirf, (long)b*DBLKSIZ, 0); 261*13305Ssam read(dirf, dirbuf, DBLKSIZ); 262*13305Ssam oldb = b; 263*13305Ssam } 264*13305Ssam if(dirbuf[i] & (1<<n)) 265*13305Ssam return(1); 266*13305Ssam return(0); 267*13305Ssam } 268*13305Ssam 269*13305Ssam setbit() 270*13305Ssam { 271*13305Ssam long bn; 272*13305Ssam register i, n, b; 273*13305Ssam 274*13305Ssam if (dbrdonly) 275*13305Ssam return -1; 276*13305Ssam if(bitno > maxbno) { 277*13305Ssam maxbno = bitno; 278*13305Ssam getbit(); 279*13305Ssam } 280*13305Ssam n = bitno % BYTESIZ; 281*13305Ssam bn = bitno / BYTESIZ; 282*13305Ssam i = bn % DBLKSIZ; 283*13305Ssam b = bn / DBLKSIZ; 284*13305Ssam dirbuf[i] |= 1<<n; 285*13305Ssam lseek(dirf, (long)b*DBLKSIZ, 0); 286*13305Ssam write(dirf, dirbuf, DBLKSIZ); 287*13305Ssam } 288*13305Ssam 289*13305Ssam clrbuf(cp, n) 290*13305Ssam register char *cp; 291*13305Ssam register n; 292*13305Ssam { 293*13305Ssam 294*13305Ssam do 295*13305Ssam *cp++ = 0; 296*13305Ssam while(--n); 297*13305Ssam } 298*13305Ssam 299*13305Ssam datum 300*13305Ssam makdatum(buf, n) 301*13305Ssam char buf[PBLKSIZ]; 302*13305Ssam { 303*13305Ssam register short *sp; 304*13305Ssam register t; 305*13305Ssam datum item; 306*13305Ssam 307*13305Ssam sp = (short *)buf; 308*13305Ssam if(n < 0 || n >= sp[0]) 309*13305Ssam goto null; 310*13305Ssam t = PBLKSIZ; 311*13305Ssam if(n > 0) 312*13305Ssam t = sp[n+1-1]; 313*13305Ssam item.dptr = buf+sp[n+1]; 314*13305Ssam item.dsize = t - sp[n+1]; 315*13305Ssam return(item); 316*13305Ssam 317*13305Ssam null: 318*13305Ssam item.dptr = NULL; 319*13305Ssam item.dsize = 0; 320*13305Ssam return(item); 321*13305Ssam } 322*13305Ssam 323*13305Ssam cmpdatum(d1, d2) 324*13305Ssam datum d1, d2; 325*13305Ssam { 326*13305Ssam register n; 327*13305Ssam register char *p1, *p2; 328*13305Ssam 329*13305Ssam n = d1.dsize; 330*13305Ssam if(n != d2.dsize) 331*13305Ssam return(n - d2.dsize); 332*13305Ssam if(n == 0) 333*13305Ssam return(0); 334*13305Ssam p1 = d1.dptr; 335*13305Ssam p2 = d2.dptr; 336*13305Ssam do 337*13305Ssam if(*p1++ != *p2++) 338*13305Ssam return(*--p1 - *--p2); 339*13305Ssam while(--n); 340*13305Ssam return(0); 341*13305Ssam } 342*13305Ssam 343*13305Ssam int hitab[16] 344*13305Ssam /* ken's 345*13305Ssam { 346*13305Ssam 055,043,036,054,063,014,004,005, 347*13305Ssam 010,064,077,000,035,027,025,071, 348*13305Ssam }; 349*13305Ssam */ 350*13305Ssam = { 61, 57, 53, 49, 45, 41, 37, 33, 351*13305Ssam 29, 25, 21, 17, 13, 9, 5, 1, 352*13305Ssam }; 353*13305Ssam long hltab[64] 354*13305Ssam = { 355*13305Ssam 06100151277L,06106161736L,06452611562L,05001724107L, 356*13305Ssam 02614772546L,04120731531L,04665262210L,07347467531L, 357*13305Ssam 06735253126L,06042345173L,03072226605L,01464164730L, 358*13305Ssam 03247435524L,07652510057L,01546775256L,05714532133L, 359*13305Ssam 06173260402L,07517101630L,02431460343L,01743245566L, 360*13305Ssam 00261675137L,02433103631L,03421772437L,04447707466L, 361*13305Ssam 04435620103L,03757017115L,03641531772L,06767633246L, 362*13305Ssam 02673230344L,00260612216L,04133454451L,00615531516L, 363*13305Ssam 06137717526L,02574116560L,02304023373L,07061702261L, 364*13305Ssam 05153031405L,05322056705L,07401116734L,06552375715L, 365*13305Ssam 06165233473L,05311063631L,01212221723L,01052267235L, 366*13305Ssam 06000615237L,01075222665L,06330216006L,04402355630L, 367*13305Ssam 01451177262L,02000133436L,06025467062L,07121076461L, 368*13305Ssam 03123433522L,01010635225L,01716177066L,05161746527L, 369*13305Ssam 01736635071L,06243505026L,03637211610L,01756474365L, 370*13305Ssam 04723077174L,03642763134L,05750130273L,03655541561L, 371*13305Ssam }; 372*13305Ssam 373*13305Ssam long 374*13305Ssam hashinc(hash) 375*13305Ssam long hash; 376*13305Ssam { 377*13305Ssam long bit; 378*13305Ssam 379*13305Ssam hash &= hmask; 380*13305Ssam bit = hmask+1; 381*13305Ssam for(;;) { 382*13305Ssam bit >>= 1; 383*13305Ssam if(bit == 0) 384*13305Ssam return(0L); 385*13305Ssam if((hash&bit) == 0) 386*13305Ssam return(hash|bit); 387*13305Ssam hash &= ~bit; 388*13305Ssam } 389*13305Ssam } 390*13305Ssam 391*13305Ssam long 392*13305Ssam calchash(item) 393*13305Ssam datum item; 394*13305Ssam { 395*13305Ssam register i, j, f; 396*13305Ssam long hashl; 397*13305Ssam int hashi; 398*13305Ssam 399*13305Ssam hashl = 0; 400*13305Ssam hashi = 0; 401*13305Ssam for(i=0; i<item.dsize; i++) { 402*13305Ssam f = item.dptr[i]; 403*13305Ssam for(j=0; j<BYTESIZ; j+=4) { 404*13305Ssam hashi += hitab[f&017]; 405*13305Ssam hashl += hltab[hashi&63]; 406*13305Ssam f >>= 4; 407*13305Ssam } 408*13305Ssam } 409*13305Ssam return(hashl); 410*13305Ssam } 411*13305Ssam 412*13305Ssam delitem(buf, n) 413*13305Ssam char buf[PBLKSIZ]; 414*13305Ssam { 415*13305Ssam register short *sp; 416*13305Ssam register i1, i2, i3; 417*13305Ssam 418*13305Ssam sp = (short *)buf; 419*13305Ssam if(n < 0 || n >= sp[0]) 420*13305Ssam goto bad; 421*13305Ssam i1 = sp[n+1]; 422*13305Ssam i2 = PBLKSIZ; 423*13305Ssam if(n > 0) 424*13305Ssam i2 = sp[n+1-1]; 425*13305Ssam i3 = sp[sp[0]+1-1]; 426*13305Ssam if(i2 > i1) 427*13305Ssam while(i1 > i3) { 428*13305Ssam i1--; 429*13305Ssam i2--; 430*13305Ssam buf[i2] = buf[i1]; 431*13305Ssam buf[i1] = 0; 432*13305Ssam } 433*13305Ssam i2 -= i1; 434*13305Ssam for(i1=n+1; i1<sp[0]; i1++) 435*13305Ssam sp[i1+1-1] = sp[i1+1] + i2; 436*13305Ssam sp[0]--; 437*13305Ssam sp[sp[0]+1] = 0; 438*13305Ssam return; 439*13305Ssam 440*13305Ssam bad: 441*13305Ssam printf("bad delitem\n"); 442*13305Ssam abort(); 443*13305Ssam } 444*13305Ssam 445*13305Ssam additem(buf, item) 446*13305Ssam char buf[PBLKSIZ]; 447*13305Ssam datum item; 448*13305Ssam { 449*13305Ssam register short *sp; 450*13305Ssam register i1, i2; 451*13305Ssam 452*13305Ssam sp = (short *)buf; 453*13305Ssam i1 = PBLKSIZ; 454*13305Ssam if(sp[0] > 0) 455*13305Ssam i1 = sp[sp[0]+1-1]; 456*13305Ssam i1 -= item.dsize; 457*13305Ssam i2 = (sp[0]+2) * sizeof(short); 458*13305Ssam if(i1 <= i2) 459*13305Ssam return(-1); 460*13305Ssam sp[sp[0]+1] = i1; 461*13305Ssam for(i2=0; i2<item.dsize; i2++) { 462*13305Ssam buf[i1] = item.dptr[i2]; 463*13305Ssam i1++; 464*13305Ssam } 465*13305Ssam sp[0]++; 466*13305Ssam return(sp[0]-1); 467*13305Ssam } 468*13305Ssam 469*13305Ssam chkblk(buf) 470*13305Ssam char buf[PBLKSIZ]; 471*13305Ssam { 472*13305Ssam register short *sp; 473*13305Ssam register t, i; 474*13305Ssam 475*13305Ssam sp = (short *)buf; 476*13305Ssam t = PBLKSIZ; 477*13305Ssam for(i=0; i<sp[0]; i++) { 478*13305Ssam if(sp[i+1] > t) 479*13305Ssam goto bad; 480*13305Ssam t = sp[i+1]; 481*13305Ssam } 482*13305Ssam if(t < (sp[0]+1)*sizeof(short)) 483*13305Ssam goto bad; 484*13305Ssam return; 485*13305Ssam 486*13305Ssam bad: 487*13305Ssam printf("bad block\n"); 488*13305Ssam abort(); 489*13305Ssam clrbuf(buf, PBLKSIZ); 490*13305Ssam } 491