security/nss/lib/dbm/src/h_page.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/nss/lib/dbm/src/h_page.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1286 @@
     1.4 +/*-
     1.5 + * Copyright (c) 1990, 1993, 1994
     1.6 + *	The Regents of the University of California.  All rights reserved.
     1.7 + *
     1.8 + * This code is derived from software contributed to Berkeley by
     1.9 + * Margo Seltzer.
    1.10 + *
    1.11 + * Redistribution and use in source and binary forms, with or without
    1.12 + * modification, are permitted provided that the following conditions
    1.13 + * are met:
    1.14 + * 1. Redistributions of source code must retain the above copyright
    1.15 + *    notice, this list of conditions and the following disclaimer.
    1.16 + * 2. Redistributions in binary form must reproduce the above copyright
    1.17 + *    notice, this list of conditions and the following disclaimer in the
    1.18 + *    documentation and/or other materials provided with the distribution.
    1.19 + * 3. ***REMOVED*** - see 
    1.20 + *    ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change
    1.21 + * 4. Neither the name of the University nor the names of its contributors
    1.22 + *    may be used to endorse or promote products derived from this software
    1.23 + *    without specific prior written permission.
    1.24 + *
    1.25 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
    1.26 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    1.27 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    1.28 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
    1.29 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    1.30 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    1.31 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    1.32 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    1.33 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    1.34 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    1.35 + * SUCH DAMAGE.
    1.36 + */
    1.37 +
    1.38 +#if defined(unix)
    1.39 +#define MY_LSEEK lseek
    1.40 +#else
    1.41 +#define MY_LSEEK new_lseek
    1.42 +extern long new_lseek(int fd, long pos, int start);
    1.43 +#endif
    1.44 +
    1.45 +#if defined(LIBC_SCCS) && !defined(lint)
    1.46 +static char sccsid[] = "@(#)hash_page.c	8.7 (Berkeley) 8/16/94";
    1.47 +#endif /* LIBC_SCCS and not lint */
    1.48 +
    1.49 +/*
    1.50 + * PACKAGE:  hashing
    1.51 + *
    1.52 + * DESCRIPTION:
    1.53 + *	Page manipulation for hashing package.
    1.54 + *
    1.55 + * ROUTINES:
    1.56 + *
    1.57 + * External
    1.58 + *	__get_page
    1.59 + *	__add_ovflpage
    1.60 + * Internal
    1.61 + *	overflow_page
    1.62 + *	open_temp
    1.63 + */
    1.64 +#ifndef macintosh
    1.65 +#include <sys/types.h>
    1.66 +#endif
    1.67 +
    1.68 +#if defined(macintosh)
    1.69 +#include <unistd.h>
    1.70 +#endif
    1.71 +
    1.72 +#include <errno.h>
    1.73 +#include <fcntl.h>
    1.74 +#if defined(_WIN32) || defined(_WINDOWS) 
    1.75 +#include <io.h>
    1.76 +#endif
    1.77 +#include <signal.h>
    1.78 +#include <stdio.h>
    1.79 +#include <stdlib.h>
    1.80 +#include <string.h>
    1.81 +
    1.82 +#if !defined(_WIN32) && !defined(_WINDOWS) && !defined(macintosh)
    1.83 +#include <unistd.h>
    1.84 +#endif
    1.85 +
    1.86 +#include <assert.h>
    1.87 +
    1.88 +#include "mcom_db.h"
    1.89 +#include "hash.h"
    1.90 +#include "page.h"
    1.91 +/* #include "extern.h" */
    1.92 +
    1.93 +extern int mkstempflags(char *path, int extraFlags);
    1.94 +
    1.95 +static uint32	*fetch_bitmap __P((HTAB *, uint32));
    1.96 +static uint32	 first_free __P((uint32));
    1.97 +static int	 open_temp __P((HTAB *));
    1.98 +static uint16	 overflow_page __P((HTAB *));
    1.99 +static void	 squeeze_key __P((uint16 *, const DBT *, const DBT *));
   1.100 +static int	 ugly_split
   1.101 +		    __P((HTAB *, uint32, BUFHEAD *, BUFHEAD *, int, int));
   1.102 +
   1.103 +#define	PAGE_INIT(P) { \
   1.104 +	((uint16 *)(P))[0] = 0; \
   1.105 +	((uint16 *)(P))[1] = hashp->BSIZE - 3 * sizeof(uint16); \
   1.106 +	((uint16 *)(P))[2] = hashp->BSIZE; \
   1.107 +}
   1.108 +
   1.109 +/* implement a new lseek using lseek that
   1.110 + * writes zero's when extending a file
   1.111 + * beyond the end.
   1.112 + */
   1.113 +long new_lseek(int fd, long offset, int origin)
   1.114 +{
   1.115 + 	long cur_pos=0;
   1.116 +	long end_pos=0;
   1.117 +	long seek_pos=0;
   1.118 +
   1.119 +	if(origin == SEEK_CUR)
   1.120 +      {	
   1.121 +      	if(offset < 1)							  
   1.122 +	    	return(lseek(fd, offset, SEEK_CUR));
   1.123 +
   1.124 +		cur_pos = lseek(fd, 0, SEEK_CUR);
   1.125 +
   1.126 +		if(cur_pos < 0)
   1.127 +			return(cur_pos);
   1.128 +	  }
   1.129 +										 
   1.130 +	end_pos = lseek(fd, 0, SEEK_END);
   1.131 +	if(end_pos < 0)
   1.132 +		return(end_pos);
   1.133 +
   1.134 +	if(origin == SEEK_SET)
   1.135 +		seek_pos = offset;
   1.136 +	else if(origin == SEEK_CUR)
   1.137 +		seek_pos = cur_pos + offset;
   1.138 +	else if(origin == SEEK_END)
   1.139 +		seek_pos = end_pos + offset;
   1.140 + 	else
   1.141 +	  {
   1.142 +	  	assert(0);
   1.143 +		return(-1);
   1.144 +	  }
   1.145 +
   1.146 + 	/* the seek position desired is before the
   1.147 +	 * end of the file.  We don't need
   1.148 +	 * to do anything special except the seek.
   1.149 +	 */
   1.150 + 	if(seek_pos <= end_pos)
   1.151 + 		return(lseek(fd, seek_pos, SEEK_SET));
   1.152 + 		
   1.153 + 	  /* the seek position is beyond the end of the
   1.154 + 	   * file.  Write zero's to the end.
   1.155 + 	   *
   1.156 +	   * we are already at the end of the file so
   1.157 +	   * we just need to "write()" zeros for the
   1.158 +	   * difference between seek_pos-end_pos and
   1.159 +	   * then seek to the position to finish
   1.160 +	   * the call
   1.161 + 	   */
   1.162 + 	  { 
   1.163 + 	 	char buffer[1024];
   1.164 +	   	long len = seek_pos-end_pos;
   1.165 +	   	memset(&buffer, 0, 1024);
   1.166 +	   	while(len > 0)
   1.167 +	      {
   1.168 +	        write(fd, (char*)&buffer, (size_t)(1024 > len ? len : 1024));
   1.169 +		    len -= 1024;
   1.170 +		  }
   1.171 +		return(lseek(fd, seek_pos, SEEK_SET));
   1.172 +	  }		
   1.173 +
   1.174 +}
   1.175 +
   1.176 +/*
   1.177 + * This is called AFTER we have verified that there is room on the page for
   1.178 + * the pair (PAIRFITS has returned true) so we go right ahead and start moving
   1.179 + * stuff on.
   1.180 + */
   1.181 +static void
   1.182 +putpair(char *p, const DBT *key, DBT * val)
   1.183 +{
   1.184 +	register uint16 *bp, n, off;
   1.185 +
   1.186 +	bp = (uint16 *)p;
   1.187 +
   1.188 +	/* Enter the key first. */
   1.189 +	n = bp[0];
   1.190 +
   1.191 +	off = OFFSET(bp) - key->size;
   1.192 +	memmove(p + off, key->data, key->size);
   1.193 +	bp[++n] = off;
   1.194 +
   1.195 +	/* Now the data. */
   1.196 +	off -= val->size;
   1.197 +	memmove(p + off, val->data, val->size);
   1.198 +	bp[++n] = off;
   1.199 +
   1.200 +	/* Adjust page info. */
   1.201 +	bp[0] = n;
   1.202 +	bp[n + 1] = off - ((n + 3) * sizeof(uint16));
   1.203 +	bp[n + 2] = off;
   1.204 +}
   1.205 +
   1.206 +/*
   1.207 + * Returns:
   1.208 + *	 0 OK
   1.209 + *	-1 error
   1.210 + */
   1.211 +extern int
   1.212 +__delpair(HTAB *hashp, BUFHEAD *bufp, int ndx)
   1.213 +{
   1.214 +	register uint16 *bp, newoff;
   1.215 +	register int n;
   1.216 +	uint16 pairlen;
   1.217 +
   1.218 +	bp = (uint16 *)bufp->page;
   1.219 +	n = bp[0];
   1.220 +
   1.221 +	if (bp[ndx + 1] < REAL_KEY)
   1.222 +		return (__big_delete(hashp, bufp));
   1.223 +	if (ndx != 1)
   1.224 +		newoff = bp[ndx - 1];
   1.225 +	else
   1.226 +		newoff = hashp->BSIZE;
   1.227 +	pairlen = newoff - bp[ndx + 1];
   1.228 +
   1.229 +	if (ndx != (n - 1)) {
   1.230 +		/* Hard Case -- need to shuffle keys */
   1.231 +		register int i;
   1.232 +		register char *src = bufp->page + (int)OFFSET(bp);
   1.233 +		uint32 dst_offset = (uint32)OFFSET(bp) + (uint32)pairlen;
   1.234 +		register char *dst = bufp->page + dst_offset;
   1.235 +		uint32 length = bp[ndx + 1] - OFFSET(bp);
   1.236 +
   1.237 +		/*
   1.238 +		 * +-----------+XXX+---------+XXX+---------+---------> +infinity
   1.239 +		 * |           |             |             |
   1.240 +		 * 0           src_offset    dst_offset    BSIZE
   1.241 +		 *
   1.242 +		 * Dst_offset is > src_offset, so if src_offset were bad, dst_offset
   1.243 +		 * would be too, therefore we check only dst_offset.
   1.244 +		 *
   1.245 +		 * If dst_offset is >= BSIZE, either OFFSET(bp), or pairlen, or both
   1.246 +		 * is corrupted.
   1.247 +		 *
   1.248 +		 * Once we know dst_offset is < BSIZE, we can subtract it from BSIZE
   1.249 +		 * to get an upper bound on length.
   1.250 +		 */
   1.251 +		if(dst_offset > (uint32)hashp->BSIZE)
   1.252 +			return(DATABASE_CORRUPTED_ERROR);
   1.253 +
   1.254 +		if(length > (uint32)(hashp->BSIZE - dst_offset))
   1.255 +			return(DATABASE_CORRUPTED_ERROR);
   1.256 +
   1.257 +		memmove(dst, src, length);
   1.258 +
   1.259 +		/* Now adjust the pointers */
   1.260 +		for (i = ndx + 2; i <= n; i += 2) {
   1.261 +			if (bp[i + 1] == OVFLPAGE) {
   1.262 +				bp[i - 2] = bp[i];
   1.263 +				bp[i - 1] = bp[i + 1];
   1.264 +			} else {
   1.265 +				bp[i - 2] = bp[i] + pairlen;
   1.266 +				bp[i - 1] = bp[i + 1] + pairlen;
   1.267 +			}
   1.268 +		}
   1.269 +	}
   1.270 +	/* Finally adjust the page data */
   1.271 +	bp[n] = OFFSET(bp) + pairlen;
   1.272 +	bp[n - 1] = bp[n + 1] + pairlen + 2 * sizeof(uint16);
   1.273 +	bp[0] = n - 2;
   1.274 +	hashp->NKEYS--;
   1.275 +
   1.276 +	bufp->flags |= BUF_MOD;
   1.277 +	return (0);
   1.278 +}
   1.279 +/*
   1.280 + * Returns:
   1.281 + *	 0 ==> OK
   1.282 + *	-1 ==> Error
   1.283 + */
   1.284 +extern int
   1.285 +__split_page(HTAB *hashp, uint32 obucket, uint32 nbucket)
   1.286 +{
   1.287 +	register BUFHEAD *new_bufp, *old_bufp;
   1.288 +	register uint16 *ino;
   1.289 +	register uint16 *tmp_uint16_array;
   1.290 +	register char *np;
   1.291 +	DBT key, val;
   1.292 +    uint16 n, ndx;
   1.293 +	int retval;
   1.294 +	uint16 copyto, diff, moved;
   1.295 +	size_t off;
   1.296 +	char *op;
   1.297 +
   1.298 +	copyto = (uint16)hashp->BSIZE;
   1.299 +	off = (uint16)hashp->BSIZE;
   1.300 +	old_bufp = __get_buf(hashp, obucket, NULL, 0);
   1.301 +	if (old_bufp == NULL)
   1.302 +		return (-1);
   1.303 +	new_bufp = __get_buf(hashp, nbucket, NULL, 0);
   1.304 +	if (new_bufp == NULL)
   1.305 +		return (-1);
   1.306 +
   1.307 +	old_bufp->flags |= (BUF_MOD | BUF_PIN);
   1.308 +	new_bufp->flags |= (BUF_MOD | BUF_PIN);
   1.309 +
   1.310 +	ino = (uint16 *)(op = old_bufp->page);
   1.311 +	np = new_bufp->page;
   1.312 +
   1.313 +	moved = 0;
   1.314 +
   1.315 +	for (n = 1, ndx = 1; n < ino[0]; n += 2) {
   1.316 +		if (ino[n + 1] < REAL_KEY) {
   1.317 +			retval = ugly_split(hashp, obucket, old_bufp, new_bufp,
   1.318 +			    (int)copyto, (int)moved);
   1.319 +			old_bufp->flags &= ~BUF_PIN;
   1.320 +			new_bufp->flags &= ~BUF_PIN;
   1.321 +			return (retval);
   1.322 +
   1.323 +		}
   1.324 +		key.data = (uint8 *)op + ino[n];
   1.325 +
   1.326 +		/* check here for ino[n] being greater than
   1.327 +		 * off.  If it is then the database has
   1.328 +		 * been corrupted.
   1.329 +		 */
   1.330 +		if(ino[n] > off)
   1.331 +			return(DATABASE_CORRUPTED_ERROR);
   1.332 +
   1.333 +		key.size = off - ino[n];
   1.334 +
   1.335 +#ifdef DEBUG
   1.336 +		/* make sure the size is positive */
   1.337 +		assert(((int)key.size) > -1);
   1.338 +#endif
   1.339 +
   1.340 +		if (__call_hash(hashp, (char *)key.data, key.size) == obucket) {
   1.341 +			/* Don't switch page */
   1.342 +			diff = copyto - off;
   1.343 +			if (diff) {
   1.344 +				copyto = ino[n + 1] + diff;
   1.345 +				memmove(op + copyto, op + ino[n + 1],
   1.346 +				    off - ino[n + 1]);
   1.347 +				ino[ndx] = copyto + ino[n] - ino[n + 1];
   1.348 +				ino[ndx + 1] = copyto;
   1.349 +			} else
   1.350 +				copyto = ino[n + 1];
   1.351 +			ndx += 2;
   1.352 +		} else {
   1.353 +			/* Switch page */
   1.354 +			val.data = (uint8 *)op + ino[n + 1];
   1.355 +			val.size = ino[n] - ino[n + 1];
   1.356 +
   1.357 +			/* if the pair doesn't fit something is horribly
   1.358 +			 * wrong.  LJM
   1.359 +			 */
   1.360 +			tmp_uint16_array = (uint16*)np;
   1.361 +			if(!PAIRFITS(tmp_uint16_array, &key, &val))
   1.362 +				return(DATABASE_CORRUPTED_ERROR);
   1.363 +
   1.364 +			putpair(np, &key, &val);
   1.365 +			moved += 2;
   1.366 +		}
   1.367 +
   1.368 +		off = ino[n + 1];
   1.369 +	}
   1.370 +
   1.371 +	/* Now clean up the page */
   1.372 +	ino[0] -= moved;
   1.373 +	FREESPACE(ino) = copyto - sizeof(uint16) * (ino[0] + 3);
   1.374 +	OFFSET(ino) = copyto;
   1.375 +
   1.376 +#ifdef DEBUG3
   1.377 +	(void)fprintf(stderr, "split %d/%d\n",
   1.378 +	    ((uint16 *)np)[0] / 2,
   1.379 +	    ((uint16 *)op)[0] / 2);
   1.380 +#endif
   1.381 +	/* unpin both pages */
   1.382 +	old_bufp->flags &= ~BUF_PIN;
   1.383 +	new_bufp->flags &= ~BUF_PIN;
   1.384 +	return (0);
   1.385 +}
   1.386 +
   1.387 +/*
   1.388 + * Called when we encounter an overflow or big key/data page during split
   1.389 + * handling.  This is special cased since we have to begin checking whether
   1.390 + * the key/data pairs fit on their respective pages and because we may need
   1.391 + * overflow pages for both the old and new pages.
   1.392 + *
   1.393 + * The first page might be a page with regular key/data pairs in which case
   1.394 + * we have a regular overflow condition and just need to go on to the next
   1.395 + * page or it might be a big key/data pair in which case we need to fix the
   1.396 + * big key/data pair.
   1.397 + *
   1.398 + * Returns:
   1.399 + *	 0 ==> success
   1.400 + *	-1 ==> failure
   1.401 + */
   1.402 +
   1.403 +/* the maximum number of loops we will allow UGLY split to chew
   1.404 + * on before we assume the database is corrupted and throw it
   1.405 + * away.
   1.406 + */
   1.407 +#define MAX_UGLY_SPLIT_LOOPS 10000
   1.408 +
   1.409 +static int
   1.410 +ugly_split(HTAB *hashp, uint32 obucket, BUFHEAD *old_bufp,
   1.411 + BUFHEAD *new_bufp,/* Same as __split_page. */ int copyto, int moved)
   1.412 +	/* int copyto;	 First byte on page which contains key/data values. */
   1.413 +	/* int moved;	 Number of pairs moved to new page. */
   1.414 +{
   1.415 +	register BUFHEAD *bufp;	/* Buffer header for ino */
   1.416 +	register uint16 *ino;	/* Page keys come off of */
   1.417 +	register uint16 *np;	/* New page */
   1.418 +	register uint16 *op;	/* Page keys go on to if they aren't moving */
   1.419 +    uint32 loop_detection=0;
   1.420 +
   1.421 +	BUFHEAD *last_bfp;	/* Last buf header OVFL needing to be freed */
   1.422 +	DBT key, val;
   1.423 +	SPLIT_RETURN ret;
   1.424 +	uint16 n, off, ov_addr, scopyto;
   1.425 +	char *cino;		/* Character value of ino */
   1.426 +	int status;
   1.427 +
   1.428 +	bufp = old_bufp;
   1.429 +	ino = (uint16 *)old_bufp->page;
   1.430 +	np = (uint16 *)new_bufp->page;
   1.431 +	op = (uint16 *)old_bufp->page;
   1.432 +	last_bfp = NULL;
   1.433 +	scopyto = (uint16)copyto;	/* ANSI */
   1.434 +
   1.435 +	n = ino[0] - 1;
   1.436 +	while (n < ino[0]) {
   1.437 +
   1.438 +
   1.439 +        /* this function goes nuts sometimes and never returns. 
   1.440 +         * I havent found the problem yet but I need a solution
   1.441 +         * so if we loop too often we assume a database curruption error
   1.442 +         * :LJM
   1.443 +         */
   1.444 +        loop_detection++;
   1.445 +
   1.446 +        if(loop_detection > MAX_UGLY_SPLIT_LOOPS)
   1.447 +            return DATABASE_CORRUPTED_ERROR;
   1.448 +
   1.449 +		if (ino[2] < REAL_KEY && ino[2] != OVFLPAGE) {
   1.450 +			if ((status = __big_split(hashp, old_bufp,
   1.451 +			    new_bufp, bufp, bufp->addr, obucket, &ret)))
   1.452 +				return (status);
   1.453 +			old_bufp = ret.oldp;
   1.454 +			if (!old_bufp)
   1.455 +				return (-1);
   1.456 +			op = (uint16 *)old_bufp->page;
   1.457 +			new_bufp = ret.newp;
   1.458 +			if (!new_bufp)
   1.459 +				return (-1);
   1.460 +			np = (uint16 *)new_bufp->page;
   1.461 +			bufp = ret.nextp;
   1.462 +			if (!bufp)
   1.463 +				return (0);
   1.464 +			cino = (char *)bufp->page;
   1.465 +			ino = (uint16 *)cino;
   1.466 +			last_bfp = ret.nextp;
   1.467 +		} else if (ino[n + 1] == OVFLPAGE) {
   1.468 +			ov_addr = ino[n];
   1.469 +			/*
   1.470 +			 * Fix up the old page -- the extra 2 are the fields
   1.471 +			 * which contained the overflow information.
   1.472 +			 */
   1.473 +			ino[0] -= (moved + 2);
   1.474 +			FREESPACE(ino) =
   1.475 +			    scopyto - sizeof(uint16) * (ino[0] + 3);
   1.476 +			OFFSET(ino) = scopyto;
   1.477 +
   1.478 +			bufp = __get_buf(hashp, ov_addr, bufp, 0);
   1.479 +			if (!bufp)
   1.480 +				return (-1);
   1.481 +
   1.482 +			ino = (uint16 *)bufp->page;
   1.483 +			n = 1;
   1.484 +			scopyto = hashp->BSIZE;
   1.485 +			moved = 0;
   1.486 +
   1.487 +			if (last_bfp)
   1.488 +				__free_ovflpage(hashp, last_bfp);
   1.489 +			last_bfp = bufp;
   1.490 +		}
   1.491 +		/* Move regular sized pairs of there are any */
   1.492 +		off = hashp->BSIZE;
   1.493 +		for (n = 1; (n < ino[0]) && (ino[n + 1] >= REAL_KEY); n += 2) {
   1.494 +			cino = (char *)ino;
   1.495 +			key.data = (uint8 *)cino + ino[n];
   1.496 +			key.size = off - ino[n];
   1.497 +			val.data = (uint8 *)cino + ino[n + 1];
   1.498 +			val.size = ino[n] - ino[n + 1];
   1.499 +			off = ino[n + 1];
   1.500 +
   1.501 +			if (__call_hash(hashp, (char*)key.data, key.size) == obucket) {
   1.502 +				/* Keep on old page */
   1.503 +				if (PAIRFITS(op, (&key), (&val)))
   1.504 +					putpair((char *)op, &key, &val);
   1.505 +				else {
   1.506 +					old_bufp =
   1.507 +					    __add_ovflpage(hashp, old_bufp);
   1.508 +					if (!old_bufp)
   1.509 +						return (-1);
   1.510 +					op = (uint16 *)old_bufp->page;
   1.511 +					putpair((char *)op, &key, &val);
   1.512 +				}
   1.513 +				old_bufp->flags |= BUF_MOD;
   1.514 +			} else {
   1.515 +				/* Move to new page */
   1.516 +				if (PAIRFITS(np, (&key), (&val)))
   1.517 +					putpair((char *)np, &key, &val);
   1.518 +				else {
   1.519 +					new_bufp =
   1.520 +					    __add_ovflpage(hashp, new_bufp);
   1.521 +					if (!new_bufp)
   1.522 +						return (-1);
   1.523 +					np = (uint16 *)new_bufp->page;
   1.524 +					putpair((char *)np, &key, &val);
   1.525 +				}
   1.526 +				new_bufp->flags |= BUF_MOD;
   1.527 +			}
   1.528 +		}
   1.529 +	}
   1.530 +	if (last_bfp)
   1.531 +		__free_ovflpage(hashp, last_bfp);
   1.532 +	return (0);
   1.533 +}
   1.534 +
   1.535 +/*
   1.536 + * Add the given pair to the page
   1.537 + *
   1.538 + * Returns:
   1.539 + *	0 ==> OK
   1.540 + *	1 ==> failure
   1.541 + */
   1.542 +extern int
   1.543 +__addel(HTAB *hashp, BUFHEAD *bufp, const DBT *key, const DBT * val)
   1.544 +{
   1.545 +	register uint16 *bp, *sop;
   1.546 +	int do_expand;
   1.547 +
   1.548 +	bp = (uint16 *)bufp->page;
   1.549 +	do_expand = 0;
   1.550 +	while (bp[0] && (bp[2] < REAL_KEY || bp[bp[0]] < REAL_KEY))
   1.551 +		/* Exception case */
   1.552 +		if (bp[2] == FULL_KEY_DATA && bp[0] == 2)
   1.553 +			/* This is the last page of a big key/data pair
   1.554 +			   and we need to add another page */
   1.555 +			break;
   1.556 +		else if (bp[2] < REAL_KEY && bp[bp[0]] != OVFLPAGE) {
   1.557 +			bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
   1.558 +			if (!bufp)
   1.559 +			  {
   1.560 +#ifdef DEBUG
   1.561 +				assert(0);
   1.562 +#endif
   1.563 +				return (-1);
   1.564 +			  }
   1.565 +			bp = (uint16 *)bufp->page;
   1.566 +		} else
   1.567 +			/* Try to squeeze key on this page */
   1.568 +			if (FREESPACE(bp) > PAIRSIZE(key, val)) {
   1.569 +			  {
   1.570 +				squeeze_key(bp, key, val);
   1.571 +
   1.572 +				/* LJM: I added this because I think it was
   1.573 +				 * left out on accident.
   1.574 +				 * if this isn't incremented nkeys will not
   1.575 +				 * be the actual number of keys in the db.
   1.576 +				 */
   1.577 +				hashp->NKEYS++;
   1.578 +				return (0);
   1.579 +			  }
   1.580 +			} else {
   1.581 +				bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
   1.582 +				if (!bufp)
   1.583 +			      {
   1.584 +#ifdef DEBUG
   1.585 +				    assert(0);
   1.586 +#endif
   1.587 +					return (-1);
   1.588 +				  }
   1.589 +				bp = (uint16 *)bufp->page;
   1.590 +			}
   1.591 +
   1.592 +	if (PAIRFITS(bp, key, val))
   1.593 +		putpair(bufp->page, key, (DBT *)val);
   1.594 +	else {
   1.595 +		do_expand = 1;
   1.596 +		bufp = __add_ovflpage(hashp, bufp);
   1.597 +		if (!bufp)
   1.598 +	      {
   1.599 +#ifdef DEBUG
   1.600 +		    assert(0);
   1.601 +#endif
   1.602 +			return (-1);
   1.603 +		  }
   1.604 +		sop = (uint16 *)bufp->page;
   1.605 +
   1.606 +		if (PAIRFITS(sop, key, val))
   1.607 +			putpair((char *)sop, key, (DBT *)val);
   1.608 +		else
   1.609 +			if (__big_insert(hashp, bufp, key, val))
   1.610 +	          {
   1.611 +#ifdef DEBUG
   1.612 +		        assert(0);
   1.613 +#endif
   1.614 +			    return (-1);
   1.615 +		      }
   1.616 +	}
   1.617 +	bufp->flags |= BUF_MOD;
   1.618 +	/*
   1.619 +	 * If the average number of keys per bucket exceeds the fill factor,
   1.620 +	 * expand the table.
   1.621 +	 */
   1.622 +	hashp->NKEYS++;
   1.623 +	if (do_expand ||
   1.624 +	    (hashp->NKEYS / (hashp->MAX_BUCKET + 1) > hashp->FFACTOR))
   1.625 +		return (__expand_table(hashp));
   1.626 +	return (0);
   1.627 +}
   1.628 +
   1.629 +/*
   1.630 + *
   1.631 + * Returns:
   1.632 + *	pointer on success
   1.633 + *	NULL on error
   1.634 + */
   1.635 +extern BUFHEAD *
   1.636 +__add_ovflpage(HTAB *hashp, BUFHEAD *bufp)
   1.637 +{
   1.638 +	register uint16 *sp;
   1.639 +	uint16 ndx, ovfl_num;
   1.640 +#ifdef DEBUG1
   1.641 +	int tmp1, tmp2;
   1.642 +#endif
   1.643 +	sp = (uint16 *)bufp->page;
   1.644 +
   1.645 +	/* Check if we are dynamically determining the fill factor */
   1.646 +	if (hashp->FFACTOR == DEF_FFACTOR) {
   1.647 +		hashp->FFACTOR = sp[0] >> 1;
   1.648 +		if (hashp->FFACTOR < MIN_FFACTOR)
   1.649 +			hashp->FFACTOR = MIN_FFACTOR;
   1.650 +	}
   1.651 +	bufp->flags |= BUF_MOD;
   1.652 +	ovfl_num = overflow_page(hashp);
   1.653 +#ifdef DEBUG1
   1.654 +	tmp1 = bufp->addr;
   1.655 +	tmp2 = bufp->ovfl ? bufp->ovfl->addr : 0;
   1.656 +#endif
   1.657 +	if (!ovfl_num || !(bufp->ovfl = __get_buf(hashp, ovfl_num, bufp, 1)))
   1.658 +		return (NULL);
   1.659 +	bufp->ovfl->flags |= BUF_MOD;
   1.660 +#ifdef DEBUG1
   1.661 +	(void)fprintf(stderr, "ADDOVFLPAGE: %d->ovfl was %d is now %d\n",
   1.662 +	    tmp1, tmp2, bufp->ovfl->addr);
   1.663 +#endif
   1.664 +	ndx = sp[0];
   1.665 +	/*
   1.666 +	 * Since a pair is allocated on a page only if there's room to add
   1.667 +	 * an overflow page, we know that the OVFL information will fit on
   1.668 +	 * the page.
   1.669 +	 */
   1.670 +	sp[ndx + 4] = OFFSET(sp);
   1.671 +	sp[ndx + 3] = FREESPACE(sp) - OVFLSIZE;
   1.672 +	sp[ndx + 1] = ovfl_num;
   1.673 +	sp[ndx + 2] = OVFLPAGE;
   1.674 +	sp[0] = ndx + 2;
   1.675 +#ifdef HASH_STATISTICS
   1.676 +	hash_overflows++;
   1.677 +#endif
   1.678 +	return (bufp->ovfl);
   1.679 +}
   1.680 +
   1.681 +/*
   1.682 + * Returns:
   1.683 + *	 0 indicates SUCCESS
   1.684 + *	-1 indicates FAILURE
   1.685 + */
   1.686 +extern int
   1.687 +__get_page(HTAB *hashp,
   1.688 +	char * p,
   1.689 +	uint32 bucket, 
   1.690 +	int is_bucket, 
   1.691 +	int is_disk, 
   1.692 +	int is_bitmap)
   1.693 +{
   1.694 +	register int fd, page;
   1.695 +	size_t size;
   1.696 +	int rsize;
   1.697 +	uint16 *bp;
   1.698 +
   1.699 +	fd = hashp->fp;
   1.700 +	size = hashp->BSIZE;
   1.701 +
   1.702 +	if ((fd == -1) || !is_disk) {
   1.703 +		PAGE_INIT(p);
   1.704 +		return (0);
   1.705 +	}
   1.706 +	if (is_bucket)
   1.707 +		page = BUCKET_TO_PAGE(bucket);
   1.708 +	else
   1.709 +		page = OADDR_TO_PAGE(bucket);
   1.710 +	if ((MY_LSEEK(fd, (off_t)page << hashp->BSHIFT, SEEK_SET) == -1) ||
   1.711 +	    ((rsize = read(fd, p, size)) == -1))
   1.712 +		return (-1);
   1.713 +
   1.714 +	bp = (uint16 *)p;
   1.715 +	if (!rsize)
   1.716 +		bp[0] = 0;	/* We hit the EOF, so initialize a new page */
   1.717 +	else
   1.718 +		if ((unsigned)rsize != size) {
   1.719 +			errno = EFTYPE;
   1.720 +			return (-1);
   1.721 +		}
   1.722 +
   1.723 +	if (!is_bitmap && !bp[0]) {
   1.724 +		PAGE_INIT(p);
   1.725 +	} else {
   1.726 +
   1.727 +#ifdef DEBUG
   1.728 +		if(BYTE_ORDER == LITTLE_ENDIAN)
   1.729 +		  {
   1.730 +			int is_little_endian;
   1.731 +			is_little_endian = BYTE_ORDER;
   1.732 +		  }
   1.733 +		else if(BYTE_ORDER == BIG_ENDIAN)
   1.734 +		  {
   1.735 +			int is_big_endian;
   1.736 +			is_big_endian = BYTE_ORDER;
   1.737 +		  }
   1.738 +		else
   1.739 +		  {
   1.740 +			assert(0);
   1.741 +		  }
   1.742 +#endif
   1.743 +
   1.744 +		if (hashp->LORDER != BYTE_ORDER) {
   1.745 +			register int i, max;
   1.746 +
   1.747 +			if (is_bitmap) {
   1.748 +				max = hashp->BSIZE >> 2; /* divide by 4 */
   1.749 +				for (i = 0; i < max; i++)
   1.750 +					M_32_SWAP(((int *)p)[i]);
   1.751 +			} else {
   1.752 +				M_16_SWAP(bp[0]);
   1.753 +				max = bp[0] + 2;
   1.754 +
   1.755 +	    		/* bound the size of max by
   1.756 +	     		 * the maximum number of entries
   1.757 +	     		 * in the array
   1.758 +	     		 */
   1.759 +				if((unsigned)max > (size / sizeof(uint16)))
   1.760 +					return(DATABASE_CORRUPTED_ERROR);
   1.761 +
   1.762 +				/* do the byte order swap
   1.763 +				 */
   1.764 +				for (i = 1; i <= max; i++)
   1.765 +					M_16_SWAP(bp[i]);
   1.766 +			}
   1.767 +		}
   1.768 +
   1.769 +		/* check the validity of the page here
   1.770 +		 * (after doing byte order swaping if necessary)
   1.771 +		 */
   1.772 +		if(!is_bitmap && bp[0] != 0)
   1.773 +		  {
   1.774 +			uint16 num_keys = bp[0];
   1.775 +			uint16 offset;
   1.776 +			uint16 i;
   1.777 +
   1.778 +			/* bp[0] is supposed to be the number of
   1.779 +			 * entries currently in the page.  If
   1.780 +			 * bp[0] is too large (larger than the whole
   1.781 +			 * page) then the page is corrupted
   1.782 +			 */
   1.783 +			if(bp[0] > (size / sizeof(uint16)))
   1.784 +				return(DATABASE_CORRUPTED_ERROR);
   1.785 +			
   1.786 +			/* bound free space */
   1.787 +			if(FREESPACE(bp) > size)
   1.788 +				return(DATABASE_CORRUPTED_ERROR);
   1.789 +		
   1.790 +			/* check each key and data offset to make
   1.791 + 			 * sure they are all within bounds they
   1.792 + 			 * should all be less than the previous
   1.793 + 			 * offset as well.
   1.794 + 			 */
   1.795 +			offset = size;
   1.796 +			for(i=1 ; i <= num_keys; i+=2)
   1.797 +  			  {
   1.798 +				/* ignore overflow pages etc. */
   1.799 +				if(bp[i+1] >= REAL_KEY)
   1.800 +	  			  {
   1.801 +						
   1.802 +					if(bp[i] > offset || bp[i+1] > bp[i])			
   1.803 +						return(DATABASE_CORRUPTED_ERROR);
   1.804 +			
   1.805 +					offset = bp[i+1];
   1.806 +	  			  }
   1.807 +				else
   1.808 +	  			  {
   1.809 +					/* there are no other valid keys after
   1.810 +		 			 * seeing a non REAL_KEY
   1.811 +		 			 */
   1.812 +					break;
   1.813 +	  			  }
   1.814 +  			  }
   1.815 +		}
   1.816 +	}
   1.817 +	return (0);
   1.818 +}
   1.819 +
   1.820 +/*
   1.821 + * Write page p to disk
   1.822 + *
   1.823 + * Returns:
   1.824 + *	 0 ==> OK
   1.825 + *	-1 ==>failure
   1.826 + */
   1.827 +extern int
   1.828 +__put_page(HTAB *hashp, char *p, uint32 bucket, int is_bucket, int is_bitmap)
   1.829 +{
   1.830 +	register int fd, page;
   1.831 +	size_t size;
   1.832 +	int wsize;
   1.833 +	off_t offset;
   1.834 +
   1.835 +	size = hashp->BSIZE;
   1.836 +	if ((hashp->fp == -1) && open_temp(hashp))
   1.837 +		return (-1);
   1.838 +	fd = hashp->fp;
   1.839 +
   1.840 +	if (hashp->LORDER != BYTE_ORDER) {
   1.841 +		register int i;
   1.842 +		register int max;
   1.843 +
   1.844 +		if (is_bitmap) {
   1.845 +			max = hashp->BSIZE >> 2;	/* divide by 4 */
   1.846 +			for (i = 0; i < max; i++)
   1.847 +				M_32_SWAP(((int *)p)[i]);
   1.848 +		} else {
   1.849 +			max = ((uint16 *)p)[0] + 2;
   1.850 +
   1.851 +            /* bound the size of max by
   1.852 +             * the maximum number of entries
   1.853 +             * in the array
   1.854 +             */
   1.855 +            if((unsigned)max > (size / sizeof(uint16)))
   1.856 +                return(DATABASE_CORRUPTED_ERROR);
   1.857 +
   1.858 +			for (i = 0; i <= max; i++)
   1.859 +				M_16_SWAP(((uint16 *)p)[i]);
   1.860 +
   1.861 +		}
   1.862 +	}
   1.863 +
   1.864 +	if (is_bucket)
   1.865 +		page = BUCKET_TO_PAGE(bucket);
   1.866 +	else
   1.867 +		page = OADDR_TO_PAGE(bucket);
   1.868 +	offset = (off_t)page << hashp->BSHIFT;
   1.869 +	if ((MY_LSEEK(fd, offset, SEEK_SET) == -1) ||
   1.870 +	    ((wsize = write(fd, p, size)) == -1))
   1.871 +		/* Errno is set */
   1.872 +		return (-1);
   1.873 +	if ((unsigned)wsize != size) {
   1.874 +		errno = EFTYPE;
   1.875 +		return (-1);
   1.876 +	}
   1.877 +#if defined(_WIN32) || defined(_WINDOWS) 
   1.878 +	if (offset + size > hashp->file_size) {
   1.879 +		hashp->updateEOF = 1;
   1.880 +	}
   1.881 +#endif
   1.882 +	/* put the page back the way it was so that it isn't byteswapped
   1.883 +	 * if it remains in memory - LJM
   1.884 +	 */
   1.885 +	if (hashp->LORDER != BYTE_ORDER) {
   1.886 +		register int i;
   1.887 +		register int max;
   1.888 +
   1.889 +		if (is_bitmap) {
   1.890 +			max = hashp->BSIZE >> 2;	/* divide by 4 */
   1.891 +			for (i = 0; i < max; i++)
   1.892 +				M_32_SWAP(((int *)p)[i]);
   1.893 +		} else {
   1.894 +    		uint16 *bp = (uint16 *)p;
   1.895 +
   1.896 +			M_16_SWAP(bp[0]);
   1.897 +			max = bp[0] + 2;
   1.898 +
   1.899 +			/* no need to bound the size if max again
   1.900 +			 * since it was done already above
   1.901 +			 */
   1.902 +
   1.903 +			/* do the byte order re-swap
   1.904 +			 */
   1.905 +			for (i = 1; i <= max; i++)
   1.906 +				M_16_SWAP(bp[i]);
   1.907 +		}
   1.908 +	}
   1.909 +
   1.910 +	return (0);
   1.911 +}
   1.912 +
   1.913 +#define BYTE_MASK	((1 << INT_BYTE_SHIFT) -1)
   1.914 +/*
   1.915 + * Initialize a new bitmap page.  Bitmap pages are left in memory
   1.916 + * once they are read in.
   1.917 + */
   1.918 +extern int
   1.919 +__ibitmap(HTAB *hashp, int pnum, int nbits, int ndx)
   1.920 +{
   1.921 +	uint32 *ip;
   1.922 +	size_t clearbytes, clearints;
   1.923 +
   1.924 +	if ((ip = (uint32 *)malloc((size_t)hashp->BSIZE)) == NULL)
   1.925 +		return (1);
   1.926 +	hashp->nmaps++;
   1.927 +	clearints = ((nbits - 1) >> INT_BYTE_SHIFT) + 1;
   1.928 +	clearbytes = clearints << INT_TO_BYTE;
   1.929 +	(void)memset((char *)ip, 0, clearbytes);
   1.930 +	(void)memset(((char *)ip) + clearbytes, 0xFF,
   1.931 +	    hashp->BSIZE - clearbytes);
   1.932 +	ip[clearints - 1] = ALL_SET << (nbits & BYTE_MASK);
   1.933 +	SETBIT(ip, 0);
   1.934 +	hashp->BITMAPS[ndx] = (uint16)pnum;
   1.935 +	hashp->mapp[ndx] = ip;
   1.936 +	return (0);
   1.937 +}
   1.938 +
   1.939 +static uint32
   1.940 +first_free(uint32 map)
   1.941 +{
   1.942 +	register uint32 i, mask;
   1.943 +
   1.944 +	mask = 0x1;
   1.945 +	for (i = 0; i < BITS_PER_MAP; i++) {
   1.946 +		if (!(mask & map))
   1.947 +			return (i);
   1.948 +		mask = mask << 1;
   1.949 +	}
   1.950 +	return (i);
   1.951 +}
   1.952 +
   1.953 +static uint16
   1.954 +overflow_page(HTAB *hashp)
   1.955 +{
   1.956 +	register uint32 *freep=NULL;
   1.957 +	register int max_free, offset, splitnum;
   1.958 +	uint16 addr;
   1.959 +	uint32 i;
   1.960 +	int bit, first_page, free_bit, free_page, in_use_bits, j;
   1.961 +#ifdef DEBUG2
   1.962 +	int tmp1, tmp2;
   1.963 +#endif
   1.964 +	splitnum = hashp->OVFL_POINT;
   1.965 +	max_free = hashp->SPARES[splitnum];
   1.966 +
   1.967 +	free_page = (max_free - 1) >> (hashp->BSHIFT + BYTE_SHIFT);
   1.968 +	free_bit = (max_free - 1) & ((hashp->BSIZE << BYTE_SHIFT) - 1);
   1.969 +
   1.970 +	/* Look through all the free maps to find the first free block */
   1.971 +	first_page = hashp->LAST_FREED >>(hashp->BSHIFT + BYTE_SHIFT);
   1.972 +	for ( i = first_page; i <= (unsigned)free_page; i++ ) {
   1.973 +		if (!(freep = (uint32 *)hashp->mapp[i]) &&
   1.974 +		    !(freep = fetch_bitmap(hashp, i)))
   1.975 +			return (0);
   1.976 +		if (i == (unsigned)free_page)
   1.977 +			in_use_bits = free_bit;
   1.978 +		else
   1.979 +			in_use_bits = (hashp->BSIZE << BYTE_SHIFT) - 1;
   1.980 +		
   1.981 +		if (i == (unsigned)first_page) {
   1.982 +			bit = hashp->LAST_FREED &
   1.983 +			    ((hashp->BSIZE << BYTE_SHIFT) - 1);
   1.984 +			j = bit / BITS_PER_MAP;
   1.985 +			bit = bit & ~(BITS_PER_MAP - 1);
   1.986 +		} else {
   1.987 +			bit = 0;
   1.988 +			j = 0;
   1.989 +		}
   1.990 +		for (; bit <= in_use_bits; j++, bit += BITS_PER_MAP)
   1.991 +			if (freep[j] != ALL_SET)
   1.992 +				goto found;
   1.993 +	}
   1.994 +
   1.995 +	/* No Free Page Found */
   1.996 +	hashp->LAST_FREED = hashp->SPARES[splitnum];
   1.997 +	hashp->SPARES[splitnum]++;
   1.998 +	offset = hashp->SPARES[splitnum] -
   1.999 +	    (splitnum ? hashp->SPARES[splitnum - 1] : 0);
  1.1000 +
  1.1001 +#define	OVMSG	"HASH: Out of overflow pages.  Increase page size\n"
  1.1002 +	if (offset > SPLITMASK) {
  1.1003 +		if (++splitnum >= NCACHED) {
  1.1004 +#ifndef macintosh
  1.1005 +			(void)write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1);
  1.1006 +#endif
  1.1007 +			return (0);
  1.1008 +		}
  1.1009 +		hashp->OVFL_POINT = splitnum;
  1.1010 +		hashp->SPARES[splitnum] = hashp->SPARES[splitnum-1];
  1.1011 +		hashp->SPARES[splitnum-1]--;
  1.1012 +		offset = 1;
  1.1013 +	}
  1.1014 +
  1.1015 +	/* Check if we need to allocate a new bitmap page */
  1.1016 +	if (free_bit == (hashp->BSIZE << BYTE_SHIFT) - 1) {
  1.1017 +		free_page++;
  1.1018 +		if (free_page >= NCACHED) {
  1.1019 +#ifndef macintosh
  1.1020 +			(void)write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1);
  1.1021 +#endif
  1.1022 +			return (0);
  1.1023 +		}
  1.1024 +		/*
  1.1025 +		 * This is tricky.  The 1 indicates that you want the new page
  1.1026 +		 * allocated with 1 clear bit.  Actually, you are going to
  1.1027 +		 * allocate 2 pages from this map.  The first is going to be
  1.1028 +		 * the map page, the second is the overflow page we were
  1.1029 +		 * looking for.  The init_bitmap routine automatically, sets
  1.1030 +		 * the first bit of itself to indicate that the bitmap itself
  1.1031 +		 * is in use.  We would explicitly set the second bit, but
  1.1032 +		 * don't have to if we tell init_bitmap not to leave it clear
  1.1033 +		 * in the first place.
  1.1034 +		 */
  1.1035 +		if (__ibitmap(hashp,
  1.1036 +		    (int)OADDR_OF(splitnum, offset), 1, free_page))
  1.1037 +			return (0);
  1.1038 +		hashp->SPARES[splitnum]++;
  1.1039 +#ifdef DEBUG2
  1.1040 +		free_bit = 2;
  1.1041 +#endif
  1.1042 +		offset++;
  1.1043 +		if (offset > SPLITMASK) {
  1.1044 +			if (++splitnum >= NCACHED) {
  1.1045 +#ifndef macintosh
  1.1046 +				(void)write(STDERR_FILENO, OVMSG,
  1.1047 +				    sizeof(OVMSG) - 1);
  1.1048 +#endif
  1.1049 +				return (0);
  1.1050 +			}
  1.1051 +			hashp->OVFL_POINT = splitnum;
  1.1052 +			hashp->SPARES[splitnum] = hashp->SPARES[splitnum-1];
  1.1053 +			hashp->SPARES[splitnum-1]--;
  1.1054 +			offset = 0;
  1.1055 +		}
  1.1056 +	} else {
  1.1057 +		/*
  1.1058 +		 * Free_bit addresses the last used bit.  Bump it to address
  1.1059 +		 * the first available bit.
  1.1060 +		 */
  1.1061 +		free_bit++;
  1.1062 +		SETBIT(freep, free_bit);
  1.1063 +	}
  1.1064 +
  1.1065 +	/* Calculate address of the new overflow page */
  1.1066 +	addr = OADDR_OF(splitnum, offset);
  1.1067 +#ifdef DEBUG2
  1.1068 +	(void)fprintf(stderr, "OVERFLOW_PAGE: ADDR: %d BIT: %d PAGE %d\n",
  1.1069 +	    addr, free_bit, free_page);
  1.1070 +#endif
  1.1071 +	return (addr);
  1.1072 +
  1.1073 +found:
  1.1074 +	bit = bit + first_free(freep[j]);
  1.1075 +	SETBIT(freep, bit);
  1.1076 +#ifdef DEBUG2
  1.1077 +	tmp1 = bit;
  1.1078 +	tmp2 = i;
  1.1079 +#endif
  1.1080 +	/*
  1.1081 +	 * Bits are addressed starting with 0, but overflow pages are addressed
  1.1082 +	 * beginning at 1. Bit is a bit addressnumber, so we need to increment
  1.1083 +	 * it to convert it to a page number.
  1.1084 +	 */
  1.1085 +	bit = 1 + bit + (i * (hashp->BSIZE << BYTE_SHIFT));
  1.1086 +	if (bit >= hashp->LAST_FREED)
  1.1087 +		hashp->LAST_FREED = bit - 1;
  1.1088 +
  1.1089 +	/* Calculate the split number for this page */
  1.1090 +	for (i = 0; (i < (unsigned)splitnum) && (bit > hashp->SPARES[i]); i++) {}
  1.1091 +	offset = (i ? bit - hashp->SPARES[i - 1] : bit);
  1.1092 +	if (offset >= SPLITMASK)
  1.1093 +		return (0);	/* Out of overflow pages */
  1.1094 +	addr = OADDR_OF(i, offset);
  1.1095 +#ifdef DEBUG2
  1.1096 +	(void)fprintf(stderr, "OVERFLOW_PAGE: ADDR: %d BIT: %d PAGE %d\n",
  1.1097 +	    addr, tmp1, tmp2);
  1.1098 +#endif
  1.1099 +
  1.1100 +	/* Allocate and return the overflow page */
  1.1101 +	return (addr);
  1.1102 +}
  1.1103 +
  1.1104 +/*
  1.1105 + * Mark this overflow page as free.
  1.1106 + */
  1.1107 +extern void
  1.1108 +__free_ovflpage(HTAB *hashp, BUFHEAD *obufp)
  1.1109 +{
  1.1110 +	uint16 addr;
  1.1111 +	uint32 *freep;
  1.1112 +	uint32 bit_address, free_page, free_bit;
  1.1113 +	uint16 ndx;
  1.1114 +
  1.1115 +	if(!obufp || !obufp->addr)
  1.1116 +	    return;
  1.1117 +
  1.1118 +	addr = obufp->addr;
  1.1119 +#ifdef DEBUG1
  1.1120 +	(void)fprintf(stderr, "Freeing %d\n", addr);
  1.1121 +#endif
  1.1122 +	ndx = (((uint16)addr) >> SPLITSHIFT);
  1.1123 +	bit_address =
  1.1124 +	    (ndx ? hashp->SPARES[ndx - 1] : 0) + (addr & SPLITMASK) - 1;
  1.1125 +	if (bit_address < (uint32)hashp->LAST_FREED)
  1.1126 +		hashp->LAST_FREED = bit_address;
  1.1127 +	free_page = (bit_address >> (hashp->BSHIFT + BYTE_SHIFT));
  1.1128 +	free_bit = bit_address & ((hashp->BSIZE << BYTE_SHIFT) - 1);
  1.1129 +
  1.1130 +	if (!(freep = hashp->mapp[free_page])) 
  1.1131 +		freep = fetch_bitmap(hashp, free_page);
  1.1132 +
  1.1133 +#ifdef DEBUG
  1.1134 +	/*
  1.1135 +	 * This had better never happen.  It means we tried to read a bitmap
  1.1136 +	 * that has already had overflow pages allocated off it, and we
  1.1137 +	 * failed to read it from the file.
  1.1138 +	 */
  1.1139 +	if (!freep)
  1.1140 +	  {
  1.1141 +		assert(0);
  1.1142 +		return;
  1.1143 +	  }
  1.1144 +#endif
  1.1145 +	CLRBIT(freep, free_bit);
  1.1146 +#ifdef DEBUG2
  1.1147 +	(void)fprintf(stderr, "FREE_OVFLPAGE: ADDR: %d BIT: %d PAGE %d\n",
  1.1148 +	    obufp->addr, free_bit, free_page);
  1.1149 +#endif
  1.1150 +	__reclaim_buf(hashp, obufp);
  1.1151 +}
  1.1152 +
  1.1153 +/*
  1.1154 + * Returns:
  1.1155 + *	 0 success
  1.1156 + *	-1 failure
  1.1157 + */
  1.1158 +static int
  1.1159 +open_temp(HTAB *hashp)
  1.1160 +{
  1.1161 +#ifdef XP_OS2
  1.1162 + 	hashp->fp = mkstemp(NULL);
  1.1163 +#else
  1.1164 +#if !defined(_WIN32) && !defined(_WINDOWS) && !defined(macintosh)
  1.1165 +	sigset_t set, oset;
  1.1166 +#endif
  1.1167 +#if !defined(macintosh)
  1.1168 +	char * tmpdir;
  1.1169 +	size_t len;
  1.1170 +	char last;
  1.1171 +#endif
  1.1172 +	static const char namestr[] = "/_hashXXXXXX";
  1.1173 +	char filename[1024];
  1.1174 +
  1.1175 +#if !defined(_WIN32) && !defined(_WINDOWS) && !defined(macintosh)
  1.1176 +	/* Block signals; make sure file goes away at process exit. */
  1.1177 +	(void)sigfillset(&set);
  1.1178 +	(void)sigprocmask(SIG_BLOCK, &set, &oset);
  1.1179 +#endif
  1.1180 +
  1.1181 +	filename[0] = 0;
  1.1182 +#if defined(macintosh)
  1.1183 +	strcat(filename, namestr + 1);
  1.1184 +#else
  1.1185 +	tmpdir = getenv("TMP");
  1.1186 +	if (!tmpdir)
  1.1187 +		tmpdir = getenv("TMPDIR");
  1.1188 +	if (!tmpdir)
  1.1189 +		tmpdir = getenv("TEMP");
  1.1190 +	if (!tmpdir)
  1.1191 +		tmpdir = ".";
  1.1192 +	len = strlen(tmpdir);
  1.1193 +	if (len && len < (sizeof filename - sizeof namestr)) {
  1.1194 +		strcpy(filename, tmpdir);
  1.1195 +	}
  1.1196 +	len = strlen(filename);
  1.1197 +	last = tmpdir[len - 1];
  1.1198 +	strcat(filename, (last == '/' || last == '\\') ? namestr + 1 : namestr);
  1.1199 +#endif
  1.1200 +
  1.1201 +#if defined(_WIN32) || defined(_WINDOWS)
  1.1202 +	if ((hashp->fp = mkstempflags(filename, _O_BINARY|_O_TEMPORARY)) != -1) {
  1.1203 +		if (hashp->filename) {
  1.1204 +			free(hashp->filename);
  1.1205 +		}
  1.1206 +		hashp->filename = strdup(filename);
  1.1207 +		hashp->is_temp = 1;
  1.1208 +	}
  1.1209 +#else
  1.1210 +	if ((hashp->fp = mkstemp(filename)) != -1) {
  1.1211 +		(void)unlink(filename);
  1.1212 +#if !defined(macintosh)
  1.1213 +		(void)fcntl(hashp->fp, F_SETFD, 1);
  1.1214 +#endif									  
  1.1215 +	}
  1.1216 +#endif
  1.1217 +
  1.1218 +#if !defined(_WIN32) && !defined(_WINDOWS) && !defined(macintosh)
  1.1219 +	(void)sigprocmask(SIG_SETMASK, &oset, (sigset_t *)NULL);
  1.1220 +#endif
  1.1221 +#endif  /* !OS2 */
  1.1222 +	return (hashp->fp != -1 ? 0 : -1);
  1.1223 +}
  1.1224 +
  1.1225 +/*
  1.1226 + * We have to know that the key will fit, but the last entry on the page is
  1.1227 + * an overflow pair, so we need to shift things.
  1.1228 + */
  1.1229 +static void
  1.1230 +squeeze_key(uint16 *sp, const DBT * key, const DBT * val)
  1.1231 +{
  1.1232 +	register char *p;
  1.1233 +	uint16 free_space, n, off, pageno;
  1.1234 +
  1.1235 +	p = (char *)sp;
  1.1236 +	n = sp[0];
  1.1237 +	free_space = FREESPACE(sp);
  1.1238 +	off = OFFSET(sp);
  1.1239 +
  1.1240 +	pageno = sp[n - 1];
  1.1241 +	off -= key->size;
  1.1242 +	sp[n - 1] = off;
  1.1243 +	memmove(p + off, key->data, key->size);
  1.1244 +	off -= val->size;
  1.1245 +	sp[n] = off;
  1.1246 +	memmove(p + off, val->data, val->size);
  1.1247 +	sp[0] = n + 2;
  1.1248 +	sp[n + 1] = pageno;
  1.1249 +	sp[n + 2] = OVFLPAGE;
  1.1250 +	FREESPACE(sp) = free_space - PAIRSIZE(key, val);
  1.1251 +	OFFSET(sp) = off;
  1.1252 +}
  1.1253 +
  1.1254 +static uint32 *
  1.1255 +fetch_bitmap(HTAB *hashp, uint32 ndx)
  1.1256 +{
  1.1257 +	if (ndx >= (unsigned)hashp->nmaps)
  1.1258 +		return (NULL);
  1.1259 +	if ((hashp->mapp[ndx] = (uint32 *)malloc((size_t)hashp->BSIZE)) == NULL)
  1.1260 +		return (NULL);
  1.1261 +	if (__get_page(hashp,
  1.1262 +	    (char *)hashp->mapp[ndx], hashp->BITMAPS[ndx], 0, 1, 1)) {
  1.1263 +		free(hashp->mapp[ndx]);
  1.1264 +		hashp->mapp[ndx] = NULL; /* NEW: 9-11-95 */
  1.1265 +		return (NULL);
  1.1266 +	}                 
  1.1267 +	return (hashp->mapp[ndx]);
  1.1268 +}
  1.1269 +
  1.1270 +#ifdef DEBUG4
  1.1271 +int
  1.1272 +print_chain(int addr)
  1.1273 +{
  1.1274 +	BUFHEAD *bufp;
  1.1275 +	short *bp, oaddr;
  1.1276 +
  1.1277 +	(void)fprintf(stderr, "%d ", addr);
  1.1278 +	bufp = __get_buf(hashp, addr, NULL, 0);
  1.1279 +	bp = (short *)bufp->page;
  1.1280 +	while (bp[0] && ((bp[bp[0]] == OVFLPAGE) ||
  1.1281 +		((bp[0] > 2) && bp[2] < REAL_KEY))) {
  1.1282 +		oaddr = bp[bp[0] - 1];
  1.1283 +		(void)fprintf(stderr, "%d ", (int)oaddr);
  1.1284 +		bufp = __get_buf(hashp, (int)oaddr, bufp, 0);
  1.1285 +		bp = (short *)bufp->page;
  1.1286 +	}
  1.1287 +	(void)fprintf(stderr, "\n");
  1.1288 +}
  1.1289 +#endif

mercurial