xref: /onnv-gate/usr/src/lib/libnsl/yp/dbm.c (revision 1219:f89f56c2d9ac)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
22132Srobinson 
230Sstevel@tonic-gate /*
24*1219Sraf  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
250Sstevel@tonic-gate  * Use is subject to license terms.
260Sstevel@tonic-gate  */
270Sstevel@tonic-gate 
280Sstevel@tonic-gate /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
290Sstevel@tonic-gate /*	  All Rights Reserved   */
300Sstevel@tonic-gate 
310Sstevel@tonic-gate /*
320Sstevel@tonic-gate  * Portions of this source code were derived from Berkeley
330Sstevel@tonic-gate  * under license from the Regents of the University of
340Sstevel@tonic-gate  * California.
350Sstevel@tonic-gate  */
360Sstevel@tonic-gate 
370Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
380Sstevel@tonic-gate 
39*1219Sraf #include "mt.h"
400Sstevel@tonic-gate #include <rpcsvc/dbm.h>
410Sstevel@tonic-gate #include <sys/types.h>
420Sstevel@tonic-gate #include <sys/stat.h>
430Sstevel@tonic-gate #include <string.h>
440Sstevel@tonic-gate #include <unistd.h>
450Sstevel@tonic-gate #include <stdlib.h>
460Sstevel@tonic-gate #include <fcntl.h>
470Sstevel@tonic-gate #include <stdio.h>
480Sstevel@tonic-gate #include <errno.h>
490Sstevel@tonic-gate 
500Sstevel@tonic-gate void dbm_access(long);
510Sstevel@tonic-gate void delitem(char *, int);
520Sstevel@tonic-gate void chkblk(char *);
530Sstevel@tonic-gate int  additem(char *, datum);
540Sstevel@tonic-gate int  getbit(void);
550Sstevel@tonic-gate int  setbit(void);
560Sstevel@tonic-gate int  cmpdatum(datum, datum);
570Sstevel@tonic-gate 
580Sstevel@tonic-gate int
dbminit(char * file)59132Srobinson dbminit(char *file)
600Sstevel@tonic-gate {
610Sstevel@tonic-gate 	struct stat statb;
620Sstevel@tonic-gate 
630Sstevel@tonic-gate 	dbrdonly = 0;
640Sstevel@tonic-gate 	if (strlcpy(pagbuf, file, sizeof (pagbuf)) >= sizeof (pagbuf) ||
650Sstevel@tonic-gate 	    strlcat(pagbuf, ".pag", sizeof (pagbuf)) >= sizeof (pagbuf)) {
660Sstevel@tonic-gate 		/*
670Sstevel@tonic-gate 		 * file.pag does not fit into pagbuf.
680Sstevel@tonic-gate 		 * fails with ENAMETOOLONG.
690Sstevel@tonic-gate 		 */
700Sstevel@tonic-gate 		errno = ENAMETOOLONG;
710Sstevel@tonic-gate 		return (-1);
720Sstevel@tonic-gate 	}
730Sstevel@tonic-gate 	pagf = open(pagbuf, 2);
740Sstevel@tonic-gate 	if (pagf < 0) {
750Sstevel@tonic-gate 		pagf = open(pagbuf, 0);
760Sstevel@tonic-gate 		dbrdonly = 1;
770Sstevel@tonic-gate 	}
780Sstevel@tonic-gate 	/*
790Sstevel@tonic-gate 	 * We know this won't overflow so it is safe to ignore the
800Sstevel@tonic-gate 	 * return value; we use strl* to prevent false hits in
810Sstevel@tonic-gate 	 * code sweeps.
820Sstevel@tonic-gate 	 */
830Sstevel@tonic-gate 	(void) strlcpy(pagbuf, file, sizeof (pagbuf));
840Sstevel@tonic-gate 	(void) strlcat(pagbuf, ".dir", sizeof (pagbuf));
850Sstevel@tonic-gate 	dirf = open(pagbuf, 2);
860Sstevel@tonic-gate 	if (dirf < 0) {
870Sstevel@tonic-gate 		dirf = open(pagbuf, 0);
880Sstevel@tonic-gate 		dbrdonly = 1;
890Sstevel@tonic-gate 	}
90132Srobinson 	if (pagf < 0 || dirf < 0)
910Sstevel@tonic-gate 		return (-1);
92*1219Sraf 	(void) fstat(dirf, &statb);
930Sstevel@tonic-gate 	maxbno = statb.st_size*BYTESIZ-1;
940Sstevel@tonic-gate 	return (0);
950Sstevel@tonic-gate }
960Sstevel@tonic-gate 
970Sstevel@tonic-gate static long oldb1 = -1;
980Sstevel@tonic-gate static long oldb2 = -1;
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate /* Avoid using cached data for subsequent accesses. */
1010Sstevel@tonic-gate int
dbmflush(void)102132Srobinson dbmflush(void)
1030Sstevel@tonic-gate {
1040Sstevel@tonic-gate 	oldb1 = -1;
1050Sstevel@tonic-gate 	oldb2 = -1;
1060Sstevel@tonic-gate 	return (0);
1070Sstevel@tonic-gate }
1080Sstevel@tonic-gate 
1090Sstevel@tonic-gate /* Clean up after ourself. */
1100Sstevel@tonic-gate int
dbmclose(void)111132Srobinson dbmclose(void)
1120Sstevel@tonic-gate {
1130Sstevel@tonic-gate 	(void) close(pagf);
1140Sstevel@tonic-gate 	(void) close(dirf);
1150Sstevel@tonic-gate 	bitno = 0;
1160Sstevel@tonic-gate 	maxbno = 0;
1170Sstevel@tonic-gate 	blkno = 0;
1180Sstevel@tonic-gate 	hmask = 0;
1190Sstevel@tonic-gate 	oldb1 = -1;
1200Sstevel@tonic-gate 	oldb2 = -1;
1210Sstevel@tonic-gate 	return (0);
1220Sstevel@tonic-gate }
1230Sstevel@tonic-gate 
1240Sstevel@tonic-gate long
forder(datum key)125132Srobinson forder(datum key)
1260Sstevel@tonic-gate {
1270Sstevel@tonic-gate 	long hash;
1280Sstevel@tonic-gate 
1290Sstevel@tonic-gate 	hash = calchash(key);
1300Sstevel@tonic-gate 	for (hmask = 0; ; hmask = (hmask<<1) + 1) {
1310Sstevel@tonic-gate 		blkno = hash & hmask;
1320Sstevel@tonic-gate 		bitno = blkno + hmask;
1330Sstevel@tonic-gate 		if (getbit() == 0)
1340Sstevel@tonic-gate 			break;
1350Sstevel@tonic-gate 	}
1360Sstevel@tonic-gate 	return (blkno);
1370Sstevel@tonic-gate }
1380Sstevel@tonic-gate 
1390Sstevel@tonic-gate datum
fetch(datum key)140132Srobinson fetch(datum key)
1410Sstevel@tonic-gate {
1420Sstevel@tonic-gate 	int i;
1430Sstevel@tonic-gate 	datum item;
1440Sstevel@tonic-gate 
1450Sstevel@tonic-gate 	dbm_access(calchash(key));
1460Sstevel@tonic-gate 	for (i = 0; ; i += 2) {
1470Sstevel@tonic-gate 		item = makdatum(pagbuf, i);
1480Sstevel@tonic-gate 		if (item.dptr == NULL) {
1490Sstevel@tonic-gate 			return (item);
1500Sstevel@tonic-gate 		}
1510Sstevel@tonic-gate 		if (cmpdatum(key, item) == 0) {
1520Sstevel@tonic-gate 			item = makdatum(pagbuf, i+1);
1530Sstevel@tonic-gate 			if (item.dptr == NULL)
1540Sstevel@tonic-gate 				(void) printf("items not in pairs\n");
1550Sstevel@tonic-gate 			return (item);
1560Sstevel@tonic-gate 		}
1570Sstevel@tonic-gate 	}
1580Sstevel@tonic-gate }
1590Sstevel@tonic-gate 
1600Sstevel@tonic-gate int
delete(datum key)161132Srobinson delete(datum key)
1620Sstevel@tonic-gate {
1630Sstevel@tonic-gate 	int i;
1640Sstevel@tonic-gate 	datum item;
1650Sstevel@tonic-gate 
166132Srobinson 	if (dbrdonly)
1670Sstevel@tonic-gate 		return (-1);
1680Sstevel@tonic-gate 	dbm_access(calchash(key));
1690Sstevel@tonic-gate 	for (i = 0; ; i += 2) {
1700Sstevel@tonic-gate 		item = makdatum(pagbuf, i);
171132Srobinson 		if (item.dptr == NULL)
1720Sstevel@tonic-gate 			return (-1);
1730Sstevel@tonic-gate 		if (cmpdatum(key, item) == 0) {
1740Sstevel@tonic-gate 			delitem(pagbuf, i);
1750Sstevel@tonic-gate 			delitem(pagbuf, i);
1760Sstevel@tonic-gate 			break;
1770Sstevel@tonic-gate 		}
1780Sstevel@tonic-gate 	}
1790Sstevel@tonic-gate 	(void) lseek(pagf, blkno*PBLKSIZ, 0);
1800Sstevel@tonic-gate 	(void) write(pagf, pagbuf, PBLKSIZ);
1810Sstevel@tonic-gate 	return (0);
1820Sstevel@tonic-gate }
1830Sstevel@tonic-gate 
1840Sstevel@tonic-gate int
store(datum key,datum dat)185132Srobinson store(datum key, datum dat)
1860Sstevel@tonic-gate {
1870Sstevel@tonic-gate 	int i;
1880Sstevel@tonic-gate 	datum item;
1890Sstevel@tonic-gate 	char ovfbuf[PBLKSIZ];
1900Sstevel@tonic-gate 
191132Srobinson 	if (dbrdonly)
1920Sstevel@tonic-gate 		return (-1);
1930Sstevel@tonic-gate loop:
1940Sstevel@tonic-gate 	dbm_access(calchash(key));
1950Sstevel@tonic-gate 	for (i = 0; ; i += 2) {
1960Sstevel@tonic-gate 		item = makdatum(pagbuf, i);
1970Sstevel@tonic-gate 		if (item.dptr == NULL)
1980Sstevel@tonic-gate 			break;
1990Sstevel@tonic-gate 		if (cmpdatum(key, item) == 0) {
2000Sstevel@tonic-gate 			delitem(pagbuf, i);
2010Sstevel@tonic-gate 			delitem(pagbuf, i);
2020Sstevel@tonic-gate 			break;
2030Sstevel@tonic-gate 		}
2040Sstevel@tonic-gate 	}
2050Sstevel@tonic-gate 	i = additem(pagbuf, key);
2060Sstevel@tonic-gate 	if (i < 0)
2070Sstevel@tonic-gate 		goto split;
2080Sstevel@tonic-gate 	if (additem(pagbuf, dat) < 0) {
2090Sstevel@tonic-gate 		delitem(pagbuf, i);
2100Sstevel@tonic-gate 		goto split;
2110Sstevel@tonic-gate 	}
2120Sstevel@tonic-gate 	(void) lseek(pagf, blkno*PBLKSIZ, 0);
2130Sstevel@tonic-gate 	(void) write(pagf, pagbuf, PBLKSIZ);
2140Sstevel@tonic-gate 	return (0);
2150Sstevel@tonic-gate 
2160Sstevel@tonic-gate split:
2170Sstevel@tonic-gate 	if (key.dsize + dat.dsize + 3 * sizeof (short) >= PBLKSIZ) {
2180Sstevel@tonic-gate 		(void) printf("entry too big\n");
2190Sstevel@tonic-gate 		return (-1);
2200Sstevel@tonic-gate 	}
221132Srobinson 	(void) memset(&ovfbuf, 0, PBLKSIZ);
2220Sstevel@tonic-gate 	for (i = 0; ; ) {
2230Sstevel@tonic-gate 		item = makdatum(pagbuf, i);
2240Sstevel@tonic-gate 		if (item.dptr == NULL)
2250Sstevel@tonic-gate 			break;
2260Sstevel@tonic-gate 		if (calchash(item) & (hmask+1)) {
2270Sstevel@tonic-gate 			(void) additem(ovfbuf, item);
2280Sstevel@tonic-gate 			delitem(pagbuf, i);
2290Sstevel@tonic-gate 			item = makdatum(pagbuf, i);
2300Sstevel@tonic-gate 			if (item.dptr == NULL) {
2310Sstevel@tonic-gate 				(void) printf("split not paired\n");
2320Sstevel@tonic-gate 				break;
2330Sstevel@tonic-gate 			}
2340Sstevel@tonic-gate 			(void) additem(ovfbuf, item);
2350Sstevel@tonic-gate 			delitem(pagbuf, i);
2360Sstevel@tonic-gate 			continue;
2370Sstevel@tonic-gate 		}
2380Sstevel@tonic-gate 		i += 2;
2390Sstevel@tonic-gate 	}
2400Sstevel@tonic-gate 	(void) lseek(pagf, blkno*PBLKSIZ, 0);
2410Sstevel@tonic-gate 	if (write(pagf, pagbuf, PBLKSIZ) < 0) {
2420Sstevel@tonic-gate 		return (-1);
2430Sstevel@tonic-gate 	}
2440Sstevel@tonic-gate 	(void) lseek(pagf, (blkno+hmask+1)*PBLKSIZ, 0);
2450Sstevel@tonic-gate 	if (write(pagf, ovfbuf, PBLKSIZ) < 0) {
2460Sstevel@tonic-gate 		return (-1);
2470Sstevel@tonic-gate 	}
2480Sstevel@tonic-gate 	if (setbit() < 0) {
2490Sstevel@tonic-gate 		return (-1);
2500Sstevel@tonic-gate 	}
2510Sstevel@tonic-gate 	goto loop;
2520Sstevel@tonic-gate }
2530Sstevel@tonic-gate 
2540Sstevel@tonic-gate datum
firstkey(void)255132Srobinson firstkey(void)
2560Sstevel@tonic-gate {
257132Srobinson 	return (firsthash(0L));
2580Sstevel@tonic-gate }
2590Sstevel@tonic-gate 
2600Sstevel@tonic-gate datum
nextkey(datum key)261132Srobinson nextkey(datum key)
2620Sstevel@tonic-gate {
2630Sstevel@tonic-gate 	int i;
2640Sstevel@tonic-gate 	datum item, bitem;
2650Sstevel@tonic-gate 	long hash;
2660Sstevel@tonic-gate 	int f;
2670Sstevel@tonic-gate 
2680Sstevel@tonic-gate #ifdef lint
2690Sstevel@tonic-gate 	bitem.dptr = NULL;
2700Sstevel@tonic-gate 	bitem.dsize = 0;
2710Sstevel@tonic-gate #endif /* lint */
2720Sstevel@tonic-gate 	hash = calchash(key);
2730Sstevel@tonic-gate 	dbm_access(hash);
2740Sstevel@tonic-gate 	f = 1;
2750Sstevel@tonic-gate 	for (i = 0; ; i += 2) {
2760Sstevel@tonic-gate 		item = makdatum(pagbuf, i);
2770Sstevel@tonic-gate 		if (item.dptr == NULL)
2780Sstevel@tonic-gate 			break;
2790Sstevel@tonic-gate 		if (cmpdatum(key, item) <= 0)
2800Sstevel@tonic-gate 			continue;
2810Sstevel@tonic-gate 		if (f || cmpdatum(bitem, item) < 0) {
2820Sstevel@tonic-gate 			bitem = item;
2830Sstevel@tonic-gate 			f = 0;
2840Sstevel@tonic-gate 		}
2850Sstevel@tonic-gate 	}
286132Srobinson 	if (f == 0)
2870Sstevel@tonic-gate 		return (bitem);
2880Sstevel@tonic-gate 	hash = hashinc(hash);
289132Srobinson 	if (hash == 0)
2900Sstevel@tonic-gate 		return (item);
291132Srobinson 	return (firsthash(hash));
2920Sstevel@tonic-gate }
2930Sstevel@tonic-gate 
2940Sstevel@tonic-gate datum
firsthash(long hash)295132Srobinson firsthash(long hash)
2960Sstevel@tonic-gate {
2970Sstevel@tonic-gate 	int i;
2980Sstevel@tonic-gate 	datum item, bitem;
2990Sstevel@tonic-gate 
3000Sstevel@tonic-gate loop:
3010Sstevel@tonic-gate 	dbm_access(hash);
3020Sstevel@tonic-gate 	bitem = makdatum(pagbuf, 0);
3030Sstevel@tonic-gate 	for (i = 2; ; i += 2) {
3040Sstevel@tonic-gate 		item = makdatum(pagbuf, i);
3050Sstevel@tonic-gate 		if (item.dptr == NULL)
3060Sstevel@tonic-gate 			break;
3070Sstevel@tonic-gate 		if (cmpdatum(bitem, item) < 0)
3080Sstevel@tonic-gate 			bitem = item;
3090Sstevel@tonic-gate 	}
310132Srobinson 	if (bitem.dptr != NULL)
3110Sstevel@tonic-gate 		return (bitem);
3120Sstevel@tonic-gate 	hash = hashinc(hash);
313132Srobinson 	if (hash == 0)
3140Sstevel@tonic-gate 		return (item);
3150Sstevel@tonic-gate 	goto loop;
3160Sstevel@tonic-gate }
3170Sstevel@tonic-gate 
3180Sstevel@tonic-gate void
dbm_access(long hash)319132Srobinson dbm_access(long hash)
3200Sstevel@tonic-gate {
3210Sstevel@tonic-gate 	ssize_t readsize;
3220Sstevel@tonic-gate 
3230Sstevel@tonic-gate 	for (hmask = 0; ; hmask = (hmask<<1) + 1) {
3240Sstevel@tonic-gate 		blkno = hash & hmask;
3250Sstevel@tonic-gate 		bitno = blkno + hmask;
3260Sstevel@tonic-gate 		if (getbit() == 0)
3270Sstevel@tonic-gate 			break;
3280Sstevel@tonic-gate 	}
3290Sstevel@tonic-gate 	if (blkno != oldb1) {
3300Sstevel@tonic-gate 		(void) lseek(pagf, blkno*PBLKSIZ, 0);
3310Sstevel@tonic-gate 		readsize = read(pagf, pagbuf, PBLKSIZ);
3320Sstevel@tonic-gate 		if (readsize != PBLKSIZ) {
333132Srobinson 			if (readsize < 0)
334132Srobinson 				readsize = 0;
335132Srobinson 			(void) memset((&pagbuf+readsize), 0, PBLKSIZ-readsize);
3360Sstevel@tonic-gate 		}
3370Sstevel@tonic-gate 		chkblk(pagbuf);
3380Sstevel@tonic-gate 		oldb1 = blkno;
3390Sstevel@tonic-gate 	}
3400Sstevel@tonic-gate }
3410Sstevel@tonic-gate 
3420Sstevel@tonic-gate int
getbit(void)3430Sstevel@tonic-gate getbit(void)
3440Sstevel@tonic-gate {
3450Sstevel@tonic-gate 	long bn;
3460Sstevel@tonic-gate 	ssize_t readsize;
3470Sstevel@tonic-gate 	long b, i, n;
3480Sstevel@tonic-gate 
349132Srobinson 	if (bitno > maxbno)
3500Sstevel@tonic-gate 		return (0);
3510Sstevel@tonic-gate 	n = bitno % BYTESIZ;
3520Sstevel@tonic-gate 	bn = bitno / BYTESIZ;
3530Sstevel@tonic-gate 	i = bn % DBLKSIZ;
3540Sstevel@tonic-gate 	b = bn / DBLKSIZ;
3550Sstevel@tonic-gate 	if (b != oldb2) {
3560Sstevel@tonic-gate 		(void) lseek(dirf, (long)b*DBLKSIZ, 0);
3570Sstevel@tonic-gate 		readsize = read(dirf, dirbuf, DBLKSIZ);
3580Sstevel@tonic-gate 		if (readsize != DBLKSIZ) {
359132Srobinson 			if (readsize < 0)
360132Srobinson 				readsize = 0;
361132Srobinson 			(void) memset(&dirbuf+readsize, 0, DBLKSIZ-readsize);
3620Sstevel@tonic-gate 		}
3630Sstevel@tonic-gate 		oldb2 = b;
3640Sstevel@tonic-gate 	}
365132Srobinson 	if (dirbuf[i] & (1<<n))
3660Sstevel@tonic-gate 		return (1);
3670Sstevel@tonic-gate 	return (0);
3680Sstevel@tonic-gate }
3690Sstevel@tonic-gate 
3700Sstevel@tonic-gate int
setbit(void)3710Sstevel@tonic-gate setbit(void)
3720Sstevel@tonic-gate {
3730Sstevel@tonic-gate 	long bn;
3740Sstevel@tonic-gate 	long i, n, b;
3750Sstevel@tonic-gate 
376132Srobinson 	if (dbrdonly)
3770Sstevel@tonic-gate 		return (-1);
3780Sstevel@tonic-gate 	if (bitno > maxbno) {
3790Sstevel@tonic-gate 		maxbno = bitno;
3800Sstevel@tonic-gate 		(void) getbit();
3810Sstevel@tonic-gate 	}
3820Sstevel@tonic-gate 	n = bitno % BYTESIZ;
3830Sstevel@tonic-gate 	bn = bitno / BYTESIZ;
3840Sstevel@tonic-gate 	i = bn % DBLKSIZ;
3850Sstevel@tonic-gate 	b = bn / DBLKSIZ;
3860Sstevel@tonic-gate 	dirbuf[i] |= 1<<n;
3870Sstevel@tonic-gate 	(void) lseek(dirf, (long)b*DBLKSIZ, 0);
388132Srobinson 	if (write(dirf, dirbuf, DBLKSIZ) < 0)
3890Sstevel@tonic-gate 		return (-1);
3900Sstevel@tonic-gate 	return (0);
3910Sstevel@tonic-gate }
3920Sstevel@tonic-gate 
3930Sstevel@tonic-gate datum
makdatum(char buf[PBLKSIZ],int n)3940Sstevel@tonic-gate makdatum(char buf[PBLKSIZ], int n)
3950Sstevel@tonic-gate {
3960Sstevel@tonic-gate 	short *sp;
3970Sstevel@tonic-gate 	int t;
3980Sstevel@tonic-gate 	datum item;
3990Sstevel@tonic-gate 
400132Srobinson 	/* LINTED pointer cast */
4010Sstevel@tonic-gate 	sp = (short *)buf;
4020Sstevel@tonic-gate 	if (n < 0 || n >= sp[0])
4030Sstevel@tonic-gate 		goto null;
4040Sstevel@tonic-gate 	t = PBLKSIZ;
4050Sstevel@tonic-gate 	if (n > 0)
4060Sstevel@tonic-gate 		t = sp[n+1-1];
4070Sstevel@tonic-gate 	item.dptr = buf+sp[n+1];
4080Sstevel@tonic-gate 	item.dsize = t - sp[n+1];
4090Sstevel@tonic-gate 	return (item);
4100Sstevel@tonic-gate 
4110Sstevel@tonic-gate null:
4120Sstevel@tonic-gate 	item.dptr = NULL;
4130Sstevel@tonic-gate 	item.dsize = 0;
4140Sstevel@tonic-gate 	return (item);
4150Sstevel@tonic-gate }
4160Sstevel@tonic-gate 
4170Sstevel@tonic-gate int
cmpdatum(datum d1,datum d2)418132Srobinson cmpdatum(datum d1, datum d2)
4190Sstevel@tonic-gate {
4200Sstevel@tonic-gate 	int n;
4210Sstevel@tonic-gate 	char *p1, *p2;
4220Sstevel@tonic-gate 
4230Sstevel@tonic-gate 	n = d1.dsize;
424132Srobinson 	if (n != d2.dsize)
4250Sstevel@tonic-gate 		return (n - d2.dsize);
426132Srobinson 	if (n == 0)
4270Sstevel@tonic-gate 		return (0);
4280Sstevel@tonic-gate 	p1 = d1.dptr;
4290Sstevel@tonic-gate 	p2 = d2.dptr;
4300Sstevel@tonic-gate 	do
431132Srobinson 		if (*p1++ != *p2++)
4320Sstevel@tonic-gate 			return (*--p1 - *--p2);
4330Sstevel@tonic-gate 	while (--n);
4340Sstevel@tonic-gate 	return (0);
4350Sstevel@tonic-gate }
4360Sstevel@tonic-gate 
4370Sstevel@tonic-gate int	hitab[16]
4380Sstevel@tonic-gate /*
4390Sstevel@tonic-gate  * ken's
4400Sstevel@tonic-gate  * {
4410Sstevel@tonic-gate  *	055, 043, 036, 054, 063, 014, 004, 005,
4420Sstevel@tonic-gate  *	010, 064, 077, 000, 035, 027, 025, 071,
4430Sstevel@tonic-gate  * };
4440Sstevel@tonic-gate  */
4450Sstevel@tonic-gate 	= {	61, 57, 53, 49, 45, 41, 37, 33,
4460Sstevel@tonic-gate 	29, 25, 21, 17, 13,  9,  5,  1,
4470Sstevel@tonic-gate };
4480Sstevel@tonic-gate long	hltab[64]
4490Sstevel@tonic-gate 	= {
4500Sstevel@tonic-gate 	06100151277L, 06106161736L, 06452611562L, 05001724107L,
4510Sstevel@tonic-gate 	02614772546L, 04120731531L, 04665262210L, 07347467531L,
4520Sstevel@tonic-gate 	06735253126L, 06042345173L, 03072226605L, 01464164730L,
4530Sstevel@tonic-gate 	03247435524L, 07652510057L, 01546775256L, 05714532133L,
4540Sstevel@tonic-gate 	06173260402L, 07517101630L, 02431460343L, 01743245566L,
4550Sstevel@tonic-gate 	00261675137L, 02433103631L, 03421772437L, 04447707466L,
4560Sstevel@tonic-gate 	04435620103L, 03757017115L, 03641531772L, 06767633246L,
4570Sstevel@tonic-gate 	02673230344L, 00260612216L, 04133454451L, 00615531516L,
4580Sstevel@tonic-gate 	06137717526L, 02574116560L, 02304023373L, 07061702261L,
4590Sstevel@tonic-gate 	05153031405L, 05322056705L, 07401116734L, 06552375715L,
4600Sstevel@tonic-gate 	06165233473L, 05311063631L, 01212221723L, 01052267235L,
4610Sstevel@tonic-gate 	06000615237L, 01075222665L, 06330216006L, 04402355630L,
4620Sstevel@tonic-gate 	01451177262L, 02000133436L, 06025467062L, 07121076461L,
4630Sstevel@tonic-gate 	03123433522L, 01010635225L, 01716177066L, 05161746527L,
4640Sstevel@tonic-gate 	01736635071L, 06243505026L, 03637211610L, 01756474365L,
4650Sstevel@tonic-gate 	04723077174L, 03642763134L, 05750130273L, 03655541561L,
4660Sstevel@tonic-gate };
4670Sstevel@tonic-gate 
4680Sstevel@tonic-gate long
hashinc(long hash)469132Srobinson hashinc(long hash)
4700Sstevel@tonic-gate {
4710Sstevel@tonic-gate 	long bit;
4720Sstevel@tonic-gate 
4730Sstevel@tonic-gate 	hash &= hmask;
4740Sstevel@tonic-gate 	bit = hmask+1;
4750Sstevel@tonic-gate 	for (; ; ) {
4760Sstevel@tonic-gate 		bit >>= 1;
477132Srobinson 		if (bit == 0)
4780Sstevel@tonic-gate 			return (0L);
479132Srobinson 		if ((hash&bit) == 0)
4800Sstevel@tonic-gate 			return (hash|bit);
4810Sstevel@tonic-gate 		hash &= ~bit;
4820Sstevel@tonic-gate 	}
4830Sstevel@tonic-gate }
4840Sstevel@tonic-gate 
4850Sstevel@tonic-gate long
calchash(datum item)486132Srobinson calchash(datum item)
4870Sstevel@tonic-gate {
4880Sstevel@tonic-gate 	int i, j, f;
4890Sstevel@tonic-gate 	long hashl;
4900Sstevel@tonic-gate 	int hashi;
4910Sstevel@tonic-gate 
4920Sstevel@tonic-gate 	hashl = 0;
4930Sstevel@tonic-gate 	hashi = 0;
4940Sstevel@tonic-gate 	for (i = 0; i < item.dsize; i++) {
4950Sstevel@tonic-gate 		f = item.dptr[i];
4960Sstevel@tonic-gate 		for (j = 0; j < BYTESIZ; j += 4) {
4970Sstevel@tonic-gate 			hashi += hitab[f&017];
4980Sstevel@tonic-gate 			hashl += hltab[hashi&63];
4990Sstevel@tonic-gate 			f >>= 4;
5000Sstevel@tonic-gate 		}
5010Sstevel@tonic-gate 	}
5020Sstevel@tonic-gate 	return (hashl);
5030Sstevel@tonic-gate }
5040Sstevel@tonic-gate 
5050Sstevel@tonic-gate void
delitem(char buf[PBLKSIZ],int n)506132Srobinson delitem(char buf[PBLKSIZ], int n)
5070Sstevel@tonic-gate {
5080Sstevel@tonic-gate 	short *sp;
5090Sstevel@tonic-gate 	int i1, i2, i3;
5100Sstevel@tonic-gate 
511132Srobinson 	/* LINTED pointer cast */
5120Sstevel@tonic-gate 	sp = (short *)buf;
5130Sstevel@tonic-gate 	if (n < 0 || n >= sp[0])
5140Sstevel@tonic-gate 		goto bad;
5150Sstevel@tonic-gate 	i1 = sp[n+1];
5160Sstevel@tonic-gate 	i2 = PBLKSIZ;
5170Sstevel@tonic-gate 	if (n > 0)
5180Sstevel@tonic-gate 		i2 = sp[n+1-1];
5190Sstevel@tonic-gate 	i3 = sp[sp[0]+1-1];
5200Sstevel@tonic-gate 	if (i2 > i1)
5210Sstevel@tonic-gate 	while (i1 > i3) {
5220Sstevel@tonic-gate 		i1--;
5230Sstevel@tonic-gate 		i2--;
5240Sstevel@tonic-gate 		buf[i2] = buf[i1];
5250Sstevel@tonic-gate 		buf[i1] = 0;
5260Sstevel@tonic-gate 	}
5270Sstevel@tonic-gate 	i2 -= i1;
5280Sstevel@tonic-gate 	for (i1 = n + 1; i1 < sp[0]; i1++)
5290Sstevel@tonic-gate 		sp[i1+1-1] = sp[i1+1] + i2;
5300Sstevel@tonic-gate 	sp[0]--;
5310Sstevel@tonic-gate 	sp[sp[0]+1] = 0;
5320Sstevel@tonic-gate 	return;
5330Sstevel@tonic-gate 
5340Sstevel@tonic-gate bad:
5350Sstevel@tonic-gate 	(void) printf("bad delitem\n");
5360Sstevel@tonic-gate 	abort();
5370Sstevel@tonic-gate }
5380Sstevel@tonic-gate 
5390Sstevel@tonic-gate int
additem(char buf[PBLKSIZ],datum item)540132Srobinson additem(char buf[PBLKSIZ], datum item)
5410Sstevel@tonic-gate {
5420Sstevel@tonic-gate 	short *sp;
5430Sstevel@tonic-gate 	int i1, i2;
5440Sstevel@tonic-gate 
545132Srobinson 	/* LINTED pointer cast */
5460Sstevel@tonic-gate 	sp = (short *)buf;
5470Sstevel@tonic-gate 	i1 = PBLKSIZ;
5480Sstevel@tonic-gate 	if (sp[0] > 0)
5490Sstevel@tonic-gate 		i1 = sp[sp[0]+1-1];
5500Sstevel@tonic-gate 	i1 -= item.dsize;
5510Sstevel@tonic-gate 	i2 = (sp[0]+2) * (int)sizeof (short);
552132Srobinson 	if (i1 <= i2)
5530Sstevel@tonic-gate 		return (-1);
5540Sstevel@tonic-gate 	sp[sp[0]+1] = (short)i1;
5550Sstevel@tonic-gate 	for (i2 = 0; i2 < item.dsize; i2++) {
5560Sstevel@tonic-gate 		buf[i1] = item.dptr[i2];
5570Sstevel@tonic-gate 		i1++;
5580Sstevel@tonic-gate 	}
5590Sstevel@tonic-gate 	sp[0]++;
5600Sstevel@tonic-gate 	return (sp[0]-1);
5610Sstevel@tonic-gate }
5620Sstevel@tonic-gate 
5630Sstevel@tonic-gate void
chkblk(char buf[PBLKSIZ])564132Srobinson chkblk(char buf[PBLKSIZ])
5650Sstevel@tonic-gate {
5660Sstevel@tonic-gate 	short *sp;
5670Sstevel@tonic-gate 	int t, i;
5680Sstevel@tonic-gate 
569132Srobinson 	/* LINTED pointer cast */
5700Sstevel@tonic-gate 	sp = (short *)buf;
5710Sstevel@tonic-gate 	t = PBLKSIZ;
5720Sstevel@tonic-gate 	for (i = 0; i < sp[0]; i++) {
5730Sstevel@tonic-gate 		if (sp[i+1] > t)
5740Sstevel@tonic-gate 			goto bad;
5750Sstevel@tonic-gate 		t = sp[i+1];
5760Sstevel@tonic-gate 	}
5770Sstevel@tonic-gate 	if (t < (sp[0]+1) * sizeof (short))
5780Sstevel@tonic-gate 		goto bad;
5790Sstevel@tonic-gate 	return;
5800Sstevel@tonic-gate 
5810Sstevel@tonic-gate bad:
5820Sstevel@tonic-gate 	(void) printf("bad block\n");
5830Sstevel@tonic-gate 	abort();
584132Srobinson 	(void) memset(&buf, 0, PBLKSIZ);
5850Sstevel@tonic-gate }
586