Annotation of 43BSDReno/lib/libc/gen/ndbm.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.