1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/dbm/src/hash.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1175 @@ 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(LIBC_SCCS) && !defined(lint) 1.39 +static char sccsid[] = "@(#)hash.c 8.9 (Berkeley) 6/16/94"; 1.40 +#endif /* LIBC_SCCS and not lint */ 1.41 + 1.42 +#if !defined(_WIN32) && !defined(_WINDOWS) && !defined(macintosh) 1.43 +#include <sys/param.h> 1.44 +#endif 1.45 + 1.46 +#if !defined(macintosh) 1.47 +#ifdef XP_OS2 1.48 +#include <sys/types.h> 1.49 +#endif 1.50 +#include <sys/stat.h> 1.51 +#endif 1.52 + 1.53 +#if defined(macintosh) 1.54 +#include <unix.h> 1.55 +#include <unistd.h> 1.56 +#endif 1.57 + 1.58 +#include <errno.h> 1.59 +#include <fcntl.h> 1.60 +#include <stdio.h> 1.61 +#include <stdlib.h> 1.62 +#include <string.h> 1.63 + 1.64 +#if !defined(_WIN32) && !defined(_WINDOWS) && !defined(macintosh) 1.65 +#include <unistd.h> 1.66 +#endif 1.67 +#if defined(_WIN32) || defined(_WINDOWS) 1.68 +#include <windows.h> 1.69 +#endif 1.70 + 1.71 +#include <assert.h> 1.72 + 1.73 +#include "mcom_db.h" 1.74 +#include "hash.h" 1.75 +#include "page.h" 1.76 + 1.77 +/* 1.78 +#include "extern.h" 1.79 +*/ 1.80 +static int alloc_segs __P((HTAB *, int)); 1.81 +static int flush_meta __P((HTAB *)); 1.82 +static int hash_access __P((HTAB *, ACTION, DBT *, DBT *)); 1.83 +static int hash_close __P((DB *)); 1.84 +static int hash_delete __P((const DB *, const DBT *, uint)); 1.85 +static int hash_fd __P((const DB *)); 1.86 +static int hash_get __P((const DB *, const DBT *, DBT *, uint)); 1.87 +static int hash_put __P((const DB *, DBT *, const DBT *, uint)); 1.88 +static void *hash_realloc __P((SEGMENT **, size_t, size_t)); 1.89 +static int hash_seq __P((const DB *, DBT *, DBT *, uint)); 1.90 +static int hash_sync __P((const DB *, uint)); 1.91 +static int hdestroy __P((HTAB *)); 1.92 +static HTAB *init_hash __P((HTAB *, const char *, HASHINFO *)); 1.93 +static int init_htab __P((HTAB *, int)); 1.94 +#if BYTE_ORDER == LITTLE_ENDIAN 1.95 +static void swap_header __P((HTAB *)); 1.96 +static void swap_header_copy __P((HASHHDR *, HASHHDR *)); 1.97 +#endif 1.98 + 1.99 +/* Fast arithmetic, relying on powers of 2, */ 1.100 +#define MOD(x, y) ((x) & ((y) - 1)) 1.101 + 1.102 +#define RETURN_ERROR(ERR, LOC) { save_errno = ERR; goto LOC; } 1.103 + 1.104 +/* Return values */ 1.105 +#define SUCCESS (0) 1.106 +#define DBM_ERROR (-1) 1.107 +#define ABNORMAL (1) 1.108 + 1.109 +#ifdef HASH_STATISTICS 1.110 +int hash_accesses, hash_collisions, hash_expansions, hash_overflows; 1.111 +#endif 1.112 + 1.113 +/* A new Lou (montulli@mozilla.com) routine. 1.114 + * 1.115 + * The database is screwed. 1.116 + * 1.117 + * This closes the file, flushing buffers as appropriate. 1.118 + */ 1.119 +static void 1.120 +__remove_database(DB *dbp) 1.121 +{ 1.122 + HTAB *hashp = (HTAB *)dbp->internal; 1.123 + 1.124 + assert(0); 1.125 + 1.126 + if (!hashp) 1.127 + return; 1.128 + hdestroy(hashp); 1.129 + dbp->internal = NULL; 1.130 +} 1.131 + 1.132 +/************************** INTERFACE ROUTINES ***************************/ 1.133 +/* OPEN/CLOSE */ 1.134 + 1.135 + 1.136 +extern DB * 1.137 +__hash_open(const char *file, int flags, int mode, const HASHINFO *info, int dflags) 1.138 +{ 1.139 + HTAB *hashp=NULL; 1.140 + struct stat statbuf; 1.141 + DB *dbp; 1.142 + int bpages, hdrsize, new_table, nsegs, save_errno; 1.143 + 1.144 + if ((flags & O_ACCMODE) == O_WRONLY) { 1.145 + errno = EINVAL; 1.146 + return NULL; 1.147 + } 1.148 + 1.149 + /* zero the statbuffer so that 1.150 + * we can check it for a non-zero 1.151 + * date to see if stat succeeded 1.152 + */ 1.153 + memset(&statbuf, 0, sizeof(struct stat)); 1.154 + 1.155 + if (!(hashp = (HTAB *)calloc(1, sizeof(HTAB)))) { 1.156 + errno = ENOMEM; 1.157 + return NULL; 1.158 + } 1.159 + hashp->fp = NO_FILE; 1.160 + if(file) 1.161 + hashp->filename = strdup(file); 1.162 + 1.163 + /* 1.164 + * Even if user wants write only, we need to be able to read 1.165 + * the actual file, so we need to open it read/write. But, the 1.166 + * field in the hashp structure needs to be accurate so that 1.167 + * we can check accesses. 1.168 + */ 1.169 + hashp->flags = flags; 1.170 + 1.171 + new_table = 0; 1.172 + if (!file || (flags & O_TRUNC) || (stat(file, &statbuf) && (errno == ENOENT))) 1.173 + { 1.174 + if (errno == ENOENT) 1.175 + errno = 0; /* Just in case someone looks at errno */ 1.176 + new_table = 1; 1.177 + } 1.178 + else if(statbuf.st_mtime && statbuf.st_size == 0) 1.179 + { 1.180 + /* check for a zero length file and delete it 1.181 + * if it exists 1.182 + */ 1.183 + new_table = 1; 1.184 + } 1.185 + hashp->file_size = statbuf.st_size; 1.186 + 1.187 + if (file) { 1.188 +#if defined(_WIN32) || defined(_WINDOWS) || defined (macintosh) || defined(XP_OS2) 1.189 + if ((hashp->fp = DBFILE_OPEN(file, flags | O_BINARY, mode)) == -1) 1.190 + RETURN_ERROR(errno, error1); 1.191 +#else 1.192 + if ((hashp->fp = open(file, flags, mode)) == -1) 1.193 + RETURN_ERROR(errno, error1); 1.194 + (void)fcntl(hashp->fp, F_SETFD, 1); 1.195 +#endif 1.196 + } 1.197 + if (new_table) { 1.198 + if (!init_hash(hashp, file, (HASHINFO *)info)) 1.199 + RETURN_ERROR(errno, error1); 1.200 + } else { 1.201 + /* Table already exists */ 1.202 + if (info && info->hash) 1.203 + hashp->hash = info->hash; 1.204 + else 1.205 + hashp->hash = __default_hash; 1.206 + 1.207 + hdrsize = read(hashp->fp, (char *)&hashp->hdr, sizeof(HASHHDR)); 1.208 + if (hdrsize == -1) 1.209 + RETURN_ERROR(errno, error1); 1.210 + if (hdrsize != sizeof(HASHHDR)) 1.211 + RETURN_ERROR(EFTYPE, error1); 1.212 +#if BYTE_ORDER == LITTLE_ENDIAN 1.213 + swap_header(hashp); 1.214 +#endif 1.215 + /* Verify file type, versions and hash function */ 1.216 + if (hashp->MAGIC != HASHMAGIC) 1.217 + RETURN_ERROR(EFTYPE, error1); 1.218 +#define OLDHASHVERSION 1 1.219 + if (hashp->VERSION != HASHVERSION && 1.220 + hashp->VERSION != OLDHASHVERSION) 1.221 + RETURN_ERROR(EFTYPE, error1); 1.222 + if (hashp->hash(CHARKEY, sizeof(CHARKEY)) != hashp->H_CHARKEY) 1.223 + RETURN_ERROR(EFTYPE, error1); 1.224 + if (hashp->NKEYS < 0) /* Old bad database. */ 1.225 + RETURN_ERROR(EFTYPE, error1); 1.226 + 1.227 + /* 1.228 + * Figure out how many segments we need. Max_Bucket is the 1.229 + * maximum bucket number, so the number of buckets is 1.230 + * max_bucket + 1. 1.231 + */ 1.232 + nsegs = (hashp->MAX_BUCKET + 1 + hashp->SGSIZE - 1) / 1.233 + hashp->SGSIZE; 1.234 + hashp->nsegs = 0; 1.235 + if (alloc_segs(hashp, nsegs)) 1.236 + /* If alloc_segs fails, errno will have been set. */ 1.237 + RETURN_ERROR(errno, error1); 1.238 + /* Read in bitmaps */ 1.239 + bpages = (hashp->SPARES[hashp->OVFL_POINT] + 1.240 + (hashp->BSIZE << BYTE_SHIFT) - 1) >> 1.241 + (hashp->BSHIFT + BYTE_SHIFT); 1.242 + 1.243 + hashp->nmaps = bpages; 1.244 + (void)memset(&hashp->mapp[0], 0, bpages * sizeof(uint32 *)); 1.245 + } 1.246 + 1.247 + /* Initialize Buffer Manager */ 1.248 + if (info && info->cachesize) 1.249 + __buf_init(hashp, (int32) info->cachesize); 1.250 + else 1.251 + __buf_init(hashp, DEF_BUFSIZE); 1.252 + 1.253 + hashp->new_file = new_table; 1.254 +#ifdef macintosh 1.255 + hashp->save_file = file && !(hashp->flags & O_RDONLY); 1.256 +#else 1.257 + hashp->save_file = file && (hashp->flags & O_RDWR); 1.258 +#endif 1.259 + hashp->cbucket = -1; 1.260 + if (!(dbp = (DB *)malloc(sizeof(DB)))) { 1.261 + RETURN_ERROR(ENOMEM, error1); 1.262 + } 1.263 + dbp->internal = hashp; 1.264 + dbp->close = hash_close; 1.265 + dbp->del = hash_delete; 1.266 + dbp->fd = hash_fd; 1.267 + dbp->get = hash_get; 1.268 + dbp->put = hash_put; 1.269 + dbp->seq = hash_seq; 1.270 + dbp->sync = hash_sync; 1.271 + dbp->type = DB_HASH; 1.272 + 1.273 +#ifdef HASH_STATISTICS 1.274 + hash_overflows = hash_accesses = hash_collisions = hash_expansions = 0; 1.275 +#endif 1.276 + return (dbp); 1.277 + 1.278 +error1: 1.279 + hdestroy(hashp); 1.280 + errno = save_errno; 1.281 + return (NULL); 1.282 +} 1.283 + 1.284 +static int 1.285 +hash_close(DB *dbp) 1.286 +{ 1.287 + HTAB *hashp; 1.288 + int retval; 1.289 + 1.290 + if (!dbp) 1.291 + return (DBM_ERROR); 1.292 + 1.293 + hashp = (HTAB *)dbp->internal; 1.294 + if(!hashp) 1.295 + return (DBM_ERROR); 1.296 + 1.297 + retval = hdestroy(hashp); 1.298 + free(dbp); 1.299 + return (retval); 1.300 +} 1.301 + 1.302 +static int hash_fd(const DB *dbp) 1.303 +{ 1.304 + HTAB *hashp; 1.305 + 1.306 + if (!dbp) 1.307 + return (DBM_ERROR); 1.308 + 1.309 + hashp = (HTAB *)dbp->internal; 1.310 + if(!hashp) 1.311 + return (DBM_ERROR); 1.312 + 1.313 + if (hashp->fp == -1) { 1.314 + errno = ENOENT; 1.315 + return (-1); 1.316 + } 1.317 + return (hashp->fp); 1.318 +} 1.319 + 1.320 +/************************** LOCAL CREATION ROUTINES **********************/ 1.321 +static HTAB * 1.322 +init_hash(HTAB *hashp, const char *file, HASHINFO *info) 1.323 +{ 1.324 + struct stat statbuf; 1.325 + int nelem; 1.326 + 1.327 + nelem = 1; 1.328 + hashp->NKEYS = 0; 1.329 + hashp->LORDER = BYTE_ORDER; 1.330 + hashp->BSIZE = DEF_BUCKET_SIZE; 1.331 + hashp->BSHIFT = DEF_BUCKET_SHIFT; 1.332 + hashp->SGSIZE = DEF_SEGSIZE; 1.333 + hashp->SSHIFT = DEF_SEGSIZE_SHIFT; 1.334 + hashp->DSIZE = DEF_DIRSIZE; 1.335 + hashp->FFACTOR = DEF_FFACTOR; 1.336 + hashp->hash = __default_hash; 1.337 + memset(hashp->SPARES, 0, sizeof(hashp->SPARES)); 1.338 + memset(hashp->BITMAPS, 0, sizeof (hashp->BITMAPS)); 1.339 + 1.340 + /* Fix bucket size to be optimal for file system */ 1.341 + if (file != NULL) { 1.342 + if (stat(file, &statbuf)) 1.343 + return (NULL); 1.344 + 1.345 +#if !defined(_WIN32) && !defined(_WINDOWS) && !defined(macintosh) && !defined(XP_OS2) 1.346 +#if defined(__QNX__) && !defined(__QNXNTO__) 1.347 + hashp->BSIZE = 512; /* preferred blk size on qnx4 */ 1.348 +#else 1.349 + hashp->BSIZE = statbuf.st_blksize; 1.350 +#endif 1.351 + 1.352 + /* new code added by Lou to reduce block 1.353 + * size down below MAX_BSIZE 1.354 + */ 1.355 + if (hashp->BSIZE > MAX_BSIZE) 1.356 + hashp->BSIZE = MAX_BSIZE; 1.357 +#endif 1.358 + hashp->BSHIFT = __log2((uint32)hashp->BSIZE); 1.359 + } 1.360 + 1.361 + if (info) { 1.362 + if (info->bsize) { 1.363 + /* Round pagesize up to power of 2 */ 1.364 + hashp->BSHIFT = __log2(info->bsize); 1.365 + hashp->BSIZE = 1 << hashp->BSHIFT; 1.366 + if (hashp->BSIZE > MAX_BSIZE) { 1.367 + errno = EINVAL; 1.368 + return (NULL); 1.369 + } 1.370 + } 1.371 + if (info->ffactor) 1.372 + hashp->FFACTOR = info->ffactor; 1.373 + if (info->hash) 1.374 + hashp->hash = info->hash; 1.375 + if (info->nelem) 1.376 + nelem = info->nelem; 1.377 + if (info->lorder) { 1.378 + if (info->lorder != BIG_ENDIAN && 1.379 + info->lorder != LITTLE_ENDIAN) { 1.380 + errno = EINVAL; 1.381 + return (NULL); 1.382 + } 1.383 + hashp->LORDER = info->lorder; 1.384 + } 1.385 + } 1.386 + /* init_htab sets errno if it fails */ 1.387 + if (init_htab(hashp, nelem)) 1.388 + return (NULL); 1.389 + else 1.390 + return (hashp); 1.391 +} 1.392 +/* 1.393 + * This calls alloc_segs which may run out of memory. Alloc_segs will 1.394 + * set errno, so we just pass the error information along. 1.395 + * 1.396 + * Returns 0 on No Error 1.397 + */ 1.398 +static int 1.399 +init_htab(HTAB *hashp, int nelem) 1.400 +{ 1.401 + register int nbuckets, nsegs; 1.402 + int l2; 1.403 + 1.404 + /* 1.405 + * Divide number of elements by the fill factor and determine a 1.406 + * desired number of buckets. Allocate space for the next greater 1.407 + * power of two number of buckets. 1.408 + */ 1.409 + nelem = (nelem - 1) / hashp->FFACTOR + 1; 1.410 + 1.411 + l2 = __log2((uint32)PR_MAX(nelem, 2)); 1.412 + nbuckets = 1 << l2; 1.413 + 1.414 + hashp->SPARES[l2] = l2 + 1; 1.415 + hashp->SPARES[l2 + 1] = l2 + 1; 1.416 + hashp->OVFL_POINT = l2; 1.417 + hashp->LAST_FREED = 2; 1.418 + 1.419 + /* First bitmap page is at: splitpoint l2 page offset 1 */ 1.420 + if (__ibitmap(hashp, (int)OADDR_OF(l2, 1), l2 + 1, 0)) 1.421 + return (-1); 1.422 + 1.423 + hashp->MAX_BUCKET = hashp->LOW_MASK = nbuckets - 1; 1.424 + hashp->HIGH_MASK = (nbuckets << 1) - 1; 1.425 + hashp->HDRPAGES = ((PR_MAX(sizeof(HASHHDR), MINHDRSIZE) - 1) >> 1.426 + hashp->BSHIFT) + 1; 1.427 + 1.428 + nsegs = (nbuckets - 1) / hashp->SGSIZE + 1; 1.429 + nsegs = 1 << __log2((uint32)nsegs); 1.430 + 1.431 + if (nsegs > hashp->DSIZE) 1.432 + hashp->DSIZE = nsegs; 1.433 + return (alloc_segs(hashp, nsegs)); 1.434 +} 1.435 + 1.436 +/********************** DESTROY/CLOSE ROUTINES ************************/ 1.437 + 1.438 +/* 1.439 + * Flushes any changes to the file if necessary and destroys the hashp 1.440 + * structure, freeing all allocated space. 1.441 + */ 1.442 +static int 1.443 +hdestroy(HTAB *hashp) 1.444 +{ 1.445 + int i, save_errno; 1.446 + 1.447 + save_errno = 0; 1.448 + 1.449 +#ifdef HASH_STATISTICS 1.450 + (void)fprintf(stderr, "hdestroy: accesses %ld collisions %ld\n", 1.451 + hash_accesses, hash_collisions); 1.452 + (void)fprintf(stderr, "hdestroy: expansions %ld\n", 1.453 + hash_expansions); 1.454 + (void)fprintf(stderr, "hdestroy: overflows %ld\n", 1.455 + hash_overflows); 1.456 + (void)fprintf(stderr, "keys %ld maxp %d segmentcount %d\n", 1.457 + hashp->NKEYS, hashp->MAX_BUCKET, hashp->nsegs); 1.458 + 1.459 + for (i = 0; i < NCACHED; i++) 1.460 + (void)fprintf(stderr, 1.461 + "spares[%d] = %d\n", i, hashp->SPARES[i]); 1.462 +#endif 1.463 + /* 1.464 + * Call on buffer manager to free buffers, and if required, 1.465 + * write them to disk. 1.466 + */ 1.467 + if (__buf_free(hashp, 1, hashp->save_file)) 1.468 + save_errno = errno; 1.469 + if (hashp->dir) { 1.470 + free(*hashp->dir); /* Free initial segments */ 1.471 + /* Free extra segments */ 1.472 + while (hashp->exsegs--) 1.473 + free(hashp->dir[--hashp->nsegs]); 1.474 + free(hashp->dir); 1.475 + } 1.476 + if (flush_meta(hashp) && !save_errno) 1.477 + save_errno = errno; 1.478 + /* Free Bigmaps */ 1.479 + for (i = 0; i < hashp->nmaps; i++) 1.480 + if (hashp->mapp[i]) 1.481 + free(hashp->mapp[i]); 1.482 + 1.483 + if (hashp->fp != -1) 1.484 + (void)close(hashp->fp); 1.485 + 1.486 + if(hashp->filename) { 1.487 +#if defined(_WIN32) || defined(_WINDOWS) || defined(XP_OS2) 1.488 + if (hashp->is_temp) 1.489 + (void)unlink(hashp->filename); 1.490 +#endif 1.491 + free(hashp->filename); 1.492 + } 1.493 + if (hashp->tmp_buf) 1.494 + free(hashp->tmp_buf); 1.495 + if (hashp->tmp_key) 1.496 + free(hashp->tmp_key); 1.497 + free(hashp); 1.498 + if (save_errno) { 1.499 + errno = save_errno; 1.500 + return (DBM_ERROR); 1.501 + } 1.502 + return (SUCCESS); 1.503 +} 1.504 + 1.505 +#if defined(_WIN32) || defined(_WINDOWS) 1.506 +/* 1.507 + * Close and reopen file to force file length update on windows. 1.508 + * 1.509 + * Returns: 1.510 + * 0 == OK 1.511 + * -1 DBM_ERROR 1.512 + */ 1.513 +static int 1.514 +update_EOF(HTAB *hashp) 1.515 +{ 1.516 +#if defined(DBM_REOPEN_ON_FLUSH) 1.517 + char * file = hashp->filename; 1.518 + off_t file_size; 1.519 + int flags; 1.520 + int mode = -1; 1.521 + struct stat statbuf; 1.522 + 1.523 + memset(&statbuf, 0, sizeof statbuf); 1.524 + 1.525 + /* make sure we won't lose the file by closing it. */ 1.526 + if (!file || (stat(file, &statbuf) && (errno == ENOENT))) { 1.527 + /* pretend we did it. */ 1.528 + return 0; 1.529 + } 1.530 + 1.531 + (void)close(hashp->fp); 1.532 + 1.533 + flags = hashp->flags & ~(O_TRUNC | O_CREAT | O_EXCL); 1.534 + 1.535 + if ((hashp->fp = DBFILE_OPEN(file, flags | O_BINARY, mode)) == -1) 1.536 + return -1; 1.537 + file_size = lseek(hashp->fp, (off_t)0, SEEK_END); 1.538 + if (file_size == -1) 1.539 + return -1; 1.540 + hashp->file_size = file_size; 1.541 + return 0; 1.542 +#else 1.543 + int fd = hashp->fp; 1.544 + off_t file_size = lseek(fd, (off_t)0, SEEK_END); 1.545 + HANDLE handle = (HANDLE)_get_osfhandle(fd); 1.546 + BOOL cool = FlushFileBuffers(handle); 1.547 +#ifdef DEBUG3 1.548 + if (!cool) { 1.549 + DWORD err = GetLastError(); 1.550 + (void)fprintf(stderr, 1.551 + "FlushFileBuffers failed, last error = %d, 0x%08x\n", 1.552 + err, err); 1.553 + } 1.554 +#endif 1.555 + if (file_size == -1) 1.556 + return -1; 1.557 + hashp->file_size = file_size; 1.558 + return cool ? 0 : -1; 1.559 +#endif 1.560 +} 1.561 +#endif 1.562 + 1.563 +/* 1.564 + * Write modified pages to disk 1.565 + * 1.566 + * Returns: 1.567 + * 0 == OK 1.568 + * -1 DBM_ERROR 1.569 + */ 1.570 +static int 1.571 +hash_sync(const DB *dbp, uint flags) 1.572 +{ 1.573 + HTAB *hashp; 1.574 + 1.575 + if (flags != 0) { 1.576 + errno = EINVAL; 1.577 + return (DBM_ERROR); 1.578 + } 1.579 + 1.580 + if (!dbp) 1.581 + return (DBM_ERROR); 1.582 + 1.583 + hashp = (HTAB *)dbp->internal; 1.584 + if(!hashp) 1.585 + return (DBM_ERROR); 1.586 + 1.587 + if (!hashp->save_file) 1.588 + return (0); 1.589 + if (__buf_free(hashp, 0, 1) || flush_meta(hashp)) 1.590 + return (DBM_ERROR); 1.591 +#if defined(_WIN32) || defined(_WINDOWS) 1.592 + if (hashp->updateEOF && hashp->filename && !hashp->is_temp) { 1.593 + int status = update_EOF(hashp); 1.594 + hashp->updateEOF = 0; 1.595 + if (status) 1.596 + return status; 1.597 + } 1.598 +#endif 1.599 + hashp->new_file = 0; 1.600 + return (0); 1.601 +} 1.602 + 1.603 +/* 1.604 + * Returns: 1.605 + * 0 == OK 1.606 + * -1 indicates that errno should be set 1.607 + */ 1.608 +static int 1.609 +flush_meta(HTAB *hashp) 1.610 +{ 1.611 + HASHHDR *whdrp; 1.612 +#if BYTE_ORDER == LITTLE_ENDIAN 1.613 + HASHHDR whdr; 1.614 +#endif 1.615 + int fp, i, wsize; 1.616 + 1.617 + if (!hashp->save_file) 1.618 + return (0); 1.619 + hashp->MAGIC = HASHMAGIC; 1.620 + hashp->VERSION = HASHVERSION; 1.621 + hashp->H_CHARKEY = hashp->hash(CHARKEY, sizeof(CHARKEY)); 1.622 + 1.623 + fp = hashp->fp; 1.624 + whdrp = &hashp->hdr; 1.625 +#if BYTE_ORDER == LITTLE_ENDIAN 1.626 + whdrp = &whdr; 1.627 + swap_header_copy(&hashp->hdr, whdrp); 1.628 +#endif 1.629 + if ((lseek(fp, (off_t)0, SEEK_SET) == -1) || 1.630 + ((wsize = write(fp, (char*)whdrp, sizeof(HASHHDR))) == -1)) 1.631 + return (-1); 1.632 + else 1.633 + if (wsize != sizeof(HASHHDR)) { 1.634 + errno = EFTYPE; 1.635 + hashp->dbmerrno = errno; 1.636 + return (-1); 1.637 + } 1.638 + for (i = 0; i < NCACHED; i++) 1.639 + if (hashp->mapp[i]) 1.640 + if (__put_page(hashp, (char *)hashp->mapp[i], 1.641 + hashp->BITMAPS[i], 0, 1)) 1.642 + return (-1); 1.643 + return (0); 1.644 +} 1.645 + 1.646 +/*******************************SEARCH ROUTINES *****************************/ 1.647 +/* 1.648 + * All the access routines return 1.649 + * 1.650 + * Returns: 1.651 + * 0 on SUCCESS 1.652 + * 1 to indicate an external DBM_ERROR (i.e. key not found, etc) 1.653 + * -1 to indicate an internal DBM_ERROR (i.e. out of memory, etc) 1.654 + */ 1.655 +static int 1.656 +hash_get( 1.657 + const DB *dbp, 1.658 + const DBT *key, 1.659 + DBT *data, 1.660 + uint flag) 1.661 +{ 1.662 + HTAB *hashp; 1.663 + int rv; 1.664 + 1.665 + hashp = (HTAB *)dbp->internal; 1.666 + if (!hashp) 1.667 + return (DBM_ERROR); 1.668 + 1.669 + if (flag) { 1.670 + hashp->dbmerrno = errno = EINVAL; 1.671 + return (DBM_ERROR); 1.672 + } 1.673 + 1.674 + rv = hash_access(hashp, HASH_GET, (DBT *)key, data); 1.675 + 1.676 + if(rv == DATABASE_CORRUPTED_ERROR) 1.677 + { 1.678 +#if defined(unix) && defined(DEBUG) 1.679 + printf("\n\nDBM Database has been corrupted, tell Lou...\n\n"); 1.680 +#endif 1.681 + __remove_database((DB *)dbp); 1.682 + } 1.683 + 1.684 + return(rv); 1.685 +} 1.686 + 1.687 +static int 1.688 +hash_put( 1.689 + const DB *dbp, 1.690 + DBT *key, 1.691 + const DBT *data, 1.692 + uint flag) 1.693 +{ 1.694 + HTAB *hashp; 1.695 + int rv; 1.696 + 1.697 + hashp = (HTAB *)dbp->internal; 1.698 + if (!hashp) 1.699 + return (DBM_ERROR); 1.700 + 1.701 + if (flag && flag != R_NOOVERWRITE) { 1.702 + hashp->dbmerrno = errno = EINVAL; 1.703 + return (DBM_ERROR); 1.704 + } 1.705 + if ((hashp->flags & O_ACCMODE) == O_RDONLY) { 1.706 + hashp->dbmerrno = errno = EPERM; 1.707 + return (DBM_ERROR); 1.708 + } 1.709 + 1.710 + rv = hash_access(hashp, flag == R_NOOVERWRITE ? 1.711 + HASH_PUTNEW : HASH_PUT, (DBT *)key, (DBT *)data); 1.712 + 1.713 + if(rv == DATABASE_CORRUPTED_ERROR) 1.714 + { 1.715 +#if defined(unix) && defined(DEBUG) 1.716 + printf("\n\nDBM Database has been corrupted, tell Lou...\n\n"); 1.717 +#endif 1.718 + __remove_database((DB *)dbp); 1.719 + } 1.720 + 1.721 + return(rv); 1.722 +} 1.723 + 1.724 +static int 1.725 +hash_delete( 1.726 + const DB *dbp, 1.727 + const DBT *key, 1.728 + uint flag) /* Ignored */ 1.729 +{ 1.730 + HTAB *hashp; 1.731 + int rv; 1.732 + 1.733 + hashp = (HTAB *)dbp->internal; 1.734 + if (!hashp) 1.735 + return (DBM_ERROR); 1.736 + 1.737 + if (flag && flag != R_CURSOR) { 1.738 + hashp->dbmerrno = errno = EINVAL; 1.739 + return (DBM_ERROR); 1.740 + } 1.741 + if ((hashp->flags & O_ACCMODE) == O_RDONLY) { 1.742 + hashp->dbmerrno = errno = EPERM; 1.743 + return (DBM_ERROR); 1.744 + } 1.745 + rv = hash_access(hashp, HASH_DELETE, (DBT *)key, NULL); 1.746 + 1.747 + if(rv == DATABASE_CORRUPTED_ERROR) 1.748 + { 1.749 +#if defined(unix) && defined(DEBUG) 1.750 + printf("\n\nDBM Database has been corrupted, tell Lou...\n\n"); 1.751 +#endif 1.752 + __remove_database((DB *)dbp); 1.753 + } 1.754 + 1.755 + return(rv); 1.756 +} 1.757 + 1.758 +#define MAX_OVERFLOW_HASH_ACCESS_LOOPS 2000 1.759 +/* 1.760 + * Assume that hashp has been set in wrapper routine. 1.761 + */ 1.762 +static int 1.763 +hash_access( 1.764 + HTAB *hashp, 1.765 + ACTION action, 1.766 + DBT *key, DBT *val) 1.767 +{ 1.768 + register BUFHEAD *rbufp; 1.769 + BUFHEAD *bufp, *save_bufp; 1.770 + register uint16 *bp; 1.771 + register long n, ndx, off; 1.772 + register size_t size; 1.773 + register char *kp; 1.774 + uint16 pageno; 1.775 + uint32 ovfl_loop_count=0; 1.776 + int32 last_overflow_page_no = -1; 1.777 + 1.778 +#ifdef HASH_STATISTICS 1.779 + hash_accesses++; 1.780 +#endif 1.781 + 1.782 + off = hashp->BSIZE; 1.783 + size = key->size; 1.784 + kp = (char *)key->data; 1.785 + rbufp = __get_buf(hashp, __call_hash(hashp, kp, size), NULL, 0); 1.786 + if (!rbufp) 1.787 + return (DATABASE_CORRUPTED_ERROR); 1.788 + save_bufp = rbufp; 1.789 + 1.790 + /* Pin the bucket chain */ 1.791 + rbufp->flags |= BUF_PIN; 1.792 + for (bp = (uint16 *)rbufp->page, n = *bp++, ndx = 1; ndx < n;) 1.793 + { 1.794 + 1.795 + if (bp[1] >= REAL_KEY) { 1.796 + /* Real key/data pair */ 1.797 + if (size == (unsigned long)(off - *bp) && 1.798 + memcmp(kp, rbufp->page + *bp, size) == 0) 1.799 + goto found; 1.800 + off = bp[1]; 1.801 +#ifdef HASH_STATISTICS 1.802 + hash_collisions++; 1.803 +#endif 1.804 + bp += 2; 1.805 + ndx += 2; 1.806 + } else if (bp[1] == OVFLPAGE) { 1.807 + 1.808 + /* database corruption: overflow loop detection */ 1.809 + if(last_overflow_page_no == (int32)*bp) 1.810 + return (DATABASE_CORRUPTED_ERROR); 1.811 + 1.812 + last_overflow_page_no = *bp; 1.813 + 1.814 + rbufp = __get_buf(hashp, *bp, rbufp, 0); 1.815 + if (!rbufp) { 1.816 + save_bufp->flags &= ~BUF_PIN; 1.817 + return (DBM_ERROR); 1.818 + } 1.819 + 1.820 + ovfl_loop_count++; 1.821 + if(ovfl_loop_count > MAX_OVERFLOW_HASH_ACCESS_LOOPS) 1.822 + return (DATABASE_CORRUPTED_ERROR); 1.823 + 1.824 + /* FOR LOOP INIT */ 1.825 + bp = (uint16 *)rbufp->page; 1.826 + n = *bp++; 1.827 + ndx = 1; 1.828 + off = hashp->BSIZE; 1.829 + } else if (bp[1] < REAL_KEY) { 1.830 + if ((ndx = 1.831 + __find_bigpair(hashp, rbufp, ndx, kp, (int)size)) > 0) 1.832 + goto found; 1.833 + if (ndx == -2) { 1.834 + bufp = rbufp; 1.835 + if (!(pageno = 1.836 + __find_last_page(hashp, &bufp))) { 1.837 + ndx = 0; 1.838 + rbufp = bufp; 1.839 + break; /* FOR */ 1.840 + } 1.841 + rbufp = __get_buf(hashp, pageno, bufp, 0); 1.842 + if (!rbufp) { 1.843 + save_bufp->flags &= ~BUF_PIN; 1.844 + return (DBM_ERROR); 1.845 + } 1.846 + /* FOR LOOP INIT */ 1.847 + bp = (uint16 *)rbufp->page; 1.848 + n = *bp++; 1.849 + ndx = 1; 1.850 + off = hashp->BSIZE; 1.851 + } else { 1.852 + save_bufp->flags &= ~BUF_PIN; 1.853 + return (DBM_ERROR); 1.854 + 1.855 + } 1.856 + } 1.857 + } 1.858 + 1.859 + /* Not found */ 1.860 + switch (action) { 1.861 + case HASH_PUT: 1.862 + case HASH_PUTNEW: 1.863 + if (__addel(hashp, rbufp, key, val)) { 1.864 + save_bufp->flags &= ~BUF_PIN; 1.865 + return (DBM_ERROR); 1.866 + } else { 1.867 + save_bufp->flags &= ~BUF_PIN; 1.868 + return (SUCCESS); 1.869 + } 1.870 + case HASH_GET: 1.871 + case HASH_DELETE: 1.872 + default: 1.873 + save_bufp->flags &= ~BUF_PIN; 1.874 + return (ABNORMAL); 1.875 + } 1.876 + 1.877 +found: 1.878 + switch (action) { 1.879 + case HASH_PUTNEW: 1.880 + save_bufp->flags &= ~BUF_PIN; 1.881 + return (ABNORMAL); 1.882 + case HASH_GET: 1.883 + bp = (uint16 *)rbufp->page; 1.884 + if (bp[ndx + 1] < REAL_KEY) { 1.885 + if (__big_return(hashp, rbufp, ndx, val, 0)) 1.886 + return (DBM_ERROR); 1.887 + } else { 1.888 + val->data = (uint8 *)rbufp->page + (int)bp[ndx + 1]; 1.889 + val->size = bp[ndx] - bp[ndx + 1]; 1.890 + } 1.891 + break; 1.892 + case HASH_PUT: 1.893 + if ((__delpair(hashp, rbufp, ndx)) || 1.894 + (__addel(hashp, rbufp, key, val))) { 1.895 + save_bufp->flags &= ~BUF_PIN; 1.896 + return (DBM_ERROR); 1.897 + } 1.898 + break; 1.899 + case HASH_DELETE: 1.900 + if (__delpair(hashp, rbufp, ndx)) 1.901 + return (DBM_ERROR); 1.902 + break; 1.903 + default: 1.904 + abort(); 1.905 + } 1.906 + save_bufp->flags &= ~BUF_PIN; 1.907 + return (SUCCESS); 1.908 +} 1.909 + 1.910 +static int 1.911 +hash_seq( 1.912 + const DB *dbp, 1.913 + DBT *key, DBT *data, 1.914 + uint flag) 1.915 +{ 1.916 + register uint32 bucket; 1.917 + register BUFHEAD *bufp; 1.918 + HTAB *hashp; 1.919 + uint16 *bp, ndx; 1.920 + 1.921 + hashp = (HTAB *)dbp->internal; 1.922 + if (!hashp) 1.923 + return (DBM_ERROR); 1.924 + 1.925 + if (flag && flag != R_FIRST && flag != R_NEXT) { 1.926 + hashp->dbmerrno = errno = EINVAL; 1.927 + return (DBM_ERROR); 1.928 + } 1.929 +#ifdef HASH_STATISTICS 1.930 + hash_accesses++; 1.931 +#endif 1.932 + if ((hashp->cbucket < 0) || (flag == R_FIRST)) { 1.933 + hashp->cbucket = 0; 1.934 + hashp->cndx = 1; 1.935 + hashp->cpage = NULL; 1.936 + } 1.937 + 1.938 + for (bp = NULL; !bp || !bp[0]; ) { 1.939 + if (!(bufp = hashp->cpage)) { 1.940 + for (bucket = hashp->cbucket; 1.941 + bucket <= (uint32)hashp->MAX_BUCKET; 1.942 + bucket++, hashp->cndx = 1) { 1.943 + bufp = __get_buf(hashp, bucket, NULL, 0); 1.944 + if (!bufp) 1.945 + return (DBM_ERROR); 1.946 + hashp->cpage = bufp; 1.947 + bp = (uint16 *)bufp->page; 1.948 + if (bp[0]) 1.949 + break; 1.950 + } 1.951 + hashp->cbucket = bucket; 1.952 + if (hashp->cbucket > hashp->MAX_BUCKET) { 1.953 + hashp->cbucket = -1; 1.954 + return (ABNORMAL); 1.955 + } 1.956 + } else 1.957 + bp = (uint16 *)hashp->cpage->page; 1.958 + 1.959 +#ifdef DEBUG 1.960 + assert(bp); 1.961 + assert(bufp); 1.962 +#endif 1.963 + while (bp[hashp->cndx + 1] == OVFLPAGE) { 1.964 + bufp = hashp->cpage = 1.965 + __get_buf(hashp, bp[hashp->cndx], bufp, 0); 1.966 + if (!bufp) 1.967 + return (DBM_ERROR); 1.968 + bp = (uint16 *)(bufp->page); 1.969 + hashp->cndx = 1; 1.970 + } 1.971 + if (!bp[0]) { 1.972 + hashp->cpage = NULL; 1.973 + ++hashp->cbucket; 1.974 + } 1.975 + } 1.976 + ndx = hashp->cndx; 1.977 + if (bp[ndx + 1] < REAL_KEY) { 1.978 + if (__big_keydata(hashp, bufp, key, data, 1)) 1.979 + return (DBM_ERROR); 1.980 + } else { 1.981 + key->data = (uint8 *)hashp->cpage->page + bp[ndx]; 1.982 + key->size = (ndx > 1 ? bp[ndx - 1] : hashp->BSIZE) - bp[ndx]; 1.983 + data->data = (uint8 *)hashp->cpage->page + bp[ndx + 1]; 1.984 + data->size = bp[ndx] - bp[ndx + 1]; 1.985 + ndx += 2; 1.986 + if (ndx > bp[0]) { 1.987 + hashp->cpage = NULL; 1.988 + hashp->cbucket++; 1.989 + hashp->cndx = 1; 1.990 + } else 1.991 + hashp->cndx = ndx; 1.992 + } 1.993 + return (SUCCESS); 1.994 +} 1.995 + 1.996 +/********************************* UTILITIES ************************/ 1.997 + 1.998 +/* 1.999 + * Returns: 1.1000 + * 0 ==> OK 1.1001 + * -1 ==> Error 1.1002 + */ 1.1003 +extern int 1.1004 +__expand_table(HTAB *hashp) 1.1005 +{ 1.1006 + uint32 old_bucket, new_bucket; 1.1007 + int new_segnum, spare_ndx; 1.1008 + size_t dirsize; 1.1009 + 1.1010 +#ifdef HASH_STATISTICS 1.1011 + hash_expansions++; 1.1012 +#endif 1.1013 + new_bucket = ++hashp->MAX_BUCKET; 1.1014 + old_bucket = (hashp->MAX_BUCKET & hashp->LOW_MASK); 1.1015 + 1.1016 + new_segnum = new_bucket >> hashp->SSHIFT; 1.1017 + 1.1018 + /* Check if we need a new segment */ 1.1019 + if (new_segnum >= hashp->nsegs) { 1.1020 + /* Check if we need to expand directory */ 1.1021 + if (new_segnum >= hashp->DSIZE) { 1.1022 + /* Reallocate directory */ 1.1023 + dirsize = hashp->DSIZE * sizeof(SEGMENT *); 1.1024 + if (!hash_realloc(&hashp->dir, dirsize, dirsize << 1)) 1.1025 + return (-1); 1.1026 + hashp->DSIZE = dirsize << 1; 1.1027 + } 1.1028 + if ((hashp->dir[new_segnum] = 1.1029 + (SEGMENT)calloc((size_t)hashp->SGSIZE, sizeof(SEGMENT))) == NULL) 1.1030 + return (-1); 1.1031 + hashp->exsegs++; 1.1032 + hashp->nsegs++; 1.1033 + } 1.1034 + /* 1.1035 + * If the split point is increasing (MAX_BUCKET's log base 2 1.1036 + * * increases), we need to copy the current contents of the spare 1.1037 + * split bucket to the next bucket. 1.1038 + */ 1.1039 + spare_ndx = __log2((uint32)(hashp->MAX_BUCKET + 1)); 1.1040 + if (spare_ndx > hashp->OVFL_POINT) { 1.1041 + hashp->SPARES[spare_ndx] = hashp->SPARES[hashp->OVFL_POINT]; 1.1042 + hashp->OVFL_POINT = spare_ndx; 1.1043 + } 1.1044 + 1.1045 + if (new_bucket > (uint32)hashp->HIGH_MASK) { 1.1046 + /* Starting a new doubling */ 1.1047 + hashp->LOW_MASK = hashp->HIGH_MASK; 1.1048 + hashp->HIGH_MASK = new_bucket | hashp->LOW_MASK; 1.1049 + } 1.1050 + /* Relocate records to the new bucket */ 1.1051 + return (__split_page(hashp, old_bucket, new_bucket)); 1.1052 +} 1.1053 + 1.1054 +/* 1.1055 + * If realloc guarantees that the pointer is not destroyed if the realloc 1.1056 + * fails, then this routine can go away. 1.1057 + */ 1.1058 +static void * 1.1059 +hash_realloc( 1.1060 + SEGMENT **p_ptr, 1.1061 + size_t oldsize, size_t newsize) 1.1062 +{ 1.1063 + register void *p; 1.1064 + 1.1065 + if ((p = malloc(newsize))) { 1.1066 + memmove(p, *p_ptr, oldsize); 1.1067 + memset((char *)p + oldsize, 0, newsize - oldsize); 1.1068 + free(*p_ptr); 1.1069 + *p_ptr = (SEGMENT *)p; 1.1070 + } 1.1071 + return (p); 1.1072 +} 1.1073 + 1.1074 +extern uint32 1.1075 +__call_hash(HTAB *hashp, char *k, size_t len) 1.1076 +{ 1.1077 + uint32 n, bucket; 1.1078 + 1.1079 + n = hashp->hash(k, len); 1.1080 + bucket = n & hashp->HIGH_MASK; 1.1081 + if (bucket > (uint32)hashp->MAX_BUCKET) 1.1082 + bucket = bucket & hashp->LOW_MASK; 1.1083 + return (bucket); 1.1084 +} 1.1085 + 1.1086 +/* 1.1087 + * Allocate segment table. On error, set errno. 1.1088 + * 1.1089 + * Returns 0 on success 1.1090 + */ 1.1091 +static int 1.1092 +alloc_segs( 1.1093 + HTAB *hashp, 1.1094 + int nsegs) 1.1095 +{ 1.1096 + register int i; 1.1097 + register SEGMENT store; 1.1098 + 1.1099 + if ((hashp->dir = 1.1100 + (SEGMENT *)calloc((size_t)hashp->DSIZE, sizeof(SEGMENT *))) == NULL) { 1.1101 + errno = ENOMEM; 1.1102 + return (-1); 1.1103 + } 1.1104 + /* Allocate segments */ 1.1105 + if ((store = 1.1106 + (SEGMENT)calloc((size_t)nsegs << hashp->SSHIFT, sizeof(SEGMENT))) == NULL) { 1.1107 + errno = ENOMEM; 1.1108 + return (-1); 1.1109 + } 1.1110 + for (i = 0; i < nsegs; i++, hashp->nsegs++) 1.1111 + hashp->dir[i] = &store[i << hashp->SSHIFT]; 1.1112 + return (0); 1.1113 +} 1.1114 + 1.1115 +#if BYTE_ORDER == LITTLE_ENDIAN 1.1116 +/* 1.1117 + * Hashp->hdr needs to be byteswapped. 1.1118 + */ 1.1119 +static void 1.1120 +swap_header_copy( 1.1121 + HASHHDR *srcp, HASHHDR *destp) 1.1122 +{ 1.1123 + int i; 1.1124 + 1.1125 + P_32_COPY(srcp->magic, destp->magic); 1.1126 + P_32_COPY(srcp->version, destp->version); 1.1127 + P_32_COPY(srcp->lorder, destp->lorder); 1.1128 + P_32_COPY(srcp->bsize, destp->bsize); 1.1129 + P_32_COPY(srcp->bshift, destp->bshift); 1.1130 + P_32_COPY(srcp->dsize, destp->dsize); 1.1131 + P_32_COPY(srcp->ssize, destp->ssize); 1.1132 + P_32_COPY(srcp->sshift, destp->sshift); 1.1133 + P_32_COPY(srcp->ovfl_point, destp->ovfl_point); 1.1134 + P_32_COPY(srcp->last_freed, destp->last_freed); 1.1135 + P_32_COPY(srcp->max_bucket, destp->max_bucket); 1.1136 + P_32_COPY(srcp->high_mask, destp->high_mask); 1.1137 + P_32_COPY(srcp->low_mask, destp->low_mask); 1.1138 + P_32_COPY(srcp->ffactor, destp->ffactor); 1.1139 + P_32_COPY(srcp->nkeys, destp->nkeys); 1.1140 + P_32_COPY(srcp->hdrpages, destp->hdrpages); 1.1141 + P_32_COPY(srcp->h_charkey, destp->h_charkey); 1.1142 + for (i = 0; i < NCACHED; i++) { 1.1143 + P_32_COPY(srcp->spares[i], destp->spares[i]); 1.1144 + P_16_COPY(srcp->bitmaps[i], destp->bitmaps[i]); 1.1145 + } 1.1146 +} 1.1147 + 1.1148 +static void 1.1149 +swap_header(HTAB *hashp) 1.1150 +{ 1.1151 + HASHHDR *hdrp; 1.1152 + int i; 1.1153 + 1.1154 + hdrp = &hashp->hdr; 1.1155 + 1.1156 + M_32_SWAP(hdrp->magic); 1.1157 + M_32_SWAP(hdrp->version); 1.1158 + M_32_SWAP(hdrp->lorder); 1.1159 + M_32_SWAP(hdrp->bsize); 1.1160 + M_32_SWAP(hdrp->bshift); 1.1161 + M_32_SWAP(hdrp->dsize); 1.1162 + M_32_SWAP(hdrp->ssize); 1.1163 + M_32_SWAP(hdrp->sshift); 1.1164 + M_32_SWAP(hdrp->ovfl_point); 1.1165 + M_32_SWAP(hdrp->last_freed); 1.1166 + M_32_SWAP(hdrp->max_bucket); 1.1167 + M_32_SWAP(hdrp->high_mask); 1.1168 + M_32_SWAP(hdrp->low_mask); 1.1169 + M_32_SWAP(hdrp->ffactor); 1.1170 + M_32_SWAP(hdrp->nkeys); 1.1171 + M_32_SWAP(hdrp->hdrpages); 1.1172 + M_32_SWAP(hdrp->h_charkey); 1.1173 + for (i = 0; i < NCACHED; i++) { 1.1174 + M_32_SWAP(hdrp->spares[i]); 1.1175 + M_16_SWAP(hdrp->bitmaps[i]); 1.1176 + } 1.1177 +} 1.1178 +#endif