10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
30Sstevel@tonic-gate * Use is subject to license terms.
40Sstevel@tonic-gate */
50Sstevel@tonic-gate
60Sstevel@tonic-gate /*
70Sstevel@tonic-gate * Copyright (c) 1983 Regents of the University of California.
80Sstevel@tonic-gate * All rights reserved. The Berkeley software License Agreement
90Sstevel@tonic-gate * specifies the terms and conditions for redistribution.
100Sstevel@tonic-gate */
110Sstevel@tonic-gate
12*722Smuffin #pragma ident "%Z%%M% %I% %E% SMI"
13*722Smuffin
140Sstevel@tonic-gate #include <sys/types.h>
150Sstevel@tonic-gate #include <sys/stat.h>
160Sstevel@tonic-gate #include <sys/file.h>
170Sstevel@tonic-gate #include <stdio.h>
180Sstevel@tonic-gate #include <errno.h>
190Sstevel@tonic-gate #include <ndbm.h>
20*722Smuffin #include <stdlib.h>
21*722Smuffin #include <string.h>
22*722Smuffin
23*722Smuffin datum dbm_do_nextkey(DBM *, datum);
240Sstevel@tonic-gate
250Sstevel@tonic-gate
260Sstevel@tonic-gate /*add support for batched writing for NIS*/
270Sstevel@tonic-gate
280Sstevel@tonic-gate #define _DBM_DEFWRITE 0x4
290Sstevel@tonic-gate #define _DBM_DIRTY 0x8
300Sstevel@tonic-gate #define _DBM_DIRDIRTY 0x10
310Sstevel@tonic-gate #define dbm_dirty(db) ((db)->dbm_flags & _DBM_DIRTY)
320Sstevel@tonic-gate #define dbm_dirdirty(db) ((db)->dbm_flags & _DBM_DIRDIRTY)
330Sstevel@tonic-gate #define dbm_defwrite(db) ((db)->dbm_flags & _DBM_DEFWRITE)
340Sstevel@tonic-gate #define dbm_setdirty(db) (db)->dbm_flags |= _DBM_DIRTY
350Sstevel@tonic-gate #define dbm_clrdirty(db) (db)->dbm_flags &= ~_DBM_DIRTY
360Sstevel@tonic-gate #define dbm_setdirdirty(db) (db)->dbm_flags |= _DBM_DIRDIRTY
370Sstevel@tonic-gate #define dbm_clrdirdirty(db) (db)->dbm_flags &= ~_DBM_DIRDIRTY
380Sstevel@tonic-gate
39*722Smuffin
40*722Smuffin static void dbm_access(DBM *, long);
41*722Smuffin static int getbit(DBM *);
42*722Smuffin static int setbit(DBM *);
43*722Smuffin static int cmpdatum(datum, datum);
44*722Smuffin static int finddatum(char [PBLKSIZ], datum);
45*722Smuffin static int delitem(char [PBLKSIZ], int);
46*722Smuffin static int additem(char [PBLKSIZ], datum, datum);
47*722Smuffin static datum makdatum(char [PBLKSIZ], int);
48*722Smuffin static long dcalchash(datum);
49*722Smuffin
500Sstevel@tonic-gate /*used to make a dbm file all at once instead of incrementally*/
51*722Smuffin void
dbm_setdefwrite(DBM * db)52*722Smuffin dbm_setdefwrite(DBM *db)
530Sstevel@tonic-gate {
540Sstevel@tonic-gate db->dbm_flags |= _DBM_DEFWRITE;
550Sstevel@tonic-gate }
560Sstevel@tonic-gate
57*722Smuffin int
dbm_flush(DBM * db)58*722Smuffin dbm_flush(DBM *db)
590Sstevel@tonic-gate {
600Sstevel@tonic-gate int ok=0;
610Sstevel@tonic-gate if (dbm_flushpag(db)<0) ok= -1;
620Sstevel@tonic-gate if (dbm_flushdir(db)<0) ok= -1;
630Sstevel@tonic-gate return(ok);
640Sstevel@tonic-gate }
650Sstevel@tonic-gate
66*722Smuffin int
dbm_flushpag(DBM * db)67*722Smuffin dbm_flushpag(DBM *db)
680Sstevel@tonic-gate {
690Sstevel@tonic-gate int ok=0;
700Sstevel@tonic-gate if (dbm_dirty(db)){ /*must page out the page*/
710Sstevel@tonic-gate (void) lseek(db->dbm_pagf, (long)(db->dbm_pagbno*PBLKSIZ), L_SET);
720Sstevel@tonic-gate if (write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ) {
730Sstevel@tonic-gate db->dbm_flags |= _DBM_IOERR;
740Sstevel@tonic-gate ok= -1;
750Sstevel@tonic-gate }
760Sstevel@tonic-gate dbm_clrdirty(db);
770Sstevel@tonic-gate }
780Sstevel@tonic-gate return(ok);
790Sstevel@tonic-gate }
800Sstevel@tonic-gate
81*722Smuffin int
dbm_flushdir(DBM * db)82*722Smuffin dbm_flushdir(DBM *db)
830Sstevel@tonic-gate {
840Sstevel@tonic-gate int ok=0;
850Sstevel@tonic-gate if (dbm_dirdirty(db)){ /*must page out the dir*/
860Sstevel@tonic-gate (void) lseek(db->dbm_dirf, (long)(db->dbm_dirbno*DBLKSIZ), L_SET);
870Sstevel@tonic-gate if (write(db->dbm_dirf, db->dbm_dirbuf, DBLKSIZ) != DBLKSIZ) {
880Sstevel@tonic-gate ok= -1;
890Sstevel@tonic-gate }
900Sstevel@tonic-gate dbm_clrdirdirty(db);
910Sstevel@tonic-gate }
920Sstevel@tonic-gate return(ok);
930Sstevel@tonic-gate }
940Sstevel@tonic-gate #define BYTESIZ 8
950Sstevel@tonic-gate #undef setbit
960Sstevel@tonic-gate
970Sstevel@tonic-gate DBM *
dbm_open(char * file,int flags,int mode)98*722Smuffin dbm_open(char *file, int flags, int mode)
990Sstevel@tonic-gate {
1000Sstevel@tonic-gate struct stat statb;
101*722Smuffin DBM *db;
1020Sstevel@tonic-gate int serrno;
1030Sstevel@tonic-gate
1040Sstevel@tonic-gate if ((db = (DBM *)malloc(sizeof *db)) == 0) {
1050Sstevel@tonic-gate errno = ENOMEM;
1060Sstevel@tonic-gate return ((DBM *)0);
1070Sstevel@tonic-gate }
1080Sstevel@tonic-gate db->dbm_flags = (flags & 03) == O_RDONLY ? _DBM_RDONLY : 0;
1090Sstevel@tonic-gate if ((flags & 03) == O_WRONLY)
1100Sstevel@tonic-gate flags = (flags & ~03) | O_RDWR;
1110Sstevel@tonic-gate if (strlcpy(db->dbm_pagbuf, file, sizeof (db->dbm_pagbuf)) >=
1120Sstevel@tonic-gate sizeof (db->dbm_pagbuf) ||
1130Sstevel@tonic-gate strlcat(db->dbm_pagbuf, ".pag", sizeof (db->dbm_pagbuf)) >=
1140Sstevel@tonic-gate sizeof (db->dbm_pagbuf)) {
1150Sstevel@tonic-gate /*
1160Sstevel@tonic-gate * file.pag does not fit into dbm_pagbuf.
1170Sstevel@tonic-gate * fails with ENAMETOOLONG.
1180Sstevel@tonic-gate */
1190Sstevel@tonic-gate serrno = ENAMETOOLONG;
1200Sstevel@tonic-gate goto bad;
1210Sstevel@tonic-gate }
1220Sstevel@tonic-gate db->dbm_pagf = open(db->dbm_pagbuf, flags, mode);
1230Sstevel@tonic-gate if (db->dbm_pagf < 0) {
1240Sstevel@tonic-gate serrno = errno;
1250Sstevel@tonic-gate goto bad;
1260Sstevel@tonic-gate }
1270Sstevel@tonic-gate /*
1280Sstevel@tonic-gate * We know this won't overflow so it is safe to ignore the
1290Sstevel@tonic-gate * return value; we use strl* to prevent false hits in
1300Sstevel@tonic-gate * code sweeps.
1310Sstevel@tonic-gate */
1320Sstevel@tonic-gate (void) strlcpy(db->dbm_pagbuf, file, sizeof (db->dbm_pagbuf));
1330Sstevel@tonic-gate (void) strlcat(db->dbm_pagbuf, ".dir", sizeof (db->dbm_pagbuf));
1340Sstevel@tonic-gate db->dbm_dirf = open(db->dbm_pagbuf, flags, mode);
1350Sstevel@tonic-gate if (db->dbm_dirf < 0) {
1360Sstevel@tonic-gate serrno = errno;
1370Sstevel@tonic-gate goto bad1;
1380Sstevel@tonic-gate }
1390Sstevel@tonic-gate (void) fstat(db->dbm_dirf, &statb);
1400Sstevel@tonic-gate db->dbm_maxbno = statb.st_size*BYTESIZ-1;
1410Sstevel@tonic-gate db->dbm_pagbno = db->dbm_dirbno = -1;
1420Sstevel@tonic-gate return (db);
1430Sstevel@tonic-gate bad1:
1440Sstevel@tonic-gate (void) close(db->dbm_pagf);
1450Sstevel@tonic-gate bad:
1460Sstevel@tonic-gate free((char *)db);
1470Sstevel@tonic-gate errno = serrno;
1480Sstevel@tonic-gate return ((DBM *)0);
1490Sstevel@tonic-gate }
1500Sstevel@tonic-gate
1510Sstevel@tonic-gate void
dbm_close(DBM * db)152*722Smuffin dbm_close(DBM *db)
1530Sstevel@tonic-gate {
154*722Smuffin (void) dbm_close_status(db);
1550Sstevel@tonic-gate }
1560Sstevel@tonic-gate
1570Sstevel@tonic-gate /*close with return code*/
1580Sstevel@tonic-gate int
dbm_close_status(DBM * db)159*722Smuffin dbm_close_status(DBM *db)
1600Sstevel@tonic-gate {
1610Sstevel@tonic-gate int ok;
1620Sstevel@tonic-gate ok=0;
1630Sstevel@tonic-gate
1640Sstevel@tonic-gate if (dbm_flush(db) <0) ok = -1;
1650Sstevel@tonic-gate if (close(db->dbm_dirf)<0) ok= -1;
1660Sstevel@tonic-gate if ( close(db->dbm_pagf)<0) ok= -1;
1670Sstevel@tonic-gate free((char *)db);
168*722Smuffin return (ok);
1690Sstevel@tonic-gate }
170*722Smuffin
1710Sstevel@tonic-gate long
dbm_forder(DBM * db,datum key)172*722Smuffin dbm_forder(DBM *db, datum key)
1730Sstevel@tonic-gate {
1740Sstevel@tonic-gate long hash;
1750Sstevel@tonic-gate
1760Sstevel@tonic-gate hash = dcalchash(key);
1770Sstevel@tonic-gate for (db->dbm_hmask=0;; db->dbm_hmask=(db->dbm_hmask<<1)+1) {
1780Sstevel@tonic-gate db->dbm_blkno = hash & db->dbm_hmask;
1790Sstevel@tonic-gate db->dbm_bitno = db->dbm_blkno + db->dbm_hmask;
1800Sstevel@tonic-gate if (getbit(db) == 0)
1810Sstevel@tonic-gate break;
1820Sstevel@tonic-gate }
1830Sstevel@tonic-gate return (db->dbm_blkno);
1840Sstevel@tonic-gate }
1850Sstevel@tonic-gate
1860Sstevel@tonic-gate datum
dbm_fetch(DBM * db,datum key)187*722Smuffin dbm_fetch(DBM *db, datum key)
1880Sstevel@tonic-gate {
189*722Smuffin int i;
1900Sstevel@tonic-gate datum item;
1910Sstevel@tonic-gate
1920Sstevel@tonic-gate if (dbm_error(db))
1930Sstevel@tonic-gate goto err;
1940Sstevel@tonic-gate dbm_access(db, dcalchash(key));
1950Sstevel@tonic-gate if ((i = finddatum(db->dbm_pagbuf, key)) >= 0) {
1960Sstevel@tonic-gate item = makdatum(db->dbm_pagbuf, i+1);
1970Sstevel@tonic-gate if (item.dptr != NULL)
1980Sstevel@tonic-gate return (item);
1990Sstevel@tonic-gate }
2000Sstevel@tonic-gate err:
2010Sstevel@tonic-gate item.dptr = NULL;
2020Sstevel@tonic-gate item.dsize = 0;
2030Sstevel@tonic-gate return (item);
2040Sstevel@tonic-gate }
2050Sstevel@tonic-gate
206*722Smuffin int
dbm_delete(DBM * db,datum key)207*722Smuffin dbm_delete(DBM *db, datum key)
2080Sstevel@tonic-gate {
209*722Smuffin int i;
2100Sstevel@tonic-gate
2110Sstevel@tonic-gate if (dbm_error(db))
2120Sstevel@tonic-gate return (-1);
2130Sstevel@tonic-gate if (dbm_rdonly(db)) {
2140Sstevel@tonic-gate errno = EPERM;
2150Sstevel@tonic-gate return (-1);
2160Sstevel@tonic-gate }
2170Sstevel@tonic-gate dbm_access(db, dcalchash(key));
2180Sstevel@tonic-gate if ((i = finddatum(db->dbm_pagbuf, key)) < 0)
2190Sstevel@tonic-gate return (-1);
2200Sstevel@tonic-gate if (!delitem(db->dbm_pagbuf, i))
2210Sstevel@tonic-gate goto err;
2220Sstevel@tonic-gate db->dbm_pagbno = db->dbm_blkno;
2230Sstevel@tonic-gate if (dbm_defwrite(db)) {
2240Sstevel@tonic-gate dbm_setdirty(db);
2250Sstevel@tonic-gate }
2260Sstevel@tonic-gate else {
2270Sstevel@tonic-gate (void) lseek(db->dbm_pagf, (long)(db->dbm_blkno*PBLKSIZ), L_SET);
2280Sstevel@tonic-gate if (write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ) {
2290Sstevel@tonic-gate err:
2300Sstevel@tonic-gate db->dbm_flags |= _DBM_IOERR;
2310Sstevel@tonic-gate return (-1);
2320Sstevel@tonic-gate }
2330Sstevel@tonic-gate }
2340Sstevel@tonic-gate return (0);
2350Sstevel@tonic-gate }
2360Sstevel@tonic-gate
237*722Smuffin int
dbm_store(DBM * db,datum key,datum dat,int replace)238*722Smuffin dbm_store(DBM *db, datum key, datum dat, int replace)
2390Sstevel@tonic-gate {
240*722Smuffin int i;
2410Sstevel@tonic-gate datum item, item1;
2420Sstevel@tonic-gate char ovfbuf[PBLKSIZ];
2430Sstevel@tonic-gate
2440Sstevel@tonic-gate if (dbm_error(db))
2450Sstevel@tonic-gate return (-1);
2460Sstevel@tonic-gate if (dbm_rdonly(db)) {
2470Sstevel@tonic-gate errno = EPERM;
2480Sstevel@tonic-gate return (-1);
2490Sstevel@tonic-gate }
2500Sstevel@tonic-gate loop:
2510Sstevel@tonic-gate dbm_access(db, dcalchash(key));
2520Sstevel@tonic-gate if ((i = finddatum(db->dbm_pagbuf, key)) >= 0) {
2530Sstevel@tonic-gate if (!replace)
2540Sstevel@tonic-gate return (1);
2550Sstevel@tonic-gate if (!delitem(db->dbm_pagbuf, i)) {
2560Sstevel@tonic-gate db->dbm_flags |= _DBM_IOERR;
2570Sstevel@tonic-gate return (-1);
2580Sstevel@tonic-gate }
2590Sstevel@tonic-gate }
2600Sstevel@tonic-gate if (!additem(db->dbm_pagbuf, key, dat))
2610Sstevel@tonic-gate goto split;
2620Sstevel@tonic-gate db->dbm_pagbno = db->dbm_blkno;
2630Sstevel@tonic-gate if (dbm_defwrite(db)) {
2640Sstevel@tonic-gate dbm_setdirty(db);
2650Sstevel@tonic-gate }
2660Sstevel@tonic-gate else {
2670Sstevel@tonic-gate
2680Sstevel@tonic-gate (void) lseek(db->dbm_pagf, (long)(db->dbm_blkno*PBLKSIZ), L_SET);
2690Sstevel@tonic-gate if (write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ) {
2700Sstevel@tonic-gate db->dbm_flags |= _DBM_IOERR;
2710Sstevel@tonic-gate return (-1);
2720Sstevel@tonic-gate }
2730Sstevel@tonic-gate }
2740Sstevel@tonic-gate return (0);
2750Sstevel@tonic-gate
2760Sstevel@tonic-gate split:
2770Sstevel@tonic-gate if (key.dsize+dat.dsize+3*sizeof(short) >= PBLKSIZ) {
2780Sstevel@tonic-gate db->dbm_flags |= _DBM_IOERR;
2790Sstevel@tonic-gate errno = ENOSPC;
2800Sstevel@tonic-gate return (-1);
2810Sstevel@tonic-gate }
2820Sstevel@tonic-gate bzero(ovfbuf, PBLKSIZ);
2830Sstevel@tonic-gate for (i=0;;) {
2840Sstevel@tonic-gate item = makdatum(db->dbm_pagbuf, i);
2850Sstevel@tonic-gate if (item.dptr == NULL)
2860Sstevel@tonic-gate break;
2870Sstevel@tonic-gate if (dcalchash(item) & (db->dbm_hmask+1)) {
2880Sstevel@tonic-gate item1 = makdatum(db->dbm_pagbuf, i+1);
2890Sstevel@tonic-gate if (item1.dptr == NULL) {
2900Sstevel@tonic-gate /*(void) fprintf(stderr, "ndbm: split not paired\n");*/
2910Sstevel@tonic-gate db->dbm_flags |= _DBM_IOERR;
2920Sstevel@tonic-gate break;
2930Sstevel@tonic-gate }
2940Sstevel@tonic-gate if (!additem(ovfbuf, item, item1) ||
2950Sstevel@tonic-gate !delitem(db->dbm_pagbuf, i)) {
2960Sstevel@tonic-gate db->dbm_flags |= _DBM_IOERR;
2970Sstevel@tonic-gate return (-1);
2980Sstevel@tonic-gate }
2990Sstevel@tonic-gate continue;
3000Sstevel@tonic-gate }
3010Sstevel@tonic-gate i += 2;
3020Sstevel@tonic-gate }
3030Sstevel@tonic-gate db->dbm_pagbno = db->dbm_blkno;
3040Sstevel@tonic-gate (void) lseek(db->dbm_pagf, (long)(db->dbm_blkno*PBLKSIZ), L_SET);
3050Sstevel@tonic-gate if (write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ) {
3060Sstevel@tonic-gate db->dbm_flags |= _DBM_IOERR;
3070Sstevel@tonic-gate return (-1);
3080Sstevel@tonic-gate }
3090Sstevel@tonic-gate dbm_clrdirty(db); /*clear dirty*/
3100Sstevel@tonic-gate (void) lseek(db->dbm_pagf,
3110Sstevel@tonic-gate (long)((db->dbm_blkno+db->dbm_hmask+1)*PBLKSIZ), L_SET);
3120Sstevel@tonic-gate if (write(db->dbm_pagf, ovfbuf, PBLKSIZ) != PBLKSIZ) {
3130Sstevel@tonic-gate db->dbm_flags |= _DBM_IOERR;
3140Sstevel@tonic-gate return (-1);
3150Sstevel@tonic-gate }
3160Sstevel@tonic-gate if (setbit(db) < 0) {
3170Sstevel@tonic-gate db->dbm_flags |= _DBM_IOERR;
3180Sstevel@tonic-gate return (-1);
3190Sstevel@tonic-gate }
3200Sstevel@tonic-gate goto loop;
3210Sstevel@tonic-gate }
322*722Smuffin
3230Sstevel@tonic-gate static long
dbm_hashinc(DBM * db,long hash)324*722Smuffin dbm_hashinc(DBM *db, long hash)
3250Sstevel@tonic-gate {
3260Sstevel@tonic-gate
3270Sstevel@tonic-gate long bit;
3280Sstevel@tonic-gate
3290Sstevel@tonic-gate hash &= db->dbm_hmask;
3300Sstevel@tonic-gate bit = db->dbm_hmask+1;
3310Sstevel@tonic-gate for(;;) {
3320Sstevel@tonic-gate bit >>= 1;
3330Sstevel@tonic-gate if(bit == 0)
3340Sstevel@tonic-gate return(0L);
3350Sstevel@tonic-gate if((hash&bit) == 0)
3360Sstevel@tonic-gate return(hash|bit);
3370Sstevel@tonic-gate hash &= ~bit;
3380Sstevel@tonic-gate }
3390Sstevel@tonic-gate }
3400Sstevel@tonic-gate
3410Sstevel@tonic-gate
3420Sstevel@tonic-gate
3430Sstevel@tonic-gate static datum nullkey= {NULL, 0};
3440Sstevel@tonic-gate
3450Sstevel@tonic-gate datum
dbm_firsthash(DBM * db,long hash)346*722Smuffin dbm_firsthash(DBM *db, long hash)
3470Sstevel@tonic-gate {
348*722Smuffin int i,j;
3490Sstevel@tonic-gate datum item, bitem;
3500Sstevel@tonic-gate
3510Sstevel@tonic-gate loop:
3520Sstevel@tonic-gate dbm_access(db, hash);
3530Sstevel@tonic-gate j=0;
3540Sstevel@tonic-gate bitem = makdatum(db->dbm_pagbuf, 0);
3550Sstevel@tonic-gate for(i=2;; i+=2) {
3560Sstevel@tonic-gate item = makdatum(db->dbm_pagbuf, i);
3570Sstevel@tonic-gate if(item.dptr == NULL)
3580Sstevel@tonic-gate break;
3590Sstevel@tonic-gate if(cmpdatum(bitem, item) < 0) {
3600Sstevel@tonic-gate j=i;
3610Sstevel@tonic-gate bitem = item;
3620Sstevel@tonic-gate }
3630Sstevel@tonic-gate }
3640Sstevel@tonic-gate if(bitem.dptr != NULL) {
3650Sstevel@tonic-gate db->dbm_keyptr = j + 2;
3660Sstevel@tonic-gate db->dbm_blkptr = db->dbm_blkno;
3670Sstevel@tonic-gate return(bitem);
3680Sstevel@tonic-gate }
3690Sstevel@tonic-gate hash = dbm_hashinc(db,hash);
3700Sstevel@tonic-gate if(hash == 0)
3710Sstevel@tonic-gate return(item); /*null item*/
3720Sstevel@tonic-gate goto loop;
3730Sstevel@tonic-gate
3740Sstevel@tonic-gate }
3750Sstevel@tonic-gate
3760Sstevel@tonic-gate datum
dbm_firstkey(DBM * db)377*722Smuffin dbm_firstkey(DBM *db)
3780Sstevel@tonic-gate {
3790Sstevel@tonic-gate
3800Sstevel@tonic-gate db->dbm_blkptr = 0L;
3810Sstevel@tonic-gate db->dbm_keyptr = 0;
3820Sstevel@tonic-gate return (dbm_firsthash(db, 0L));
3830Sstevel@tonic-gate }
384*722Smuffin
3850Sstevel@tonic-gate datum
dbm_nextkey(DBM * db)386*722Smuffin dbm_nextkey(DBM *db)
3870Sstevel@tonic-gate {
3880Sstevel@tonic-gate
3890Sstevel@tonic-gate return (dbm_do_nextkey(db, nullkey));
3900Sstevel@tonic-gate }
3910Sstevel@tonic-gate
3920Sstevel@tonic-gate /*this is used if keyptr-2,blocknum doesn't point to the previous
3930Sstevel@tonic-gate specific key allowing the fast hash order search --
3940Sstevel@tonic-gate its use indicates user tampering with our state variables,
3950Sstevel@tonic-gate which some evil users might do to search from some specific place.
3960Sstevel@tonic-gate It finds the first key at or after blkptr,keyptr in block seq order
3970Sstevel@tonic-gate this requires looking at all sorts of emtpy blocks in many cases*/
3980Sstevel@tonic-gate
399*722Smuffin static datum
dbm_slow_nextkey(DBM * db)400*722Smuffin dbm_slow_nextkey(DBM *db)
4010Sstevel@tonic-gate {
4020Sstevel@tonic-gate struct stat statb;
4030Sstevel@tonic-gate datum item;
4040Sstevel@tonic-gate
4050Sstevel@tonic-gate if (dbm_error(db) || fstat(db->dbm_pagf, &statb) < 0)
4060Sstevel@tonic-gate goto err;
4070Sstevel@tonic-gate statb.st_size /= PBLKSIZ;
4080Sstevel@tonic-gate
409*722Smuffin for (;;) {
4100Sstevel@tonic-gate if (db->dbm_blkptr != db->dbm_pagbno) {
4110Sstevel@tonic-gate
4120Sstevel@tonic-gate if (dbm_dirty(db)) dbm_flushpag(db);
4130Sstevel@tonic-gate
4140Sstevel@tonic-gate db->dbm_pagbno = db->dbm_blkptr;
4150Sstevel@tonic-gate (void) lseek(db->dbm_pagf, (long)(db->dbm_blkptr*PBLKSIZ), L_SET);
4160Sstevel@tonic-gate if (read(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ)
4170Sstevel@tonic-gate bzero(db->dbm_pagbuf, PBLKSIZ);
4180Sstevel@tonic-gate #ifdef DEBUG
4190Sstevel@tonic-gate else if (chkblk(db->dbm_pagbuf) < 0)
4200Sstevel@tonic-gate db->dbm_flags |= _DBM_IOERR;
4210Sstevel@tonic-gate #endif
4220Sstevel@tonic-gate }
4230Sstevel@tonic-gate /*Am I an empty block?*/
4240Sstevel@tonic-gate if (((short *)db->dbm_pagbuf)[0] != 0) {
4250Sstevel@tonic-gate item = makdatum(db->dbm_pagbuf, db->dbm_keyptr);
4260Sstevel@tonic-gate if (item.dptr != NULL) {
4270Sstevel@tonic-gate db->dbm_keyptr += 2;
4280Sstevel@tonic-gate return (item);
4290Sstevel@tonic-gate }
4300Sstevel@tonic-gate db->dbm_keyptr = 0;
4310Sstevel@tonic-gate }
4320Sstevel@tonic-gate /*go to next sequential block*/
4330Sstevel@tonic-gate if (++db->dbm_blkptr >= statb.st_size)
4340Sstevel@tonic-gate break;
4350Sstevel@tonic-gate }
4360Sstevel@tonic-gate err:
4370Sstevel@tonic-gate item.dptr = NULL;
4380Sstevel@tonic-gate item.dsize = 0;
4390Sstevel@tonic-gate return (item);
4400Sstevel@tonic-gate }
4410Sstevel@tonic-gate
4420Sstevel@tonic-gate datum
dbm_do_nextkey(DBM * db,datum inkey)443*722Smuffin dbm_do_nextkey(DBM *db, datum inkey)
4440Sstevel@tonic-gate {
4450Sstevel@tonic-gate datum item,bitem;
4460Sstevel@tonic-gate long hash;
4470Sstevel@tonic-gate datum key;
4480Sstevel@tonic-gate int f;
449*722Smuffin int i;
450*722Smuffin int j;
451*722Smuffin short *sp;
452*722Smuffin int n;
453*722Smuffin char *p1, *p2;
4540Sstevel@tonic-gate
4550Sstevel@tonic-gate if ( dbm_error(db) ) {
4560Sstevel@tonic-gate item.dptr = NULL;
4570Sstevel@tonic-gate item.dsize = 0;
4580Sstevel@tonic-gate return (item);
4590Sstevel@tonic-gate }
4600Sstevel@tonic-gate
4610Sstevel@tonic-gate /*user has supplied lastkey*/
4620Sstevel@tonic-gate
4630Sstevel@tonic-gate if(inkey.dptr != NULL) {
4640Sstevel@tonic-gate dbm_access(db, (hash=dcalchash(inkey)));
4650Sstevel@tonic-gate if ((i = finddatum(db->dbm_pagbuf, inkey)) >= 0) {
4660Sstevel@tonic-gate db->dbm_keyptr = i + 2;
4670Sstevel@tonic-gate db->dbm_blkptr = db->dbm_blkno;
4680Sstevel@tonic-gate }
4690Sstevel@tonic-gate key=inkey;
4700Sstevel@tonic-gate }
4710Sstevel@tonic-gate else {
4720Sstevel@tonic-gate /*is this a manual firstkey request? */
4730Sstevel@tonic-gate
4740Sstevel@tonic-gate if (db->dbm_blkptr == 0L &&
4750Sstevel@tonic-gate db->dbm_keyptr == 0)
476*722Smuffin return (dbm_firsthash(db, 0L));
4770Sstevel@tonic-gate
4780Sstevel@tonic-gate /*no -- get lastkey this is like dbm_access by blkptr*/
4790Sstevel@tonic-gate
4800Sstevel@tonic-gate if (db->dbm_blkptr != db->dbm_pagbno) {
4810Sstevel@tonic-gate
4820Sstevel@tonic-gate if (dbm_dirty(db)) dbm_flushpag(db);
4830Sstevel@tonic-gate db->dbm_pagbno = db->dbm_blkptr;
4840Sstevel@tonic-gate (void) lseek(db->dbm_pagf, (long)(db->dbm_blkptr*PBLKSIZ), L_SET);
4850Sstevel@tonic-gate if (read(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ)
4860Sstevel@tonic-gate bzero(db->dbm_pagbuf, PBLKSIZ);
4870Sstevel@tonic-gate #ifdef DEBUG
4880Sstevel@tonic-gate else if (chkblk(db->dbm_pagbuf) < 0)
4890Sstevel@tonic-gate db->dbm_flags |= _DBM_IOERR;
4900Sstevel@tonic-gate #endif
4910Sstevel@tonic-gate }
4920Sstevel@tonic-gate /*now just make up last key datum*/
4930Sstevel@tonic-gate if (db->dbm_keyptr >=2) key= makdatum(db->dbm_pagbuf,(db->dbm_keyptr-2));
4940Sstevel@tonic-gate else key=nullkey;
4950Sstevel@tonic-gate
4960Sstevel@tonic-gate /* the keyptr pagbuf have failed us, the user must
4970Sstevel@tonic-gate be an extra clever moron who depends on
4980Sstevel@tonic-gate these variables and their former meaning.
4990Sstevel@tonic-gate If we set the variables this would have got
5000Sstevel@tonic-gate us the key for sure! So give him the old algorithm.*/
501*722Smuffin if (key.dptr == NULL) return (dbm_slow_nextkey(db));
5020Sstevel@tonic-gate }
5030Sstevel@tonic-gate
5040Sstevel@tonic-gate /*at this point the last key is paged in and
5050Sstevel@tonic-gate we can proceed as in old dbm -- like Ken did his. */
5060Sstevel@tonic-gate
5070Sstevel@tonic-gate f = 1;
5080Sstevel@tonic-gate j=0;
5090Sstevel@tonic-gate sp = (short *)db->dbm_pagbuf;
5100Sstevel@tonic-gate
5110Sstevel@tonic-gate for(i=0;; i+=2) {
5120Sstevel@tonic-gate
5130Sstevel@tonic-gate /*begin put makdatum inline*/
5140Sstevel@tonic-gate
5150Sstevel@tonic-gate if ((unsigned)i >= sp[0]) {
5160Sstevel@tonic-gate item.dptr = NULL;
5170Sstevel@tonic-gate item.dsize = 0;
5180Sstevel@tonic-gate break; /*from below*/
5190Sstevel@tonic-gate }
5200Sstevel@tonic-gate else {
5210Sstevel@tonic-gate if (i > 0) item.dsize = sp[i] - sp[i+1];
5220Sstevel@tonic-gate else item.dsize = PBLKSIZ - sp[i+1];
5230Sstevel@tonic-gate item.dptr = db->dbm_pagbuf+sp[i+1];
5240Sstevel@tonic-gate }
5250Sstevel@tonic-gate
5260Sstevel@tonic-gate /* item = makdatum(db->dbm_pagbuf, i);*/
5270Sstevel@tonic-gate /*end put makdatum inline*/
5280Sstevel@tonic-gate
5290Sstevel@tonic-gate if(item.dptr == NULL)
5300Sstevel@tonic-gate break;
5310Sstevel@tonic-gate /*inline cmpdatum*/
5320Sstevel@tonic-gate
5330Sstevel@tonic-gate
5340Sstevel@tonic-gate n = key.dsize;
5350Sstevel@tonic-gate if(n != item.dsize)
5360Sstevel@tonic-gate if( (n - item.dsize) <= 0 ) continue;
5370Sstevel@tonic-gate else { }
5380Sstevel@tonic-gate else {
5390Sstevel@tonic-gate if(n == 0) continue;
5400Sstevel@tonic-gate p1 = key.dptr;
5410Sstevel@tonic-gate p2 = item.dptr;
5420Sstevel@tonic-gate do
5430Sstevel@tonic-gate if(*p1++ != *p2++)
5440Sstevel@tonic-gate if((*--p1 - *--p2) > 0) goto keep_going;
5450Sstevel@tonic-gate else continue;
5460Sstevel@tonic-gate while(--n);
5470Sstevel@tonic-gate continue;
5480Sstevel@tonic-gate }
5490Sstevel@tonic-gate
5500Sstevel@tonic-gate keep_going:
5510Sstevel@tonic-gate
5520Sstevel@tonic-gate /*end inline cmpdatum*/
5530Sstevel@tonic-gate /*if(cmpdatum(key, item) <= 0)
5540Sstevel@tonic-gate continue;*/
5550Sstevel@tonic-gate if (f) {
5560Sstevel@tonic-gate bitem = item;
5570Sstevel@tonic-gate j=i;
5580Sstevel@tonic-gate f = 0;
5590Sstevel@tonic-gate }
5600Sstevel@tonic-gate else {
5610Sstevel@tonic-gate
5620Sstevel@tonic-gate /* if(cmpdatum(bitem, item) < 0)*/
5630Sstevel@tonic-gate
5640Sstevel@tonic-gate n = bitem.dsize;
5650Sstevel@tonic-gate if(n != item.dsize)
5660Sstevel@tonic-gate {
5670Sstevel@tonic-gate if((n - item.dsize) <0) {
5680Sstevel@tonic-gate bitem = item;
5690Sstevel@tonic-gate j=i;
5700Sstevel@tonic-gate }
5710Sstevel@tonic-gate }
5720Sstevel@tonic-gate else if (n != 0) {
5730Sstevel@tonic-gate p1 = bitem.dptr;
5740Sstevel@tonic-gate p2 = item.dptr;
5750Sstevel@tonic-gate do
5760Sstevel@tonic-gate if(*p1++ != *p2++) {
5770Sstevel@tonic-gate if((*--p1 - *--p2) <0) {
5780Sstevel@tonic-gate bitem = item;
5790Sstevel@tonic-gate j=i;
5800Sstevel@tonic-gate }
5810Sstevel@tonic-gate break;
5820Sstevel@tonic-gate }
5830Sstevel@tonic-gate while(--n);
5840Sstevel@tonic-gate }
5850Sstevel@tonic-gate }
5860Sstevel@tonic-gate }
5870Sstevel@tonic-gate
5880Sstevel@tonic-gate if(f == 0) {
5890Sstevel@tonic-gate db->dbm_keyptr = j + 2;
5900Sstevel@tonic-gate db->dbm_blkptr = db->dbm_blkno;
591*722Smuffin return (bitem);
5920Sstevel@tonic-gate }
5930Sstevel@tonic-gate
5940Sstevel@tonic-gate /*really need hash at this point*/
5950Sstevel@tonic-gate /*if he gave us a key we have already calculated the hash*/
5960Sstevel@tonic-gate /*if not get it*/
5970Sstevel@tonic-gate if (inkey.dptr == NULL) hash=dcalchash(key);
5980Sstevel@tonic-gate hash = dbm_hashinc(db,hash);
5990Sstevel@tonic-gate
6000Sstevel@tonic-gate if(hash == 0)
601*722Smuffin return (item); /*null*/
6020Sstevel@tonic-gate /*get first item on next page in hash table order*/
603*722Smuffin return (dbm_firsthash(db, hash));
6040Sstevel@tonic-gate
6050Sstevel@tonic-gate
6060Sstevel@tonic-gate }
6070Sstevel@tonic-gate
608*722Smuffin static void
dbm_access(DBM * db,long hash)609*722Smuffin dbm_access(DBM *db, long hash)
6100Sstevel@tonic-gate {
611*722Smuffin int b, i, n;
612*722Smuffin long bn;
613*722Smuffin long my_bitno;
614*722Smuffin long my_hmask;
615*722Smuffin long my_blkno;
6160Sstevel@tonic-gate
6170Sstevel@tonic-gate for (my_hmask=0;; my_hmask=(my_hmask<<1)+1) {
6180Sstevel@tonic-gate my_blkno = hash & my_hmask;
6190Sstevel@tonic-gate my_bitno = my_blkno + my_hmask;
6200Sstevel@tonic-gate /*getbit inline*/
6210Sstevel@tonic-gate if (my_bitno > db->dbm_maxbno) break;
6220Sstevel@tonic-gate n = my_bitno % BYTESIZ;
6230Sstevel@tonic-gate bn = my_bitno / BYTESIZ;
6240Sstevel@tonic-gate i = bn % DBLKSIZ;
6250Sstevel@tonic-gate b = bn / DBLKSIZ;
6260Sstevel@tonic-gate if (b != db->dbm_dirbno) {
6270Sstevel@tonic-gate if (dbm_dirdirty(db)) dbm_flushdir(db); /*must flush*/
6280Sstevel@tonic-gate db->dbm_dirbno = b;
6290Sstevel@tonic-gate (void) lseek(db->dbm_dirf, (long)(b*DBLKSIZ), L_SET);
6300Sstevel@tonic-gate if (read(db->dbm_dirf, db->dbm_dirbuf, DBLKSIZ) != DBLKSIZ)
6310Sstevel@tonic-gate bzero(db->dbm_dirbuf, DBLKSIZ);
6320Sstevel@tonic-gate }
6330Sstevel@tonic-gate if ( (db->dbm_dirbuf[i] & (1<<n)) == 0 ) break;
6340Sstevel@tonic-gate
6350Sstevel@tonic-gate /*
6360Sstevel@tonic-gate if (getbit(db) == 0)
6370Sstevel@tonic-gate break;
6380Sstevel@tonic-gate */
6390Sstevel@tonic-gate }
6400Sstevel@tonic-gate /*copy*/
6410Sstevel@tonic-gate db->dbm_blkno=my_blkno;
6420Sstevel@tonic-gate db->dbm_bitno=my_bitno;
6430Sstevel@tonic-gate db->dbm_hmask=my_hmask;
6440Sstevel@tonic-gate
6450Sstevel@tonic-gate if (my_blkno != db->dbm_pagbno) {
6460Sstevel@tonic-gate if (dbm_dirty(db)){ /*must page out the page*/
6470Sstevel@tonic-gate (void) lseek(db->dbm_pagf, (long)(db->dbm_pagbno*PBLKSIZ), L_SET);
6480Sstevel@tonic-gate if (write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ) {
6490Sstevel@tonic-gate db->dbm_flags |= _DBM_IOERR;
6500Sstevel@tonic-gate }
6510Sstevel@tonic-gate dbm_clrdirty(db);
6520Sstevel@tonic-gate }
6530Sstevel@tonic-gate
6540Sstevel@tonic-gate db->dbm_pagbno = my_blkno;
6550Sstevel@tonic-gate (void) lseek(db->dbm_pagf, (long)(my_blkno*PBLKSIZ), L_SET);
6560Sstevel@tonic-gate if (read(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ)
6570Sstevel@tonic-gate bzero(db->dbm_pagbuf, PBLKSIZ);
6580Sstevel@tonic-gate #ifdef DEBUG
6590Sstevel@tonic-gate else if (chkblk(db->dbm_pagbuf) < 0)
6600Sstevel@tonic-gate db->dbm_flags |= _DBM_IOERR;
6610Sstevel@tonic-gate #endif
6620Sstevel@tonic-gate }
6630Sstevel@tonic-gate }
6640Sstevel@tonic-gate
665*722Smuffin static int
getbit(DBM * db)666*722Smuffin getbit(DBM *db)
6670Sstevel@tonic-gate {
6680Sstevel@tonic-gate long bn;
669*722Smuffin int b, i, n;
6700Sstevel@tonic-gate
6710Sstevel@tonic-gate
6720Sstevel@tonic-gate if (db->dbm_bitno > db->dbm_maxbno)
6730Sstevel@tonic-gate return (0);
6740Sstevel@tonic-gate n = db->dbm_bitno % BYTESIZ;
6750Sstevel@tonic-gate bn = db->dbm_bitno / BYTESIZ;
6760Sstevel@tonic-gate i = bn % DBLKSIZ;
6770Sstevel@tonic-gate b = bn / DBLKSIZ;
6780Sstevel@tonic-gate if (b != db->dbm_dirbno) {
6790Sstevel@tonic-gate if (dbm_dirdirty(db)) dbm_flushdir(db); /*must flush*/
6800Sstevel@tonic-gate db->dbm_dirbno = b;
6810Sstevel@tonic-gate (void) lseek(db->dbm_dirf, (long)(b*DBLKSIZ), L_SET);
6820Sstevel@tonic-gate if (read(db->dbm_dirf, db->dbm_dirbuf, DBLKSIZ) != DBLKSIZ)
6830Sstevel@tonic-gate bzero(db->dbm_dirbuf, DBLKSIZ);
6840Sstevel@tonic-gate }
6850Sstevel@tonic-gate return (db->dbm_dirbuf[i] & (1<<n));
6860Sstevel@tonic-gate }
6870Sstevel@tonic-gate
688*722Smuffin static int
setbit(DBM * db)689*722Smuffin setbit(DBM *db)
6900Sstevel@tonic-gate {
6910Sstevel@tonic-gate long bn;
692*722Smuffin int i, n, b;
6930Sstevel@tonic-gate
6940Sstevel@tonic-gate if (db->dbm_bitno > db->dbm_maxbno)
6950Sstevel@tonic-gate db->dbm_maxbno = db->dbm_bitno;
6960Sstevel@tonic-gate n = db->dbm_bitno % BYTESIZ;
6970Sstevel@tonic-gate bn = db->dbm_bitno / BYTESIZ;
6980Sstevel@tonic-gate i = bn % DBLKSIZ;
6990Sstevel@tonic-gate b = bn / DBLKSIZ;
7000Sstevel@tonic-gate if (b != db->dbm_dirbno) {
7010Sstevel@tonic-gate if (dbm_dirdirty(db)) dbm_flushdir(db);
7020Sstevel@tonic-gate db->dbm_dirbno = b;
7030Sstevel@tonic-gate (void) lseek(db->dbm_dirf, (long)(b*DBLKSIZ), L_SET);
7040Sstevel@tonic-gate if (read(db->dbm_dirf, db->dbm_dirbuf, DBLKSIZ) != DBLKSIZ)
7050Sstevel@tonic-gate bzero(db->dbm_dirbuf, DBLKSIZ);
7060Sstevel@tonic-gate }
7070Sstevel@tonic-gate db->dbm_dirbuf[i] |= 1<<n;
7080Sstevel@tonic-gate db->dbm_dirbno = b;
7090Sstevel@tonic-gate if (dbm_defwrite(db)) {
7100Sstevel@tonic-gate dbm_setdirdirty(db);
7110Sstevel@tonic-gate } else{
7120Sstevel@tonic-gate (void) lseek(db->dbm_dirf, (long)(b*DBLKSIZ), L_SET);
7130Sstevel@tonic-gate if (write(db->dbm_dirf, db->dbm_dirbuf, DBLKSIZ) != DBLKSIZ) {
7140Sstevel@tonic-gate return (-1);
7150Sstevel@tonic-gate }
7160Sstevel@tonic-gate }
7170Sstevel@tonic-gate return (0);
7180Sstevel@tonic-gate }
7190Sstevel@tonic-gate
7200Sstevel@tonic-gate static datum
makdatum(char buf[PBLKSIZ],int n)721*722Smuffin makdatum(char buf[PBLKSIZ], int n)
7220Sstevel@tonic-gate {
723*722Smuffin short *sp;
724*722Smuffin int t;
7250Sstevel@tonic-gate datum item;
7260Sstevel@tonic-gate
7270Sstevel@tonic-gate sp = (short *)buf;
7280Sstevel@tonic-gate if ((unsigned)n >= sp[0]) {
7290Sstevel@tonic-gate item.dptr = NULL;
7300Sstevel@tonic-gate item.dsize = 0;
7310Sstevel@tonic-gate return (item);
7320Sstevel@tonic-gate }
7330Sstevel@tonic-gate t = PBLKSIZ;
7340Sstevel@tonic-gate if (n > 0)
7350Sstevel@tonic-gate t = sp[n];
7360Sstevel@tonic-gate item.dptr = buf+sp[n+1];
7370Sstevel@tonic-gate item.dsize = t - sp[n+1];
7380Sstevel@tonic-gate return (item);
7390Sstevel@tonic-gate }
7400Sstevel@tonic-gate
741*722Smuffin static int
cmpdatum(datum d1,datum d2)742*722Smuffin cmpdatum(datum d1, datum d2)
7430Sstevel@tonic-gate {
744*722Smuffin int n;
745*722Smuffin char *p1, *p2;
7460Sstevel@tonic-gate
7470Sstevel@tonic-gate n = d1.dsize;
7480Sstevel@tonic-gate if(n != d2.dsize)
7490Sstevel@tonic-gate return(n - d2.dsize);
7500Sstevel@tonic-gate if(n == 0)
7510Sstevel@tonic-gate return(0);
7520Sstevel@tonic-gate p1 = d1.dptr;
7530Sstevel@tonic-gate p2 = d2.dptr;
7540Sstevel@tonic-gate do
7550Sstevel@tonic-gate if(*p1++ != *p2++)
7560Sstevel@tonic-gate return(*--p1 - *--p2);
7570Sstevel@tonic-gate while(--n);
7580Sstevel@tonic-gate return(0);
7590Sstevel@tonic-gate }
7600Sstevel@tonic-gate
761*722Smuffin static int
finddatum(char buf[PBLKSIZ],datum item)762*722Smuffin finddatum(char buf[PBLKSIZ], datum item)
7630Sstevel@tonic-gate {
764*722Smuffin short *sp;
765*722Smuffin int i, n, j;
7660Sstevel@tonic-gate
7670Sstevel@tonic-gate sp = (short *)buf;
7680Sstevel@tonic-gate n = PBLKSIZ;
7690Sstevel@tonic-gate for (i=0, j=sp[0]; i<j; i+=2, n = sp[i]) {
7700Sstevel@tonic-gate n -= sp[i+1];
7710Sstevel@tonic-gate if (n != item.dsize)
7720Sstevel@tonic-gate continue;
7730Sstevel@tonic-gate if (n == 0 || bcmp(&buf[sp[i+1]], item.dptr, n) == 0)
7740Sstevel@tonic-gate return (i);
7750Sstevel@tonic-gate }
7760Sstevel@tonic-gate return (-1);
7770Sstevel@tonic-gate }
7780Sstevel@tonic-gate
7790Sstevel@tonic-gate static int hitab[16]
7800Sstevel@tonic-gate = { 61, 57, 53, 49, 45, 41, 37, 33,
7810Sstevel@tonic-gate 29, 25, 21, 17, 13, 9, 5, 1,
7820Sstevel@tonic-gate };
783*722Smuffin
7840Sstevel@tonic-gate static long hltab[64]
7850Sstevel@tonic-gate = {
7860Sstevel@tonic-gate 06100151277L,06106161736L,06452611562L,05001724107L,
7870Sstevel@tonic-gate 02614772546L,04120731531L,04665262210L,07347467531L,
7880Sstevel@tonic-gate 06735253126L,06042345173L,03072226605L,01464164730L,
7890Sstevel@tonic-gate 03247435524L,07652510057L,01546775256L,05714532133L,
7900Sstevel@tonic-gate 06173260402L,07517101630L,02431460343L,01743245566L,
7910Sstevel@tonic-gate 00261675137L,02433103631L,03421772437L,04447707466L,
7920Sstevel@tonic-gate 04435620103L,03757017115L,03641531772L,06767633246L,
7930Sstevel@tonic-gate 02673230344L,00260612216L,04133454451L,00615531516L,
7940Sstevel@tonic-gate 06137717526L,02574116560L,02304023373L,07061702261L,
7950Sstevel@tonic-gate 05153031405L,05322056705L,07401116734L,06552375715L,
7960Sstevel@tonic-gate 06165233473L,05311063631L,01212221723L,01052267235L,
7970Sstevel@tonic-gate 06000615237L,01075222665L,06330216006L,04402355630L,
7980Sstevel@tonic-gate 01451177262L,02000133436L,06025467062L,07121076461L,
7990Sstevel@tonic-gate 03123433522L,01010635225L,01716177066L,05161746527L,
8000Sstevel@tonic-gate 01736635071L,06243505026L,03637211610L,01756474365L,
8010Sstevel@tonic-gate 04723077174L,03642763134L,05750130273L,03655541561L,
8020Sstevel@tonic-gate };
8030Sstevel@tonic-gate
8040Sstevel@tonic-gate static long
dcalchash(datum item)805*722Smuffin dcalchash(datum item)
8060Sstevel@tonic-gate {
807*722Smuffin int s, c, j;
808*722Smuffin char *cp;
809*722Smuffin long hashl;
810*722Smuffin int hashi;
8110Sstevel@tonic-gate
8120Sstevel@tonic-gate hashl = 0;
8130Sstevel@tonic-gate hashi = 0;
8140Sstevel@tonic-gate for (cp = item.dptr, s=item.dsize; --s >= 0; ) {
8150Sstevel@tonic-gate c = *cp++;
8160Sstevel@tonic-gate for (j=0; j<BYTESIZ; j+=4) {
8170Sstevel@tonic-gate hashi += hitab[c&017];
8180Sstevel@tonic-gate hashl += hltab[hashi&63];
8190Sstevel@tonic-gate c >>= 4;
8200Sstevel@tonic-gate }
8210Sstevel@tonic-gate }
8220Sstevel@tonic-gate return (hashl);
8230Sstevel@tonic-gate }
8240Sstevel@tonic-gate
8250Sstevel@tonic-gate /*
8260Sstevel@tonic-gate * Delete pairs of items (n & n+1).
8270Sstevel@tonic-gate */
828*722Smuffin static int
delitem(char buf[PBLKSIZ],int n)829*722Smuffin delitem(char buf[PBLKSIZ], int n)
8300Sstevel@tonic-gate {
831*722Smuffin short *sp, *sp1;
832*722Smuffin int i1, i2;
8330Sstevel@tonic-gate
8340Sstevel@tonic-gate sp = (short *)buf;
8350Sstevel@tonic-gate i2 = sp[0];
8360Sstevel@tonic-gate if ((unsigned)n >= i2 || (n & 1))
8370Sstevel@tonic-gate return (0);
8380Sstevel@tonic-gate if (n == i2-2) {
8390Sstevel@tonic-gate sp[0] -= 2;
8400Sstevel@tonic-gate return (1);
8410Sstevel@tonic-gate }
8420Sstevel@tonic-gate i1 = PBLKSIZ;
8430Sstevel@tonic-gate if (n > 0)
8440Sstevel@tonic-gate i1 = sp[n];
8450Sstevel@tonic-gate i1 -= sp[n+2];
8460Sstevel@tonic-gate if (i1 > 0) {
8470Sstevel@tonic-gate i2 = sp[i2];
8480Sstevel@tonic-gate bcopy(&buf[i2], &buf[i2 + i1], sp[n+2] - i2);
8490Sstevel@tonic-gate }
8500Sstevel@tonic-gate sp[0] -= 2;
8510Sstevel@tonic-gate for (sp1 = sp + sp[0], sp += n+1; sp <= sp1; sp++)
8520Sstevel@tonic-gate sp[0] = sp[2] + i1;
8530Sstevel@tonic-gate return (1);
8540Sstevel@tonic-gate }
8550Sstevel@tonic-gate
8560Sstevel@tonic-gate /*
8570Sstevel@tonic-gate * Add pairs of items (item & item1).
8580Sstevel@tonic-gate */
859*722Smuffin static int
additem(char buf[PBLKSIZ],datum item,datum item1)860*722Smuffin additem(char buf[PBLKSIZ], datum item, datum item1)
8610Sstevel@tonic-gate {
862*722Smuffin short *sp;
863*722Smuffin int i1, i2;
8640Sstevel@tonic-gate
8650Sstevel@tonic-gate sp = (short *)buf;
8660Sstevel@tonic-gate i1 = PBLKSIZ;
8670Sstevel@tonic-gate i2 = sp[0];
8680Sstevel@tonic-gate if (i2 > 0)
8690Sstevel@tonic-gate i1 = sp[i2];
8700Sstevel@tonic-gate i1 -= item.dsize + item1.dsize;
8710Sstevel@tonic-gate if (i1 <= (i2+3) * sizeof(short))
8720Sstevel@tonic-gate return (0);
8730Sstevel@tonic-gate sp[0] += 2;
8740Sstevel@tonic-gate sp[++i2] = i1 + item1.dsize;
8750Sstevel@tonic-gate bcopy(item.dptr, &buf[i1 + item1.dsize], item.dsize);
8760Sstevel@tonic-gate sp[++i2] = i1;
8770Sstevel@tonic-gate bcopy(item1.dptr, &buf[i1], item1.dsize);
8780Sstevel@tonic-gate return (1);
8790Sstevel@tonic-gate }
8800Sstevel@tonic-gate
8810Sstevel@tonic-gate #ifdef DEBUG
882*722Smuffin static int
chkblk(char buf[PBLKSIZ])883*722Smuffin chkblk(char buf[PBLKSIZ])
8840Sstevel@tonic-gate {
885*722Smuffin short *sp;
886*722Smuffin int t, i;
8870Sstevel@tonic-gate
8880Sstevel@tonic-gate sp = (short *)buf;
8890Sstevel@tonic-gate t = PBLKSIZ;
8900Sstevel@tonic-gate for (i=0; i<sp[0]; i++) {
8910Sstevel@tonic-gate if (sp[i+1] > t)
8920Sstevel@tonic-gate return (-1);
8930Sstevel@tonic-gate t = sp[i+1];
8940Sstevel@tonic-gate }
8950Sstevel@tonic-gate if (t < (sp[0]+1)*sizeof(short))
8960Sstevel@tonic-gate return (-1);
8970Sstevel@tonic-gate return (0);
8980Sstevel@tonic-gate }
8990Sstevel@tonic-gate #endif
900