1 /*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 1996, 1997, 1998 5 * Sleepycat Software. All rights reserved. 6 */ 7 8 #include "config.h" 9 10 #ifndef lint 11 static const char sccsid[] = "@(#)db_pr.c 10.40 (Sleepycat) 11/22/98"; 12 #endif /* not lint */ 13 14 #ifndef NO_SYSTEM_INCLUDES 15 #include <sys/types.h> 16 17 #include <ctype.h> 18 #include <errno.h> 19 #include <stdlib.h> 20 #include <string.h> 21 #include <unistd.h> 22 #endif 23 24 #include "db_int.h" 25 #include "db_page.h" 26 #include "btree.h" 27 #include "hash.h" 28 #include "db_am.h" 29 30 static void __db_proff __P((void *)); 31 static void __db_psize __P((DB_MPOOLFILE *)); 32 33 /* 34 * __db_loadme -- 35 * Force loading of this file. 36 * 37 * PUBLIC: void __db_loadme __P((void)); 38 */ 39 void 40 __db_loadme() 41 { 42 getpid(); 43 } 44 45 static FILE *set_fp; 46 47 /* 48 * 64K is the maximum page size, so by default we check for offsets 49 * larger than that, and, where possible, we refine the test. 50 */ 51 #define PSIZE_BOUNDARY (64 * 1024 + 1) 52 static size_t set_psize = PSIZE_BOUNDARY; 53 54 /* 55 * __db_prinit -- 56 * Initialize tree printing routines. 57 * 58 * PUBLIC: FILE *__db_prinit __P((FILE *)); 59 */ 60 FILE * 61 __db_prinit(fp) 62 FILE *fp; 63 { 64 if (set_fp == NULL) 65 set_fp = fp == NULL ? stdout : fp; 66 return (set_fp); 67 } 68 69 /* 70 * __db_dump -- 71 * Dump the tree to a file. 72 * 73 * PUBLIC: int __db_dump __P((DB *, char *, int)); 74 */ 75 int 76 __db_dump(dbp, name, all) 77 DB *dbp; 78 char *name; 79 int all; 80 { 81 FILE *fp, *save_fp; 82 83 COMPQUIET(save_fp, NULL); 84 85 if (set_psize == PSIZE_BOUNDARY) 86 __db_psize(dbp->mpf); 87 88 if (name != NULL) { 89 if ((fp = fopen(name, "w")) == NULL) 90 return (errno); 91 save_fp = set_fp; 92 set_fp = fp; 93 } else 94 fp = __db_prinit(NULL); 95 96 (void)__db_prdb(dbp); 97 if (dbp->type == DB_HASH) 98 (void)__db_prhash(dbp); 99 else 100 (void)__db_prbtree(dbp); 101 fprintf(fp, "%s\n", DB_LINE); 102 __db_prtree(dbp->mpf, all); 103 104 if (name != NULL) { 105 (void)fclose(fp); 106 set_fp = save_fp; 107 } 108 return (0); 109 } 110 111 /* 112 * __db_prdb -- 113 * Print out the DB structure information. 114 * 115 * PUBLIC: int __db_prdb __P((DB *)); 116 */ 117 int 118 __db_prdb(dbp) 119 DB *dbp; 120 { 121 static const FN fn[] = { 122 { DB_AM_DUP, "duplicates" }, 123 { DB_AM_INMEM, "in-memory" }, 124 { DB_AM_LOCKING, "locking" }, 125 { DB_AM_LOGGING, "logging" }, 126 { DB_AM_MLOCAL, "local mpool" }, 127 { DB_AM_PGDEF, "default page size" }, 128 { DB_AM_RDONLY, "read-only" }, 129 { DB_AM_SWAP, "needswap" }, 130 { DB_AM_THREAD, "thread" }, 131 { DB_BT_RECNUM, "btree:recnum" }, 132 { DB_DBM_ERROR, "dbm/ndbm error" }, 133 { DB_RE_DELIMITER, "recno:delimiter" }, 134 { DB_RE_FIXEDLEN, "recno:fixed-length" }, 135 { DB_RE_PAD, "recno:pad" }, 136 { DB_RE_RENUMBER, "recno:renumber" }, 137 { DB_RE_SNAPSHOT, "recno:snapshot" }, 138 { 0 }, 139 }; 140 FILE *fp; 141 const char *t; 142 143 fp = __db_prinit(NULL); 144 145 switch (dbp->type) { 146 case DB_BTREE: 147 t = "btree"; 148 break; 149 case DB_HASH: 150 t = "hash"; 151 break; 152 case DB_RECNO: 153 t = "recno"; 154 break; 155 default: 156 t = "UNKNOWN"; 157 break; 158 } 159 160 fprintf(fp, "%s ", t); 161 __db_prflags(dbp->flags, fn, fp); 162 fprintf(fp, "\n"); 163 164 return (0); 165 } 166 167 /* 168 * __db_prbtree -- 169 * Print out the btree internal information. 170 * 171 * PUBLIC: int __db_prbtree __P((DB *)); 172 */ 173 int 174 __db_prbtree(dbp) 175 DB *dbp; 176 { 177 static const FN mfn[] = { 178 { BTM_DUP, "duplicates" }, 179 { BTM_RECNO, "recno" }, 180 { BTM_RECNUM, "btree:recnum" }, 181 { BTM_FIXEDLEN, "recno:fixed-length" }, 182 { BTM_RENUMBER, "recno:renumber" }, 183 { 0 }, 184 }; 185 DBC *dbc; 186 BTMETA *mp; 187 BTREE *t; 188 FILE *fp; 189 PAGE *h; 190 RECNO *rp; 191 db_pgno_t i; 192 int cnt, ret; 193 const char *sep; 194 195 t = dbp->internal; 196 fp = __db_prinit(NULL); 197 if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0) 198 return (ret); 199 200 (void)fprintf(fp, "%s\nOn-page metadata:\n", DB_LINE); 201 202 i = PGNO_METADATA; 203 if ((ret = memp_fget(dbp->mpf, &i, 0, (PAGE **)&mp)) != 0) { 204 (void)dbc->c_close(dbc); 205 return (ret); 206 } 207 208 fprintf(fp, "lsn.file: %lu lsn.offset: %lu\n", 209 (u_long)LSN(mp).file, (u_long)LSN(mp).offset); 210 (void)fprintf(fp, "magic %#lx\n", (u_long)mp->magic); 211 (void)fprintf(fp, "version %#lx\n", (u_long)mp->version); 212 (void)fprintf(fp, "pagesize %lu\n", (u_long)mp->pagesize); 213 (void)fprintf(fp, "maxkey: %lu minkey: %lu\n", 214 (u_long)mp->maxkey, (u_long)mp->minkey); 215 216 (void)fprintf(fp, "free list: %lu", (u_long)mp->free); 217 for (i = mp->free, cnt = 0, sep = ", "; i != PGNO_INVALID;) { 218 if ((ret = memp_fget(dbp->mpf, &i, 0, &h)) != 0) 219 return (ret); 220 i = h->next_pgno; 221 (void)memp_fput(dbp->mpf, h, 0); 222 (void)fprintf(fp, "%s%lu", sep, (u_long)i); 223 if (++cnt % 10 == 0) { 224 (void)fprintf(fp, "\n"); 225 cnt = 0; 226 sep = ""; 227 } else 228 sep = ", "; 229 } 230 (void)fprintf(fp, "\n"); 231 232 (void)fprintf(fp, "flags %#lx", (u_long)mp->flags); 233 __db_prflags(mp->flags, mfn, fp); 234 (void)fprintf(fp, "\n"); 235 (void)memp_fput(dbp->mpf, mp, 0); 236 237 (void)fprintf(fp, "%s\nDB_INFO:\n", DB_LINE); 238 (void)fprintf(fp, "bt_maxkey: %lu bt_minkey: %lu\n", 239 (u_long)t->bt_maxkey, (u_long)t->bt_minkey); 240 (void)fprintf(fp, "bt_compare: %#lx bt_prefix: %#lx\n", 241 (u_long)t->bt_compare, (u_long)t->bt_prefix); 242 if ((rp = t->recno) != NULL) { 243 (void)fprintf(fp, 244 "re_delim: %#lx re_pad: %#lx re_len: %lu re_source: %s\n", 245 (u_long)rp->re_delim, (u_long)rp->re_pad, 246 (u_long)rp->re_len, 247 rp->re_source == NULL ? "" : rp->re_source); 248 (void)fprintf(fp, 249 "cmap: %#lx smap: %#lx emap: %#lx msize: %lu\n", 250 (u_long)rp->re_cmap, (u_long)rp->re_smap, 251 (u_long)rp->re_emap, (u_long)rp->re_msize); 252 } 253 (void)fprintf(fp, "ovflsize: %lu\n", (u_long)t->bt_ovflsize); 254 (void)fflush(fp); 255 return (dbc->c_close(dbc)); 256 } 257 258 /* 259 * __db_prhash -- 260 * Print out the hash internal information. 261 * 262 * PUBLIC: int __db_prhash __P((DB *)); 263 */ 264 int 265 __db_prhash(dbp) 266 DB *dbp; 267 { 268 FILE *fp; 269 DBC *dbc; 270 HASH_CURSOR *hcp; 271 int i, put_page, ret; 272 db_pgno_t pgno; 273 274 fp = __db_prinit(NULL); 275 if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0) 276 return (ret); 277 hcp = (HASH_CURSOR *)dbc->internal; 278 279 /* 280 * In this case, hcp->hdr will never be null, if we decide 281 * to pass dbc's to this routine instead, then it could be. 282 */ 283 if (hcp->hdr == NULL) { 284 pgno = PGNO_METADATA; 285 if ((ret = memp_fget(dbp->mpf, &pgno, 0, &hcp->hdr)) != 0) 286 return (ret); 287 put_page = 1; 288 } else 289 put_page = 0; 290 291 fprintf(fp, "\tmagic %#lx\n", (u_long)hcp->hdr->magic); 292 fprintf(fp, "\tversion %lu\n", (u_long)hcp->hdr->version); 293 fprintf(fp, "\tpagesize %lu\n", (u_long)hcp->hdr->pagesize); 294 fprintf(fp, "\tovfl_point %lu\n", (u_long)hcp->hdr->ovfl_point); 295 fprintf(fp, "\tlast_freed %lu\n", (u_long)hcp->hdr->last_freed); 296 fprintf(fp, "\tmax_bucket %lu\n", (u_long)hcp->hdr->max_bucket); 297 fprintf(fp, "\thigh_mask %#lx\n", (u_long)hcp->hdr->high_mask); 298 fprintf(fp, "\tlow_mask %#lx\n", (u_long)hcp->hdr->low_mask); 299 fprintf(fp, "\tffactor %lu\n", (u_long)hcp->hdr->ffactor); 300 fprintf(fp, "\tnelem %lu\n", (u_long)hcp->hdr->nelem); 301 fprintf(fp, "\th_charkey %#lx\n", (u_long)hcp->hdr->h_charkey); 302 303 for (i = 0; i < NCACHED; i++) 304 fprintf(fp, "%lu ", (u_long)hcp->hdr->spares[i]); 305 fprintf(fp, "\n"); 306 307 (void)fflush(fp); 308 if (put_page) { 309 (void)memp_fput(dbp->mpf, (PAGE *)hcp->hdr, 0); 310 hcp->hdr = NULL; 311 } 312 return (dbc->c_close(dbc)); 313 } 314 315 /* 316 * __db_prtree -- 317 * Print out the entire tree. 318 * 319 * PUBLIC: int __db_prtree __P((DB_MPOOLFILE *, int)); 320 */ 321 int 322 __db_prtree(mpf, all) 323 DB_MPOOLFILE *mpf; 324 int all; 325 { 326 PAGE *h; 327 db_pgno_t i; 328 329 if (set_psize == PSIZE_BOUNDARY) 330 __db_psize(mpf); 331 332 for (i = PGNO_ROOT;; ++i) { 333 if (memp_fget(mpf, &i, 0, &h) != 0) 334 break; 335 (void)__db_prpage(h, all); 336 (void)memp_fput(mpf, h, 0); 337 } 338 (void)fflush(__db_prinit(NULL)); 339 return (0); 340 } 341 342 /* 343 * __db_prnpage 344 * -- Print out a specific page. 345 * 346 * PUBLIC: int __db_prnpage __P((DB_MPOOLFILE *, db_pgno_t)); 347 */ 348 int 349 __db_prnpage(mpf, pgno) 350 DB_MPOOLFILE *mpf; 351 db_pgno_t pgno; 352 { 353 PAGE *h; 354 int ret; 355 356 if (set_psize == PSIZE_BOUNDARY) 357 __db_psize(mpf); 358 359 if ((ret = memp_fget(mpf, &pgno, 0, &h)) != 0) 360 return (ret); 361 362 ret = __db_prpage(h, 1); 363 (void)fflush(__db_prinit(NULL)); 364 365 (void)memp_fput(mpf, h, 0); 366 return (ret); 367 } 368 369 /* 370 * __db_prpage 371 * -- Print out a page. 372 * 373 * PUBLIC: int __db_prpage __P((PAGE *, int)); 374 */ 375 int 376 __db_prpage(h, all) 377 PAGE *h; 378 int all; 379 { 380 BINTERNAL *bi; 381 BKEYDATA *bk; 382 HOFFPAGE a_hkd; 383 FILE *fp; 384 RINTERNAL *ri; 385 db_indx_t dlen, len, i; 386 db_pgno_t pgno; 387 int deleted, ret; 388 const char *s; 389 u_int8_t *ep, *hk, *p; 390 void *sp; 391 392 fp = __db_prinit(NULL); 393 394 switch (TYPE(h)) { 395 case P_DUPLICATE: 396 s = "duplicate"; 397 break; 398 case P_HASH: 399 s = "hash"; 400 break; 401 case P_IBTREE: 402 s = "btree internal"; 403 break; 404 case P_INVALID: 405 s = "invalid"; 406 break; 407 case P_IRECNO: 408 s = "recno internal"; 409 break; 410 case P_LBTREE: 411 s = "btree leaf"; 412 break; 413 case P_LRECNO: 414 s = "recno leaf"; 415 break; 416 case P_OVERFLOW: 417 s = "overflow"; 418 break; 419 default: 420 fprintf(fp, "ILLEGAL PAGE TYPE: page: %lu type: %lu\n", 421 (u_long)h->pgno, (u_long)TYPE(h)); 422 return (1); 423 } 424 fprintf(fp, "page %4lu: (%s)\n", (u_long)h->pgno, s); 425 fprintf(fp, " lsn.file: %lu lsn.offset: %lu", 426 (u_long)LSN(h).file, (u_long)LSN(h).offset); 427 if (TYPE(h) == P_IBTREE || TYPE(h) == P_IRECNO || 428 (TYPE(h) == P_LRECNO && h->pgno == PGNO_ROOT)) 429 fprintf(fp, " total records: %4lu", (u_long)RE_NREC(h)); 430 fprintf(fp, "\n"); 431 if (TYPE(h) != P_IBTREE && TYPE(h) != P_IRECNO) 432 fprintf(fp, " prev: %4lu next: %4lu", 433 (u_long)PREV_PGNO(h), (u_long)NEXT_PGNO(h)); 434 if (TYPE(h) == P_IBTREE || TYPE(h) == P_LBTREE) 435 fprintf(fp, " level: %2lu", (u_long)h->level); 436 if (TYPE(h) == P_OVERFLOW) { 437 fprintf(fp, " ref cnt: %4lu ", (u_long)OV_REF(h)); 438 __db_pr((u_int8_t *)h + P_OVERHEAD, OV_LEN(h)); 439 return (0); 440 } 441 fprintf(fp, " entries: %4lu", (u_long)NUM_ENT(h)); 442 fprintf(fp, " offset: %4lu\n", (u_long)HOFFSET(h)); 443 444 if (!all || TYPE(h) == P_INVALID) 445 return (0); 446 447 ret = 0; 448 for (i = 0; i < NUM_ENT(h); i++) { 449 if (P_ENTRY(h, i) - (u_int8_t *)h < P_OVERHEAD || 450 (size_t)(P_ENTRY(h, i) - (u_int8_t *)h) >= set_psize) { 451 fprintf(fp, 452 "ILLEGAL PAGE OFFSET: indx: %lu of %lu\n", 453 (u_long)i, (u_long)h->inp[i]); 454 ret = EINVAL; 455 continue; 456 } 457 deleted = 0; 458 switch (TYPE(h)) { 459 case P_HASH: 460 case P_IBTREE: 461 case P_IRECNO: 462 sp = P_ENTRY(h, i); 463 break; 464 case P_LBTREE: 465 sp = P_ENTRY(h, i); 466 deleted = i % 2 == 0 && 467 B_DISSET(GET_BKEYDATA(h, i + O_INDX)->type); 468 break; 469 case P_LRECNO: 470 case P_DUPLICATE: 471 sp = P_ENTRY(h, i); 472 deleted = B_DISSET(GET_BKEYDATA(h, i)->type); 473 break; 474 default: 475 fprintf(fp, 476 "ILLEGAL PAGE ITEM: %lu\n", (u_long)TYPE(h)); 477 ret = EINVAL; 478 continue; 479 } 480 fprintf(fp, " %s[%03lu] %4lu ", 481 deleted ? "D" : " ", (u_long)i, (u_long)h->inp[i]); 482 switch (TYPE(h)) { 483 case P_HASH: 484 hk = sp; 485 switch (HPAGE_PTYPE(hk)) { 486 case H_OFFDUP: 487 memcpy(&pgno, 488 HOFFDUP_PGNO(hk), sizeof(db_pgno_t)); 489 fprintf(fp, 490 "%4lu [offpage dups]\n", (u_long)pgno); 491 break; 492 case H_DUPLICATE: 493 /* 494 * If this is the first item on a page, then 495 * we cannot figure out how long it is, so 496 * we only print the first one in the duplicate 497 * set. 498 */ 499 if (i != 0) 500 len = LEN_HKEYDATA(h, 0, i); 501 else 502 len = 1; 503 504 fprintf(fp, "Duplicates:\n"); 505 for (p = HKEYDATA_DATA(hk), 506 ep = p + len; p < ep;) { 507 memcpy(&dlen, p, sizeof(db_indx_t)); 508 p += sizeof(db_indx_t); 509 fprintf(fp, "\t\t"); 510 __db_pr(p, dlen); 511 p += sizeof(db_indx_t) + dlen; 512 } 513 break; 514 case H_KEYDATA: 515 if (i != 0) 516 __db_pr(HKEYDATA_DATA(hk), 517 LEN_HKEYDATA(h, 0, i)); 518 else 519 fprintf(fp, "%s\n", HKEYDATA_DATA(hk)); 520 break; 521 case H_OFFPAGE: 522 memcpy(&a_hkd, hk, HOFFPAGE_SIZE); 523 fprintf(fp, 524 "overflow: total len: %4lu page: %4lu\n", 525 (u_long)a_hkd.tlen, (u_long)a_hkd.pgno); 526 break; 527 } 528 break; 529 case P_IBTREE: 530 bi = sp; 531 fprintf(fp, "count: %4lu pgno: %4lu ", 532 (u_long)bi->nrecs, (u_long)bi->pgno); 533 switch (B_TYPE(bi->type)) { 534 case B_KEYDATA: 535 __db_pr(bi->data, bi->len); 536 break; 537 case B_DUPLICATE: 538 case B_OVERFLOW: 539 __db_proff(bi->data); 540 break; 541 default: 542 fprintf(fp, "ILLEGAL BINTERNAL TYPE: %lu\n", 543 (u_long)B_TYPE(bi->type)); 544 ret = EINVAL; 545 break; 546 } 547 break; 548 case P_IRECNO: 549 ri = sp; 550 fprintf(fp, "entries %4lu pgno %4lu\n", 551 (u_long)ri->nrecs, (u_long)ri->pgno); 552 break; 553 case P_LBTREE: 554 case P_LRECNO: 555 case P_DUPLICATE: 556 bk = sp; 557 switch (B_TYPE(bk->type)) { 558 case B_KEYDATA: 559 __db_pr(bk->data, bk->len); 560 break; 561 case B_DUPLICATE: 562 case B_OVERFLOW: 563 __db_proff(bk); 564 break; 565 default: 566 fprintf(fp, 567 "ILLEGAL DUPLICATE/LBTREE/LRECNO TYPE: %lu\n", 568 (u_long)B_TYPE(bk->type)); 569 ret = EINVAL; 570 break; 571 } 572 break; 573 } 574 } 575 (void)fflush(fp); 576 return (ret); 577 } 578 579 /* 580 * __db_isbad 581 * -- Decide if a page is corrupted. 582 * 583 * PUBLIC: int __db_isbad __P((PAGE *, int)); 584 */ 585 int 586 __db_isbad(h, die) 587 PAGE *h; 588 int die; 589 { 590 BINTERNAL *bi; 591 BKEYDATA *bk; 592 FILE *fp; 593 db_indx_t i; 594 u_int type; 595 596 fp = __db_prinit(NULL); 597 598 switch (TYPE(h)) { 599 case P_DUPLICATE: 600 case P_HASH: 601 case P_IBTREE: 602 case P_INVALID: 603 case P_IRECNO: 604 case P_LBTREE: 605 case P_LRECNO: 606 case P_OVERFLOW: 607 break; 608 default: 609 fprintf(fp, "ILLEGAL PAGE TYPE: page: %lu type: %lu\n", 610 (u_long)h->pgno, (u_long)TYPE(h)); 611 goto bad; 612 } 613 614 for (i = 0; i < NUM_ENT(h); i++) { 615 if (P_ENTRY(h, i) - (u_int8_t *)h < P_OVERHEAD || 616 (size_t)(P_ENTRY(h, i) - (u_int8_t *)h) >= set_psize) { 617 fprintf(fp, 618 "ILLEGAL PAGE OFFSET: indx: %lu of %lu\n", 619 (u_long)i, (u_long)h->inp[i]); 620 goto bad; 621 } 622 switch (TYPE(h)) { 623 case P_HASH: 624 type = HPAGE_TYPE(h, i); 625 if (type != H_OFFDUP && 626 type != H_DUPLICATE && 627 type != H_KEYDATA && 628 type != H_OFFPAGE) { 629 fprintf(fp, "ILLEGAL HASH TYPE: %lu\n", 630 (u_long)type); 631 goto bad; 632 } 633 break; 634 case P_IBTREE: 635 bi = GET_BINTERNAL(h, i); 636 if (B_TYPE(bi->type) != B_KEYDATA && 637 B_TYPE(bi->type) != B_DUPLICATE && 638 B_TYPE(bi->type) != B_OVERFLOW) { 639 fprintf(fp, "ILLEGAL BINTERNAL TYPE: %lu\n", 640 (u_long)B_TYPE(bi->type)); 641 goto bad; 642 } 643 break; 644 case P_IRECNO: 645 case P_LBTREE: 646 case P_LRECNO: 647 break; 648 case P_DUPLICATE: 649 bk = GET_BKEYDATA(h, i); 650 if (B_TYPE(bk->type) != B_KEYDATA && 651 B_TYPE(bk->type) != B_DUPLICATE && 652 B_TYPE(bk->type) != B_OVERFLOW) { 653 fprintf(fp, 654 "ILLEGAL DUPLICATE/LBTREE/LRECNO TYPE: %lu\n", 655 (u_long)B_TYPE(bk->type)); 656 goto bad; 657 } 658 break; 659 default: 660 fprintf(fp, 661 "ILLEGAL PAGE ITEM: %lu\n", (u_long)TYPE(h)); 662 goto bad; 663 } 664 } 665 return (0); 666 667 bad: if (die) { 668 abort(); 669 /* NOTREACHED */ 670 } 671 return (1); 672 } 673 674 /* 675 * __db_pr -- 676 * Print out a data element. 677 * 678 * PUBLIC: void __db_pr __P((u_int8_t *, u_int32_t)); 679 */ 680 void 681 __db_pr(p, len) 682 u_int8_t *p; 683 u_int32_t len; 684 { 685 FILE *fp; 686 u_int lastch; 687 int i; 688 689 fp = __db_prinit(NULL); 690 691 fprintf(fp, "len: %3lu", (u_long)len); 692 lastch = '.'; 693 if (len != 0) { 694 fprintf(fp, " data: "); 695 for (i = len <= 20 ? len : 20; i > 0; --i, ++p) { 696 lastch = *p; 697 if (isprint(*p) || *p == '\n') 698 fprintf(fp, "%c", *p); 699 else 700 fprintf(fp, "0x%.2x", (u_int)*p); 701 } 702 if (len > 20) { 703 fprintf(fp, "..."); 704 lastch = '.'; 705 } 706 } 707 if (lastch != '\n') 708 fprintf(fp, "\n"); 709 } 710 711 /* 712 * __db_prdbt -- 713 * Print out a DBT data element. 714 * 715 * PUBLIC: int __db_prdbt __P((DBT *, int, FILE *)); 716 */ 717 int 718 __db_prdbt(dbtp, checkprint, fp) 719 DBT *dbtp; 720 int checkprint; 721 FILE *fp; 722 { 723 static const char hex[] = "0123456789abcdef"; 724 u_int8_t *p; 725 u_int32_t len; 726 727 /* 728 * !!! 729 * This routine is the routine that dumps out items in the format 730 * used by db_dump(1) and db_load(1). This means that the format 731 * cannot change. 732 */ 733 if (checkprint) { 734 for (len = dbtp->size, p = dbtp->data; len--; ++p) 735 if (isprint(*p)) { 736 if (*p == '\\' && fprintf(fp, "\\") != 1) 737 return (EIO); 738 if (fprintf(fp, "%c", *p) != 1) 739 return (EIO); 740 } else 741 if (fprintf(fp, "\\%c%c", 742 hex[(u_int8_t)(*p & 0xf0) >> 4], 743 hex[*p & 0x0f]) != 3) 744 return (EIO); 745 } else 746 for (len = dbtp->size, p = dbtp->data; len--; ++p) 747 if (fprintf(fp, "%c%c", 748 hex[(u_int8_t)(*p & 0xf0) >> 4], 749 hex[*p & 0x0f]) != 2) 750 return (EIO); 751 752 return (fprintf(fp, "\n") == 1 ? 0 : EIO); 753 } 754 755 /* 756 * __db_proff -- 757 * Print out an off-page element. 758 */ 759 static void 760 __db_proff(vp) 761 void *vp; 762 { 763 FILE *fp; 764 BOVERFLOW *bo; 765 766 fp = __db_prinit(NULL); 767 768 bo = vp; 769 switch (B_TYPE(bo->type)) { 770 case B_OVERFLOW: 771 fprintf(fp, "overflow: total len: %4lu page: %4lu\n", 772 (u_long)bo->tlen, (u_long)bo->pgno); 773 break; 774 case B_DUPLICATE: 775 fprintf(fp, "duplicate: page: %4lu\n", (u_long)bo->pgno); 776 break; 777 } 778 } 779 780 /* 781 * __db_prflags -- 782 * Print out flags values. 783 * 784 * PUBLIC: void __db_prflags __P((u_int32_t, const FN *, FILE *)); 785 */ 786 void 787 __db_prflags(flags, fn, fp) 788 u_int32_t flags; 789 FN const *fn; 790 FILE *fp; 791 { 792 const FN *fnp; 793 int found; 794 const char *sep; 795 796 sep = " ("; 797 for (found = 0, fnp = fn; fnp->mask != 0; ++fnp) 798 if (LF_ISSET(fnp->mask)) { 799 fprintf(fp, "%s%s", sep, fnp->name); 800 sep = ", "; 801 found = 1; 802 } 803 if (found) 804 fprintf(fp, ")"); 805 } 806 807 /* 808 * __db_psize -- 809 * Get the page size. 810 */ 811 static void 812 __db_psize(mpf) 813 DB_MPOOLFILE *mpf; 814 { 815 BTMETA *mp; 816 db_pgno_t pgno; 817 818 set_psize = PSIZE_BOUNDARY - 1; 819 820 pgno = PGNO_METADATA; 821 if (memp_fget(mpf, &pgno, 0, &mp) != 0) 822 return; 823 824 switch (mp->magic) { 825 case DB_BTREEMAGIC: 826 case DB_HASHMAGIC: 827 set_psize = mp->pagesize; 828 break; 829 } 830 (void)memp_fput(mpf, mp, 0); 831 } 832