Bug Summary

File:s/lib/dbm/src/h_bigkey.c
Warning:line 194, column 5
Value stored to 'pageno' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name h_bigkey.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/nss-scan-build/nss/lib/dbm/src -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/var/lib/jenkins/workspace/nss-scan-build/nss/lib/dbm/src -resource-dir /usr/lib/llvm-18/lib/clang/18 -D HAVE_STRERROR -D LINUX -D linux -D XP_UNIX -D XP_UNIX -D DEBUG -U NDEBUG -D _DEFAULT_SOURCE -D _BSD_SOURCE -D _POSIX_SOURCE -D SDB_MEASURE_USE_TEMP_DIR -D _REENTRANT -D DEBUG -U NDEBUG -D _DEFAULT_SOURCE -D _BSD_SOURCE -D _POSIX_SOURCE -D SDB_MEASURE_USE_TEMP_DIR -D _REENTRANT -D NSS_DISABLE_SSE3 -D NSS_NO_INIT_SUPPORT -D USE_UTIL_DIRECTLY -D NO_NSPR_10_SUPPORT -D SSL_DISABLE_DEPRECATED_CIPHER_SUITE_NAMES -D STDC_HEADERS -D HAVE_STRERROR -D HAVE_SNPRINTF -D MEMMOVE -D __DBINTERFACE_PRIVATE -I ../../../../dist/Linux4.19_x86_64_gcc_glibc_PTH_64_DBG.OBJ/include -I ../../../../dist/public/dbm -I ../../../../dist/private/dbm -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -std=c99 -ferror-limit 19 -fgnuc-version=4.2.1 -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-05-18-082241-28900-1 -x c h_bigkey.c
1/*-
2 * Copyright (c) 1990, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Margo Seltzer.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. ***REMOVED*** - see
17 * ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change
18 * 4. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35#if defined(LIBC_SCCS) && !defined(lint)
36static char sccsid[] = "@(#)hash_bigkey.c 8.3 (Berkeley) 5/31/94";
37#endif /* LIBC_SCCS and not lint */
38
39/*
40 * PACKAGE: hash
41 * DESCRIPTION:
42 * Big key/data handling for the hashing package.
43 *
44 * ROUTINES:
45 * External
46 * __big_keydata
47 * __big_split
48 * __big_insert
49 * __big_return
50 * __big_delete
51 * __find_last_page
52 * Internal
53 * collect_key
54 * collect_data
55 */
56
57#if !defined(_WIN32) && !defined(_WINDOWS) && !defined(macintosh)
58#include <sys/param.h>
59#endif
60
61#include <errno(*__errno_location ()).h>
62#include <stdio.h>
63#include <stdlib.h>
64#include <string.h>
65
66#ifdef DEBUG1
67#include <assert.h>
68#endif
69
70#include "mcom_db.h"
71#include "hash.h"
72#include "page.h"
73/* #include "extern.h" */
74
75static int collect_key(HTAB *, BUFHEAD *, int, DBT *, int);
76static int collect_data(HTAB *, BUFHEAD *, int, int);
77
78/*
79 * Big_insert
80 *
81 * You need to do an insert and the key/data pair is too big
82 *
83 * Returns:
84 * 0 ==> OK
85 *-1 ==> ERROR
86 */
87extern int
88dbm_big_insert(HTAB *hashp, BUFHEAD *bufp, const DBT *key, const DBT *val)
89{
90 register uint16 *p;
91 uint key_size, n, val_size;
92 uint16 space, move_bytes, off;
93 char *cp, *key_data, *val_data;
94
95 cp = bufp->page; /* Character pointer of p. */
96 p = (uint16 *)cp;
97
98 key_data = (char *)key->data;
99 key_size = key->size;
100 val_data = (char *)val->data;
101 val_size = val->size;
102
103 /* First move the Key */
104 for (space = FREESPACE(p)((p)[(p)[0] + 1]) - BIGOVERHEAD(4 * sizeof(uint16)); key_size;
105 space = FREESPACE(p)((p)[(p)[0] + 1]) - BIGOVERHEAD(4 * sizeof(uint16))) {
106 move_bytes = PR_MIN(space, key_size)((space)<(key_size)?(space):(key_size));
107 off = OFFSET(p)((p)[(p)[0] + 2]) - move_bytes;
108 memmove(cp + off, key_data, move_bytes);
109 key_size -= move_bytes;
110 key_data += move_bytes;
111 n = p[0];
112 p[++n] = off;
113 p[0] = ++n;
114 FREESPACE(p)((p)[(p)[0] + 1]) = off - PAGE_META(n)(((n) + 3) * sizeof(uint16));
115 OFFSET(p)((p)[(p)[0] + 2]) = off;
116 p[n] = PARTIAL_KEY1;
117 bufp = dbm_add_ovflpage(hashp, bufp);
118 if (!bufp)
119 return (-1);
120 n = p[0];
121 if (!key_size) {
122 if (FREESPACE(p)((p)[(p)[0] + 1])) {
123 move_bytes = PR_MIN(FREESPACE(p), val_size)((((p)[(p)[0] + 1]))<(val_size)?(((p)[(p)[0] + 1])):(val_size
))
;
124 off = OFFSET(p)((p)[(p)[0] + 2]) - move_bytes;
125 p[n] = off;
126 memmove(cp + off, val_data, move_bytes);
127 val_data += move_bytes;
128 val_size -= move_bytes;
129 p[n - 2] = FULL_KEY_DATA3;
130 FREESPACE(p)((p)[(p)[0] + 1]) = FREESPACE(p)((p)[(p)[0] + 1]) - move_bytes;
131 OFFSET(p)((p)[(p)[0] + 2]) = off;
132 } else
133 p[n - 2] = FULL_KEY2;
134 }
135 p = (uint16 *)bufp->page;
136 cp = bufp->page;
137 bufp->flags |= BUF_MOD0x0001;
138 }
139
140 /* Now move the data */
141 for (space = FREESPACE(p)((p)[(p)[0] + 1]) - BIGOVERHEAD(4 * sizeof(uint16)); val_size;
142 space = FREESPACE(p)((p)[(p)[0] + 1]) - BIGOVERHEAD(4 * sizeof(uint16))) {
143 move_bytes = PR_MIN(space, val_size)((space)<(val_size)?(space):(val_size));
144 /*
145 * Here's the hack to make sure that if the data ends on the
146 * same page as the key ends, FREESPACE is at least one.
147 */
148 if (space == val_size && val_size == val->size)
149 move_bytes--;
150 off = OFFSET(p)((p)[(p)[0] + 2]) - move_bytes;
151 memmove(cp + off, val_data, move_bytes);
152 val_size -= move_bytes;
153 val_data += move_bytes;
154 n = p[0];
155 p[++n] = off;
156 p[0] = ++n;
157 FREESPACE(p)((p)[(p)[0] + 1]) = off - PAGE_META(n)(((n) + 3) * sizeof(uint16));
158 OFFSET(p)((p)[(p)[0] + 2]) = off;
159 if (val_size) {
160 p[n] = FULL_KEY2;
161 bufp = dbm_add_ovflpage(hashp, bufp);
162 if (!bufp)
163 return (-1);
164 cp = bufp->page;
165 p = (uint16 *)cp;
166 } else
167 p[n] = FULL_KEY_DATA3;
168 bufp->flags |= BUF_MOD0x0001;
169 }
170 return (0);
171}
172
173/*
174 * Called when bufp's page contains a partial key (index should be 1)
175 *
176 * All pages in the big key/data pair except bufp are freed. We cannot
177 * free bufp because the page pointing to it is lost and we can't get rid
178 * of its pointer.
179 *
180 * Returns:
181 * 0 => OK
182 *-1 => ERROR
183 */
184extern int
185dbm_big_delete(HTAB *hashp, BUFHEAD *bufp)
186{
187 register BUFHEAD *last_bfp, *rbufp;
188 uint16 *bp, pageno;
189 int key_done, n;
190
191 rbufp = bufp;
192 last_bfp = NULL((void*)0);
193 bp = (uint16 *)bufp->page;
194 pageno = 0;
Value stored to 'pageno' is never read
195 key_done = 0;
196
197 while (!key_done || (bp[2] != FULL_KEY_DATA3)) {
198 if (bp[2] == FULL_KEY2 || bp[2] == FULL_KEY_DATA3)
199 key_done = 1;
200
201 /*
202 * If there is freespace left on a FULL_KEY_DATA page, then
203 * the data is short and fits entirely on this page, and this
204 * is the last page.
205 */
206 if (bp[2] == FULL_KEY_DATA3 && FREESPACE(bp)((bp)[(bp)[0] + 1]))
207 break;
208 pageno = bp[bp[0] - 1];
209 rbufp->flags |= BUF_MOD0x0001;
210 rbufp = dbm_get_buf(hashp, pageno, rbufp, 0);
211 if (last_bfp)
212 dbm_free_ovflpage(hashp, last_bfp);
213 last_bfp = rbufp;
214 if (!rbufp)
215 return (-1); /* Error. */
216 bp = (uint16 *)rbufp->page;
217 }
218
219 /*
220 * If we get here then rbufp points to the last page of the big
221 * key/data pair. Bufp points to the first one -- it should now be
222 * empty pointing to the next page after this pair. Can't free it
223 * because we don't have the page pointing to it.
224 */
225
226 /* This is information from the last page of the pair. */
227 n = bp[0];
228 pageno = bp[n - 1];
229
230 /* Now, bp is the first page of the pair. */
231 bp = (uint16 *)bufp->page;
232 if (n > 2) {
233 /* There is an overflow page. */
234 bp[1] = pageno;
235 bp[2] = OVFLPAGE0;
236 bufp->ovfl = rbufp->ovfl;
237 } else
238 /* This is the last page. */
239 bufp->ovfl = NULL((void*)0);
240 n -= 2;
241 bp[0] = n;
242 FREESPACE(bp)((bp)[(bp)[0] + 1]) = hashp->BSIZEhdr.bsize - PAGE_META(n)(((n) + 3) * sizeof(uint16));
243 OFFSET(bp)((bp)[(bp)[0] + 2]) = hashp->BSIZEhdr.bsize - 1;
244
245 bufp->flags |= BUF_MOD0x0001;
246 if (rbufp)
247 dbm_free_ovflpage(hashp, rbufp);
248 if (last_bfp != rbufp)
249 dbm_free_ovflpage(hashp, last_bfp);
250
251 hashp->NKEYShdr.nkeys--;
252 return (0);
253}
254/*
255 * Returns:
256 * 0 = key not found
257 * -1 = get next overflow page
258 * -2 means key not found and this is big key/data
259 * -3 error
260 */
261extern int
262dbm_find_bigpair(HTAB *hashp, BUFHEAD *bufp, int ndx, char *key, int size)
263{
264 register uint16 *bp;
265 register char *p;
266 int ksize;
267 uint16 bytes;
268 char *kkey;
269
270 bp = (uint16 *)bufp->page;
271 p = bufp->page;
272 ksize = size;
273 kkey = key;
274
275 for (bytes = hashp->BSIZEhdr.bsize - bp[ndx];
276 bytes <= size && bp[ndx + 1] == PARTIAL_KEY1;
277 bytes = hashp->BSIZEhdr.bsize - bp[ndx]) {
278 if (memcmp(p + bp[ndx], kkey, bytes))
279 return (-2);
280 kkey += bytes;
281 ksize -= bytes;
282 bufp = dbm_get_buf(hashp, bp[ndx + 2], bufp, 0);
283 if (!bufp)
284 return (-3);
285 p = bufp->page;
286 bp = (uint16 *)p;
287 ndx = 1;
288 }
289
290 if (bytes != ksize || memcmp(p + bp[ndx], kkey, bytes)) {
291#ifdef HASH_STATISTICS
292 ++hash_collisions;
293#endif
294 return (-2);
295 } else
296 return (ndx);
297}
298
299/*
300 * Given the buffer pointer of the first overflow page of a big pair,
301 * find the end of the big pair
302 *
303 * This will set bpp to the buffer header of the last page of the big pair.
304 * It will return the pageno of the overflow page following the last page
305 * of the pair; 0 if there isn't any (i.e. big pair is the last key in the
306 * bucket)
307 */
308extern uint16
309dbm_find_last_page(HTAB *hashp, BUFHEAD **bpp)
310{
311 BUFHEAD *bufp;
312 uint16 *bp, pageno;
313 uint n;
314
315 bufp = *bpp;
316 bp = (uint16 *)bufp->page;
317 for (;;) {
318 n = bp[0];
319
320 /*
321 * This is the last page if: the tag is FULL_KEY_DATA and
322 * either only 2 entries OVFLPAGE marker is explicit there
323 * is freespace on the page.
324 */
325 if (bp[2] == FULL_KEY_DATA3 &&
326 ((n == 2) || (bp[n] == OVFLPAGE0) || (FREESPACE(bp)((bp)[(bp)[0] + 1]))))
327 break;
328
329 /* LJM bound the size of n to reasonable limits
330 */
331 if (n > hashp->BSIZEhdr.bsize / sizeof(uint16))
332 return (0);
333
334 pageno = bp[n - 1];
335 bufp = dbm_get_buf(hashp, pageno, bufp, 0);
336 if (!bufp)
337 return (0); /* Need to indicate an error! */
338 bp = (uint16 *)bufp->page;
339 }
340
341 *bpp = bufp;
342 if (bp[0] > 2)
343 return (bp[3]);
344 else
345 return (0);
346}
347
348/*
349 * Return the data for the key/data pair that begins on this page at this
350 * index (index should always be 1).
351 */
352extern int
353dbm_big_return(
354 HTAB *hashp,
355 BUFHEAD *bufp,
356 int ndx,
357 DBT *val,
358 int set_current)
359{
360 BUFHEAD *save_p;
361 uint16 *bp, len, off, save_addr;
362 char *tp;
363 int save_flags;
364
365 bp = (uint16 *)bufp->page;
366 while (bp[ndx + 1] == PARTIAL_KEY1) {
367 bufp = dbm_get_buf(hashp, bp[bp[0] - 1], bufp, 0);
368 if (!bufp)
369 return (-1);
370 bp = (uint16 *)bufp->page;
371 ndx = 1;
372 }
373
374 if (bp[ndx + 1] == FULL_KEY2) {
375 bufp = dbm_get_buf(hashp, bp[bp[0] - 1], bufp, 0);
376 if (!bufp)
377 return (-1);
378 bp = (uint16 *)bufp->page;
379 save_p = bufp;
380 save_addr = save_p->addr;
381 off = bp[1];
382 len = 0;
383 } else if (!FREESPACE(bp)((bp)[(bp)[0] + 1])) {
384 /*
385 * This is a hack. We can't distinguish between
386 * FULL_KEY_DATA that contains complete data or
387 * incomplete data, so we require that if the data
388 * is complete, there is at least 1 byte of free
389 * space left.
390 */
391 off = bp[bp[0]];
392 len = bp[1] - off;
393 save_p = bufp;
394 save_addr = bufp->addr;
395 bufp = dbm_get_buf(hashp, bp[bp[0] - 1], bufp, 0);
396 if (!bufp)
397 return (-1);
398 bp = (uint16 *)bufp->page;
399 } else {
400 /* The data is all on one page. */
401 tp = (char *)bp;
402 off = bp[bp[0]];
403 val->data = (uint8 *)tp + off;
404 val->size = bp[1] - off;
405 if (set_current) {
406 if (bp[0] == 2) { /* No more buckets in
407 * chain */
408 hashp->cpage = NULL((void*)0);
409 hashp->cbucket++;
410 hashp->cndx = 1;
411 } else {
412 hashp->cpage = dbm_get_buf(hashp,
413 bp[bp[0] - 1], bufp, 0);
414 if (!hashp->cpage)
415 return (-1);
416 hashp->cndx = 1;
417 if (!((uint16 *)
418 hashp->cpage->page)[0]) {
419 hashp->cbucket++;
420 hashp->cpage = NULL((void*)0);
421 }
422 }
423 }
424 return (0);
425 }
426
427 /* pin our saved buf so that we don't lose if
428 * we run out of buffers */
429 save_flags = save_p->flags;
430 save_p->flags |= BUF_PIN0x0008;
431 val->size = collect_data(hashp, bufp, (int)len, set_current);
432 save_p->flags = save_flags;
433 if (val->size == (size_t)-1)
434 return (-1);
435 if (save_p->addr != save_addr) {
436 /* We are pretty short on buffers. */
437 errno(*__errno_location ()) = EINVAL22; /* OUT OF BUFFERS */
438 return (-1);
439 }
440 memmove(hashp->tmp_buf, (save_p->page) + off, len);
441 val->data = (uint8 *)hashp->tmp_buf;
442 return (0);
443}
444
445/*
446 * Count how big the total datasize is by looping through the pages. Then
447 * allocate a buffer and copy the data in the second loop. NOTE: Our caller
448 * may already have a bp which it is holding onto. The caller is
449 * responsible for copying that bp into our temp buffer. 'len' is how much
450 * space to reserve for that buffer.
451 */
452static int
453collect_data(
454 HTAB *hashp,
455 BUFHEAD *bufp,
456 int len, int set)
457{
458 register uint16 *bp;
459 BUFHEAD *save_bufp;
460 int save_flags;
461 int mylen, totlen;
462
463 /*
464 * save the input buf head because we need to walk the list twice.
465 * pin it to make sure it doesn't leave the buffer pool.
466 * This has the effect of growing the buffer pool if necessary.
467 */
468 save_bufp = bufp;
469 save_flags = save_bufp->flags;
470 save_bufp->flags |= BUF_PIN0x0008;
471
472 /* read the length of the buffer */
473 for (totlen = len; bufp; bufp = dbm_get_buf(hashp, bp[bp[0] - 1], bufp, 0)) {
474 bp = (uint16 *)bufp->page;
475 mylen = hashp->BSIZEhdr.bsize - bp[1];
476
477 /* if mylen ever goes negative it means that the
478 * page is screwed up.
479 */
480 if (mylen < 0) {
481 save_bufp->flags = save_flags;
482 return (-1);
483 }
484 totlen += mylen;
485 if (bp[2] == FULL_KEY_DATA3) { /* End of Data */
486 break;
487 }
488 }
489
490 if (!bufp) {
491 save_bufp->flags = save_flags;
492 return (-1);
493 }
494
495 /* allocate a temp buf */
496 if (hashp->tmp_buf)
497 free(hashp->tmp_buf);
498 if ((hashp->tmp_buf = (char *)malloc((size_t)totlen)) == NULL((void*)0)) {
499 save_bufp->flags = save_flags;
500 return (-1);
501 }
502
503 /* copy the buffers back into temp buf */
504 for (bufp = save_bufp; bufp;
505 bufp = dbm_get_buf(hashp, bp[bp[0] - 1], bufp, 0)) {
506 bp = (uint16 *)bufp->page;
507 mylen = hashp->BSIZEhdr.bsize - bp[1];
508 memmove(&hashp->tmp_buf[len], (bufp->page) + bp[1], (size_t)mylen);
509 len += mylen;
510 if (bp[2] == FULL_KEY_DATA3) {
511 break;
512 }
513 }
514
515 /* 'clear' the pin flags */
516 save_bufp->flags = save_flags;
517
518 /* update the database cursor */
519 if (set) {
520 hashp->cndx = 1;
521 if (bp[0] == 2) { /* No more buckets in chain */
522 hashp->cpage = NULL((void*)0);
523 hashp->cbucket++;
524 } else {
525 hashp->cpage = dbm_get_buf(hashp, bp[bp[0] - 1], bufp, 0);
526 if (!hashp->cpage)
527 return (-1);
528 else if (!((uint16 *)hashp->cpage->page)[0]) {
529 hashp->cbucket++;
530 hashp->cpage = NULL((void*)0);
531 }
532 }
533 }
534 return (totlen);
535}
536
537/*
538 * Fill in the key and data for this big pair.
539 */
540extern int
541dbm_big_keydata(
542 HTAB *hashp,
543 BUFHEAD *bufp,
544 DBT *key, DBT *val,
545 int set)
546{
547 key->size = collect_key(hashp, bufp, 0, val, set);
548 if (key->size == (size_t)-1)
549 return (-1);
550 key->data = (uint8 *)hashp->tmp_key;
551 return (0);
552}
553
554/*
555 * Count how big the total key size is by recursing through the pages. Then
556 * collect the data, allocate a buffer and copy the key as you recurse up.
557 */
558static int
559collect_key(
560 HTAB *hashp,
561 BUFHEAD *bufp,
562 int len,
563 DBT *val,
564 int set)
565{
566 BUFHEAD *xbp;
567 char *p;
568 int mylen, totlen;
569 uint16 *bp, save_addr;
570
571 p = bufp->page;
572 bp = (uint16 *)p;
573 mylen = hashp->BSIZEhdr.bsize - bp[1];
574
575 save_addr = bufp->addr;
576 totlen = len + mylen;
577 if (bp[2] == FULL_KEY2 || bp[2] == FULL_KEY_DATA3) { /* End of Key. */
578 if (hashp->tmp_key != NULL((void*)0))
579 free(hashp->tmp_key);
580 if ((hashp->tmp_key = (char *)malloc((size_t)totlen)) == NULL((void*)0))
581 return (-1);
582 if (dbm_big_return(hashp, bufp, 1, val, set))
583 return (-1);
584 } else {
585 xbp = dbm_get_buf(hashp, bp[bp[0] - 1], bufp, 0);
586 if (!xbp || ((totlen =
587 collect_key(hashp, xbp, totlen, val, set)) < 1))
588 return (-1);
589 }
590 if (bufp->addr != save_addr) {
591 errno(*__errno_location ()) = EINVAL22; /* MIS -- OUT OF BUFFERS */
592 return (-1);
593 }
594 memmove(&hashp->tmp_key[len], (bufp->page) + bp[1], (size_t)mylen);
595 return (totlen);
596}
597
598/*
599 * Returns:
600 * 0 => OK
601 * -1 => error
602 */
603extern int
604dbm_big_split(
605 HTAB *hashp,
606 BUFHEAD *op, /* Pointer to where to put keys that go in old bucket */
607 BUFHEAD *np, /* Pointer to new bucket page */
608 /* Pointer to first page containing the big key/data */
609 BUFHEAD *big_keyp,
610 uint32 addr, /* Address of big_keyp */
611 uint32 obucket, /* Old Bucket */
612 SPLIT_RETURN *ret)
613{
614 register BUFHEAD *tmpp;
615 register uint16 *tp;
616 BUFHEAD *bp;
617 DBT key, val;
618 uint32 change;
619 uint16 free_space, n, off;
620
621 bp = big_keyp;
622
623 /* Now figure out where the big key/data goes */
624 if (dbm_big_keydata(hashp, big_keyp, &key, &val, 0))
625 return (-1);
626 change = (dbm_call_hash(hashp, (char *)key.data, key.size) != obucket);
627
628 if ((ret->next_addr = dbm_find_last_page(hashp, &big_keyp))) {
629 if (!(ret->nextp =
630 dbm_get_buf(hashp, ret->next_addr, big_keyp, 0)))
631 return (-1);
632 ;
633 } else
634 ret->nextp = NULL((void*)0);
635
636/* Now make one of np/op point to the big key/data pair */
637#ifdef DEBUG1
638 assert(np->ovfl == NULL)((np->ovfl == ((void*)0)) ? (void) (0) : __assert_fail ("np->ovfl == NULL"
, "h_bigkey.c", 638, __extension__ __PRETTY_FUNCTION__))
;
639#endif
640 if (change)
641 tmpp = np;
642 else
643 tmpp = op;
644
645 tmpp->flags |= BUF_MOD0x0001;
646#ifdef DEBUG1
647 (void)fprintf(stderrstderr,
648 "BIG_SPLIT: %d->ovfl was %d is now %d\n", tmpp->addr,
649 (tmpp->ovfl ? tmpp->ovfl->addr : 0), (bp ? bp->addr : 0));
650#endif
651 tmpp->ovfl = bp; /* one of op/np point to big_keyp */
652 tp = (uint16 *)tmpp->page;
653
654#if 0 /* this get's tripped on database corrupted error */
655 assert(FREESPACE(tp) >= OVFLSIZE)((((tp)[(tp)[0] + 1]) >= (2 * sizeof(uint16))) ? (void) (0
) : __assert_fail ("FREESPACE(tp) >= OVFLSIZE", "h_bigkey.c"
, 655, __extension__ __PRETTY_FUNCTION__))
;
656#endif
657 if (FREESPACE(tp)((tp)[(tp)[0] + 1]) < OVFLSIZE(2 * sizeof(uint16)))
658 return (DATABASE_CORRUPTED_ERROR-999);
659
660 n = tp[0];
661 off = OFFSET(tp)((tp)[(tp)[0] + 2]);
662 free_space = FREESPACE(tp)((tp)[(tp)[0] + 1]);
663 tp[++n] = (uint16)addr;
664 tp[++n] = OVFLPAGE0;
665 tp[0] = n;
666 OFFSET(tp)((tp)[(tp)[0] + 2]) = off;
667 FREESPACE(tp)((tp)[(tp)[0] + 1]) = free_space - OVFLSIZE(2 * sizeof(uint16));
668
669 /*
670 * Finally, set the new and old return values. BIG_KEYP contains a
671 * pointer to the last page of the big key_data pair. Make sure that
672 * big_keyp has no following page (2 elements) or create an empty
673 * following page.
674 */
675
676 ret->newp = np;
677 ret->oldp = op;
678
679 tp = (uint16 *)big_keyp->page;
680 big_keyp->flags |= BUF_MOD0x0001;
681 if (tp[0] > 2) {
682 /*
683 * There may be either one or two offsets on this page. If
684 * there is one, then the overflow page is linked on normally
685 * and tp[4] is OVFLPAGE. If there are two, tp[4] contains
686 * the second offset and needs to get stuffed in after the
687 * next overflow page is added.
688 */
689 n = tp[4];
690 free_space = FREESPACE(tp)((tp)[(tp)[0] + 1]);
691 off = OFFSET(tp)((tp)[(tp)[0] + 2]);
692 tp[0] -= 2;
693 FREESPACE(tp)((tp)[(tp)[0] + 1]) = free_space + OVFLSIZE(2 * sizeof(uint16));
694 OFFSET(tp)((tp)[(tp)[0] + 2]) = off;
695 tmpp = dbm_add_ovflpage(hashp, big_keyp);
696 if (!tmpp)
697 return (-1);
698 tp[4] = n;
699 } else
700 tmpp = big_keyp;
701
702 if (change)
703 ret->newp = tmpp;
704 else
705 ret->oldp = tmpp;
706 return (0);
707}