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