113305Ssam #ifndef lint 2*22023Ssam static char sccsid[] = "@(#)dbm.c 4.4 (Berkeley) 06/04/85"; 313305Ssam #endif 413305Ssam 513305Ssam #include "dbm.h" 613305Ssam #include <sys/types.h> 713305Ssam #include <sys/stat.h> 813305Ssam 913305Ssam dbminit(file) 1013305Ssam char *file; 1113305Ssam { 1213305Ssam struct stat statb; 1313305Ssam 1413305Ssam dbrdonly = 0; 1513305Ssam strcpy(pagbuf, file); 1613305Ssam strcat(pagbuf, ".pag"); 1713305Ssam pagf = open(pagbuf, 2); 1813305Ssam if (pagf < 0) { 1913305Ssam pagf = open(pagbuf, 0); 2013305Ssam dbrdonly = 1; 2113305Ssam } 2213305Ssam 2313305Ssam strcpy(pagbuf, file); 2413305Ssam strcat(pagbuf, ".dir"); 2513305Ssam dirf = open(pagbuf, 2); 2613305Ssam if (dirf < 0) { 2713305Ssam dirf = open(pagbuf, 0); 2813305Ssam dbrdonly = 1; 2913305Ssam } 3013305Ssam if(pagf < 0 || dirf < 0) { 31*22023Ssam printf("dbm: %s: cannot open database\n", file); 3213305Ssam return(-1); 3313305Ssam } 3413305Ssam fstat(dirf, &statb); 3513305Ssam maxbno = statb.st_size*BYTESIZ-1; 3613305Ssam return(0); 3713305Ssam } 3813305Ssam 3913305Ssam long 4013305Ssam forder(key) 4113305Ssam datum key; 4213305Ssam { 4313305Ssam long hash; 4413305Ssam 4513305Ssam hash = calchash(key); 4613305Ssam for(hmask=0;; hmask=(hmask<<1)+1) { 4713305Ssam blkno = hash & hmask; 4813305Ssam bitno = blkno + hmask; 4913305Ssam if(getbit() == 0) 5013305Ssam break; 5113305Ssam } 5213305Ssam return(blkno); 5313305Ssam } 5413305Ssam 5513305Ssam datum 5613305Ssam fetch(key) 5713305Ssam datum key; 5813305Ssam { 5913305Ssam register i; 6013305Ssam datum item; 6113305Ssam 6213305Ssam dbm_access(calchash(key)); 6313305Ssam for(i=0;; i+=2) { 6413305Ssam item = makdatum(pagbuf, i); 6513305Ssam if(item.dptr == NULL) 6613305Ssam return(item); 6713305Ssam if(cmpdatum(key, item) == 0) { 6813305Ssam item = makdatum(pagbuf, i+1); 6913305Ssam if(item.dptr == NULL) 70*22023Ssam printf("dbm: items not in pairs\n"); 7113305Ssam return(item); 7213305Ssam } 7313305Ssam } 7413305Ssam } 7513305Ssam 7613305Ssam delete(key) 7713305Ssam datum key; 7813305Ssam { 7913305Ssam register i; 8013305Ssam datum item; 8113305Ssam 8213305Ssam if (dbrdonly) 8313305Ssam return -1; 8413305Ssam dbm_access(calchash(key)); 8513305Ssam for(i=0;; i+=2) { 8613305Ssam item = makdatum(pagbuf, i); 8713305Ssam if(item.dptr == NULL) 8813305Ssam return(-1); 8913305Ssam if(cmpdatum(key, item) == 0) { 9013305Ssam delitem(pagbuf, i); 9113305Ssam delitem(pagbuf, i); 9213305Ssam break; 9313305Ssam } 9413305Ssam } 9513305Ssam lseek(pagf, blkno*PBLKSIZ, 0); 9613305Ssam write(pagf, pagbuf, PBLKSIZ); 9713305Ssam return(0); 9813305Ssam } 9913305Ssam 10013305Ssam store(key, dat) 10113305Ssam datum key, dat; 10213305Ssam { 10313305Ssam register i; 10413305Ssam datum item; 10513305Ssam char ovfbuf[PBLKSIZ]; 10613305Ssam 10713305Ssam if (dbrdonly) 10813305Ssam return -1; 10913305Ssam loop: 11013305Ssam dbm_access(calchash(key)); 11113305Ssam for(i=0;; i+=2) { 11213305Ssam item = makdatum(pagbuf, i); 11313305Ssam if(item.dptr == NULL) 11413305Ssam break; 11513305Ssam if(cmpdatum(key, item) == 0) { 11613305Ssam delitem(pagbuf, i); 11713305Ssam delitem(pagbuf, i); 11813305Ssam break; 11913305Ssam } 12013305Ssam } 12113305Ssam i = additem(pagbuf, key); 12213305Ssam if(i < 0) 12313305Ssam goto split; 12413305Ssam if(additem(pagbuf, dat) < 0) { 12513305Ssam delitem(pagbuf, i); 12613305Ssam goto split; 12713305Ssam } 12813305Ssam lseek(pagf, blkno*PBLKSIZ, 0); 12913305Ssam write(pagf, pagbuf, PBLKSIZ); 13013305Ssam return (0); 13113305Ssam 13213305Ssam split: 13318610Sralph if(key.dsize+dat.dsize+3*sizeof(short) >= PBLKSIZ) { 134*22023Ssam printf("dbm: entry too big\n"); 13513305Ssam return (-1); 13613305Ssam } 13713305Ssam clrbuf(ovfbuf, PBLKSIZ); 13813305Ssam for(i=0;;) { 13913305Ssam item = makdatum(pagbuf, i); 14013305Ssam if(item.dptr == NULL) 14113305Ssam break; 14213305Ssam if(calchash(item) & (hmask+1)) { 14313305Ssam additem(ovfbuf, item); 14413305Ssam delitem(pagbuf, i); 14513305Ssam item = makdatum(pagbuf, i); 14613305Ssam if(item.dptr == NULL) { 147*22023Ssam printf("dbm: split not paired\n"); 14813305Ssam break; 14913305Ssam } 15013305Ssam additem(ovfbuf, item); 15113305Ssam delitem(pagbuf, i); 15213305Ssam continue; 15313305Ssam } 15413305Ssam i += 2; 15513305Ssam } 15613305Ssam lseek(pagf, blkno*PBLKSIZ, 0); 15713305Ssam write(pagf, pagbuf, PBLKSIZ); 15813305Ssam lseek(pagf, (blkno+hmask+1)*PBLKSIZ, 0); 15913305Ssam write(pagf, ovfbuf, PBLKSIZ); 16013305Ssam setbit(); 16113305Ssam goto loop; 16213305Ssam } 16313305Ssam 16413305Ssam datum 16513305Ssam firstkey() 16613305Ssam { 16713305Ssam return(firsthash(0L)); 16813305Ssam } 16913305Ssam 17013305Ssam datum 17113305Ssam nextkey(key) 17213305Ssam datum key; 17313305Ssam { 17413305Ssam register i; 17513305Ssam datum item, bitem; 17613305Ssam long hash; 17713305Ssam int f; 17813305Ssam 17913305Ssam hash = calchash(key); 18013305Ssam dbm_access(hash); 18113305Ssam f = 1; 18213305Ssam for(i=0;; i+=2) { 18313305Ssam item = makdatum(pagbuf, i); 18413305Ssam if(item.dptr == NULL) 18513305Ssam break; 18613305Ssam if(cmpdatum(key, item) <= 0) 18713305Ssam continue; 18813305Ssam if(f || cmpdatum(bitem, item) < 0) { 18913305Ssam bitem = item; 19013305Ssam f = 0; 19113305Ssam } 19213305Ssam } 19313305Ssam if(f == 0) 19413305Ssam return(bitem); 19513305Ssam hash = hashinc(hash); 19613305Ssam if(hash == 0) 19713305Ssam return(item); 19813305Ssam return(firsthash(hash)); 19913305Ssam } 20013305Ssam 20113305Ssam datum 20213305Ssam firsthash(hash) 20313305Ssam long hash; 20413305Ssam { 20513305Ssam register i; 20613305Ssam datum item, bitem; 20713305Ssam 20813305Ssam loop: 20913305Ssam dbm_access(hash); 21013305Ssam bitem = makdatum(pagbuf, 0); 21113305Ssam for(i=2;; i+=2) { 21213305Ssam item = makdatum(pagbuf, i); 21313305Ssam if(item.dptr == NULL) 21413305Ssam break; 21513305Ssam if(cmpdatum(bitem, item) < 0) 21613305Ssam bitem = item; 21713305Ssam } 21813305Ssam if(bitem.dptr != NULL) 21913305Ssam return(bitem); 22013305Ssam hash = hashinc(hash); 22113305Ssam if(hash == 0) 22213305Ssam return(item); 22313305Ssam goto loop; 22413305Ssam } 22513305Ssam 22613305Ssam dbm_access(hash) 22713305Ssam long hash; 22813305Ssam { 22913305Ssam static long oldb = -1; 23013305Ssam 23113305Ssam for(hmask=0;; hmask=(hmask<<1)+1) { 23213305Ssam blkno = hash & hmask; 23313305Ssam bitno = blkno + hmask; 23413305Ssam if(getbit() == 0) 23513305Ssam break; 23613305Ssam } 23713305Ssam if(blkno != oldb) { 23813305Ssam clrbuf(pagbuf, PBLKSIZ); 23913305Ssam lseek(pagf, blkno*PBLKSIZ, 0); 24013305Ssam read(pagf, pagbuf, PBLKSIZ); 24113305Ssam chkblk(pagbuf); 24213305Ssam oldb = blkno; 24313305Ssam } 24413305Ssam } 24513305Ssam 24613305Ssam getbit() 24713305Ssam { 24813305Ssam long bn; 24913305Ssam register b, i, n; 25013305Ssam static oldb = -1; 25113305Ssam 25213305Ssam if(bitno > maxbno) 25313305Ssam return(0); 25413305Ssam n = bitno % BYTESIZ; 25513305Ssam bn = bitno / BYTESIZ; 25613305Ssam i = bn % DBLKSIZ; 25713305Ssam b = bn / DBLKSIZ; 25813305Ssam if(b != oldb) { 25913305Ssam clrbuf(dirbuf, DBLKSIZ); 26013305Ssam lseek(dirf, (long)b*DBLKSIZ, 0); 26113305Ssam read(dirf, dirbuf, DBLKSIZ); 26213305Ssam oldb = b; 26313305Ssam } 26413305Ssam if(dirbuf[i] & (1<<n)) 26513305Ssam return(1); 26613305Ssam return(0); 26713305Ssam } 26813305Ssam 26913305Ssam setbit() 27013305Ssam { 27113305Ssam long bn; 27213305Ssam register i, n, b; 27313305Ssam 27413305Ssam if (dbrdonly) 27513305Ssam return -1; 27613305Ssam if(bitno > maxbno) { 27713305Ssam maxbno = bitno; 27813305Ssam getbit(); 27913305Ssam } 28013305Ssam n = bitno % BYTESIZ; 28113305Ssam bn = bitno / BYTESIZ; 28213305Ssam i = bn % DBLKSIZ; 28313305Ssam b = bn / DBLKSIZ; 28413305Ssam dirbuf[i] |= 1<<n; 28513305Ssam lseek(dirf, (long)b*DBLKSIZ, 0); 28613305Ssam write(dirf, dirbuf, DBLKSIZ); 28713305Ssam } 28813305Ssam 28913305Ssam clrbuf(cp, n) 29013305Ssam register char *cp; 29113305Ssam register n; 29213305Ssam { 29313305Ssam 29413305Ssam do 29513305Ssam *cp++ = 0; 29613305Ssam while(--n); 29713305Ssam } 29813305Ssam 29913305Ssam datum 30013305Ssam makdatum(buf, n) 30113305Ssam char buf[PBLKSIZ]; 30213305Ssam { 30313305Ssam register short *sp; 30413305Ssam register t; 30513305Ssam datum item; 30613305Ssam 30713305Ssam sp = (short *)buf; 30813305Ssam if(n < 0 || n >= sp[0]) 30913305Ssam goto null; 31013305Ssam t = PBLKSIZ; 31113305Ssam if(n > 0) 31213305Ssam t = sp[n+1-1]; 31313305Ssam item.dptr = buf+sp[n+1]; 31413305Ssam item.dsize = t - sp[n+1]; 31513305Ssam return(item); 31613305Ssam 31713305Ssam null: 31813305Ssam item.dptr = NULL; 31913305Ssam item.dsize = 0; 32013305Ssam return(item); 32113305Ssam } 32213305Ssam 32313305Ssam cmpdatum(d1, d2) 32413305Ssam datum d1, d2; 32513305Ssam { 32613305Ssam register n; 32713305Ssam register char *p1, *p2; 32813305Ssam 32913305Ssam n = d1.dsize; 33013305Ssam if(n != d2.dsize) 33113305Ssam return(n - d2.dsize); 33213305Ssam if(n == 0) 33313305Ssam return(0); 33413305Ssam p1 = d1.dptr; 33513305Ssam p2 = d2.dptr; 33613305Ssam do 33713305Ssam if(*p1++ != *p2++) 33813305Ssam return(*--p1 - *--p2); 33913305Ssam while(--n); 34013305Ssam return(0); 34113305Ssam } 34213305Ssam 34313305Ssam int hitab[16] 34413305Ssam /* ken's 34513305Ssam { 34613305Ssam 055,043,036,054,063,014,004,005, 34713305Ssam 010,064,077,000,035,027,025,071, 34813305Ssam }; 34913305Ssam */ 35013305Ssam = { 61, 57, 53, 49, 45, 41, 37, 33, 35113305Ssam 29, 25, 21, 17, 13, 9, 5, 1, 35213305Ssam }; 35313305Ssam long hltab[64] 35413305Ssam = { 35513305Ssam 06100151277L,06106161736L,06452611562L,05001724107L, 35613305Ssam 02614772546L,04120731531L,04665262210L,07347467531L, 35713305Ssam 06735253126L,06042345173L,03072226605L,01464164730L, 35813305Ssam 03247435524L,07652510057L,01546775256L,05714532133L, 35913305Ssam 06173260402L,07517101630L,02431460343L,01743245566L, 36013305Ssam 00261675137L,02433103631L,03421772437L,04447707466L, 36113305Ssam 04435620103L,03757017115L,03641531772L,06767633246L, 36213305Ssam 02673230344L,00260612216L,04133454451L,00615531516L, 36313305Ssam 06137717526L,02574116560L,02304023373L,07061702261L, 36413305Ssam 05153031405L,05322056705L,07401116734L,06552375715L, 36513305Ssam 06165233473L,05311063631L,01212221723L,01052267235L, 36613305Ssam 06000615237L,01075222665L,06330216006L,04402355630L, 36713305Ssam 01451177262L,02000133436L,06025467062L,07121076461L, 36813305Ssam 03123433522L,01010635225L,01716177066L,05161746527L, 36913305Ssam 01736635071L,06243505026L,03637211610L,01756474365L, 37013305Ssam 04723077174L,03642763134L,05750130273L,03655541561L, 37113305Ssam }; 37213305Ssam 37313305Ssam long 37413305Ssam hashinc(hash) 37513305Ssam long hash; 37613305Ssam { 37713305Ssam long bit; 37813305Ssam 37913305Ssam hash &= hmask; 38013305Ssam bit = hmask+1; 38113305Ssam for(;;) { 38213305Ssam bit >>= 1; 38313305Ssam if(bit == 0) 38413305Ssam return(0L); 38513305Ssam if((hash&bit) == 0) 38613305Ssam return(hash|bit); 38713305Ssam hash &= ~bit; 38813305Ssam } 38913305Ssam } 39013305Ssam 39113305Ssam long 39213305Ssam calchash(item) 39313305Ssam datum item; 39413305Ssam { 39513305Ssam register i, j, f; 39613305Ssam long hashl; 39713305Ssam int hashi; 39813305Ssam 39913305Ssam hashl = 0; 40013305Ssam hashi = 0; 40113305Ssam for(i=0; i<item.dsize; i++) { 40213305Ssam f = item.dptr[i]; 40313305Ssam for(j=0; j<BYTESIZ; j+=4) { 40413305Ssam hashi += hitab[f&017]; 40513305Ssam hashl += hltab[hashi&63]; 40613305Ssam f >>= 4; 40713305Ssam } 40813305Ssam } 40913305Ssam return(hashl); 41013305Ssam } 41113305Ssam 41213305Ssam delitem(buf, n) 41313305Ssam char buf[PBLKSIZ]; 41413305Ssam { 41513305Ssam register short *sp; 41613305Ssam register i1, i2, i3; 41713305Ssam 41813305Ssam sp = (short *)buf; 41913305Ssam if(n < 0 || n >= sp[0]) 42013305Ssam goto bad; 42113305Ssam i1 = sp[n+1]; 42213305Ssam i2 = PBLKSIZ; 42313305Ssam if(n > 0) 42413305Ssam i2 = sp[n+1-1]; 42513305Ssam i3 = sp[sp[0]+1-1]; 42613305Ssam if(i2 > i1) 42713305Ssam while(i1 > i3) { 42813305Ssam i1--; 42913305Ssam i2--; 43013305Ssam buf[i2] = buf[i1]; 43113305Ssam buf[i1] = 0; 43213305Ssam } 43313305Ssam i2 -= i1; 43413305Ssam for(i1=n+1; i1<sp[0]; i1++) 43513305Ssam sp[i1+1-1] = sp[i1+1] + i2; 43613305Ssam sp[0]--; 43713305Ssam sp[sp[0]+1] = 0; 43813305Ssam return; 43913305Ssam 44013305Ssam bad: 441*22023Ssam printf("dbm: bad delitem\n"); 44213305Ssam abort(); 44313305Ssam } 44413305Ssam 44513305Ssam additem(buf, item) 44613305Ssam char buf[PBLKSIZ]; 44713305Ssam datum item; 44813305Ssam { 44913305Ssam register short *sp; 45013305Ssam register i1, i2; 45113305Ssam 45213305Ssam sp = (short *)buf; 45313305Ssam i1 = PBLKSIZ; 45413305Ssam if(sp[0] > 0) 45513305Ssam i1 = sp[sp[0]+1-1]; 45613305Ssam i1 -= item.dsize; 45713305Ssam i2 = (sp[0]+2) * sizeof(short); 45813305Ssam if(i1 <= i2) 45913305Ssam return(-1); 46013305Ssam sp[sp[0]+1] = i1; 46113305Ssam for(i2=0; i2<item.dsize; i2++) { 46213305Ssam buf[i1] = item.dptr[i2]; 46313305Ssam i1++; 46413305Ssam } 46513305Ssam sp[0]++; 46613305Ssam return(sp[0]-1); 46713305Ssam } 46813305Ssam 46913305Ssam chkblk(buf) 47013305Ssam char buf[PBLKSIZ]; 47113305Ssam { 47213305Ssam register short *sp; 47313305Ssam register t, i; 47413305Ssam 47513305Ssam sp = (short *)buf; 47613305Ssam t = PBLKSIZ; 47713305Ssam for(i=0; i<sp[0]; i++) { 47813305Ssam if(sp[i+1] > t) 47913305Ssam goto bad; 48013305Ssam t = sp[i+1]; 48113305Ssam } 48213305Ssam if(t < (sp[0]+1)*sizeof(short)) 48313305Ssam goto bad; 48413305Ssam return; 48513305Ssam 48613305Ssam bad: 48721874Sbloom printf("dbm: bad block\n"); 48813305Ssam abort(); 48913305Ssam clrbuf(buf, PBLKSIZ); 49013305Ssam } 491