xref: /titanic_50/usr/src/lib/libbc/libc/gen/common/ndbm.c (revision 5d54f3d8999eac1762fe0a8c7177d20f1f201fae)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * Copyright 2002 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate 
67c478bd9Sstevel@tonic-gate /*
77c478bd9Sstevel@tonic-gate  * Copyright (c) 1983 Regents of the University of California.
87c478bd9Sstevel@tonic-gate  * All rights reserved.  The Berkeley software License Agreement
97c478bd9Sstevel@tonic-gate  * specifies the terms and conditions for redistribution.
107c478bd9Sstevel@tonic-gate  */
117c478bd9Sstevel@tonic-gate 
12*5d54f3d8Smuffin #pragma ident	"%Z%%M%	%I%	%E% SMI"
13*5d54f3d8Smuffin 
147c478bd9Sstevel@tonic-gate #include <sys/types.h>
157c478bd9Sstevel@tonic-gate #include <sys/stat.h>
167c478bd9Sstevel@tonic-gate #include <sys/file.h>
177c478bd9Sstevel@tonic-gate #include <stdio.h>
187c478bd9Sstevel@tonic-gate #include <errno.h>
197c478bd9Sstevel@tonic-gate #include <ndbm.h>
20*5d54f3d8Smuffin #include <stdlib.h>
21*5d54f3d8Smuffin #include <string.h>
22*5d54f3d8Smuffin 
23*5d54f3d8Smuffin datum dbm_do_nextkey(DBM *, datum);
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*add support for batched writing for NIS*/
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate #define _DBM_DEFWRITE 0x4
297c478bd9Sstevel@tonic-gate #define _DBM_DIRTY 0x8
307c478bd9Sstevel@tonic-gate #define _DBM_DIRDIRTY 0x10
317c478bd9Sstevel@tonic-gate #define dbm_dirty(db) ((db)->dbm_flags & _DBM_DIRTY)
327c478bd9Sstevel@tonic-gate #define dbm_dirdirty(db) ((db)->dbm_flags & _DBM_DIRDIRTY)
337c478bd9Sstevel@tonic-gate #define dbm_defwrite(db) ((db)->dbm_flags & _DBM_DEFWRITE)
347c478bd9Sstevel@tonic-gate #define dbm_setdirty(db) (db)->dbm_flags |= _DBM_DIRTY
357c478bd9Sstevel@tonic-gate #define dbm_clrdirty(db) (db)->dbm_flags &= ~_DBM_DIRTY
367c478bd9Sstevel@tonic-gate #define dbm_setdirdirty(db) (db)->dbm_flags |= _DBM_DIRDIRTY
377c478bd9Sstevel@tonic-gate #define dbm_clrdirdirty(db) (db)->dbm_flags &= ~_DBM_DIRDIRTY
387c478bd9Sstevel@tonic-gate 
39*5d54f3d8Smuffin 
40*5d54f3d8Smuffin static void	dbm_access(DBM *, long);
41*5d54f3d8Smuffin static int	getbit(DBM *);
42*5d54f3d8Smuffin static int	setbit(DBM *);
43*5d54f3d8Smuffin static int	cmpdatum(datum, datum);
44*5d54f3d8Smuffin static int	finddatum(char [PBLKSIZ], datum);
45*5d54f3d8Smuffin static int	delitem(char [PBLKSIZ], int);
46*5d54f3d8Smuffin static int	additem(char [PBLKSIZ], datum, datum);
47*5d54f3d8Smuffin static datum	makdatum(char [PBLKSIZ], int);
48*5d54f3d8Smuffin static long	dcalchash(datum);
49*5d54f3d8Smuffin 
507c478bd9Sstevel@tonic-gate /*used to make a dbm file all at once instead of incrementally*/
51*5d54f3d8Smuffin void
dbm_setdefwrite(DBM * db)52*5d54f3d8Smuffin dbm_setdefwrite(DBM *db)
537c478bd9Sstevel@tonic-gate {
547c478bd9Sstevel@tonic-gate 	db->dbm_flags |= _DBM_DEFWRITE;
557c478bd9Sstevel@tonic-gate }
567c478bd9Sstevel@tonic-gate 
57*5d54f3d8Smuffin int
dbm_flush(DBM * db)58*5d54f3d8Smuffin dbm_flush(DBM *db)
597c478bd9Sstevel@tonic-gate {
607c478bd9Sstevel@tonic-gate 	int ok=0;
617c478bd9Sstevel@tonic-gate 	if (dbm_flushpag(db)<0) ok= -1;
627c478bd9Sstevel@tonic-gate 	if (dbm_flushdir(db)<0) ok= -1;
637c478bd9Sstevel@tonic-gate 	return(ok);
647c478bd9Sstevel@tonic-gate }
657c478bd9Sstevel@tonic-gate 
66*5d54f3d8Smuffin int
dbm_flushpag(DBM * db)67*5d54f3d8Smuffin dbm_flushpag(DBM *db)
687c478bd9Sstevel@tonic-gate {
697c478bd9Sstevel@tonic-gate 	int ok=0;
707c478bd9Sstevel@tonic-gate 	if (dbm_dirty(db)){ /*must page out the page*/
717c478bd9Sstevel@tonic-gate 		(void) lseek(db->dbm_pagf, (long)(db->dbm_pagbno*PBLKSIZ), L_SET);
727c478bd9Sstevel@tonic-gate 		if (write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ) {
737c478bd9Sstevel@tonic-gate 			db->dbm_flags |= _DBM_IOERR;
747c478bd9Sstevel@tonic-gate 			ok= -1;
757c478bd9Sstevel@tonic-gate 			}
767c478bd9Sstevel@tonic-gate 		dbm_clrdirty(db);
777c478bd9Sstevel@tonic-gate 	}
787c478bd9Sstevel@tonic-gate 	return(ok);
797c478bd9Sstevel@tonic-gate }
807c478bd9Sstevel@tonic-gate 
81*5d54f3d8Smuffin int
dbm_flushdir(DBM * db)82*5d54f3d8Smuffin dbm_flushdir(DBM *db)
837c478bd9Sstevel@tonic-gate {
847c478bd9Sstevel@tonic-gate 	int ok=0;
857c478bd9Sstevel@tonic-gate 	if (dbm_dirdirty(db)){ /*must page out the dir*/
867c478bd9Sstevel@tonic-gate 	(void) lseek(db->dbm_dirf, (long)(db->dbm_dirbno*DBLKSIZ), L_SET);
877c478bd9Sstevel@tonic-gate 	if (write(db->dbm_dirf, db->dbm_dirbuf, DBLKSIZ) != DBLKSIZ) {
887c478bd9Sstevel@tonic-gate 		ok= -1;
897c478bd9Sstevel@tonic-gate 		}
907c478bd9Sstevel@tonic-gate 	dbm_clrdirdirty(db);
917c478bd9Sstevel@tonic-gate 	}
927c478bd9Sstevel@tonic-gate 	return(ok);
937c478bd9Sstevel@tonic-gate }
947c478bd9Sstevel@tonic-gate #define BYTESIZ 8
957c478bd9Sstevel@tonic-gate #undef setbit
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate DBM *
dbm_open(char * file,int flags,int mode)98*5d54f3d8Smuffin dbm_open(char *file, int flags, int mode)
997c478bd9Sstevel@tonic-gate {
1007c478bd9Sstevel@tonic-gate 	struct stat statb;
101*5d54f3d8Smuffin 	DBM *db;
1027c478bd9Sstevel@tonic-gate 	int	serrno;
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate 	if ((db = (DBM *)malloc(sizeof *db)) == 0) {
1057c478bd9Sstevel@tonic-gate 		errno = ENOMEM;
1067c478bd9Sstevel@tonic-gate 		return ((DBM *)0);
1077c478bd9Sstevel@tonic-gate 	}
1087c478bd9Sstevel@tonic-gate 	db->dbm_flags = (flags & 03) == O_RDONLY ? _DBM_RDONLY : 0;
1097c478bd9Sstevel@tonic-gate 	if ((flags & 03) == O_WRONLY)
1107c478bd9Sstevel@tonic-gate 		flags = (flags & ~03) | O_RDWR;
1117c478bd9Sstevel@tonic-gate 	if (strlcpy(db->dbm_pagbuf, file, sizeof (db->dbm_pagbuf)) >=
1127c478bd9Sstevel@tonic-gate 	    sizeof (db->dbm_pagbuf) ||
1137c478bd9Sstevel@tonic-gate 	    strlcat(db->dbm_pagbuf, ".pag", sizeof (db->dbm_pagbuf)) >=
1147c478bd9Sstevel@tonic-gate 	    sizeof (db->dbm_pagbuf)) {
1157c478bd9Sstevel@tonic-gate 		/*
1167c478bd9Sstevel@tonic-gate 		 * file.pag does not fit into dbm_pagbuf.
1177c478bd9Sstevel@tonic-gate 		 * fails with ENAMETOOLONG.
1187c478bd9Sstevel@tonic-gate 		 */
1197c478bd9Sstevel@tonic-gate 		serrno = ENAMETOOLONG;
1207c478bd9Sstevel@tonic-gate 		goto bad;
1217c478bd9Sstevel@tonic-gate 	}
1227c478bd9Sstevel@tonic-gate 	db->dbm_pagf = open(db->dbm_pagbuf, flags, mode);
1237c478bd9Sstevel@tonic-gate 	if (db->dbm_pagf < 0) {
1247c478bd9Sstevel@tonic-gate 		serrno = errno;
1257c478bd9Sstevel@tonic-gate 		goto bad;
1267c478bd9Sstevel@tonic-gate 	}
1277c478bd9Sstevel@tonic-gate 	/*
1287c478bd9Sstevel@tonic-gate 	 * We know this won't overflow so it is safe to ignore the
1297c478bd9Sstevel@tonic-gate 	 * return value; we use strl* to prevent false hits in
1307c478bd9Sstevel@tonic-gate 	 * code sweeps.
1317c478bd9Sstevel@tonic-gate 	 */
1327c478bd9Sstevel@tonic-gate 	(void) strlcpy(db->dbm_pagbuf, file, sizeof (db->dbm_pagbuf));
1337c478bd9Sstevel@tonic-gate 	(void) strlcat(db->dbm_pagbuf, ".dir", sizeof (db->dbm_pagbuf));
1347c478bd9Sstevel@tonic-gate 	db->dbm_dirf = open(db->dbm_pagbuf, flags, mode);
1357c478bd9Sstevel@tonic-gate 	if (db->dbm_dirf < 0) {
1367c478bd9Sstevel@tonic-gate 		serrno = errno;
1377c478bd9Sstevel@tonic-gate 		goto bad1;
1387c478bd9Sstevel@tonic-gate 	}
1397c478bd9Sstevel@tonic-gate 	(void) fstat(db->dbm_dirf, &statb);
1407c478bd9Sstevel@tonic-gate 	db->dbm_maxbno = statb.st_size*BYTESIZ-1;
1417c478bd9Sstevel@tonic-gate 	db->dbm_pagbno = db->dbm_dirbno = -1;
1427c478bd9Sstevel@tonic-gate 	return (db);
1437c478bd9Sstevel@tonic-gate bad1:
1447c478bd9Sstevel@tonic-gate 	(void) close(db->dbm_pagf);
1457c478bd9Sstevel@tonic-gate bad:
1467c478bd9Sstevel@tonic-gate 	free((char *)db);
1477c478bd9Sstevel@tonic-gate 	errno = serrno;
1487c478bd9Sstevel@tonic-gate 	return ((DBM *)0);
1497c478bd9Sstevel@tonic-gate }
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate void
dbm_close(DBM * db)152*5d54f3d8Smuffin dbm_close(DBM *db)
1537c478bd9Sstevel@tonic-gate {
1547c478bd9Sstevel@tonic-gate 	(void) dbm_close_status(db);
1557c478bd9Sstevel@tonic-gate }
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate /*close with return code*/
1587c478bd9Sstevel@tonic-gate int
dbm_close_status(DBM * db)159*5d54f3d8Smuffin dbm_close_status(DBM *db)
1607c478bd9Sstevel@tonic-gate {
1617c478bd9Sstevel@tonic-gate 	int ok;
1627c478bd9Sstevel@tonic-gate 	ok=0;
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate 	if (dbm_flush(db) <0)   ok = -1;
1657c478bd9Sstevel@tonic-gate 	if (close(db->dbm_dirf)<0) ok= -1;
1667c478bd9Sstevel@tonic-gate 	if ( close(db->dbm_pagf)<0) ok= -1;
1677c478bd9Sstevel@tonic-gate 	free((char *)db);
1687c478bd9Sstevel@tonic-gate 	return (ok);
1697c478bd9Sstevel@tonic-gate }
170*5d54f3d8Smuffin 
1717c478bd9Sstevel@tonic-gate long
dbm_forder(DBM * db,datum key)172*5d54f3d8Smuffin dbm_forder(DBM *db, datum key)
1737c478bd9Sstevel@tonic-gate {
1747c478bd9Sstevel@tonic-gate 	long hash;
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate 	hash = dcalchash(key);
1777c478bd9Sstevel@tonic-gate 	for (db->dbm_hmask=0;; db->dbm_hmask=(db->dbm_hmask<<1)+1) {
1787c478bd9Sstevel@tonic-gate 		db->dbm_blkno = hash & db->dbm_hmask;
1797c478bd9Sstevel@tonic-gate 		db->dbm_bitno = db->dbm_blkno + db->dbm_hmask;
1807c478bd9Sstevel@tonic-gate 		if (getbit(db) == 0)
1817c478bd9Sstevel@tonic-gate 			break;
1827c478bd9Sstevel@tonic-gate 	}
1837c478bd9Sstevel@tonic-gate 	return (db->dbm_blkno);
1847c478bd9Sstevel@tonic-gate }
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate datum
dbm_fetch(DBM * db,datum key)187*5d54f3d8Smuffin dbm_fetch(DBM *db, datum key)
1887c478bd9Sstevel@tonic-gate {
189*5d54f3d8Smuffin 	int i;
1907c478bd9Sstevel@tonic-gate 	datum item;
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate 	if (dbm_error(db))
1937c478bd9Sstevel@tonic-gate 		goto err;
1947c478bd9Sstevel@tonic-gate 	dbm_access(db, dcalchash(key));
1957c478bd9Sstevel@tonic-gate 	if ((i = finddatum(db->dbm_pagbuf, key)) >= 0) {
1967c478bd9Sstevel@tonic-gate 		item = makdatum(db->dbm_pagbuf, i+1);
1977c478bd9Sstevel@tonic-gate 		if (item.dptr != NULL)
1987c478bd9Sstevel@tonic-gate 			return (item);
1997c478bd9Sstevel@tonic-gate 	}
2007c478bd9Sstevel@tonic-gate err:
2017c478bd9Sstevel@tonic-gate 	item.dptr = NULL;
2027c478bd9Sstevel@tonic-gate 	item.dsize = 0;
2037c478bd9Sstevel@tonic-gate 	return (item);
2047c478bd9Sstevel@tonic-gate }
2057c478bd9Sstevel@tonic-gate 
206*5d54f3d8Smuffin int
dbm_delete(DBM * db,datum key)207*5d54f3d8Smuffin dbm_delete(DBM *db, datum key)
2087c478bd9Sstevel@tonic-gate {
209*5d54f3d8Smuffin 	int i;
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate 	if (dbm_error(db))
2127c478bd9Sstevel@tonic-gate 		return (-1);
2137c478bd9Sstevel@tonic-gate 	if (dbm_rdonly(db)) {
2147c478bd9Sstevel@tonic-gate 		errno = EPERM;
2157c478bd9Sstevel@tonic-gate 		return (-1);
2167c478bd9Sstevel@tonic-gate 	}
2177c478bd9Sstevel@tonic-gate 	dbm_access(db, dcalchash(key));
2187c478bd9Sstevel@tonic-gate 	if ((i = finddatum(db->dbm_pagbuf, key)) < 0)
2197c478bd9Sstevel@tonic-gate 		return (-1);
2207c478bd9Sstevel@tonic-gate 	if (!delitem(db->dbm_pagbuf, i))
2217c478bd9Sstevel@tonic-gate 		goto err;
2227c478bd9Sstevel@tonic-gate 	db->dbm_pagbno = db->dbm_blkno;
2237c478bd9Sstevel@tonic-gate 	if (dbm_defwrite(db)) {
2247c478bd9Sstevel@tonic-gate 		dbm_setdirty(db);
2257c478bd9Sstevel@tonic-gate 	}
2267c478bd9Sstevel@tonic-gate 	else {
2277c478bd9Sstevel@tonic-gate 	(void) lseek(db->dbm_pagf, (long)(db->dbm_blkno*PBLKSIZ), L_SET);
2287c478bd9Sstevel@tonic-gate 	if (write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ) {
2297c478bd9Sstevel@tonic-gate 	err:
2307c478bd9Sstevel@tonic-gate 		db->dbm_flags |= _DBM_IOERR;
2317c478bd9Sstevel@tonic-gate 		return (-1);
2327c478bd9Sstevel@tonic-gate 	}
2337c478bd9Sstevel@tonic-gate 	}
2347c478bd9Sstevel@tonic-gate 	return (0);
2357c478bd9Sstevel@tonic-gate }
2367c478bd9Sstevel@tonic-gate 
237*5d54f3d8Smuffin int
dbm_store(DBM * db,datum key,datum dat,int replace)238*5d54f3d8Smuffin dbm_store(DBM *db, datum key, datum dat, int replace)
2397c478bd9Sstevel@tonic-gate {
240*5d54f3d8Smuffin 	int i;
2417c478bd9Sstevel@tonic-gate 	datum item, item1;
2427c478bd9Sstevel@tonic-gate 	char ovfbuf[PBLKSIZ];
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate 	if (dbm_error(db))
2457c478bd9Sstevel@tonic-gate 		return (-1);
2467c478bd9Sstevel@tonic-gate 	if (dbm_rdonly(db)) {
2477c478bd9Sstevel@tonic-gate 		errno = EPERM;
2487c478bd9Sstevel@tonic-gate 		return (-1);
2497c478bd9Sstevel@tonic-gate 	}
2507c478bd9Sstevel@tonic-gate loop:
2517c478bd9Sstevel@tonic-gate 	dbm_access(db, dcalchash(key));
2527c478bd9Sstevel@tonic-gate 	if ((i = finddatum(db->dbm_pagbuf, key)) >= 0) {
2537c478bd9Sstevel@tonic-gate 		if (!replace)
2547c478bd9Sstevel@tonic-gate 			return (1);
2557c478bd9Sstevel@tonic-gate 		if (!delitem(db->dbm_pagbuf, i)) {
2567c478bd9Sstevel@tonic-gate 			db->dbm_flags |= _DBM_IOERR;
2577c478bd9Sstevel@tonic-gate 			return (-1);
2587c478bd9Sstevel@tonic-gate 		}
2597c478bd9Sstevel@tonic-gate 	}
2607c478bd9Sstevel@tonic-gate 	if (!additem(db->dbm_pagbuf, key, dat))
2617c478bd9Sstevel@tonic-gate 		goto split;
2627c478bd9Sstevel@tonic-gate 	db->dbm_pagbno = db->dbm_blkno;
2637c478bd9Sstevel@tonic-gate 	if (dbm_defwrite(db)) {
2647c478bd9Sstevel@tonic-gate 		dbm_setdirty(db);
2657c478bd9Sstevel@tonic-gate 	}
2667c478bd9Sstevel@tonic-gate 	else {
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 		(void) lseek(db->dbm_pagf, (long)(db->dbm_blkno*PBLKSIZ), L_SET);
2697c478bd9Sstevel@tonic-gate 		if (write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ) {
2707c478bd9Sstevel@tonic-gate 			db->dbm_flags |= _DBM_IOERR;
2717c478bd9Sstevel@tonic-gate 			return (-1);
2727c478bd9Sstevel@tonic-gate 		}
2737c478bd9Sstevel@tonic-gate 	}
2747c478bd9Sstevel@tonic-gate 	return (0);
2757c478bd9Sstevel@tonic-gate 
2767c478bd9Sstevel@tonic-gate split:
2777c478bd9Sstevel@tonic-gate 	if (key.dsize+dat.dsize+3*sizeof(short) >= PBLKSIZ) {
2787c478bd9Sstevel@tonic-gate 		db->dbm_flags |= _DBM_IOERR;
2797c478bd9Sstevel@tonic-gate 		errno = ENOSPC;
2807c478bd9Sstevel@tonic-gate 		return (-1);
2817c478bd9Sstevel@tonic-gate 	}
2827c478bd9Sstevel@tonic-gate 	bzero(ovfbuf, PBLKSIZ);
2837c478bd9Sstevel@tonic-gate 	for (i=0;;) {
2847c478bd9Sstevel@tonic-gate 		item = makdatum(db->dbm_pagbuf, i);
2857c478bd9Sstevel@tonic-gate 		if (item.dptr == NULL)
2867c478bd9Sstevel@tonic-gate 			break;
2877c478bd9Sstevel@tonic-gate 		if (dcalchash(item) & (db->dbm_hmask+1)) {
2887c478bd9Sstevel@tonic-gate 			item1 = makdatum(db->dbm_pagbuf, i+1);
2897c478bd9Sstevel@tonic-gate 			if (item1.dptr == NULL) {
2907c478bd9Sstevel@tonic-gate 				/*(void) fprintf(stderr, "ndbm: split not paired\n");*/
2917c478bd9Sstevel@tonic-gate 				db->dbm_flags |= _DBM_IOERR;
2927c478bd9Sstevel@tonic-gate 				break;
2937c478bd9Sstevel@tonic-gate 			}
2947c478bd9Sstevel@tonic-gate 			if (!additem(ovfbuf, item, item1) ||
2957c478bd9Sstevel@tonic-gate 			    !delitem(db->dbm_pagbuf, i)) {
2967c478bd9Sstevel@tonic-gate 				db->dbm_flags |= _DBM_IOERR;
2977c478bd9Sstevel@tonic-gate 				return (-1);
2987c478bd9Sstevel@tonic-gate 			}
2997c478bd9Sstevel@tonic-gate 			continue;
3007c478bd9Sstevel@tonic-gate 		}
3017c478bd9Sstevel@tonic-gate 		i += 2;
3027c478bd9Sstevel@tonic-gate 	}
3037c478bd9Sstevel@tonic-gate 	db->dbm_pagbno = db->dbm_blkno;
3047c478bd9Sstevel@tonic-gate 	(void) lseek(db->dbm_pagf, (long)(db->dbm_blkno*PBLKSIZ), L_SET);
3057c478bd9Sstevel@tonic-gate 	if (write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ) {
3067c478bd9Sstevel@tonic-gate 		db->dbm_flags |= _DBM_IOERR;
3077c478bd9Sstevel@tonic-gate 		return (-1);
3087c478bd9Sstevel@tonic-gate 	}
3097c478bd9Sstevel@tonic-gate 	dbm_clrdirty(db); /*clear dirty*/
3107c478bd9Sstevel@tonic-gate 	(void) lseek(db->dbm_pagf,
3117c478bd9Sstevel@tonic-gate 		(long)((db->dbm_blkno+db->dbm_hmask+1)*PBLKSIZ), L_SET);
3127c478bd9Sstevel@tonic-gate 	if (write(db->dbm_pagf, ovfbuf, PBLKSIZ) != PBLKSIZ) {
3137c478bd9Sstevel@tonic-gate 		db->dbm_flags |= _DBM_IOERR;
3147c478bd9Sstevel@tonic-gate 		return (-1);
3157c478bd9Sstevel@tonic-gate 	}
3167c478bd9Sstevel@tonic-gate 	if (setbit(db) < 0) {
3177c478bd9Sstevel@tonic-gate 		db->dbm_flags |= _DBM_IOERR;
3187c478bd9Sstevel@tonic-gate 		return (-1);
3197c478bd9Sstevel@tonic-gate 	}
3207c478bd9Sstevel@tonic-gate 	goto loop;
3217c478bd9Sstevel@tonic-gate }
322*5d54f3d8Smuffin 
3237c478bd9Sstevel@tonic-gate static long
dbm_hashinc(DBM * db,long hash)324*5d54f3d8Smuffin dbm_hashinc(DBM *db, long hash)
3257c478bd9Sstevel@tonic-gate {
3267c478bd9Sstevel@tonic-gate 
3277c478bd9Sstevel@tonic-gate 	long bit;
3287c478bd9Sstevel@tonic-gate 
3297c478bd9Sstevel@tonic-gate 	hash &= db->dbm_hmask;
3307c478bd9Sstevel@tonic-gate 	bit = db->dbm_hmask+1;
3317c478bd9Sstevel@tonic-gate 	for(;;) {
3327c478bd9Sstevel@tonic-gate 		bit >>= 1;
3337c478bd9Sstevel@tonic-gate 		if(bit == 0)
3347c478bd9Sstevel@tonic-gate 			return(0L);
3357c478bd9Sstevel@tonic-gate 		if((hash&bit) == 0)
3367c478bd9Sstevel@tonic-gate 			return(hash|bit);
3377c478bd9Sstevel@tonic-gate 		hash &= ~bit;
3387c478bd9Sstevel@tonic-gate 	}
3397c478bd9Sstevel@tonic-gate }
3407c478bd9Sstevel@tonic-gate 
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate 
3437c478bd9Sstevel@tonic-gate static datum nullkey= {NULL, 0};
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate datum
dbm_firsthash(DBM * db,long hash)346*5d54f3d8Smuffin dbm_firsthash(DBM *db, long hash)
3477c478bd9Sstevel@tonic-gate {
348*5d54f3d8Smuffin 	int i,j;
3497c478bd9Sstevel@tonic-gate 	datum item, bitem;
3507c478bd9Sstevel@tonic-gate 
3517c478bd9Sstevel@tonic-gate loop:
3527c478bd9Sstevel@tonic-gate 	dbm_access(db, hash);
3537c478bd9Sstevel@tonic-gate 	j=0;
3547c478bd9Sstevel@tonic-gate 	bitem = makdatum(db->dbm_pagbuf, 0);
3557c478bd9Sstevel@tonic-gate 	for(i=2;; i+=2) {
3567c478bd9Sstevel@tonic-gate 		item = makdatum(db->dbm_pagbuf, i);
3577c478bd9Sstevel@tonic-gate 		if(item.dptr == NULL)
3587c478bd9Sstevel@tonic-gate 			break;
3597c478bd9Sstevel@tonic-gate 		if(cmpdatum(bitem, item) < 0) {
3607c478bd9Sstevel@tonic-gate 			j=i;
3617c478bd9Sstevel@tonic-gate 			bitem = item;
3627c478bd9Sstevel@tonic-gate 			}
3637c478bd9Sstevel@tonic-gate 	}
3647c478bd9Sstevel@tonic-gate 	if(bitem.dptr != NULL) {
3657c478bd9Sstevel@tonic-gate 	        db->dbm_keyptr = j + 2;
3667c478bd9Sstevel@tonic-gate 	        db->dbm_blkptr = db->dbm_blkno;
3677c478bd9Sstevel@tonic-gate 		return(bitem);
3687c478bd9Sstevel@tonic-gate 	}
3697c478bd9Sstevel@tonic-gate 	hash = dbm_hashinc(db,hash);
3707c478bd9Sstevel@tonic-gate 	if(hash == 0)
3717c478bd9Sstevel@tonic-gate 		return(item); /*null item*/
3727c478bd9Sstevel@tonic-gate 	goto loop;
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate }
3757c478bd9Sstevel@tonic-gate 
3767c478bd9Sstevel@tonic-gate datum
dbm_firstkey(DBM * db)377*5d54f3d8Smuffin dbm_firstkey(DBM *db)
3787c478bd9Sstevel@tonic-gate {
3797c478bd9Sstevel@tonic-gate 
3807c478bd9Sstevel@tonic-gate 	db->dbm_blkptr = 0L;
3817c478bd9Sstevel@tonic-gate 	db->dbm_keyptr = 0;
3827c478bd9Sstevel@tonic-gate 	return (dbm_firsthash(db, 0L));
3837c478bd9Sstevel@tonic-gate }
384*5d54f3d8Smuffin 
3857c478bd9Sstevel@tonic-gate datum
dbm_nextkey(DBM * db)386*5d54f3d8Smuffin dbm_nextkey(DBM *db)
3877c478bd9Sstevel@tonic-gate {
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate 	return (dbm_do_nextkey(db, nullkey));
3907c478bd9Sstevel@tonic-gate }
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate /*this is used if keyptr-2,blocknum doesn't point to the previous
3937c478bd9Sstevel@tonic-gate specific key allowing the fast hash order search --
3947c478bd9Sstevel@tonic-gate its use indicates user tampering with our state variables,
3957c478bd9Sstevel@tonic-gate which some evil users might do to search from some specific place.
3967c478bd9Sstevel@tonic-gate It finds the first key at or after blkptr,keyptr in block seq order
3977c478bd9Sstevel@tonic-gate this requires looking at all sorts of emtpy blocks in many cases*/
3987c478bd9Sstevel@tonic-gate 
399*5d54f3d8Smuffin static datum
dbm_slow_nextkey(DBM * db)400*5d54f3d8Smuffin dbm_slow_nextkey(DBM *db)
4017c478bd9Sstevel@tonic-gate {
4027c478bd9Sstevel@tonic-gate 	struct stat statb;
4037c478bd9Sstevel@tonic-gate 	datum item;
4047c478bd9Sstevel@tonic-gate 
4057c478bd9Sstevel@tonic-gate 	if (dbm_error(db) || fstat(db->dbm_pagf, &statb) < 0)
4067c478bd9Sstevel@tonic-gate 		goto err;
4077c478bd9Sstevel@tonic-gate 	statb.st_size /= PBLKSIZ;
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate 	for (;;) {
4107c478bd9Sstevel@tonic-gate 		if (db->dbm_blkptr != db->dbm_pagbno) {
4117c478bd9Sstevel@tonic-gate 
4127c478bd9Sstevel@tonic-gate 			if (dbm_dirty(db)) dbm_flushpag(db);
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate 			db->dbm_pagbno = db->dbm_blkptr;
4157c478bd9Sstevel@tonic-gate 			(void) lseek(db->dbm_pagf, (long)(db->dbm_blkptr*PBLKSIZ), L_SET);
4167c478bd9Sstevel@tonic-gate 			if (read(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ)
4177c478bd9Sstevel@tonic-gate 				bzero(db->dbm_pagbuf, PBLKSIZ);
4187c478bd9Sstevel@tonic-gate #ifdef DEBUG
4197c478bd9Sstevel@tonic-gate 			else if (chkblk(db->dbm_pagbuf) < 0)
4207c478bd9Sstevel@tonic-gate 				db->dbm_flags |= _DBM_IOERR;
4217c478bd9Sstevel@tonic-gate #endif
4227c478bd9Sstevel@tonic-gate 		}
4237c478bd9Sstevel@tonic-gate 		/*Am I an empty block?*/
4247c478bd9Sstevel@tonic-gate 		if (((short *)db->dbm_pagbuf)[0] != 0) {
4257c478bd9Sstevel@tonic-gate 			item = makdatum(db->dbm_pagbuf, db->dbm_keyptr);
4267c478bd9Sstevel@tonic-gate 			if (item.dptr != NULL) {
4277c478bd9Sstevel@tonic-gate 				db->dbm_keyptr += 2;
4287c478bd9Sstevel@tonic-gate 				return (item);
4297c478bd9Sstevel@tonic-gate 			}
4307c478bd9Sstevel@tonic-gate 			db->dbm_keyptr = 0;
4317c478bd9Sstevel@tonic-gate 		}
4327c478bd9Sstevel@tonic-gate 		/*go to next sequential block*/
4337c478bd9Sstevel@tonic-gate 		if (++db->dbm_blkptr >= statb.st_size)
4347c478bd9Sstevel@tonic-gate 			break;
4357c478bd9Sstevel@tonic-gate 	}
4367c478bd9Sstevel@tonic-gate err:
4377c478bd9Sstevel@tonic-gate 	item.dptr = NULL;
4387c478bd9Sstevel@tonic-gate 	item.dsize = 0;
4397c478bd9Sstevel@tonic-gate 	return (item);
4407c478bd9Sstevel@tonic-gate }
4417c478bd9Sstevel@tonic-gate 
4427c478bd9Sstevel@tonic-gate datum
dbm_do_nextkey(DBM * db,datum inkey)443*5d54f3d8Smuffin dbm_do_nextkey(DBM *db, datum inkey)
4447c478bd9Sstevel@tonic-gate {
4457c478bd9Sstevel@tonic-gate 	datum item,bitem;
4467c478bd9Sstevel@tonic-gate 	long hash;
4477c478bd9Sstevel@tonic-gate 	datum key;
4487c478bd9Sstevel@tonic-gate 	int f;
449*5d54f3d8Smuffin 	int i;
450*5d54f3d8Smuffin 	int j;
451*5d54f3d8Smuffin 	short *sp;
452*5d54f3d8Smuffin 	int n;
453*5d54f3d8Smuffin 	char *p1, *p2;
4547c478bd9Sstevel@tonic-gate 
4557c478bd9Sstevel@tonic-gate 	if ( dbm_error(db) ) {
4567c478bd9Sstevel@tonic-gate 		item.dptr = NULL;
4577c478bd9Sstevel@tonic-gate 		item.dsize = 0;
4587c478bd9Sstevel@tonic-gate 		return (item);
4597c478bd9Sstevel@tonic-gate 	}
4607c478bd9Sstevel@tonic-gate 
4617c478bd9Sstevel@tonic-gate 	/*user has supplied lastkey*/
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate 	if(inkey.dptr != NULL) {
4647c478bd9Sstevel@tonic-gate 	       dbm_access(db, (hash=dcalchash(inkey)));
4657c478bd9Sstevel@tonic-gate 	       if ((i = finddatum(db->dbm_pagbuf, inkey)) >= 0) {
4667c478bd9Sstevel@tonic-gate 		       db->dbm_keyptr = i + 2;
4677c478bd9Sstevel@tonic-gate 		       db->dbm_blkptr = db->dbm_blkno;
4687c478bd9Sstevel@tonic-gate 	       }
4697c478bd9Sstevel@tonic-gate 	       key=inkey;
4707c478bd9Sstevel@tonic-gate        }
4717c478bd9Sstevel@tonic-gate        else  {
4727c478bd9Sstevel@tonic-gate 		/*is this a manual firstkey request? */
4737c478bd9Sstevel@tonic-gate 
4747c478bd9Sstevel@tonic-gate 		if (db->dbm_blkptr == 0L &&
4757c478bd9Sstevel@tonic-gate 			db->dbm_keyptr == 0)
4767c478bd9Sstevel@tonic-gate 			return (dbm_firsthash(db, 0L));
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate 		/*no -- get lastkey this is like dbm_access by blkptr*/
4797c478bd9Sstevel@tonic-gate 
4807c478bd9Sstevel@tonic-gate 		if (db->dbm_blkptr != db->dbm_pagbno) {
4817c478bd9Sstevel@tonic-gate 
4827c478bd9Sstevel@tonic-gate 			if (dbm_dirty(db)) dbm_flushpag(db);
4837c478bd9Sstevel@tonic-gate 			db->dbm_pagbno = db->dbm_blkptr;
4847c478bd9Sstevel@tonic-gate 			(void) lseek(db->dbm_pagf, (long)(db->dbm_blkptr*PBLKSIZ), L_SET);
4857c478bd9Sstevel@tonic-gate 			if (read(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ)
4867c478bd9Sstevel@tonic-gate 				bzero(db->dbm_pagbuf, PBLKSIZ);
4877c478bd9Sstevel@tonic-gate #ifdef DEBUG
4887c478bd9Sstevel@tonic-gate 			else if (chkblk(db->dbm_pagbuf) < 0)
4897c478bd9Sstevel@tonic-gate 			db->dbm_flags |= _DBM_IOERR;
4907c478bd9Sstevel@tonic-gate #endif
4917c478bd9Sstevel@tonic-gate 		}
4927c478bd9Sstevel@tonic-gate 		/*now just make up last key datum*/
4937c478bd9Sstevel@tonic-gate 		if (db->dbm_keyptr >=2) key= makdatum(db->dbm_pagbuf,(db->dbm_keyptr-2));
4947c478bd9Sstevel@tonic-gate 		else key=nullkey;
4957c478bd9Sstevel@tonic-gate 
4967c478bd9Sstevel@tonic-gate 	/* the keyptr pagbuf have failed us, the user must
4977c478bd9Sstevel@tonic-gate 	be an extra clever moron who depends on
4987c478bd9Sstevel@tonic-gate 	these variables and their former meaning.
4997c478bd9Sstevel@tonic-gate 	If we set the variables this would have got
5007c478bd9Sstevel@tonic-gate 	us the key for sure! So give him the old algorithm.*/
5017c478bd9Sstevel@tonic-gate 		if (key.dptr == NULL) return (dbm_slow_nextkey(db));
5027c478bd9Sstevel@tonic-gate 	}
5037c478bd9Sstevel@tonic-gate 
5047c478bd9Sstevel@tonic-gate 	/*at this point the last key is paged in and
5057c478bd9Sstevel@tonic-gate 	we can proceed as in old dbm -- like Ken did his. */
5067c478bd9Sstevel@tonic-gate 
5077c478bd9Sstevel@tonic-gate 	f = 1;
5087c478bd9Sstevel@tonic-gate 	j=0;
5097c478bd9Sstevel@tonic-gate 	sp = (short *)db->dbm_pagbuf;
5107c478bd9Sstevel@tonic-gate 
5117c478bd9Sstevel@tonic-gate 	for(i=0;; i+=2) {
5127c478bd9Sstevel@tonic-gate 
5137c478bd9Sstevel@tonic-gate 		/*begin put makdatum inline*/
5147c478bd9Sstevel@tonic-gate 
5157c478bd9Sstevel@tonic-gate 		if ((unsigned)i >= sp[0]) {
5167c478bd9Sstevel@tonic-gate 			item.dptr = NULL;
5177c478bd9Sstevel@tonic-gate 			item.dsize = 0;
5187c478bd9Sstevel@tonic-gate 			break; /*from below*/
5197c478bd9Sstevel@tonic-gate 		}
5207c478bd9Sstevel@tonic-gate 		else {
5217c478bd9Sstevel@tonic-gate 			if (i > 0) item.dsize = sp[i] - sp[i+1];
5227c478bd9Sstevel@tonic-gate 			else item.dsize = PBLKSIZ - sp[i+1];
5237c478bd9Sstevel@tonic-gate 			item.dptr = db->dbm_pagbuf+sp[i+1];
5247c478bd9Sstevel@tonic-gate 		}
5257c478bd9Sstevel@tonic-gate 
5267c478bd9Sstevel@tonic-gate 		/*	item = makdatum(db->dbm_pagbuf, i);*/
5277c478bd9Sstevel@tonic-gate 		/*end put makdatum inline*/
5287c478bd9Sstevel@tonic-gate 
5297c478bd9Sstevel@tonic-gate 		if(item.dptr == NULL)
5307c478bd9Sstevel@tonic-gate 			break;
5317c478bd9Sstevel@tonic-gate /*inline cmpdatum*/
5327c478bd9Sstevel@tonic-gate 
5337c478bd9Sstevel@tonic-gate 
5347c478bd9Sstevel@tonic-gate 		n = key.dsize;
5357c478bd9Sstevel@tonic-gate 		if(n != item.dsize)
5367c478bd9Sstevel@tonic-gate 			if( (n - item.dsize) <= 0 ) continue;
5377c478bd9Sstevel@tonic-gate 			else { }
5387c478bd9Sstevel@tonic-gate 		else {
5397c478bd9Sstevel@tonic-gate 			if(n == 0) continue;
5407c478bd9Sstevel@tonic-gate 			p1 = key.dptr;
5417c478bd9Sstevel@tonic-gate 			p2 = item.dptr;
5427c478bd9Sstevel@tonic-gate 			do
5437c478bd9Sstevel@tonic-gate 				if(*p1++ != *p2++)
5447c478bd9Sstevel@tonic-gate 					if((*--p1 - *--p2) > 0) goto keep_going;
5457c478bd9Sstevel@tonic-gate 					else continue;
5467c478bd9Sstevel@tonic-gate 			while(--n);
5477c478bd9Sstevel@tonic-gate 			continue;
5487c478bd9Sstevel@tonic-gate 			}
5497c478bd9Sstevel@tonic-gate 
5507c478bd9Sstevel@tonic-gate keep_going:
5517c478bd9Sstevel@tonic-gate 
5527c478bd9Sstevel@tonic-gate /*end inline cmpdatum*/
5537c478bd9Sstevel@tonic-gate 		/*if(cmpdatum(key, item) <= 0)
5547c478bd9Sstevel@tonic-gate 			continue;*/
5557c478bd9Sstevel@tonic-gate 		if (f) {
5567c478bd9Sstevel@tonic-gate 			bitem = item;
5577c478bd9Sstevel@tonic-gate 			j=i;
5587c478bd9Sstevel@tonic-gate 			f = 0;
5597c478bd9Sstevel@tonic-gate 		}
5607c478bd9Sstevel@tonic-gate 		else {
5617c478bd9Sstevel@tonic-gate 
5627c478bd9Sstevel@tonic-gate /*		if(cmpdatum(bitem, item) < 0)*/
5637c478bd9Sstevel@tonic-gate 
5647c478bd9Sstevel@tonic-gate 		n = bitem.dsize;
5657c478bd9Sstevel@tonic-gate 		if(n != item.dsize)
5667c478bd9Sstevel@tonic-gate 			{
5677c478bd9Sstevel@tonic-gate 			if((n - item.dsize) <0) {
5687c478bd9Sstevel@tonic-gate 					bitem = item;
5697c478bd9Sstevel@tonic-gate 					j=i;
5707c478bd9Sstevel@tonic-gate 				}
5717c478bd9Sstevel@tonic-gate 			}
5727c478bd9Sstevel@tonic-gate 			else  if (n != 0) {
5737c478bd9Sstevel@tonic-gate 				p1 = bitem.dptr;
5747c478bd9Sstevel@tonic-gate 				p2 = item.dptr;
5757c478bd9Sstevel@tonic-gate 				do
5767c478bd9Sstevel@tonic-gate 				if(*p1++ != *p2++) {
5777c478bd9Sstevel@tonic-gate 					if((*--p1 - *--p2) <0) {
5787c478bd9Sstevel@tonic-gate 						bitem = item;
5797c478bd9Sstevel@tonic-gate 						j=i;
5807c478bd9Sstevel@tonic-gate 					}
5817c478bd9Sstevel@tonic-gate 					break;
5827c478bd9Sstevel@tonic-gate 				}
5837c478bd9Sstevel@tonic-gate 				while(--n);
5847c478bd9Sstevel@tonic-gate 			}
5857c478bd9Sstevel@tonic-gate 		}
5867c478bd9Sstevel@tonic-gate 	}
5877c478bd9Sstevel@tonic-gate 
5887c478bd9Sstevel@tonic-gate 	if(f == 0) {
5897c478bd9Sstevel@tonic-gate 	        db->dbm_keyptr = j + 2;
5907c478bd9Sstevel@tonic-gate 	        db->dbm_blkptr = db->dbm_blkno;
5917c478bd9Sstevel@tonic-gate 		return (bitem);
5927c478bd9Sstevel@tonic-gate 	}
5937c478bd9Sstevel@tonic-gate 
5947c478bd9Sstevel@tonic-gate 	/*really need hash at this point*/
5957c478bd9Sstevel@tonic-gate 	/*if he gave us a key we have already calculated the hash*/
5967c478bd9Sstevel@tonic-gate 	/*if not get it*/
5977c478bd9Sstevel@tonic-gate 	if (inkey.dptr == NULL) hash=dcalchash(key);
5987c478bd9Sstevel@tonic-gate 	hash = dbm_hashinc(db,hash);
5997c478bd9Sstevel@tonic-gate 
6007c478bd9Sstevel@tonic-gate 	if(hash == 0)
6017c478bd9Sstevel@tonic-gate 		return (item); /*null*/
6027c478bd9Sstevel@tonic-gate 	/*get first item on next page in hash table order*/
6037c478bd9Sstevel@tonic-gate 	return (dbm_firsthash(db, hash));
6047c478bd9Sstevel@tonic-gate 
6057c478bd9Sstevel@tonic-gate 
6067c478bd9Sstevel@tonic-gate }
6077c478bd9Sstevel@tonic-gate 
608*5d54f3d8Smuffin static void
dbm_access(DBM * db,long hash)609*5d54f3d8Smuffin dbm_access(DBM *db, long hash)
6107c478bd9Sstevel@tonic-gate {
611*5d54f3d8Smuffin 	int b, i, n;
612*5d54f3d8Smuffin 	long bn;
613*5d54f3d8Smuffin 	long my_bitno;
614*5d54f3d8Smuffin 	long my_hmask;
615*5d54f3d8Smuffin 	long my_blkno;
6167c478bd9Sstevel@tonic-gate 
6177c478bd9Sstevel@tonic-gate 	for (my_hmask=0;; my_hmask=(my_hmask<<1)+1) {
6187c478bd9Sstevel@tonic-gate 		my_blkno = hash & my_hmask;
6197c478bd9Sstevel@tonic-gate 		my_bitno = my_blkno + my_hmask;
6207c478bd9Sstevel@tonic-gate 		/*getbit inline*/
6217c478bd9Sstevel@tonic-gate 		if (my_bitno > db->dbm_maxbno) break;
6227c478bd9Sstevel@tonic-gate 		n = my_bitno % BYTESIZ;
6237c478bd9Sstevel@tonic-gate 		bn = my_bitno / BYTESIZ;
6247c478bd9Sstevel@tonic-gate 		i = bn % DBLKSIZ;
6257c478bd9Sstevel@tonic-gate 		b = bn / DBLKSIZ;
6267c478bd9Sstevel@tonic-gate 		if (b != db->dbm_dirbno) {
6277c478bd9Sstevel@tonic-gate 			if (dbm_dirdirty(db)) dbm_flushdir(db); /*must flush*/
6287c478bd9Sstevel@tonic-gate 			db->dbm_dirbno = b;
6297c478bd9Sstevel@tonic-gate 			(void) lseek(db->dbm_dirf, (long)(b*DBLKSIZ), L_SET);
6307c478bd9Sstevel@tonic-gate 			if (read(db->dbm_dirf, db->dbm_dirbuf, DBLKSIZ) != DBLKSIZ)
6317c478bd9Sstevel@tonic-gate 				bzero(db->dbm_dirbuf, DBLKSIZ);
6327c478bd9Sstevel@tonic-gate 		}
6337c478bd9Sstevel@tonic-gate 		if ( (db->dbm_dirbuf[i] & (1<<n)) == 0 ) break;
6347c478bd9Sstevel@tonic-gate 
6357c478bd9Sstevel@tonic-gate 		/*
6367c478bd9Sstevel@tonic-gate 		if (getbit(db) == 0)
6377c478bd9Sstevel@tonic-gate 			break;
6387c478bd9Sstevel@tonic-gate 		*/
6397c478bd9Sstevel@tonic-gate 	}
6407c478bd9Sstevel@tonic-gate 	/*copy*/
6417c478bd9Sstevel@tonic-gate 	db->dbm_blkno=my_blkno;
6427c478bd9Sstevel@tonic-gate 	db->dbm_bitno=my_bitno;
6437c478bd9Sstevel@tonic-gate 	db->dbm_hmask=my_hmask;
6447c478bd9Sstevel@tonic-gate 
6457c478bd9Sstevel@tonic-gate 	if (my_blkno != db->dbm_pagbno) {
6467c478bd9Sstevel@tonic-gate 		if (dbm_dirty(db)){ /*must page out the page*/
6477c478bd9Sstevel@tonic-gate 			(void) lseek(db->dbm_pagf, (long)(db->dbm_pagbno*PBLKSIZ), L_SET);
6487c478bd9Sstevel@tonic-gate 			if (write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ) {
6497c478bd9Sstevel@tonic-gate 				db->dbm_flags |= _DBM_IOERR;
6507c478bd9Sstevel@tonic-gate 			}
6517c478bd9Sstevel@tonic-gate 		dbm_clrdirty(db);
6527c478bd9Sstevel@tonic-gate 		}
6537c478bd9Sstevel@tonic-gate 
6547c478bd9Sstevel@tonic-gate 		db->dbm_pagbno = my_blkno;
6557c478bd9Sstevel@tonic-gate 		(void) lseek(db->dbm_pagf, (long)(my_blkno*PBLKSIZ), L_SET);
6567c478bd9Sstevel@tonic-gate 		if (read(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ)
6577c478bd9Sstevel@tonic-gate 			bzero(db->dbm_pagbuf, PBLKSIZ);
6587c478bd9Sstevel@tonic-gate #ifdef DEBUG
6597c478bd9Sstevel@tonic-gate 		else if (chkblk(db->dbm_pagbuf) < 0)
6607c478bd9Sstevel@tonic-gate 			db->dbm_flags |= _DBM_IOERR;
6617c478bd9Sstevel@tonic-gate #endif
6627c478bd9Sstevel@tonic-gate 	}
6637c478bd9Sstevel@tonic-gate }
6647c478bd9Sstevel@tonic-gate 
665*5d54f3d8Smuffin static int
getbit(DBM * db)666*5d54f3d8Smuffin getbit(DBM *db)
6677c478bd9Sstevel@tonic-gate {
6687c478bd9Sstevel@tonic-gate 	long bn;
669*5d54f3d8Smuffin 	int b, i, n;
6707c478bd9Sstevel@tonic-gate 
6717c478bd9Sstevel@tonic-gate 
6727c478bd9Sstevel@tonic-gate 	if (db->dbm_bitno > db->dbm_maxbno)
6737c478bd9Sstevel@tonic-gate 		return (0);
6747c478bd9Sstevel@tonic-gate 	n = db->dbm_bitno % BYTESIZ;
6757c478bd9Sstevel@tonic-gate 	bn = db->dbm_bitno / BYTESIZ;
6767c478bd9Sstevel@tonic-gate 	i = bn % DBLKSIZ;
6777c478bd9Sstevel@tonic-gate 	b = bn / DBLKSIZ;
6787c478bd9Sstevel@tonic-gate 	if (b != db->dbm_dirbno) {
6797c478bd9Sstevel@tonic-gate 		if (dbm_dirdirty(db)) dbm_flushdir(db); /*must flush*/
6807c478bd9Sstevel@tonic-gate 		db->dbm_dirbno = b;
6817c478bd9Sstevel@tonic-gate 		(void) lseek(db->dbm_dirf, (long)(b*DBLKSIZ), L_SET);
6827c478bd9Sstevel@tonic-gate 		if (read(db->dbm_dirf, db->dbm_dirbuf, DBLKSIZ) != DBLKSIZ)
6837c478bd9Sstevel@tonic-gate 			bzero(db->dbm_dirbuf, DBLKSIZ);
6847c478bd9Sstevel@tonic-gate 	}
6857c478bd9Sstevel@tonic-gate 	return (db->dbm_dirbuf[i] & (1<<n));
6867c478bd9Sstevel@tonic-gate }
6877c478bd9Sstevel@tonic-gate 
688*5d54f3d8Smuffin static int
setbit(DBM * db)689*5d54f3d8Smuffin setbit(DBM *db)
6907c478bd9Sstevel@tonic-gate {
6917c478bd9Sstevel@tonic-gate 	long bn;
692*5d54f3d8Smuffin 	int i, n, b;
6937c478bd9Sstevel@tonic-gate 
6947c478bd9Sstevel@tonic-gate 	if (db->dbm_bitno > db->dbm_maxbno)
6957c478bd9Sstevel@tonic-gate 		db->dbm_maxbno = db->dbm_bitno;
6967c478bd9Sstevel@tonic-gate 	n = db->dbm_bitno % BYTESIZ;
6977c478bd9Sstevel@tonic-gate 	bn = db->dbm_bitno / BYTESIZ;
6987c478bd9Sstevel@tonic-gate 	i = bn % DBLKSIZ;
6997c478bd9Sstevel@tonic-gate 	b = bn / DBLKSIZ;
7007c478bd9Sstevel@tonic-gate 	if (b != db->dbm_dirbno) {
7017c478bd9Sstevel@tonic-gate 		if (dbm_dirdirty(db)) dbm_flushdir(db);
7027c478bd9Sstevel@tonic-gate 		db->dbm_dirbno = b;
7037c478bd9Sstevel@tonic-gate 		(void) lseek(db->dbm_dirf, (long)(b*DBLKSIZ), L_SET);
7047c478bd9Sstevel@tonic-gate 		if (read(db->dbm_dirf, db->dbm_dirbuf, DBLKSIZ) != DBLKSIZ)
7057c478bd9Sstevel@tonic-gate 			bzero(db->dbm_dirbuf, DBLKSIZ);
7067c478bd9Sstevel@tonic-gate 	}
7077c478bd9Sstevel@tonic-gate 	db->dbm_dirbuf[i] |= 1<<n;
7087c478bd9Sstevel@tonic-gate 	db->dbm_dirbno = b;
7097c478bd9Sstevel@tonic-gate 	if (dbm_defwrite(db)) {
7107c478bd9Sstevel@tonic-gate 	dbm_setdirdirty(db);
7117c478bd9Sstevel@tonic-gate 	} else{
7127c478bd9Sstevel@tonic-gate 	(void) lseek(db->dbm_dirf, (long)(b*DBLKSIZ), L_SET);
7137c478bd9Sstevel@tonic-gate 	if (write(db->dbm_dirf, db->dbm_dirbuf, DBLKSIZ) != DBLKSIZ) {
7147c478bd9Sstevel@tonic-gate 		return (-1);
7157c478bd9Sstevel@tonic-gate 	}
7167c478bd9Sstevel@tonic-gate 	}
7177c478bd9Sstevel@tonic-gate 	return (0);
7187c478bd9Sstevel@tonic-gate }
7197c478bd9Sstevel@tonic-gate 
7207c478bd9Sstevel@tonic-gate static datum
makdatum(char buf[PBLKSIZ],int n)721*5d54f3d8Smuffin makdatum(char buf[PBLKSIZ], int n)
7227c478bd9Sstevel@tonic-gate {
723*5d54f3d8Smuffin 	short *sp;
724*5d54f3d8Smuffin 	int t;
7257c478bd9Sstevel@tonic-gate 	datum item;
7267c478bd9Sstevel@tonic-gate 
7277c478bd9Sstevel@tonic-gate 	sp = (short *)buf;
7287c478bd9Sstevel@tonic-gate 	if ((unsigned)n >= sp[0]) {
7297c478bd9Sstevel@tonic-gate 		item.dptr = NULL;
7307c478bd9Sstevel@tonic-gate 		item.dsize = 0;
7317c478bd9Sstevel@tonic-gate 		return (item);
7327c478bd9Sstevel@tonic-gate 	}
7337c478bd9Sstevel@tonic-gate 	t = PBLKSIZ;
7347c478bd9Sstevel@tonic-gate 	if (n > 0)
7357c478bd9Sstevel@tonic-gate 		t = sp[n];
7367c478bd9Sstevel@tonic-gate 	item.dptr = buf+sp[n+1];
7377c478bd9Sstevel@tonic-gate 	item.dsize = t - sp[n+1];
7387c478bd9Sstevel@tonic-gate 	return (item);
7397c478bd9Sstevel@tonic-gate }
7407c478bd9Sstevel@tonic-gate 
741*5d54f3d8Smuffin static int
cmpdatum(datum d1,datum d2)742*5d54f3d8Smuffin cmpdatum(datum d1, datum d2)
7437c478bd9Sstevel@tonic-gate {
744*5d54f3d8Smuffin 	int n;
745*5d54f3d8Smuffin 	char *p1, *p2;
7467c478bd9Sstevel@tonic-gate 
7477c478bd9Sstevel@tonic-gate 	n = d1.dsize;
7487c478bd9Sstevel@tonic-gate 	if(n != d2.dsize)
7497c478bd9Sstevel@tonic-gate 		return(n - d2.dsize);
7507c478bd9Sstevel@tonic-gate 	if(n == 0)
7517c478bd9Sstevel@tonic-gate 		return(0);
7527c478bd9Sstevel@tonic-gate 	p1 = d1.dptr;
7537c478bd9Sstevel@tonic-gate 	p2 = d2.dptr;
7547c478bd9Sstevel@tonic-gate 	do
7557c478bd9Sstevel@tonic-gate 		if(*p1++ != *p2++)
7567c478bd9Sstevel@tonic-gate 			return(*--p1 - *--p2);
7577c478bd9Sstevel@tonic-gate 	while(--n);
7587c478bd9Sstevel@tonic-gate 	return(0);
7597c478bd9Sstevel@tonic-gate }
7607c478bd9Sstevel@tonic-gate 
761*5d54f3d8Smuffin static int
finddatum(char buf[PBLKSIZ],datum item)762*5d54f3d8Smuffin finddatum(char buf[PBLKSIZ], datum item)
7637c478bd9Sstevel@tonic-gate {
764*5d54f3d8Smuffin 	short *sp;
765*5d54f3d8Smuffin 	int i, n, j;
7667c478bd9Sstevel@tonic-gate 
7677c478bd9Sstevel@tonic-gate 	sp = (short *)buf;
7687c478bd9Sstevel@tonic-gate 	n = PBLKSIZ;
7697c478bd9Sstevel@tonic-gate 	for (i=0, j=sp[0]; i<j; i+=2, n = sp[i]) {
7707c478bd9Sstevel@tonic-gate 		n -= sp[i+1];
7717c478bd9Sstevel@tonic-gate 		if (n != item.dsize)
7727c478bd9Sstevel@tonic-gate 			continue;
7737c478bd9Sstevel@tonic-gate 		if (n == 0 || bcmp(&buf[sp[i+1]], item.dptr, n) == 0)
7747c478bd9Sstevel@tonic-gate 			return (i);
7757c478bd9Sstevel@tonic-gate 	}
7767c478bd9Sstevel@tonic-gate 	return (-1);
7777c478bd9Sstevel@tonic-gate }
7787c478bd9Sstevel@tonic-gate 
7797c478bd9Sstevel@tonic-gate static  int hitab[16]
7807c478bd9Sstevel@tonic-gate  = {    61, 57, 53, 49, 45, 41, 37, 33,
7817c478bd9Sstevel@tonic-gate 	29, 25, 21, 17, 13,  9,  5,  1,
7827c478bd9Sstevel@tonic-gate };
783*5d54f3d8Smuffin 
7847c478bd9Sstevel@tonic-gate static  long hltab[64]
7857c478bd9Sstevel@tonic-gate  = {
7867c478bd9Sstevel@tonic-gate 	06100151277L,06106161736L,06452611562L,05001724107L,
7877c478bd9Sstevel@tonic-gate 	02614772546L,04120731531L,04665262210L,07347467531L,
7887c478bd9Sstevel@tonic-gate 	06735253126L,06042345173L,03072226605L,01464164730L,
7897c478bd9Sstevel@tonic-gate 	03247435524L,07652510057L,01546775256L,05714532133L,
7907c478bd9Sstevel@tonic-gate 	06173260402L,07517101630L,02431460343L,01743245566L,
7917c478bd9Sstevel@tonic-gate 	00261675137L,02433103631L,03421772437L,04447707466L,
7927c478bd9Sstevel@tonic-gate 	04435620103L,03757017115L,03641531772L,06767633246L,
7937c478bd9Sstevel@tonic-gate 	02673230344L,00260612216L,04133454451L,00615531516L,
7947c478bd9Sstevel@tonic-gate 	06137717526L,02574116560L,02304023373L,07061702261L,
7957c478bd9Sstevel@tonic-gate 	05153031405L,05322056705L,07401116734L,06552375715L,
7967c478bd9Sstevel@tonic-gate 	06165233473L,05311063631L,01212221723L,01052267235L,
7977c478bd9Sstevel@tonic-gate 	06000615237L,01075222665L,06330216006L,04402355630L,
7987c478bd9Sstevel@tonic-gate 	01451177262L,02000133436L,06025467062L,07121076461L,
7997c478bd9Sstevel@tonic-gate 	03123433522L,01010635225L,01716177066L,05161746527L,
8007c478bd9Sstevel@tonic-gate 	01736635071L,06243505026L,03637211610L,01756474365L,
8017c478bd9Sstevel@tonic-gate 	04723077174L,03642763134L,05750130273L,03655541561L,
8027c478bd9Sstevel@tonic-gate };
8037c478bd9Sstevel@tonic-gate 
8047c478bd9Sstevel@tonic-gate static long
dcalchash(datum item)805*5d54f3d8Smuffin dcalchash(datum item)
8067c478bd9Sstevel@tonic-gate {
807*5d54f3d8Smuffin 	int s, c, j;
808*5d54f3d8Smuffin 	char *cp;
809*5d54f3d8Smuffin 	long hashl;
810*5d54f3d8Smuffin 	int hashi;
8117c478bd9Sstevel@tonic-gate 
8127c478bd9Sstevel@tonic-gate 	hashl = 0;
8137c478bd9Sstevel@tonic-gate 	hashi = 0;
8147c478bd9Sstevel@tonic-gate 	for (cp = item.dptr, s=item.dsize; --s >= 0; ) {
8157c478bd9Sstevel@tonic-gate 		c = *cp++;
8167c478bd9Sstevel@tonic-gate 		for (j=0; j<BYTESIZ; j+=4) {
8177c478bd9Sstevel@tonic-gate 			hashi += hitab[c&017];
8187c478bd9Sstevel@tonic-gate 			hashl += hltab[hashi&63];
8197c478bd9Sstevel@tonic-gate 			c >>= 4;
8207c478bd9Sstevel@tonic-gate 		}
8217c478bd9Sstevel@tonic-gate 	}
8227c478bd9Sstevel@tonic-gate 	return (hashl);
8237c478bd9Sstevel@tonic-gate }
8247c478bd9Sstevel@tonic-gate 
8257c478bd9Sstevel@tonic-gate /*
8267c478bd9Sstevel@tonic-gate  * Delete pairs of items (n & n+1).
8277c478bd9Sstevel@tonic-gate  */
828*5d54f3d8Smuffin static int
delitem(char buf[PBLKSIZ],int n)829*5d54f3d8Smuffin delitem(char buf[PBLKSIZ], int n)
8307c478bd9Sstevel@tonic-gate {
831*5d54f3d8Smuffin 	short *sp, *sp1;
832*5d54f3d8Smuffin 	int i1, i2;
8337c478bd9Sstevel@tonic-gate 
8347c478bd9Sstevel@tonic-gate 	sp = (short *)buf;
8357c478bd9Sstevel@tonic-gate 	i2 = sp[0];
8367c478bd9Sstevel@tonic-gate 	if ((unsigned)n >= i2 || (n & 1))
8377c478bd9Sstevel@tonic-gate 		return (0);
8387c478bd9Sstevel@tonic-gate 	if (n == i2-2) {
8397c478bd9Sstevel@tonic-gate 		sp[0] -= 2;
8407c478bd9Sstevel@tonic-gate 		return (1);
8417c478bd9Sstevel@tonic-gate 	}
8427c478bd9Sstevel@tonic-gate 	i1 = PBLKSIZ;
8437c478bd9Sstevel@tonic-gate 	if (n > 0)
8447c478bd9Sstevel@tonic-gate 		i1 = sp[n];
8457c478bd9Sstevel@tonic-gate 	i1 -= sp[n+2];
8467c478bd9Sstevel@tonic-gate 	if (i1 > 0) {
8477c478bd9Sstevel@tonic-gate 		i2 = sp[i2];
8487c478bd9Sstevel@tonic-gate 		bcopy(&buf[i2], &buf[i2 + i1], sp[n+2] - i2);
8497c478bd9Sstevel@tonic-gate 	}
8507c478bd9Sstevel@tonic-gate 	sp[0] -= 2;
8517c478bd9Sstevel@tonic-gate 	for (sp1 = sp + sp[0], sp += n+1; sp <= sp1; sp++)
8527c478bd9Sstevel@tonic-gate 		sp[0] = sp[2] + i1;
8537c478bd9Sstevel@tonic-gate 	return (1);
8547c478bd9Sstevel@tonic-gate }
8557c478bd9Sstevel@tonic-gate 
8567c478bd9Sstevel@tonic-gate /*
8577c478bd9Sstevel@tonic-gate  * Add pairs of items (item & item1).
8587c478bd9Sstevel@tonic-gate  */
859*5d54f3d8Smuffin static int
additem(char buf[PBLKSIZ],datum item,datum item1)860*5d54f3d8Smuffin additem(char buf[PBLKSIZ], datum item, datum item1)
8617c478bd9Sstevel@tonic-gate {
862*5d54f3d8Smuffin 	short *sp;
863*5d54f3d8Smuffin 	int i1, i2;
8647c478bd9Sstevel@tonic-gate 
8657c478bd9Sstevel@tonic-gate 	sp = (short *)buf;
8667c478bd9Sstevel@tonic-gate 	i1 = PBLKSIZ;
8677c478bd9Sstevel@tonic-gate 	i2 = sp[0];
8687c478bd9Sstevel@tonic-gate 	if (i2 > 0)
8697c478bd9Sstevel@tonic-gate 		i1 = sp[i2];
8707c478bd9Sstevel@tonic-gate 	i1 -= item.dsize + item1.dsize;
8717c478bd9Sstevel@tonic-gate 	if (i1 <= (i2+3) * sizeof(short))
8727c478bd9Sstevel@tonic-gate 		return (0);
8737c478bd9Sstevel@tonic-gate 	sp[0] += 2;
8747c478bd9Sstevel@tonic-gate 	sp[++i2] = i1 + item1.dsize;
8757c478bd9Sstevel@tonic-gate 	bcopy(item.dptr, &buf[i1 + item1.dsize], item.dsize);
8767c478bd9Sstevel@tonic-gate 	sp[++i2] = i1;
8777c478bd9Sstevel@tonic-gate 	bcopy(item1.dptr, &buf[i1], item1.dsize);
8787c478bd9Sstevel@tonic-gate 	return (1);
8797c478bd9Sstevel@tonic-gate }
8807c478bd9Sstevel@tonic-gate 
8817c478bd9Sstevel@tonic-gate #ifdef DEBUG
882*5d54f3d8Smuffin static int
chkblk(char buf[PBLKSIZ])883*5d54f3d8Smuffin chkblk(char buf[PBLKSIZ])
8847c478bd9Sstevel@tonic-gate {
885*5d54f3d8Smuffin 	short *sp;
886*5d54f3d8Smuffin 	int t, i;
8877c478bd9Sstevel@tonic-gate 
8887c478bd9Sstevel@tonic-gate 	sp = (short *)buf;
8897c478bd9Sstevel@tonic-gate 	t = PBLKSIZ;
8907c478bd9Sstevel@tonic-gate 	for (i=0; i<sp[0]; i++) {
8917c478bd9Sstevel@tonic-gate 		if (sp[i+1] > t)
8927c478bd9Sstevel@tonic-gate 			return (-1);
8937c478bd9Sstevel@tonic-gate 		t = sp[i+1];
8947c478bd9Sstevel@tonic-gate 	}
8957c478bd9Sstevel@tonic-gate 	if (t < (sp[0]+1)*sizeof(short))
8967c478bd9Sstevel@tonic-gate 		return (-1);
8977c478bd9Sstevel@tonic-gate 	return (0);
8987c478bd9Sstevel@tonic-gate }
8997c478bd9Sstevel@tonic-gate #endif
900