xref: /illumos-gate/usr/src/lib/libc/port/gen/ndbm.c (revision 18c77f76bd37990b65147cab2225a4d2b19391a1)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5a574db85Sraf  * Common Development and Distribution License (the "License").
6a574db85Sraf  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
21a574db85Sraf 
227c478bd9Sstevel@tonic-gate /*
23a574db85Sraf  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
2548bbca81SDaniel Hoffman  * Copyright (c) 2016 by Delphix. All rights reserved.
267c478bd9Sstevel@tonic-gate  */
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
297c478bd9Sstevel@tonic-gate /*	  All Rights Reserved	*/
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate /*
327c478bd9Sstevel@tonic-gate  * University Copyright- Copyright (c) 1982, 1986, 1988
337c478bd9Sstevel@tonic-gate  * The Regents of the University of California
347c478bd9Sstevel@tonic-gate  * All Rights Reserved
357c478bd9Sstevel@tonic-gate  *
367c478bd9Sstevel@tonic-gate  * University Acknowledgment- Portions of this document are derived from
377c478bd9Sstevel@tonic-gate  * software developed by the University of California, Berkeley, and its
387c478bd9Sstevel@tonic-gate  * contributors.
397c478bd9Sstevel@tonic-gate  */
407c478bd9Sstevel@tonic-gate 
417257d1b4Sraf #include "lint.h"
427c478bd9Sstevel@tonic-gate #include <sys/types.h>
437c478bd9Sstevel@tonic-gate #include <sys/stat.h>
447c478bd9Sstevel@tonic-gate #include <fcntl.h>
457c478bd9Sstevel@tonic-gate #include <sys/file.h>
467c478bd9Sstevel@tonic-gate #include <stdio.h>
477c478bd9Sstevel@tonic-gate #include <stdlib.h>
487c478bd9Sstevel@tonic-gate #include <errno.h>
497c478bd9Sstevel@tonic-gate #include <ndbm.h>
507c478bd9Sstevel@tonic-gate #include <unistd.h>
517c478bd9Sstevel@tonic-gate #include <string.h>
52a574db85Sraf #include <pthread.h>
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate /* add support for batched writing for NIS */
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate #define	_DBM_DEFWRITE 0x4
577c478bd9Sstevel@tonic-gate #define	_DBM_DIRTY 0x8
587c478bd9Sstevel@tonic-gate #define	_DBM_DIRDIRTY 0x10
597c478bd9Sstevel@tonic-gate #define	dbm_dirty(db) ((db)->dbm_flags & _DBM_DIRTY)
607c478bd9Sstevel@tonic-gate #define	dbm_dirdirty(db) ((db)->dbm_flags & _DBM_DIRDIRTY)
617c478bd9Sstevel@tonic-gate #define	dbm_defwrite(db) ((db)->dbm_flags & _DBM_DEFWRITE)
627c478bd9Sstevel@tonic-gate #define	dbm_setdirty(db) (db)->dbm_flags |= _DBM_DIRTY
637c478bd9Sstevel@tonic-gate #define	dbm_clrdirty(db) (db)->dbm_flags &= ~_DBM_DIRTY
647c478bd9Sstevel@tonic-gate #define	dbm_setdirdirty(db) (db)->dbm_flags |= _DBM_DIRDIRTY
657c478bd9Sstevel@tonic-gate #define	dbm_clrdirdirty(db) (db)->dbm_flags &= ~_DBM_DIRDIRTY
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate /*
687c478bd9Sstevel@tonic-gate  * forward declarations
697c478bd9Sstevel@tonic-gate  */
707c478bd9Sstevel@tonic-gate static datum makdatum(char *, int);
717c478bd9Sstevel@tonic-gate static unsigned long dcalchash(datum);
727c478bd9Sstevel@tonic-gate static void dbm_access(DBM *, unsigned long);
737c478bd9Sstevel@tonic-gate static int finddatum(char *, datum);
747c478bd9Sstevel@tonic-gate static int delitem(char *, int);
757c478bd9Sstevel@tonic-gate static int additem(char *, datum, datum);
767c478bd9Sstevel@tonic-gate static int cmpdatum(datum, datum);
777c478bd9Sstevel@tonic-gate static int setbit(DBM *);
787c478bd9Sstevel@tonic-gate static int getbit(DBM *);
797c478bd9Sstevel@tonic-gate static int dbm_flushdir(DBM *);
807c478bd9Sstevel@tonic-gate static int dbm_flushpag(DBM *db);
81*18c77f76SBill Sommerfeld #ifdef NDBM_DEBUG
82*18c77f76SBill Sommerfeld static int chkblk(char buf[PBLKSIZ]);
83*18c77f76SBill Sommerfeld #endif
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate /* the following three are required by mapfile-vers */
867c478bd9Sstevel@tonic-gate datum dbm_do_nextkey(DBM *, datum);
877c478bd9Sstevel@tonic-gate int dbm_close_status(DBM *);
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate /* used to make a dbm file all at once instead of incrementally */
907c478bd9Sstevel@tonic-gate void
dbm_setdefwrite(DBM * db)917c478bd9Sstevel@tonic-gate dbm_setdefwrite(DBM *db)
927c478bd9Sstevel@tonic-gate {
937c478bd9Sstevel@tonic-gate 	db->dbm_flags |= _DBM_DEFWRITE;
947c478bd9Sstevel@tonic-gate }
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate #undef	dbm_error
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate int
dbm_error(DBM * db)997c478bd9Sstevel@tonic-gate dbm_error(DBM *db)
1007c478bd9Sstevel@tonic-gate {
1017c478bd9Sstevel@tonic-gate 	return (db->dbm_flags & _DBM_IOERR);
1027c478bd9Sstevel@tonic-gate }
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate #undef	dbm_clearerr
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate int
dbm_clearerr(DBM * db)1077c478bd9Sstevel@tonic-gate dbm_clearerr(DBM *db)
1087c478bd9Sstevel@tonic-gate {
1097c478bd9Sstevel@tonic-gate 	return (db->dbm_flags &= ~_DBM_IOERR);
1107c478bd9Sstevel@tonic-gate }
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate int
dbm_flush(DBM * db)1137c478bd9Sstevel@tonic-gate dbm_flush(DBM *db)
1147c478bd9Sstevel@tonic-gate {
1157c478bd9Sstevel@tonic-gate 	int ok = 0;
1167c478bd9Sstevel@tonic-gate 	if (dbm_flushpag(db) < 0)
1177c478bd9Sstevel@tonic-gate 		ok = -1;
1187c478bd9Sstevel@tonic-gate 	if (dbm_flushdir(db) < 0)
1197c478bd9Sstevel@tonic-gate 		ok = -1;
1207c478bd9Sstevel@tonic-gate 	return (ok);
1217c478bd9Sstevel@tonic-gate }
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate static int
dbm_flushpag(DBM * db)1247c478bd9Sstevel@tonic-gate dbm_flushpag(DBM *db)
1257c478bd9Sstevel@tonic-gate {
1267c478bd9Sstevel@tonic-gate 	int ok = 0;
1277c478bd9Sstevel@tonic-gate 	off64_t where;
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate 	if (dbm_dirty(db)) { /* must page out the page */
1307c478bd9Sstevel@tonic-gate 		where = (((off64_t)db->dbm_pagbno) * PBLKSIZ);
1317c478bd9Sstevel@tonic-gate 		if ((lseek64(db->dbm_pagf, where, L_SET) != where) ||
1327c478bd9Sstevel@tonic-gate 		    (write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ)) {
1337c478bd9Sstevel@tonic-gate 			db->dbm_flags |= _DBM_IOERR;
1347c478bd9Sstevel@tonic-gate 			ok = -1;
1357c478bd9Sstevel@tonic-gate 		}
1367c478bd9Sstevel@tonic-gate 		dbm_clrdirty(db);
1377c478bd9Sstevel@tonic-gate 	}
1387c478bd9Sstevel@tonic-gate 	return (ok);
1397c478bd9Sstevel@tonic-gate }
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate static int
dbm_flushdir(DBM * db)1427c478bd9Sstevel@tonic-gate dbm_flushdir(DBM *db)
1437c478bd9Sstevel@tonic-gate {
1447c478bd9Sstevel@tonic-gate 	int ok = 0;
1457c478bd9Sstevel@tonic-gate 	off64_t where;
1467c478bd9Sstevel@tonic-gate 	if (dbm_dirdirty(db)) { /* must page out the dir */
1477c478bd9Sstevel@tonic-gate 		where = (((off64_t)db->dbm_dirbno) * DBLKSIZ);
1487c478bd9Sstevel@tonic-gate 		if ((lseek64(db->dbm_dirf, where, L_SET) != where) ||
1497c478bd9Sstevel@tonic-gate 		    (write(db->dbm_dirf, db->dbm_dirbuf, DBLKSIZ) != DBLKSIZ)) {
1507c478bd9Sstevel@tonic-gate 			ok = -1;
1517c478bd9Sstevel@tonic-gate 		}
1527c478bd9Sstevel@tonic-gate 		dbm_clrdirdirty(db);
1537c478bd9Sstevel@tonic-gate 	}
1547c478bd9Sstevel@tonic-gate 	return (ok);
1557c478bd9Sstevel@tonic-gate }
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate #define	BYTESIZ 8
1587c478bd9Sstevel@tonic-gate #undef setbit
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate DBM *
dbm_open(const char * file,int flags,mode_t mode)1617c478bd9Sstevel@tonic-gate dbm_open(const char *file, int flags, mode_t mode)
1627c478bd9Sstevel@tonic-gate {
1637c478bd9Sstevel@tonic-gate 	struct stat64 statb;
1647c478bd9Sstevel@tonic-gate 	DBM *db;
1657c478bd9Sstevel@tonic-gate 	int	serrno;
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate 	if ((db = (DBM *)malloc(sizeof (*db))) == 0) {
1687c478bd9Sstevel@tonic-gate 		errno = ENOMEM;
1697c478bd9Sstevel@tonic-gate 		return ((DBM *)0);
1707c478bd9Sstevel@tonic-gate 	}
1717c478bd9Sstevel@tonic-gate 	db->dbm_flags = (flags & 03) == O_RDONLY ? _DBM_RDONLY : 0;
1727c478bd9Sstevel@tonic-gate 	if ((flags & 03) == O_WRONLY)
1737c478bd9Sstevel@tonic-gate 		flags = (flags & ~03) | O_RDWR;
1747c478bd9Sstevel@tonic-gate 	if (strlcpy(db->dbm_pagbuf, file, sizeof (db->dbm_pagbuf)) >=
1757c478bd9Sstevel@tonic-gate 	    sizeof (db->dbm_pagbuf) ||
1767c478bd9Sstevel@tonic-gate 	    strlcat(db->dbm_pagbuf, ".pag", sizeof (db->dbm_pagbuf)) >=
1777c478bd9Sstevel@tonic-gate 	    sizeof (db->dbm_pagbuf)) {
1787c478bd9Sstevel@tonic-gate 		/*
1797c478bd9Sstevel@tonic-gate 		 * file.pag does not fit into dbm_pagbuf.
1807c478bd9Sstevel@tonic-gate 		 * fail with ENAMETOOLONG.
1817c478bd9Sstevel@tonic-gate 		 */
1827c478bd9Sstevel@tonic-gate 		serrno = ENAMETOOLONG;
1837c478bd9Sstevel@tonic-gate 		goto bad;
1847c478bd9Sstevel@tonic-gate 	}
1857c478bd9Sstevel@tonic-gate 	db->dbm_pagf = open64(db->dbm_pagbuf, flags, mode);
1867c478bd9Sstevel@tonic-gate 	if (db->dbm_pagf < 0) {
1877c478bd9Sstevel@tonic-gate 		serrno = errno;
1887c478bd9Sstevel@tonic-gate 		goto bad;
1897c478bd9Sstevel@tonic-gate 	}
1907c478bd9Sstevel@tonic-gate 	/*
1917c478bd9Sstevel@tonic-gate 	 * We know this won't overflow so it is safe to ignore the
1927c478bd9Sstevel@tonic-gate 	 * return value; we use strl* to prevent false hits in
1937c478bd9Sstevel@tonic-gate 	 * code sweeps.
1947c478bd9Sstevel@tonic-gate 	 */
1957c478bd9Sstevel@tonic-gate 	(void) strlcpy(db->dbm_pagbuf, file, sizeof (db->dbm_pagbuf));
1967c478bd9Sstevel@tonic-gate 	(void) strlcat(db->dbm_pagbuf, ".dir", sizeof (db->dbm_pagbuf));
1977c478bd9Sstevel@tonic-gate 	db->dbm_dirf = open64(db->dbm_pagbuf, flags, mode);
1987c478bd9Sstevel@tonic-gate 	if (db->dbm_dirf < 0) {
1997c478bd9Sstevel@tonic-gate 		serrno = errno;
2007c478bd9Sstevel@tonic-gate 		goto bad1;
2017c478bd9Sstevel@tonic-gate 	}
2027c478bd9Sstevel@tonic-gate 	(void) fstat64(db->dbm_dirf, &statb);
2037c478bd9Sstevel@tonic-gate 	db->dbm_maxbno = statb.st_size * BYTESIZ-1;
2047c478bd9Sstevel@tonic-gate 	db->dbm_pagbno = db->dbm_dirbno = -1;
2057c478bd9Sstevel@tonic-gate 	return (db);
2067c478bd9Sstevel@tonic-gate bad1:
2077c478bd9Sstevel@tonic-gate 	(void) close(db->dbm_pagf);
2087c478bd9Sstevel@tonic-gate bad:
2097c478bd9Sstevel@tonic-gate 	free((char *)db);
2107c478bd9Sstevel@tonic-gate 	errno = serrno;
2117c478bd9Sstevel@tonic-gate 	return ((DBM *)0);
2127c478bd9Sstevel@tonic-gate }
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate void
dbm_close(DBM * db)2157c478bd9Sstevel@tonic-gate dbm_close(DBM *db)
2167c478bd9Sstevel@tonic-gate {
2177c478bd9Sstevel@tonic-gate (void) dbm_close_status(db);
2187c478bd9Sstevel@tonic-gate }
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate /* close with return code */
2217c478bd9Sstevel@tonic-gate int
dbm_close_status(DBM * db)2227c478bd9Sstevel@tonic-gate dbm_close_status(DBM *db)
2237c478bd9Sstevel@tonic-gate {
2247c478bd9Sstevel@tonic-gate 	int ok;
2257c478bd9Sstevel@tonic-gate 	ok = 0;
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 	if (dbm_flush(db) < 0)
2287c478bd9Sstevel@tonic-gate 		ok = -1;
2297c478bd9Sstevel@tonic-gate 	if (close(db->dbm_dirf) < 0)
2307c478bd9Sstevel@tonic-gate 		ok = -1;
2317c478bd9Sstevel@tonic-gate 	if (close(db->dbm_pagf) < 0)
2327c478bd9Sstevel@tonic-gate 		ok = -1;
2337c478bd9Sstevel@tonic-gate 	free((char *)db);
2347c478bd9Sstevel@tonic-gate 	return (ok);
2357c478bd9Sstevel@tonic-gate }
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate long
dbm_forder(DBM * db,datum key)2387c478bd9Sstevel@tonic-gate dbm_forder(DBM *db, datum key)
2397c478bd9Sstevel@tonic-gate {
2407c478bd9Sstevel@tonic-gate 	unsigned long hash;
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate 	hash = dcalchash(key);
2437c478bd9Sstevel@tonic-gate 	for (db->dbm_hmask = 0; ; db->dbm_hmask = (db->dbm_hmask<<1)+1) {
2447c478bd9Sstevel@tonic-gate 		db->dbm_blkno = hash & db->dbm_hmask;
2457c478bd9Sstevel@tonic-gate 		db->dbm_bitno = db->dbm_blkno + db->dbm_hmask;
2467c478bd9Sstevel@tonic-gate 		if (getbit(db) == 0)
2477c478bd9Sstevel@tonic-gate 			break;
2487c478bd9Sstevel@tonic-gate 	}
2497c478bd9Sstevel@tonic-gate 	return (db->dbm_blkno);
2507c478bd9Sstevel@tonic-gate }
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate datum
dbm_fetch(DBM * db,datum key)2537c478bd9Sstevel@tonic-gate dbm_fetch(DBM *db, datum key)
2547c478bd9Sstevel@tonic-gate {
2557c478bd9Sstevel@tonic-gate 	int i;
2567c478bd9Sstevel@tonic-gate 	datum item;
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate 	if (dbm_error(db))
2597c478bd9Sstevel@tonic-gate 		goto err;
2607c478bd9Sstevel@tonic-gate 	dbm_access(db, dcalchash(key));
2617c478bd9Sstevel@tonic-gate 	if ((i = finddatum(db->dbm_pagbuf, key)) >= 0) {
2627c478bd9Sstevel@tonic-gate 		item = makdatum(db->dbm_pagbuf, i+1);
2637c478bd9Sstevel@tonic-gate 		if (item.dptr != NULL)
2647c478bd9Sstevel@tonic-gate 			return (item);
2657c478bd9Sstevel@tonic-gate 	}
2667c478bd9Sstevel@tonic-gate err:
2677c478bd9Sstevel@tonic-gate 	item.dptr = NULL;
2687c478bd9Sstevel@tonic-gate 	item.dsize = 0;
2697c478bd9Sstevel@tonic-gate 	return (item);
2707c478bd9Sstevel@tonic-gate }
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate int
dbm_delete(DBM * db,datum key)2737c478bd9Sstevel@tonic-gate dbm_delete(DBM *db, datum key)
2747c478bd9Sstevel@tonic-gate {
2757c478bd9Sstevel@tonic-gate 	int i;
2767c478bd9Sstevel@tonic-gate 	off64_t where;
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate 	if (dbm_error(db))
2797c478bd9Sstevel@tonic-gate 		return (-1);
2807c478bd9Sstevel@tonic-gate 	if (dbm_rdonly(db)) {
2817c478bd9Sstevel@tonic-gate 		errno = EPERM;
2827c478bd9Sstevel@tonic-gate 		return (-1);
2837c478bd9Sstevel@tonic-gate 	}
2847c478bd9Sstevel@tonic-gate 	dbm_access(db, dcalchash(key));
2857c478bd9Sstevel@tonic-gate 	if ((i = finddatum(db->dbm_pagbuf, key)) < 0)
2867c478bd9Sstevel@tonic-gate 		return (-1);
2877c478bd9Sstevel@tonic-gate 	if (!delitem(db->dbm_pagbuf, i))
2887c478bd9Sstevel@tonic-gate 		goto err;
2897c478bd9Sstevel@tonic-gate 	db->dbm_pagbno = db->dbm_blkno;
2907c478bd9Sstevel@tonic-gate 	if (dbm_defwrite(db)) {
2917c478bd9Sstevel@tonic-gate 		dbm_setdirty(db);
2927c478bd9Sstevel@tonic-gate 	} else {
2937c478bd9Sstevel@tonic-gate 		where = (((off64_t)db->dbm_blkno) * PBLKSIZ);
2947c478bd9Sstevel@tonic-gate 		if ((lseek64(db->dbm_pagf, where, L_SET) != where) ||
2957c478bd9Sstevel@tonic-gate 		    (write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ)) {
2967c478bd9Sstevel@tonic-gate 			err:
2977c478bd9Sstevel@tonic-gate 				db->dbm_flags |= _DBM_IOERR;
2987c478bd9Sstevel@tonic-gate 				return (-1);
2997c478bd9Sstevel@tonic-gate 		}
3007c478bd9Sstevel@tonic-gate 	}
3017c478bd9Sstevel@tonic-gate 	return (0);
3027c478bd9Sstevel@tonic-gate }
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate int
dbm_store(DBM * db,datum key,datum dat,int replace)3057c478bd9Sstevel@tonic-gate dbm_store(DBM *db, datum key, datum dat, int replace)
3067c478bd9Sstevel@tonic-gate {
3077c478bd9Sstevel@tonic-gate 	int i;
3087c478bd9Sstevel@tonic-gate 	datum item, item1;
3097c478bd9Sstevel@tonic-gate 	char ovfbuf[PBLKSIZ];
3107c478bd9Sstevel@tonic-gate 	unsigned long hashdiff, key_hash, item_hash;
3117c478bd9Sstevel@tonic-gate 	off64_t where;
3127c478bd9Sstevel@tonic-gate 
3137c478bd9Sstevel@tonic-gate 	if (dbm_error(db))
3147c478bd9Sstevel@tonic-gate 		return (-1);
3157c478bd9Sstevel@tonic-gate 	if (dbm_rdonly(db)) {
3167c478bd9Sstevel@tonic-gate 		errno = EPERM;
3177c478bd9Sstevel@tonic-gate 		return (-1);
3187c478bd9Sstevel@tonic-gate 	}
3197c478bd9Sstevel@tonic-gate loop:
3207c478bd9Sstevel@tonic-gate 	key_hash = dcalchash(key);
3217c478bd9Sstevel@tonic-gate 	dbm_access(db, key_hash);
3227c478bd9Sstevel@tonic-gate 	if ((i = finddatum(db->dbm_pagbuf, key)) >= 0) {
3237c478bd9Sstevel@tonic-gate 		if (!replace)
3247c478bd9Sstevel@tonic-gate 			return (1);
3257c478bd9Sstevel@tonic-gate 		if (!delitem(db->dbm_pagbuf, i)) {
3267c478bd9Sstevel@tonic-gate 			db->dbm_flags |= _DBM_IOERR;
3277c478bd9Sstevel@tonic-gate 			return (-1);
3287c478bd9Sstevel@tonic-gate 		}
3297c478bd9Sstevel@tonic-gate 	}
3307c478bd9Sstevel@tonic-gate 	if (!additem(db->dbm_pagbuf, key, dat))
3317c478bd9Sstevel@tonic-gate 		goto split;
3327c478bd9Sstevel@tonic-gate 	db->dbm_pagbno = db->dbm_blkno;
3337c478bd9Sstevel@tonic-gate 	if (dbm_defwrite(db)) {
3347c478bd9Sstevel@tonic-gate 		dbm_setdirty(db);
3357c478bd9Sstevel@tonic-gate 	} else {
3367c478bd9Sstevel@tonic-gate 		where = (((off64_t)db->dbm_blkno) * PBLKSIZ);
3377c478bd9Sstevel@tonic-gate 		if ((lseek64(db->dbm_pagf, where, L_SET) != where) ||
3387c478bd9Sstevel@tonic-gate 		    (write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ)) {
3397c478bd9Sstevel@tonic-gate 			db->dbm_flags |= _DBM_IOERR;
3407c478bd9Sstevel@tonic-gate 			return (-1);
3417c478bd9Sstevel@tonic-gate 		}
3427c478bd9Sstevel@tonic-gate 	}
3437c478bd9Sstevel@tonic-gate 	return (0);
3447c478bd9Sstevel@tonic-gate split:
3457c478bd9Sstevel@tonic-gate 	hashdiff = 0;
3467c478bd9Sstevel@tonic-gate 	if (key.dsize + dat.dsize + 3 * (int)sizeof (short) >= PBLKSIZ) {
3477c478bd9Sstevel@tonic-gate 		db->dbm_flags |= _DBM_IOERR;
3487c478bd9Sstevel@tonic-gate 		errno = ENOSPC;
3497c478bd9Sstevel@tonic-gate 		return (-1);
3507c478bd9Sstevel@tonic-gate 	}
3517c478bd9Sstevel@tonic-gate 	(void) memset(ovfbuf, 0, PBLKSIZ);
3527c478bd9Sstevel@tonic-gate 	for (i = 0; ; ) {
3537c478bd9Sstevel@tonic-gate 		item = makdatum(db->dbm_pagbuf, i);
3547c478bd9Sstevel@tonic-gate 		if (item.dptr == NULL)
3557c478bd9Sstevel@tonic-gate 			break;
3567c478bd9Sstevel@tonic-gate 		item_hash = dcalchash(item);
3577c478bd9Sstevel@tonic-gate 		if (item_hash != key_hash) {
3587c478bd9Sstevel@tonic-gate 			hashdiff++;
3597c478bd9Sstevel@tonic-gate 		}
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate 		if (item_hash & (db->dbm_hmask+1)) {
3627c478bd9Sstevel@tonic-gate 			item1 = makdatum(db->dbm_pagbuf, i+1);
3637c478bd9Sstevel@tonic-gate 			if (item1.dptr == NULL) {
3647c478bd9Sstevel@tonic-gate 				/* (void) fprintf(stderr, "ndbm: */
3657c478bd9Sstevel@tonic-gate 				/* split not paired\n"); */
3667c478bd9Sstevel@tonic-gate 				db->dbm_flags |= _DBM_IOERR;
3677c478bd9Sstevel@tonic-gate 				break;
3687c478bd9Sstevel@tonic-gate 			}
3697c478bd9Sstevel@tonic-gate 			if (!additem(ovfbuf, item, item1) ||
3707c478bd9Sstevel@tonic-gate 			    !delitem(db->dbm_pagbuf, i)) {
3717c478bd9Sstevel@tonic-gate 				db->dbm_flags |= _DBM_IOERR;
3727c478bd9Sstevel@tonic-gate 				return (-1);
3737c478bd9Sstevel@tonic-gate 			}
3747c478bd9Sstevel@tonic-gate 			continue;
3757c478bd9Sstevel@tonic-gate 		}
3767c478bd9Sstevel@tonic-gate 		i += 2;
3777c478bd9Sstevel@tonic-gate 	}
3787c478bd9Sstevel@tonic-gate 	db->dbm_pagbno = db->dbm_blkno;
3797c478bd9Sstevel@tonic-gate 	where = (((off64_t)db->dbm_blkno) * PBLKSIZ);
3807c478bd9Sstevel@tonic-gate 	if ((lseek64(db->dbm_pagf, where, L_SET) != where) ||
3817c478bd9Sstevel@tonic-gate 	    (write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ)) {
3827c478bd9Sstevel@tonic-gate 		db->dbm_flags |= _DBM_IOERR;
3837c478bd9Sstevel@tonic-gate 		return (-1);
3847c478bd9Sstevel@tonic-gate 	}
3857c478bd9Sstevel@tonic-gate 	dbm_clrdirty(db); /* clear dirty */
3867c478bd9Sstevel@tonic-gate 	where = (((off64_t)db->dbm_blkno + db->dbm_hmask + 1) * PBLKSIZ);
3877c478bd9Sstevel@tonic-gate 	if ((lseek64(db->dbm_pagf, where, L_SET) != where) ||
3887c478bd9Sstevel@tonic-gate 	    (write(db->dbm_pagf, ovfbuf, PBLKSIZ) != PBLKSIZ)) {
3897c478bd9Sstevel@tonic-gate 		db->dbm_flags |= _DBM_IOERR;
3907c478bd9Sstevel@tonic-gate 		return (-1);
3917c478bd9Sstevel@tonic-gate 	}
3927c478bd9Sstevel@tonic-gate 	if (setbit(db) < 0) {
3937c478bd9Sstevel@tonic-gate 		db->dbm_flags |= _DBM_IOERR;
3947c478bd9Sstevel@tonic-gate 		return (-1);
3957c478bd9Sstevel@tonic-gate 	}
3967c478bd9Sstevel@tonic-gate 	if (hashdiff == 0) {
3977c478bd9Sstevel@tonic-gate 		db->dbm_flags |= _DBM_IOERR;
3987c478bd9Sstevel@tonic-gate 		return (-1);
3997c478bd9Sstevel@tonic-gate 	}
4007c478bd9Sstevel@tonic-gate 	goto loop;
4017c478bd9Sstevel@tonic-gate }
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate static unsigned long
dbm_hashinc(DBM * db,unsigned long hash)4047c478bd9Sstevel@tonic-gate dbm_hashinc(DBM *db, unsigned long hash)
4057c478bd9Sstevel@tonic-gate {
4067c478bd9Sstevel@tonic-gate 	long bit;
4077c478bd9Sstevel@tonic-gate 
4087c478bd9Sstevel@tonic-gate 	hash &= db->dbm_hmask;
4097c478bd9Sstevel@tonic-gate 	bit = db->dbm_hmask+1;
4107c478bd9Sstevel@tonic-gate 	for (;;) {
4117c478bd9Sstevel@tonic-gate 		bit >>= 1;
4127c478bd9Sstevel@tonic-gate 		if (bit == 0)
4137c478bd9Sstevel@tonic-gate 			return (0L);
4147c478bd9Sstevel@tonic-gate 		if ((hash&bit) == 0)
4157c478bd9Sstevel@tonic-gate 			return (hash|bit);
4167c478bd9Sstevel@tonic-gate 		hash &= ~bit;
4177c478bd9Sstevel@tonic-gate 	}
4187c478bd9Sstevel@tonic-gate }
4197c478bd9Sstevel@tonic-gate 
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate 
4227c478bd9Sstevel@tonic-gate static datum nullkey = {NULL, 0};
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate datum
dbm_firsthash(DBM * db,unsigned long hash)4257c478bd9Sstevel@tonic-gate dbm_firsthash(DBM *db, unsigned long hash)
4267c478bd9Sstevel@tonic-gate {
4277c478bd9Sstevel@tonic-gate 	int i, j;
4287c478bd9Sstevel@tonic-gate 	datum item, bitem;
4297c478bd9Sstevel@tonic-gate 
4307c478bd9Sstevel@tonic-gate loop:
4317c478bd9Sstevel@tonic-gate 	dbm_access(db, hash);
4327c478bd9Sstevel@tonic-gate 	j = 0;
4337c478bd9Sstevel@tonic-gate 	bitem = makdatum(db->dbm_pagbuf, 0);
4347c478bd9Sstevel@tonic-gate 	for (i = 2; ; i += 2) {
4357c478bd9Sstevel@tonic-gate 		item = makdatum(db->dbm_pagbuf, i);
4367c478bd9Sstevel@tonic-gate 		if (item.dptr == NULL)
4377c478bd9Sstevel@tonic-gate 			break;
4387c478bd9Sstevel@tonic-gate 		if (cmpdatum(bitem, item) < 0) {
4397c478bd9Sstevel@tonic-gate 			j = i;
4407c478bd9Sstevel@tonic-gate 			bitem = item;
4417c478bd9Sstevel@tonic-gate 		}
4427c478bd9Sstevel@tonic-gate 	}
4437c478bd9Sstevel@tonic-gate 	if (bitem.dptr != NULL) {
4447c478bd9Sstevel@tonic-gate 		db->dbm_keyptr = j + 2;
4457c478bd9Sstevel@tonic-gate 		db->dbm_blkptr = db->dbm_blkno;
4467c478bd9Sstevel@tonic-gate 		return (bitem);
4477c478bd9Sstevel@tonic-gate 	}
4487c478bd9Sstevel@tonic-gate 	hash = dbm_hashinc(db, hash);
4497c478bd9Sstevel@tonic-gate 	if (hash == 0)
4507c478bd9Sstevel@tonic-gate 		return (item); /* null item */
4517c478bd9Sstevel@tonic-gate 	goto loop;
4527c478bd9Sstevel@tonic-gate 
4537c478bd9Sstevel@tonic-gate }
4547c478bd9Sstevel@tonic-gate 
4557c478bd9Sstevel@tonic-gate datum
dbm_firstkey(DBM * db)4567c478bd9Sstevel@tonic-gate dbm_firstkey(DBM *db)
4577c478bd9Sstevel@tonic-gate {
458a574db85Sraf 	/*
459a574db85Sraf 	 * For some reason, the Posix specification (SUSv3)
460a574db85Sraf 	 * says that dbm_firstkey() is not a cancellation point.
461a574db85Sraf 	 * It really should be, but in order to pass the SUSv3
462a574db85Sraf 	 * test suite we make it not a cancellation point.
463a574db85Sraf 	 * XXX: fix me when the SUSv3 specification gets fixed.
464a574db85Sraf 	 */
465a574db85Sraf 	int cancel_state;
466a574db85Sraf 	datum rval;
4677c478bd9Sstevel@tonic-gate 
4687c478bd9Sstevel@tonic-gate 	db->dbm_blkptr = 0L;
4697c478bd9Sstevel@tonic-gate 	db->dbm_keyptr = 0;
470a574db85Sraf 	(void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancel_state);
471a574db85Sraf 	rval = dbm_firsthash(db, 0L);
472a574db85Sraf 	(void) pthread_setcancelstate(cancel_state, NULL);
473a574db85Sraf 	return (rval);
4747c478bd9Sstevel@tonic-gate }
4757c478bd9Sstevel@tonic-gate 
4767c478bd9Sstevel@tonic-gate datum
dbm_nextkey(DBM * db)4777c478bd9Sstevel@tonic-gate dbm_nextkey(DBM *db)
4787c478bd9Sstevel@tonic-gate {
4797c478bd9Sstevel@tonic-gate 
4807c478bd9Sstevel@tonic-gate 	return (dbm_do_nextkey(db, nullkey));
4817c478bd9Sstevel@tonic-gate }
4827c478bd9Sstevel@tonic-gate 
4837c478bd9Sstevel@tonic-gate /*
4847c478bd9Sstevel@tonic-gate  * this is used if keyptr-2, blocknum doesn't point to the previous
4857c478bd9Sstevel@tonic-gate  * specific key allowing the fast hash order search --
4867c478bd9Sstevel@tonic-gate  * its use indicates user tampering with our state variables,
4877c478bd9Sstevel@tonic-gate  * which some evil users might do to search from some specific place.
4887c478bd9Sstevel@tonic-gate  * It finds the first key at or after blkptr, keyptr in block seq order
4897c478bd9Sstevel@tonic-gate  * this requires looking at all sorts of emtpy blocks in many cases
4907c478bd9Sstevel@tonic-gate  */
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate static
4937c478bd9Sstevel@tonic-gate datum
dbm_slow_nextkey(DBM * db)4947c478bd9Sstevel@tonic-gate dbm_slow_nextkey(DBM *db)
4957c478bd9Sstevel@tonic-gate {
4967c478bd9Sstevel@tonic-gate 
4977c478bd9Sstevel@tonic-gate 	struct stat64 statb;
4987c478bd9Sstevel@tonic-gate 	datum item;
4997c478bd9Sstevel@tonic-gate 	off64_t where;
5007c478bd9Sstevel@tonic-gate 
5017c478bd9Sstevel@tonic-gate 	if (dbm_error(db) || fstat64(db->dbm_pagf, &statb) < 0)
5027c478bd9Sstevel@tonic-gate 		goto err;
5037c478bd9Sstevel@tonic-gate 	statb.st_size /= PBLKSIZ;
5047c478bd9Sstevel@tonic-gate 
5057c478bd9Sstevel@tonic-gate 	for (;;) {
5067c478bd9Sstevel@tonic-gate 		if (db->dbm_blkptr != db->dbm_pagbno) {
5077c478bd9Sstevel@tonic-gate 
5087c478bd9Sstevel@tonic-gate 			if (dbm_dirty(db)) (void) dbm_flushpag(db);
5097c478bd9Sstevel@tonic-gate 
5107c478bd9Sstevel@tonic-gate 			db->dbm_pagbno = db->dbm_blkptr;
5117c478bd9Sstevel@tonic-gate 			where = (((off64_t)db->dbm_blkptr) * PBLKSIZ);
5127c478bd9Sstevel@tonic-gate 			if ((lseek64(db->dbm_pagf, where, L_SET) != where) ||
5137c478bd9Sstevel@tonic-gate 			    (read(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) !=
5147c478bd9Sstevel@tonic-gate 			    PBLKSIZ))
5157c478bd9Sstevel@tonic-gate 				(void) memset(db->dbm_pagbuf, 0, PBLKSIZ);
516*18c77f76SBill Sommerfeld #ifdef NDBM_DEBUG
5177c478bd9Sstevel@tonic-gate 			else if (chkblk(db->dbm_pagbuf) < 0)
5187c478bd9Sstevel@tonic-gate 				db->dbm_flags |= _DBM_IOERR;
5197c478bd9Sstevel@tonic-gate #endif
5207c478bd9Sstevel@tonic-gate 		}
5217c478bd9Sstevel@tonic-gate 		/* Am I an empty block? */
5227c478bd9Sstevel@tonic-gate 		if (((short *)(uintptr_t)db->dbm_pagbuf)[0] != 0) {
5237c478bd9Sstevel@tonic-gate 			item = makdatum(db->dbm_pagbuf, db->dbm_keyptr);
5247c478bd9Sstevel@tonic-gate 			if (item.dptr != NULL) {
5257c478bd9Sstevel@tonic-gate 				db->dbm_keyptr += 2;
5267c478bd9Sstevel@tonic-gate 				return (item);
5277c478bd9Sstevel@tonic-gate 			}
5287c478bd9Sstevel@tonic-gate 			db->dbm_keyptr = 0;
5297c478bd9Sstevel@tonic-gate 		}
5307c478bd9Sstevel@tonic-gate 		/* go to next sequential block */
5317c478bd9Sstevel@tonic-gate 		if (++db->dbm_blkptr >= statb.st_size)
5327c478bd9Sstevel@tonic-gate 			break;
5337c478bd9Sstevel@tonic-gate 	}
5347c478bd9Sstevel@tonic-gate err:
5357c478bd9Sstevel@tonic-gate 	item.dptr = NULL;
5367c478bd9Sstevel@tonic-gate 	item.dsize = 0;
5377c478bd9Sstevel@tonic-gate 	return (item);
5387c478bd9Sstevel@tonic-gate }
5397c478bd9Sstevel@tonic-gate 
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate 
5427c478bd9Sstevel@tonic-gate datum
dbm_do_nextkey(DBM * db,datum inkey)5437c478bd9Sstevel@tonic-gate dbm_do_nextkey(DBM *db, datum inkey)
5447c478bd9Sstevel@tonic-gate {
5457c478bd9Sstevel@tonic-gate 	datum item, bitem;
5467c478bd9Sstevel@tonic-gate 	unsigned long hash;
5477c478bd9Sstevel@tonic-gate 	datum key;
5487c478bd9Sstevel@tonic-gate 	int f;
5497c478bd9Sstevel@tonic-gate 	int i;
5507c478bd9Sstevel@tonic-gate 	int j;
5517c478bd9Sstevel@tonic-gate 	short *sp;
5527c478bd9Sstevel@tonic-gate 	long n;
5537c478bd9Sstevel@tonic-gate 	char *p1, *p2;
5547c478bd9Sstevel@tonic-gate 	off64_t where;
5557c478bd9Sstevel@tonic-gate 
5567c478bd9Sstevel@tonic-gate 	if (dbm_error(db)) {
5577c478bd9Sstevel@tonic-gate 		item.dptr = NULL;
5587c478bd9Sstevel@tonic-gate 		item.dsize = 0;
5597c478bd9Sstevel@tonic-gate 		return (item);
5607c478bd9Sstevel@tonic-gate 	}
5617c478bd9Sstevel@tonic-gate 
5627c478bd9Sstevel@tonic-gate 	/* user has supplied lastkey */
5637c478bd9Sstevel@tonic-gate 
5647c478bd9Sstevel@tonic-gate 	if (inkey.dptr != NULL) {
5657c478bd9Sstevel@tonic-gate 		dbm_access(db, (hash = dcalchash(inkey)));
5667c478bd9Sstevel@tonic-gate 		if ((i = finddatum(db->dbm_pagbuf, inkey)) >= 0) {
5677c478bd9Sstevel@tonic-gate 			db->dbm_keyptr = i + 2;
5687c478bd9Sstevel@tonic-gate 			db->dbm_blkptr = db->dbm_blkno;
5697c478bd9Sstevel@tonic-gate 		}
5707c478bd9Sstevel@tonic-gate 		key = inkey;
5717c478bd9Sstevel@tonic-gate 	} else  {
5727c478bd9Sstevel@tonic-gate 		/* is this a manual firstkey request? */
5737c478bd9Sstevel@tonic-gate 
5747c478bd9Sstevel@tonic-gate 		if (db->dbm_blkptr == 0L &&
5757c478bd9Sstevel@tonic-gate 		    db->dbm_keyptr == 0)
5767c478bd9Sstevel@tonic-gate 			return (dbm_firsthash(db, 0L));
5777c478bd9Sstevel@tonic-gate 
5787c478bd9Sstevel@tonic-gate 		/* no -- get lastkey this is like dbm_access by blkptr */
5797c478bd9Sstevel@tonic-gate 
5807c478bd9Sstevel@tonic-gate 		if (db->dbm_blkptr != db->dbm_pagbno) {
5817c478bd9Sstevel@tonic-gate 
5827c478bd9Sstevel@tonic-gate 			if (dbm_dirty(db)) (void) dbm_flushpag(db);
5837c478bd9Sstevel@tonic-gate 			db->dbm_pagbno = db->dbm_blkptr;
5847c478bd9Sstevel@tonic-gate 			where = (((off64_t)db->dbm_blkptr) * PBLKSIZ);
5857c478bd9Sstevel@tonic-gate 			if ((lseek64(db->dbm_pagf, where, L_SET) != where) ||
5867c478bd9Sstevel@tonic-gate 			    (read(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) !=
5877c478bd9Sstevel@tonic-gate 			    PBLKSIZ))
5887c478bd9Sstevel@tonic-gate 				(void) memset(db->dbm_pagbuf, 0, PBLKSIZ);
589*18c77f76SBill Sommerfeld #ifdef NDBM_DEBUG
5907c478bd9Sstevel@tonic-gate 			else if (chkblk(db->dbm_pagbuf) < 0)
5917c478bd9Sstevel@tonic-gate 			db->dbm_flags |= _DBM_IOERR;
5927c478bd9Sstevel@tonic-gate #endif
5937c478bd9Sstevel@tonic-gate 		}
5947c478bd9Sstevel@tonic-gate 		/* now just make up last key datum */
5957c478bd9Sstevel@tonic-gate 		if (db->dbm_keyptr >= 2)
5967c478bd9Sstevel@tonic-gate 			key = makdatum(db->dbm_pagbuf, (db->dbm_keyptr-2));
5977c478bd9Sstevel@tonic-gate 		else key = nullkey;
5987c478bd9Sstevel@tonic-gate 
5997c478bd9Sstevel@tonic-gate 		/*
6007c478bd9Sstevel@tonic-gate 		 * the keyptr pagbuf have failed us, the user must
6017c478bd9Sstevel@tonic-gate 		 * be an extra clever moron who depends on
6027c478bd9Sstevel@tonic-gate 		 * these variables and their former meaning.
6037c478bd9Sstevel@tonic-gate 		 * If we set the variables this would have got
60448bbca81SDaniel Hoffman 		 * us the key for sure! So give it the old algorithm.
6057c478bd9Sstevel@tonic-gate 		 */
6067c478bd9Sstevel@tonic-gate 		if (key.dptr == NULL)
6077c478bd9Sstevel@tonic-gate 			return (dbm_slow_nextkey(db));
6087c478bd9Sstevel@tonic-gate 	}
6097c478bd9Sstevel@tonic-gate 
6107c478bd9Sstevel@tonic-gate 	/*
6117c478bd9Sstevel@tonic-gate 	 * at this point the last key is paged in and
6127c478bd9Sstevel@tonic-gate 	 * we can proceed as in old dbm -- like Ken did his.
6137c478bd9Sstevel@tonic-gate 	 */
6147c478bd9Sstevel@tonic-gate 
6157c478bd9Sstevel@tonic-gate 	f = 1;
6167c478bd9Sstevel@tonic-gate 	j = 0;
6177c478bd9Sstevel@tonic-gate 	sp = (short *)(uintptr_t)db->dbm_pagbuf;
6187c478bd9Sstevel@tonic-gate 
6197c478bd9Sstevel@tonic-gate 	for (i = 0; ; i += 2) {
6207c478bd9Sstevel@tonic-gate 
6217c478bd9Sstevel@tonic-gate 		/* begin put makdatum inline */
6227c478bd9Sstevel@tonic-gate 
6237c478bd9Sstevel@tonic-gate 		if ((unsigned)i >= sp[0]) {
6247c478bd9Sstevel@tonic-gate 			item.dptr = NULL;
6257c478bd9Sstevel@tonic-gate 			item.dsize = 0;
6267c478bd9Sstevel@tonic-gate 			break; /* from below */
6277c478bd9Sstevel@tonic-gate 		} else {
6287c478bd9Sstevel@tonic-gate 			if (i > 0) item.dsize = sp[i] - sp[i + 1];
6297c478bd9Sstevel@tonic-gate 			else item.dsize = PBLKSIZ - sp[i + 1];
6307c478bd9Sstevel@tonic-gate 			item.dptr = db->dbm_pagbuf+sp[i + 1];
6317c478bd9Sstevel@tonic-gate 		}
6327c478bd9Sstevel@tonic-gate 
6337c478bd9Sstevel@tonic-gate 		/* item = makdatum(db->dbm_pagbuf, i); */
6347c478bd9Sstevel@tonic-gate 		/* end put makdatum inline */
6357c478bd9Sstevel@tonic-gate 
6367c478bd9Sstevel@tonic-gate 		if (item.dptr == NULL)
6377c478bd9Sstevel@tonic-gate 			break;
6387c478bd9Sstevel@tonic-gate /* inline cmpdatum */
6397c478bd9Sstevel@tonic-gate 
6407c478bd9Sstevel@tonic-gate 
6417c478bd9Sstevel@tonic-gate 		n = key.dsize;
6427c478bd9Sstevel@tonic-gate 		if (n != item.dsize) {
6437c478bd9Sstevel@tonic-gate 			if ((n - item.dsize) <= 0)
6447c478bd9Sstevel@tonic-gate 				continue;
6457c478bd9Sstevel@tonic-gate 		} else {
6467c478bd9Sstevel@tonic-gate 			if (n == 0) continue;
6477c478bd9Sstevel@tonic-gate 			p1 = key.dptr;
6487c478bd9Sstevel@tonic-gate 			p2 = item.dptr;
6497c478bd9Sstevel@tonic-gate 			do {
6507c478bd9Sstevel@tonic-gate 				if (*p1++ != *p2++)
6517c478bd9Sstevel@tonic-gate 					if ((*--p1 - *--p2) > 0)
6527c478bd9Sstevel@tonic-gate 						goto keep_going;
6537c478bd9Sstevel@tonic-gate 					else continue;
6547c478bd9Sstevel@tonic-gate 			} while (--n);
6557c478bd9Sstevel@tonic-gate 			continue;
6567c478bd9Sstevel@tonic-gate 		}
6577c478bd9Sstevel@tonic-gate 
6587c478bd9Sstevel@tonic-gate keep_going:
6597c478bd9Sstevel@tonic-gate 
6607c478bd9Sstevel@tonic-gate /* end inline cmpdatum */
6617c478bd9Sstevel@tonic-gate 		/*
6627c478bd9Sstevel@tonic-gate 		 * if (cmpdatum(key, item) <= 0)
6637c478bd9Sstevel@tonic-gate 		 *	continue;
6647c478bd9Sstevel@tonic-gate 		 */
6657c478bd9Sstevel@tonic-gate 
6667c478bd9Sstevel@tonic-gate 		if (f) {
6677c478bd9Sstevel@tonic-gate 			bitem = item;
6687c478bd9Sstevel@tonic-gate 			j = i;
6697c478bd9Sstevel@tonic-gate 			f = 0;
6707c478bd9Sstevel@tonic-gate 		} else {
6717c478bd9Sstevel@tonic-gate 
6727c478bd9Sstevel@tonic-gate 			/* if (cmpdatum(bitem, item) < 0) */
6737c478bd9Sstevel@tonic-gate 
6747c478bd9Sstevel@tonic-gate 			n = bitem.dsize;
6757c478bd9Sstevel@tonic-gate 			if (n != item.dsize) {
6767c478bd9Sstevel@tonic-gate 				if ((n - item.dsize) < 0) {
6777c478bd9Sstevel@tonic-gate 					bitem = item;
6787c478bd9Sstevel@tonic-gate 					j = i;
6797c478bd9Sstevel@tonic-gate 				}
6807c478bd9Sstevel@tonic-gate 			} else
6817c478bd9Sstevel@tonic-gate 				if (n != 0) {
6827c478bd9Sstevel@tonic-gate 					p1 = bitem.dptr;
6837c478bd9Sstevel@tonic-gate 					p2 = item.dptr;
6847c478bd9Sstevel@tonic-gate 					do {
6857c478bd9Sstevel@tonic-gate 					if (*p1++ != *p2++) {
6867c478bd9Sstevel@tonic-gate 						if ((*--p1 - *--p2) < 0) {
6877c478bd9Sstevel@tonic-gate 							bitem = item;
6887c478bd9Sstevel@tonic-gate 							j = i;
6897c478bd9Sstevel@tonic-gate 						}
6907c478bd9Sstevel@tonic-gate 						break;
6917c478bd9Sstevel@tonic-gate 					}
6927c478bd9Sstevel@tonic-gate 					} while (--n);
6937c478bd9Sstevel@tonic-gate 				}
6947c478bd9Sstevel@tonic-gate 			}
6957c478bd9Sstevel@tonic-gate 	}
6967c478bd9Sstevel@tonic-gate 
6977c478bd9Sstevel@tonic-gate 	if (f == 0) {
6987c478bd9Sstevel@tonic-gate 		db->dbm_keyptr = j + 2;
6997c478bd9Sstevel@tonic-gate 		db->dbm_blkptr = db->dbm_blkno;
7007c478bd9Sstevel@tonic-gate 		return (bitem);
7017c478bd9Sstevel@tonic-gate 	}
7027c478bd9Sstevel@tonic-gate 
7037c478bd9Sstevel@tonic-gate 	/* really need hash at this point */
70448bbca81SDaniel Hoffman 	/* if it gave us a key we have already calculated the hash */
70548bbca81SDaniel Hoffman 	/* if not get the hash */
7067c478bd9Sstevel@tonic-gate 	if (inkey.dptr == NULL)
7077c478bd9Sstevel@tonic-gate 		hash = dcalchash(key);
7087c478bd9Sstevel@tonic-gate 	hash = dbm_hashinc(db, hash);
7097c478bd9Sstevel@tonic-gate 
7107c478bd9Sstevel@tonic-gate 	if (hash == 0)
7117c478bd9Sstevel@tonic-gate 		return (item); /* null */
7127c478bd9Sstevel@tonic-gate 	/* get first item on next page in hash table order */
7137c478bd9Sstevel@tonic-gate 	return (dbm_firsthash(db, hash));
7147c478bd9Sstevel@tonic-gate 
7157c478bd9Sstevel@tonic-gate 
7167c478bd9Sstevel@tonic-gate }
7177c478bd9Sstevel@tonic-gate 
7187c478bd9Sstevel@tonic-gate static void
dbm_access(DBM * db,unsigned long hash)7197c478bd9Sstevel@tonic-gate dbm_access(DBM *db, unsigned long hash)
7207c478bd9Sstevel@tonic-gate {
7217c478bd9Sstevel@tonic-gate 	long b, i, n;
7227c478bd9Sstevel@tonic-gate 	long bn;
7237c478bd9Sstevel@tonic-gate 	long my_bitno;
7247c478bd9Sstevel@tonic-gate 	long my_hmask;
7257c478bd9Sstevel@tonic-gate 	long my_blkno;
7267c478bd9Sstevel@tonic-gate 	int j = (sizeof (my_hmask)) * 8;
7277c478bd9Sstevel@tonic-gate 	off64_t where;
7287c478bd9Sstevel@tonic-gate 
7297c478bd9Sstevel@tonic-gate 	for (my_hmask = 0; j-- > 0; my_hmask = (my_hmask<<1) + 1) {
7307c478bd9Sstevel@tonic-gate 		my_blkno = hash & my_hmask;
7317c478bd9Sstevel@tonic-gate 		my_bitno = my_blkno + my_hmask;
7327c478bd9Sstevel@tonic-gate 		/* getbit inline */
7337c478bd9Sstevel@tonic-gate 		if (my_bitno > db->dbm_maxbno) break;
7347c478bd9Sstevel@tonic-gate 		n = my_bitno % BYTESIZ;
7357c478bd9Sstevel@tonic-gate 		bn = my_bitno / BYTESIZ;
7367c478bd9Sstevel@tonic-gate 		i = bn % DBLKSIZ;
7377c478bd9Sstevel@tonic-gate 		b = bn / DBLKSIZ;
7387c478bd9Sstevel@tonic-gate 		if (b != db->dbm_dirbno) {
7397c478bd9Sstevel@tonic-gate 			if (dbm_dirdirty(db))
7407c478bd9Sstevel@tonic-gate 				(void) dbm_flushdir(db); /* must flush */
7417c478bd9Sstevel@tonic-gate 			db->dbm_dirbno = b;
7427c478bd9Sstevel@tonic-gate 			where = (((off64_t)b) * DBLKSIZ);
7437c478bd9Sstevel@tonic-gate 			if ((lseek64(db->dbm_dirf, where, L_SET) != where) ||
7447c478bd9Sstevel@tonic-gate 			    (read(db->dbm_dirf, db->dbm_dirbuf, DBLKSIZ) !=
7457c478bd9Sstevel@tonic-gate 			    DBLKSIZ))
7467c478bd9Sstevel@tonic-gate 				(void) memset(db->dbm_dirbuf, 0, DBLKSIZ);
7477c478bd9Sstevel@tonic-gate 		}
7487c478bd9Sstevel@tonic-gate 		if ((db->dbm_dirbuf[i] & (1<<n)) == 0) break;
7497c478bd9Sstevel@tonic-gate 
7507c478bd9Sstevel@tonic-gate 		/*
7517c478bd9Sstevel@tonic-gate 		 * if (getbit(db) == 0)
7527c478bd9Sstevel@tonic-gate 		 *	break;
7537c478bd9Sstevel@tonic-gate 		 */
7547c478bd9Sstevel@tonic-gate 	}
7557c478bd9Sstevel@tonic-gate 	/* copy */
7567c478bd9Sstevel@tonic-gate 	db->dbm_blkno = my_blkno;
7577c478bd9Sstevel@tonic-gate 	db->dbm_bitno = my_bitno;
7587c478bd9Sstevel@tonic-gate 	db->dbm_hmask = my_hmask;
7597c478bd9Sstevel@tonic-gate 
7607c478bd9Sstevel@tonic-gate 	if (my_blkno != db->dbm_pagbno) {
7617c478bd9Sstevel@tonic-gate 		if (dbm_dirty(db)) { /* must page out the page */
7627c478bd9Sstevel@tonic-gate 			where = (((off64_t)db->dbm_pagbno) * PBLKSIZ);
7637c478bd9Sstevel@tonic-gate 			if ((lseek64(db->dbm_pagf, where, L_SET) != where) ||
7647c478bd9Sstevel@tonic-gate 			    (write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) !=
7657c478bd9Sstevel@tonic-gate 			    PBLKSIZ)) {
7667c478bd9Sstevel@tonic-gate 				db->dbm_flags |= _DBM_IOERR;
7677c478bd9Sstevel@tonic-gate 			}
7687c478bd9Sstevel@tonic-gate 		dbm_clrdirty(db);
7697c478bd9Sstevel@tonic-gate 		}
7707c478bd9Sstevel@tonic-gate 
7717c478bd9Sstevel@tonic-gate 		db->dbm_pagbno = my_blkno;
7727c478bd9Sstevel@tonic-gate 		where = (((off64_t)my_blkno) * PBLKSIZ);
7737c478bd9Sstevel@tonic-gate 		if ((lseek64(db->dbm_pagf, where, L_SET) != where) ||
7747c478bd9Sstevel@tonic-gate 		    (read(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ))
7757c478bd9Sstevel@tonic-gate 			(void) memset(db->dbm_pagbuf, 0, PBLKSIZ);
776*18c77f76SBill Sommerfeld #ifdef NDBM_DEBUG
7777c478bd9Sstevel@tonic-gate 		else if (chkblk(db->dbm_pagbuf) < 0)
7787c478bd9Sstevel@tonic-gate 			db->dbm_flags |= _DBM_IOERR;
7797c478bd9Sstevel@tonic-gate #endif
7807c478bd9Sstevel@tonic-gate 	}
7817c478bd9Sstevel@tonic-gate }
7827c478bd9Sstevel@tonic-gate 
7837c478bd9Sstevel@tonic-gate static int
getbit(DBM * db)7847c478bd9Sstevel@tonic-gate getbit(DBM *db)
7857c478bd9Sstevel@tonic-gate {
7867c478bd9Sstevel@tonic-gate 	long bn;
7877c478bd9Sstevel@tonic-gate 	long b, i, n;
7887c478bd9Sstevel@tonic-gate 	off64_t where;
7897c478bd9Sstevel@tonic-gate 
7907c478bd9Sstevel@tonic-gate 	if (db->dbm_bitno > db->dbm_maxbno)
7917c478bd9Sstevel@tonic-gate 		return (0);
7927c478bd9Sstevel@tonic-gate 	n = db->dbm_bitno % BYTESIZ;
7937c478bd9Sstevel@tonic-gate 	bn = db->dbm_bitno / BYTESIZ;
7947c478bd9Sstevel@tonic-gate 	i = bn % DBLKSIZ;
7957c478bd9Sstevel@tonic-gate 	b = bn / DBLKSIZ;
7967c478bd9Sstevel@tonic-gate 	if (b != db->dbm_dirbno) {
7977c478bd9Sstevel@tonic-gate 		if (dbm_dirdirty(db))
7987c478bd9Sstevel@tonic-gate 			(void) dbm_flushdir(db); /* must flush */
7997c478bd9Sstevel@tonic-gate 		db->dbm_dirbno = b;
8007c478bd9Sstevel@tonic-gate 		where = (((off64_t)b) * DBLKSIZ);
8017c478bd9Sstevel@tonic-gate 		if ((lseek64(db->dbm_dirf, where, L_SET) != where) ||
8027c478bd9Sstevel@tonic-gate 		    (read(db->dbm_dirf, db->dbm_dirbuf, DBLKSIZ) != DBLKSIZ))
8037c478bd9Sstevel@tonic-gate 			(void) memset(db->dbm_dirbuf, 0, DBLKSIZ);
8047c478bd9Sstevel@tonic-gate 	}
8057c478bd9Sstevel@tonic-gate 	return (db->dbm_dirbuf[i] & (1<<n));
8067c478bd9Sstevel@tonic-gate }
8077c478bd9Sstevel@tonic-gate 
8087c478bd9Sstevel@tonic-gate static int
setbit(DBM * db)8097c478bd9Sstevel@tonic-gate setbit(DBM *db)
8107c478bd9Sstevel@tonic-gate {
8117c478bd9Sstevel@tonic-gate 	long bn;
8127c478bd9Sstevel@tonic-gate 	long i, n, b;
8137c478bd9Sstevel@tonic-gate 	off64_t where;
8147c478bd9Sstevel@tonic-gate 
8157c478bd9Sstevel@tonic-gate 	if (db->dbm_bitno > db->dbm_maxbno)
8167c478bd9Sstevel@tonic-gate 		db->dbm_maxbno = db->dbm_bitno;
8177c478bd9Sstevel@tonic-gate 	n = db->dbm_bitno % BYTESIZ;
8187c478bd9Sstevel@tonic-gate 	bn = db->dbm_bitno / BYTESIZ;
8197c478bd9Sstevel@tonic-gate 	i = bn % DBLKSIZ;
8207c478bd9Sstevel@tonic-gate 	b = bn / DBLKSIZ;
8217c478bd9Sstevel@tonic-gate 	if (b != db->dbm_dirbno) {
8227c478bd9Sstevel@tonic-gate 		if (dbm_dirdirty(db))
8237c478bd9Sstevel@tonic-gate 			(void) dbm_flushdir(db);
8247c478bd9Sstevel@tonic-gate 		db->dbm_dirbno = b;
8257c478bd9Sstevel@tonic-gate 		where = (((off64_t)b) * DBLKSIZ);
8267c478bd9Sstevel@tonic-gate 		if ((lseek64(db->dbm_dirf, where, L_SET) != where) ||
8277c478bd9Sstevel@tonic-gate 		    (read(db->dbm_dirf, db->dbm_dirbuf, DBLKSIZ) != DBLKSIZ))
8287c478bd9Sstevel@tonic-gate 			(void) memset(db->dbm_dirbuf, 0, DBLKSIZ);
8297c478bd9Sstevel@tonic-gate 	}
8307c478bd9Sstevel@tonic-gate 	db->dbm_dirbuf[i] |= 1<<n;
8317c478bd9Sstevel@tonic-gate 	db->dbm_dirbno = b;
8327c478bd9Sstevel@tonic-gate 	if (dbm_defwrite(db)) {
8337c478bd9Sstevel@tonic-gate 		dbm_setdirdirty(db);
8347c478bd9Sstevel@tonic-gate 	} else {
8357c478bd9Sstevel@tonic-gate 		where = (((off64_t)b) * DBLKSIZ);
8367c478bd9Sstevel@tonic-gate 		if ((lseek64(db->dbm_dirf, where, L_SET) != where) ||
8377c478bd9Sstevel@tonic-gate 		    (write(db->dbm_dirf, db->dbm_dirbuf, DBLKSIZ) != DBLKSIZ)) {
8387c478bd9Sstevel@tonic-gate 			return (-1);
8397c478bd9Sstevel@tonic-gate 		}
8407c478bd9Sstevel@tonic-gate 	}
8417c478bd9Sstevel@tonic-gate 	return (0);
8427c478bd9Sstevel@tonic-gate }
8437c478bd9Sstevel@tonic-gate 
8447c478bd9Sstevel@tonic-gate static datum
makdatum(char * buf,int n)8452829495dSToomas Soome makdatum(char *buf, int n)
8467c478bd9Sstevel@tonic-gate {
8477c478bd9Sstevel@tonic-gate 	short *sp;
8487c478bd9Sstevel@tonic-gate 	int t;
8497c478bd9Sstevel@tonic-gate 	datum item;
8507c478bd9Sstevel@tonic-gate 
8517c478bd9Sstevel@tonic-gate 	sp = (short *)(uintptr_t)buf;
8527c478bd9Sstevel@tonic-gate 	if ((unsigned)n >= sp[0]) {
8537c478bd9Sstevel@tonic-gate 		item.dptr = NULL;
8547c478bd9Sstevel@tonic-gate 		item.dsize = 0;
8557c478bd9Sstevel@tonic-gate 		return (item);
8567c478bd9Sstevel@tonic-gate 	}
8577c478bd9Sstevel@tonic-gate 	t = PBLKSIZ;
8587c478bd9Sstevel@tonic-gate 	if (n > 0)
8597c478bd9Sstevel@tonic-gate 		t = sp[n];
8607c478bd9Sstevel@tonic-gate 	item.dptr = buf + sp[n + 1];
8617c478bd9Sstevel@tonic-gate 	item.dsize = t - sp[n + 1];
8627c478bd9Sstevel@tonic-gate 	return (item);
8637c478bd9Sstevel@tonic-gate }
8647c478bd9Sstevel@tonic-gate 
8657c478bd9Sstevel@tonic-gate static int
cmpdatum(datum d1,datum d2)8667c478bd9Sstevel@tonic-gate cmpdatum(datum d1, datum d2)
8677c478bd9Sstevel@tonic-gate {
8687c478bd9Sstevel@tonic-gate 	long n;
8697c478bd9Sstevel@tonic-gate 	char *p1, *p2;
8707c478bd9Sstevel@tonic-gate 
8717c478bd9Sstevel@tonic-gate 	n = d1.dsize;
8727c478bd9Sstevel@tonic-gate 	if (n != d2.dsize)
8737c478bd9Sstevel@tonic-gate 		return ((int)(n - d2.dsize));
8747c478bd9Sstevel@tonic-gate 	if (n == 0)
8757c478bd9Sstevel@tonic-gate 		return (0);
8767c478bd9Sstevel@tonic-gate 	p1 = d1.dptr;
8777c478bd9Sstevel@tonic-gate 	p2 = d2.dptr;
8787c478bd9Sstevel@tonic-gate 	do {
8797c478bd9Sstevel@tonic-gate 		if (*p1 != *p2)
8807c478bd9Sstevel@tonic-gate 			return (*p1 - *p2);
8817c478bd9Sstevel@tonic-gate 		else {
8827c478bd9Sstevel@tonic-gate 			p1++;
8837c478bd9Sstevel@tonic-gate 			p2++;
8847c478bd9Sstevel@tonic-gate 		}
8857c478bd9Sstevel@tonic-gate 	} while (--n);
8867c478bd9Sstevel@tonic-gate 	return (0);
8877c478bd9Sstevel@tonic-gate }
8887c478bd9Sstevel@tonic-gate 
8897c478bd9Sstevel@tonic-gate static int
finddatum(char * buf,datum item)8902829495dSToomas Soome finddatum(char *buf, datum item)
8917c478bd9Sstevel@tonic-gate {
8927c478bd9Sstevel@tonic-gate 	short *sp;
8937c478bd9Sstevel@tonic-gate 	int i, n, j;
8947c478bd9Sstevel@tonic-gate 
8957c478bd9Sstevel@tonic-gate 	sp = (short *)(uintptr_t)buf;
8967c478bd9Sstevel@tonic-gate 	n = PBLKSIZ;
8977c478bd9Sstevel@tonic-gate 	for (i = 0, j = sp[0]; i < j; i += 2, n = sp[i]) {
8987c478bd9Sstevel@tonic-gate 		n -= sp[i + 1];
8997c478bd9Sstevel@tonic-gate 		if (n != item.dsize)
9007c478bd9Sstevel@tonic-gate 			continue;
9017c478bd9Sstevel@tonic-gate 		if (n == 0 || memcmp(&buf[sp[i+1]], item.dptr, n) == 0)
9027c478bd9Sstevel@tonic-gate 			return (i);
9037c478bd9Sstevel@tonic-gate 	}
9047c478bd9Sstevel@tonic-gate 	return (-1);
9057c478bd9Sstevel@tonic-gate }
9067c478bd9Sstevel@tonic-gate 
9077c478bd9Sstevel@tonic-gate static const int hitab[16]
9087c478bd9Sstevel@tonic-gate /*
9097c478bd9Sstevel@tonic-gate  * ken's
9107c478bd9Sstevel@tonic-gate  * {
9117c478bd9Sstevel@tonic-gate  *	055, 043, 036, 054, 063, 014, 004, 005,
9127c478bd9Sstevel@tonic-gate  *	010, 064, 077, 000, 035, 027, 025, 071,
9137c478bd9Sstevel@tonic-gate  * };
9147c478bd9Sstevel@tonic-gate  */
9157c478bd9Sstevel@tonic-gate 	= {    61, 57, 53, 49, 45, 41, 37, 33,
9167c478bd9Sstevel@tonic-gate 		29, 25, 21, 17, 13,  9,  5,  1,
9177c478bd9Sstevel@tonic-gate };
9187c478bd9Sstevel@tonic-gate 
9197c478bd9Sstevel@tonic-gate /* could consider to make it 32-bit int table to minimize memory usage */
9207c478bd9Sstevel@tonic-gate static const long hltab[64]
9217c478bd9Sstevel@tonic-gate 	= {
9227c478bd9Sstevel@tonic-gate 	06100151277L, 06106161736L, 06452611562L, 05001724107L,
9237c478bd9Sstevel@tonic-gate 	02614772546L, 04120731531L, 04665262210L, 07347467531L,
9247c478bd9Sstevel@tonic-gate 	06735253126L, 06042345173L, 03072226605L, 01464164730L,
9257c478bd9Sstevel@tonic-gate 	03247435524L, 07652510057L, 01546775256L, 05714532133L,
9267c478bd9Sstevel@tonic-gate 	06173260402L, 07517101630L, 02431460343L, 01743245566L,
9277c478bd9Sstevel@tonic-gate 	00261675137L, 02433103631L, 03421772437L, 04447707466L,
9287c478bd9Sstevel@tonic-gate 	04435620103L, 03757017115L, 03641531772L, 06767633246L,
9297c478bd9Sstevel@tonic-gate 	02673230344L, 00260612216L, 04133454451L, 00615531516L,
9307c478bd9Sstevel@tonic-gate 	06137717526L, 02574116560L, 02304023373L, 07061702261L,
9317c478bd9Sstevel@tonic-gate 	05153031405L, 05322056705L, 07401116734L, 06552375715L,
9327c478bd9Sstevel@tonic-gate 	06165233473L, 05311063631L, 01212221723L, 01052267235L,
9337c478bd9Sstevel@tonic-gate 	06000615237L, 01075222665L, 06330216006L, 04402355630L,
9347c478bd9Sstevel@tonic-gate 	01451177262L, 02000133436L, 06025467062L, 07121076461L,
9357c478bd9Sstevel@tonic-gate 	03123433522L, 01010635225L, 01716177066L, 05161746527L,
9367c478bd9Sstevel@tonic-gate 	01736635071L, 06243505026L, 03637211610L, 01756474365L,
9377c478bd9Sstevel@tonic-gate 	04723077174L, 03642763134L, 05750130273L, 03655541561L,
9387c478bd9Sstevel@tonic-gate };
9397c478bd9Sstevel@tonic-gate 
9407c478bd9Sstevel@tonic-gate static unsigned long
dcalchash(datum item)9417c478bd9Sstevel@tonic-gate dcalchash(datum item)
9427c478bd9Sstevel@tonic-gate {
9437c478bd9Sstevel@tonic-gate 	long s;
9447c478bd9Sstevel@tonic-gate 	int c, j;
9457c478bd9Sstevel@tonic-gate 	char *cp;
9467c478bd9Sstevel@tonic-gate 	unsigned long hashl;
9477c478bd9Sstevel@tonic-gate 	long hashi;
9487c478bd9Sstevel@tonic-gate 
9497c478bd9Sstevel@tonic-gate 	hashl = 0;
9507c478bd9Sstevel@tonic-gate 	hashi = 0;
9517c478bd9Sstevel@tonic-gate 	for (cp = item.dptr, s = item.dsize; --s >= 0; ) {
9527c478bd9Sstevel@tonic-gate 		c = *cp++;
9537c478bd9Sstevel@tonic-gate 		for (j = 0; j < BYTESIZ; j += 4) {
9547c478bd9Sstevel@tonic-gate 			hashi += hitab[c&017];
9557c478bd9Sstevel@tonic-gate 			hashl += hltab[hashi&63];
9567c478bd9Sstevel@tonic-gate 			c >>= 4;
9577c478bd9Sstevel@tonic-gate 		}
9587c478bd9Sstevel@tonic-gate 	}
9597c478bd9Sstevel@tonic-gate 	return (hashl);
9607c478bd9Sstevel@tonic-gate }
9617c478bd9Sstevel@tonic-gate 
9627c478bd9Sstevel@tonic-gate /*
9637c478bd9Sstevel@tonic-gate  * Delete pairs of items (n & n+1).
9647c478bd9Sstevel@tonic-gate  */
9657c478bd9Sstevel@tonic-gate static int
delitem(char * buf,int n)9662829495dSToomas Soome delitem(char *buf, int n)
9677c478bd9Sstevel@tonic-gate {
9687c478bd9Sstevel@tonic-gate 	short *sp, *sp1;
9697c478bd9Sstevel@tonic-gate 	int i1, i2;
9707c478bd9Sstevel@tonic-gate 
9717c478bd9Sstevel@tonic-gate 	sp = (short *)(uintptr_t)buf;
9727c478bd9Sstevel@tonic-gate 	i2 = sp[0];
9737c478bd9Sstevel@tonic-gate 	if ((unsigned)n >= i2 || (n & 1))
9747c478bd9Sstevel@tonic-gate 		return (0);
9757c478bd9Sstevel@tonic-gate 	if (n == i2-2) {
9767c478bd9Sstevel@tonic-gate 		sp[0] -= 2;
9777c478bd9Sstevel@tonic-gate 		return (1);
9787c478bd9Sstevel@tonic-gate 	}
9797c478bd9Sstevel@tonic-gate 	i1 = PBLKSIZ;
9807c478bd9Sstevel@tonic-gate 	if (n > 0)
9817c478bd9Sstevel@tonic-gate 		i1 = sp[n];
9827c478bd9Sstevel@tonic-gate 	i1 -= sp[n+2];
9837c478bd9Sstevel@tonic-gate 	if (i1 > 0) {
9847c478bd9Sstevel@tonic-gate 		i2 = sp[i2];
9857c478bd9Sstevel@tonic-gate 		(void) memmove(&buf[i2 + i1], &buf[i2], sp[n+2] - i2);
9867c478bd9Sstevel@tonic-gate 	}
9877c478bd9Sstevel@tonic-gate 	sp[0] -= 2;
9887c478bd9Sstevel@tonic-gate 	for (sp1 = sp + sp[0], sp += n+1; sp <= sp1; sp++)
9897c478bd9Sstevel@tonic-gate 		sp[0] = sp[2] + i1;
9907c478bd9Sstevel@tonic-gate 	return (1);
9917c478bd9Sstevel@tonic-gate }
9927c478bd9Sstevel@tonic-gate 
9937c478bd9Sstevel@tonic-gate /*
9947c478bd9Sstevel@tonic-gate  * Add pairs of items (item & item1).
9957c478bd9Sstevel@tonic-gate  */
9967c478bd9Sstevel@tonic-gate static int
additem(char * buf,datum item,datum item1)9972829495dSToomas Soome additem(char *buf, datum item, datum item1)
9987c478bd9Sstevel@tonic-gate {
9997c478bd9Sstevel@tonic-gate 	short *sp;
10007c478bd9Sstevel@tonic-gate 	int i1, i2;
10017c478bd9Sstevel@tonic-gate 
10027c478bd9Sstevel@tonic-gate 	sp = (short *)(uintptr_t)buf;
10037c478bd9Sstevel@tonic-gate 	i1 = PBLKSIZ;
10047c478bd9Sstevel@tonic-gate 	i2 = sp[0];
10057c478bd9Sstevel@tonic-gate 	if (i2 > 0)
10067c478bd9Sstevel@tonic-gate 		i1 = sp[i2];
10077c478bd9Sstevel@tonic-gate 	i1 -= item.dsize + item1.dsize;
10087c478bd9Sstevel@tonic-gate 	if (i1 <= (i2+3) * (int)sizeof (short))
10097c478bd9Sstevel@tonic-gate 		return (0);
10107c478bd9Sstevel@tonic-gate 	sp[0] += 2;
10117c478bd9Sstevel@tonic-gate 	sp[++i2] = (short)(i1 + item1.dsize);
10127c478bd9Sstevel@tonic-gate 	(void) memmove(&buf[i1 + item1.dsize], item.dptr, item.dsize);
10137c478bd9Sstevel@tonic-gate 	sp[++i2] = i1;
10147c478bd9Sstevel@tonic-gate 	(void) memmove(&buf[i1], item1.dptr, item1.dsize);
10157c478bd9Sstevel@tonic-gate 	return (1);
10167c478bd9Sstevel@tonic-gate }
10177c478bd9Sstevel@tonic-gate 
1018*18c77f76SBill Sommerfeld #ifdef NDBM_DEBUG
10197c478bd9Sstevel@tonic-gate static int
chkblk(char buf[PBLKSIZ])10207c478bd9Sstevel@tonic-gate chkblk(char buf[PBLKSIZ])
10217c478bd9Sstevel@tonic-gate {
10227c478bd9Sstevel@tonic-gate 	short *sp;
10237c478bd9Sstevel@tonic-gate 	int t, i;
10247c478bd9Sstevel@tonic-gate 
10257c478bd9Sstevel@tonic-gate 	sp = (short *)buf;
10267c478bd9Sstevel@tonic-gate 	t = PBLKSIZ;
10277c478bd9Sstevel@tonic-gate 	for (i = 0; i < sp[0]; i++) {
10287c478bd9Sstevel@tonic-gate 		if (sp[i + 1] > t)
10297c478bd9Sstevel@tonic-gate 			return (-1);
10307c478bd9Sstevel@tonic-gate 		t = sp[i + 1];
10317c478bd9Sstevel@tonic-gate 	}
10327c478bd9Sstevel@tonic-gate 	if (t < (sp[0] + 1) * sizeof (short))
10337c478bd9Sstevel@tonic-gate 		return (-1);
10347c478bd9Sstevel@tonic-gate 	return (0);
10357c478bd9Sstevel@tonic-gate }
10367c478bd9Sstevel@tonic-gate #endif
1037