|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1983 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #if defined(LIBC_SCCS) && !defined(lint) ! 8: static char sccsid[] = "@(#)ndbm.c 5.4 (Berkeley) 9/4/87"; ! 9: #endif LIBC_SCCS and not lint ! 10: ! 11: #include <sys/types.h> ! 12: #include <sys/stat.h> ! 13: #include <sys/file.h> ! 14: #include <stdio.h> ! 15: #include <errno.h> ! 16: #include <ndbm.h> ! 17: ! 18: #define BYTESIZ 8 ! 19: #undef setbit ! 20: ! 21: static datum makdatum(); ! 22: static long hashinc(); ! 23: static long dcalchash(); ! 24: extern int errno; ! 25: ! 26: DBM * ! 27: dbm_open(file, flags, mode) ! 28: char *file; ! 29: int flags, mode; ! 30: { ! 31: struct stat statb; ! 32: register DBM *db; ! 33: ! 34: if ((db = (DBM *)malloc(sizeof *db)) == 0) { ! 35: errno = ENOMEM; ! 36: return ((DBM *)0); ! 37: } ! 38: db->dbm_flags = (flags & 03) == O_RDONLY ? _DBM_RDONLY : 0; ! 39: if ((flags & 03) == O_WRONLY) ! 40: flags = (flags & ~03) | O_RDWR; ! 41: strcpy(db->dbm_pagbuf, file); ! 42: strcat(db->dbm_pagbuf, ".pag"); ! 43: db->dbm_pagf = open(db->dbm_pagbuf, flags, mode); ! 44: if (db->dbm_pagf < 0) ! 45: goto bad; ! 46: strcpy(db->dbm_pagbuf, file); ! 47: strcat(db->dbm_pagbuf, ".dir"); ! 48: db->dbm_dirf = open(db->dbm_pagbuf, flags, mode); ! 49: if (db->dbm_dirf < 0) ! 50: goto bad1; ! 51: fstat(db->dbm_dirf, &statb); ! 52: db->dbm_maxbno = statb.st_size*BYTESIZ-1; ! 53: db->dbm_pagbno = db->dbm_dirbno = -1; ! 54: return (db); ! 55: bad1: ! 56: (void) close(db->dbm_pagf); ! 57: bad: ! 58: free((char *)db); ! 59: return ((DBM *)0); ! 60: } ! 61: ! 62: void ! 63: dbm_close(db) ! 64: DBM *db; ! 65: { ! 66: ! 67: (void) close(db->dbm_dirf); ! 68: (void) close(db->dbm_pagf); ! 69: free((char *)db); ! 70: } ! 71: ! 72: long ! 73: dbm_forder(db, key) ! 74: register DBM *db; ! 75: datum key; ! 76: { ! 77: long hash; ! 78: ! 79: hash = dcalchash(key); ! 80: for (db->dbm_hmask=0;; db->dbm_hmask=(db->dbm_hmask<<1)+1) { ! 81: db->dbm_blkno = hash & db->dbm_hmask; ! 82: db->dbm_bitno = db->dbm_blkno + db->dbm_hmask; ! 83: if (getbit(db) == 0) ! 84: break; ! 85: } ! 86: return (db->dbm_blkno); ! 87: } ! 88: ! 89: datum ! 90: dbm_fetch(db, key) ! 91: register DBM *db; ! 92: datum key; ! 93: { ! 94: register i; ! 95: datum item; ! 96: ! 97: if (dbm_error(db)) ! 98: goto err; ! 99: dbm_access(db, dcalchash(key)); ! 100: if ((i = finddatum(db->dbm_pagbuf, key)) >= 0) { ! 101: item = makdatum(db->dbm_pagbuf, i+1); ! 102: if (item.dptr != NULL) ! 103: return (item); ! 104: } ! 105: err: ! 106: item.dptr = NULL; ! 107: item.dsize = 0; ! 108: return (item); ! 109: } ! 110: ! 111: dbm_delete(db, key) ! 112: register DBM *db; ! 113: datum key; ! 114: { ! 115: register i; ! 116: datum item; ! 117: ! 118: if (dbm_error(db)) ! 119: return (-1); ! 120: if (dbm_rdonly(db)) { ! 121: errno = EPERM; ! 122: return (-1); ! 123: } ! 124: dbm_access(db, dcalchash(key)); ! 125: if ((i = finddatum(db->dbm_pagbuf, key)) < 0) ! 126: return (-1); ! 127: if (!delitem(db->dbm_pagbuf, i)) ! 128: goto err; ! 129: db->dbm_pagbno = db->dbm_blkno; ! 130: (void) lseek(db->dbm_pagf, db->dbm_blkno*PBLKSIZ, L_SET); ! 131: if (write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ) { ! 132: err: ! 133: db->dbm_flags |= _DBM_IOERR; ! 134: return (-1); ! 135: } ! 136: return (0); ! 137: } ! 138: ! 139: dbm_store(db, key, dat, replace) ! 140: register DBM *db; ! 141: datum key, dat; ! 142: int replace; ! 143: { ! 144: register i; ! 145: datum item, item1; ! 146: char ovfbuf[PBLKSIZ]; ! 147: ! 148: if (dbm_error(db)) ! 149: return (-1); ! 150: if (dbm_rdonly(db)) { ! 151: errno = EPERM; ! 152: return (-1); ! 153: } ! 154: loop: ! 155: dbm_access(db, dcalchash(key)); ! 156: if ((i = finddatum(db->dbm_pagbuf, key)) >= 0) { ! 157: if (!replace) ! 158: return (1); ! 159: if (!delitem(db->dbm_pagbuf, i)) { ! 160: db->dbm_flags |= _DBM_IOERR; ! 161: return (-1); ! 162: } ! 163: } ! 164: if (!additem(db->dbm_pagbuf, key, dat)) ! 165: goto split; ! 166: db->dbm_pagbno = db->dbm_blkno; ! 167: (void) lseek(db->dbm_pagf, db->dbm_blkno*PBLKSIZ, L_SET); ! 168: if (write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ) { ! 169: db->dbm_flags |= _DBM_IOERR; ! 170: return (-1); ! 171: } ! 172: return (0); ! 173: ! 174: split: ! 175: if (key.dsize+dat.dsize+3*sizeof(short) >= PBLKSIZ) { ! 176: db->dbm_flags |= _DBM_IOERR; ! 177: errno = ENOSPC; ! 178: return (-1); ! 179: } ! 180: bzero(ovfbuf, PBLKSIZ); ! 181: for (i=0;;) { ! 182: item = makdatum(db->dbm_pagbuf, i); ! 183: if (item.dptr == NULL) ! 184: break; ! 185: if (dcalchash(item) & (db->dbm_hmask+1)) { ! 186: item1 = makdatum(db->dbm_pagbuf, i+1); ! 187: if (item1.dptr == NULL) { ! 188: fprintf(stderr, "ndbm: split not paired\n"); ! 189: db->dbm_flags |= _DBM_IOERR; ! 190: break; ! 191: } ! 192: if (!additem(ovfbuf, item, item1) || ! 193: !delitem(db->dbm_pagbuf, i)) { ! 194: db->dbm_flags |= _DBM_IOERR; ! 195: return (-1); ! 196: } ! 197: continue; ! 198: } ! 199: i += 2; ! 200: } ! 201: db->dbm_pagbno = db->dbm_blkno; ! 202: (void) lseek(db->dbm_pagf, db->dbm_blkno*PBLKSIZ, L_SET); ! 203: if (write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ) { ! 204: db->dbm_flags |= _DBM_IOERR; ! 205: return (-1); ! 206: } ! 207: (void) lseek(db->dbm_pagf, (db->dbm_blkno+db->dbm_hmask+1)*PBLKSIZ, L_SET); ! 208: if (write(db->dbm_pagf, ovfbuf, PBLKSIZ) != PBLKSIZ) { ! 209: db->dbm_flags |= _DBM_IOERR; ! 210: return (-1); ! 211: } ! 212: setbit(db); ! 213: goto loop; ! 214: } ! 215: ! 216: datum ! 217: dbm_firstkey(db) ! 218: DBM *db; ! 219: { ! 220: ! 221: db->dbm_blkptr = 0L; ! 222: db->dbm_keyptr = 0; ! 223: return (dbm_nextkey(db)); ! 224: } ! 225: ! 226: datum ! 227: dbm_nextkey(db) ! 228: register DBM *db; ! 229: { ! 230: struct stat statb; ! 231: datum item; ! 232: ! 233: if (dbm_error(db) || fstat(db->dbm_pagf, &statb) < 0) ! 234: goto err; ! 235: statb.st_size /= PBLKSIZ; ! 236: for (;;) { ! 237: if (db->dbm_blkptr != db->dbm_pagbno) { ! 238: db->dbm_pagbno = db->dbm_blkptr; ! 239: (void) lseek(db->dbm_pagf, db->dbm_blkptr*PBLKSIZ, L_SET); ! 240: if (read(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ) ! 241: bzero(db->dbm_pagbuf, PBLKSIZ); ! 242: #ifdef DEBUG ! 243: else if (chkblk(db->dbm_pagbuf) < 0) ! 244: db->dbm_flags |= _DBM_IOERR; ! 245: #endif ! 246: } ! 247: if (((short *)db->dbm_pagbuf)[0] != 0) { ! 248: item = makdatum(db->dbm_pagbuf, db->dbm_keyptr); ! 249: if (item.dptr != NULL) { ! 250: db->dbm_keyptr += 2; ! 251: return (item); ! 252: } ! 253: db->dbm_keyptr = 0; ! 254: } ! 255: if (++db->dbm_blkptr >= statb.st_size) ! 256: break; ! 257: } ! 258: err: ! 259: item.dptr = NULL; ! 260: item.dsize = 0; ! 261: return (item); ! 262: } ! 263: ! 264: static ! 265: dbm_access(db, hash) ! 266: register DBM *db; ! 267: long hash; ! 268: { ! 269: ! 270: for (db->dbm_hmask=0;; db->dbm_hmask=(db->dbm_hmask<<1)+1) { ! 271: db->dbm_blkno = hash & db->dbm_hmask; ! 272: db->dbm_bitno = db->dbm_blkno + db->dbm_hmask; ! 273: if (getbit(db) == 0) ! 274: break; ! 275: } ! 276: if (db->dbm_blkno != db->dbm_pagbno) { ! 277: db->dbm_pagbno = db->dbm_blkno; ! 278: (void) lseek(db->dbm_pagf, db->dbm_blkno*PBLKSIZ, L_SET); ! 279: if (read(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ) ! 280: bzero(db->dbm_pagbuf, PBLKSIZ); ! 281: #ifdef DEBUG ! 282: else if (chkblk(db->dbm_pagbuf) < 0) ! 283: db->dbm_flags |= _DBM_IOERR; ! 284: #endif ! 285: } ! 286: } ! 287: ! 288: static ! 289: getbit(db) ! 290: register DBM *db; ! 291: { ! 292: long bn; ! 293: register b, i, n; ! 294: ! 295: ! 296: if (db->dbm_bitno > db->dbm_maxbno) ! 297: return (0); ! 298: n = db->dbm_bitno % BYTESIZ; ! 299: bn = db->dbm_bitno / BYTESIZ; ! 300: i = bn % DBLKSIZ; ! 301: b = bn / DBLKSIZ; ! 302: if (b != db->dbm_dirbno) { ! 303: db->dbm_dirbno = b; ! 304: (void) lseek(db->dbm_dirf, (long)b*DBLKSIZ, L_SET); ! 305: if (read(db->dbm_dirf, db->dbm_dirbuf, DBLKSIZ) != DBLKSIZ) ! 306: bzero(db->dbm_dirbuf, DBLKSIZ); ! 307: } ! 308: return (db->dbm_dirbuf[i] & (1<<n)); ! 309: } ! 310: ! 311: static ! 312: setbit(db) ! 313: register DBM *db; ! 314: { ! 315: long bn; ! 316: register i, n, b; ! 317: ! 318: if (db->dbm_bitno > db->dbm_maxbno) ! 319: db->dbm_maxbno = db->dbm_bitno; ! 320: n = db->dbm_bitno % BYTESIZ; ! 321: bn = db->dbm_bitno / BYTESIZ; ! 322: i = bn % DBLKSIZ; ! 323: b = bn / DBLKSIZ; ! 324: if (b != db->dbm_dirbno) { ! 325: db->dbm_dirbno = b; ! 326: (void) lseek(db->dbm_dirf, (long)b*DBLKSIZ, L_SET); ! 327: if (read(db->dbm_dirf, db->dbm_dirbuf, DBLKSIZ) != DBLKSIZ) ! 328: bzero(db->dbm_dirbuf, DBLKSIZ); ! 329: } ! 330: db->dbm_dirbuf[i] |= 1<<n; ! 331: db->dbm_dirbno = b; ! 332: (void) lseek(db->dbm_dirf, (long)b*DBLKSIZ, L_SET); ! 333: if (write(db->dbm_dirf, db->dbm_dirbuf, DBLKSIZ) != DBLKSIZ) ! 334: db->dbm_flags |= _DBM_IOERR; ! 335: } ! 336: ! 337: static datum ! 338: makdatum(buf, n) ! 339: char buf[PBLKSIZ]; ! 340: { ! 341: register short *sp; ! 342: register t; ! 343: datum item; ! 344: ! 345: sp = (short *)buf; ! 346: if ((unsigned)n >= sp[0]) { ! 347: item.dptr = NULL; ! 348: item.dsize = 0; ! 349: return (item); ! 350: } ! 351: t = PBLKSIZ; ! 352: if (n > 0) ! 353: t = sp[n]; ! 354: item.dptr = buf+sp[n+1]; ! 355: item.dsize = t - sp[n+1]; ! 356: return (item); ! 357: } ! 358: ! 359: static ! 360: finddatum(buf, item) ! 361: char buf[PBLKSIZ]; ! 362: datum item; ! 363: { ! 364: register short *sp; ! 365: register int i, n, j; ! 366: ! 367: sp = (short *)buf; ! 368: n = PBLKSIZ; ! 369: for (i=0, j=sp[0]; i<j; i+=2, n = sp[i]) { ! 370: n -= sp[i+1]; ! 371: if (n != item.dsize) ! 372: continue; ! 373: if (n == 0 || bcmp(&buf[sp[i+1]], item.dptr, n) == 0) ! 374: return (i); ! 375: } ! 376: return (-1); ! 377: } ! 378: ! 379: static int hitab[16] ! 380: /* ken's ! 381: { ! 382: 055,043,036,054,063,014,004,005, ! 383: 010,064,077,000,035,027,025,071, ! 384: }; ! 385: */ ! 386: = { 61, 57, 53, 49, 45, 41, 37, 33, ! 387: 29, 25, 21, 17, 13, 9, 5, 1, ! 388: }; ! 389: static long hltab[64] ! 390: = { ! 391: 06100151277L,06106161736L,06452611562L,05001724107L, ! 392: 02614772546L,04120731531L,04665262210L,07347467531L, ! 393: 06735253126L,06042345173L,03072226605L,01464164730L, ! 394: 03247435524L,07652510057L,01546775256L,05714532133L, ! 395: 06173260402L,07517101630L,02431460343L,01743245566L, ! 396: 00261675137L,02433103631L,03421772437L,04447707466L, ! 397: 04435620103L,03757017115L,03641531772L,06767633246L, ! 398: 02673230344L,00260612216L,04133454451L,00615531516L, ! 399: 06137717526L,02574116560L,02304023373L,07061702261L, ! 400: 05153031405L,05322056705L,07401116734L,06552375715L, ! 401: 06165233473L,05311063631L,01212221723L,01052267235L, ! 402: 06000615237L,01075222665L,06330216006L,04402355630L, ! 403: 01451177262L,02000133436L,06025467062L,07121076461L, ! 404: 03123433522L,01010635225L,01716177066L,05161746527L, ! 405: 01736635071L,06243505026L,03637211610L,01756474365L, ! 406: 04723077174L,03642763134L,05750130273L,03655541561L, ! 407: }; ! 408: ! 409: static long ! 410: hashinc(db, hash) ! 411: register DBM *db; ! 412: long hash; ! 413: { ! 414: long bit; ! 415: ! 416: hash &= db->dbm_hmask; ! 417: bit = db->dbm_hmask+1; ! 418: for (;;) { ! 419: bit >>= 1; ! 420: if (bit == 0) ! 421: return (0L); ! 422: if ((hash & bit) == 0) ! 423: return (hash | bit); ! 424: hash &= ~bit; ! 425: } ! 426: } ! 427: ! 428: static long ! 429: dcalchash(item) ! 430: datum item; ! 431: { ! 432: register int s, c, j; ! 433: register char *cp; ! 434: register long hashl; ! 435: register int hashi; ! 436: ! 437: hashl = 0; ! 438: hashi = 0; ! 439: for (cp = item.dptr, s=item.dsize; --s >= 0; ) { ! 440: c = *cp++; ! 441: for (j=0; j<BYTESIZ; j+=4) { ! 442: hashi += hitab[c&017]; ! 443: hashl += hltab[hashi&63]; ! 444: c >>= 4; ! 445: } ! 446: } ! 447: return (hashl); ! 448: } ! 449: ! 450: /* ! 451: * Delete pairs of items (n & n+1). ! 452: */ ! 453: static ! 454: delitem(buf, n) ! 455: char buf[PBLKSIZ]; ! 456: { ! 457: register short *sp, *sp1; ! 458: register i1, i2; ! 459: ! 460: sp = (short *)buf; ! 461: i2 = sp[0]; ! 462: if ((unsigned)n >= i2 || (n & 1)) ! 463: return (0); ! 464: if (n == i2-2) { ! 465: sp[0] -= 2; ! 466: return (1); ! 467: } ! 468: i1 = PBLKSIZ; ! 469: if (n > 0) ! 470: i1 = sp[n]; ! 471: i1 -= sp[n+2]; ! 472: if (i1 > 0) { ! 473: i2 = sp[i2]; ! 474: bcopy(&buf[i2], &buf[i2 + i1], sp[n+2] - i2); ! 475: } ! 476: sp[0] -= 2; ! 477: for (sp1 = sp + sp[0], sp += n+1; sp <= sp1; sp++) ! 478: sp[0] = sp[2] + i1; ! 479: return (1); ! 480: } ! 481: ! 482: /* ! 483: * Add pairs of items (item & item1). ! 484: */ ! 485: static ! 486: additem(buf, item, item1) ! 487: char buf[PBLKSIZ]; ! 488: datum item, item1; ! 489: { ! 490: register short *sp; ! 491: register i1, i2; ! 492: ! 493: sp = (short *)buf; ! 494: i1 = PBLKSIZ; ! 495: i2 = sp[0]; ! 496: if (i2 > 0) ! 497: i1 = sp[i2]; ! 498: i1 -= item.dsize + item1.dsize; ! 499: if (i1 <= (i2+3) * (int)sizeof(short)) ! 500: return (0); ! 501: sp[0] += 2; ! 502: sp[++i2] = i1 + item1.dsize; ! 503: bcopy(item.dptr, &buf[i1 + item1.dsize], item.dsize); ! 504: sp[++i2] = i1; ! 505: bcopy(item1.dptr, &buf[i1], item1.dsize); ! 506: return (1); ! 507: } ! 508: ! 509: #ifdef DEBUG ! 510: static ! 511: chkblk(buf) ! 512: char buf[PBLKSIZ]; ! 513: { ! 514: register short *sp; ! 515: register t, i; ! 516: ! 517: sp = (short *)buf; ! 518: t = PBLKSIZ; ! 519: for (i=0; i<sp[0]; i++) { ! 520: if (sp[i+1] > t) ! 521: return (-1); ! 522: t = sp[i+1]; ! 523: } ! 524: if (t < (sp[0]+1)*sizeof(short)) ! 525: return (-1); ! 526: return (0); ! 527: } ! 528: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.