xref: /onnv-gate/usr/src/lib/libbc/libc/gen/common/ndbm.c (revision 722:636b850d4ee9)
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