db_pr.c

Go to the documentation of this file.
00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 1996, 1997, 1998, 1999, 2000
00005  *      Sleepycat Software.  All rights reserved.
00006  */
00007 
00008 #include "config.h"
00009 
00010 #ifndef lint
00011 static const char revid[] = "$Id: db__pr_8c-source.html,v 1.1 2008/06/08 10:18:09 sebdiaz Exp $";
00012 #endif /* not lint */
00013 
00014 #ifndef NO_SYSTEM_INCLUDES
00015 #include <sys/types.h>
00016 
00017 #include <ctype.h>
00018 #include <errno.h>
00019 #include <stdlib.h>
00020 #include <string.h>
00021 #include <unistd.h>
00022 #endif
00023 
00024 #include "db_int.h"
00025 #include "db_page.h"
00026 #include "btree.h"
00027 #include "hash.h"
00028 #include "qam.h"
00029 #include "db_am.h"
00030 #include "db_verify.h"
00031 
00032 static int       __db_bmeta __P((DB *, FILE *, BTMETA *, u_int32_t));
00033 static int       __db_hmeta __P((DB *, FILE *, HMETA *, u_int32_t));
00034 static void      __db_meta __P((DB *, DBMETA *, FILE *, FN const *, u_int32_t));
00035 static const char       *__db_dbtype_to_string __P((DB *));
00036 static void      __db_prdb __P((DB *, FILE *, u_int32_t));
00037 static FILE     *__db_prinit __P((FILE *));
00038 static void      __db_proff __P((void *));
00039 static int       __db_prtree __P((DB *, u_int32_t));
00040 static void      __db_psize __P((DB *));
00041 static int       __db_qmeta __P((DB *, FILE *, QMETA *, u_int32_t));
00042 
00043 /*
00044  * 64K is the maximum page size, so by default we check for offsets larger
00045  * than that, and, where possible, we refine the test.
00046  */
00047 #define PSIZE_BOUNDARY  (64 * 1024 + 1)
00048 static size_t set_psize = PSIZE_BOUNDARY;
00049 
00050 static FILE *set_fp;                            /* Output file descriptor. */
00051 
00052 /*
00053  * CDB___db_loadme --
00054  *      A nice place to put a breakpoint.
00055  *
00056  * PUBLIC: void CDB___db_loadme __P((void));
00057  */
00058 void
00059 CDB___db_loadme()
00060 {
00061         getpid();
00062 }
00063 
00064 /*
00065  * CDB___db_dump --
00066  *      Dump the tree to a file.
00067  *
00068  * PUBLIC: int CDB___db_dump __P((DB *, char *, char *));
00069  */
00070 int
00071 CDB___db_dump(dbp, op, name)
00072         DB *dbp;
00073         char *op, *name;
00074 {
00075         FILE *fp, *save_fp;
00076         u_int32_t flags;
00077 
00078         COMPQUIET(save_fp, NULL);
00079 
00080         if (set_psize == PSIZE_BOUNDARY)
00081                 __db_psize(dbp);
00082 
00083         if (name != NULL) {
00084                 if ((fp = fopen(name, "w")) == NULL)
00085                         return (CDB___os_get_errno());
00086                 save_fp = set_fp;
00087                 set_fp = fp;
00088         } else
00089                 fp = __db_prinit(NULL);
00090 
00091         for (flags = 0; *op != '\0'; ++op)
00092                 switch (*op) {
00093                 case 'a':
00094                         LF_SET(DB_PR_PAGE);
00095                         break;
00096                 case 'h':
00097                         break;
00098                 case 'r':
00099                         LF_SET(DB_PR_RECOVERYTEST);
00100                         break;
00101                 default:
00102                         return (EINVAL);
00103                 }
00104 
00105         __db_prdb(dbp, fp, flags);
00106 
00107         fprintf(fp, "%s\n", DB_LINE);
00108 
00109         (void)__db_prtree(dbp, flags);
00110 
00111         fflush(fp);
00112 
00113         if (name != NULL) {
00114                 fclose(fp);
00115                 set_fp = save_fp;
00116         }
00117         return (0);
00118 }
00119 
00120 /*
00121  * __db_prdb --
00122  *      Print out the DB structure information.
00123  */
00124 static void
00125 __db_prdb(dbp, fp, flags)
00126         DB *dbp;
00127         FILE *fp;
00128         u_int32_t flags;
00129 {
00130         static const FN fn[] = {
00131                 { DB_AM_DISCARD,        "discard cached pages" },
00132                 { DB_AM_DUP,            "duplicates" },
00133                 { DB_AM_INMEM,          "in-memory" },
00134                 { DB_AM_PGDEF,          "default page size" },
00135                 { DB_AM_RDONLY,         "read-only" },
00136                 { DB_AM_SUBDB,          "multiple-databases" },
00137                 { DB_AM_SWAP,           "needswap" },
00138                 { DB_BT_RECNUM,         "btree:recnum" },
00139                 { DB_BT_REVSPLIT,       "btree:no reverse split" },
00140                 { DB_DBM_ERROR,         "dbm/ndbm error" },
00141                 { DB_OPEN_CALLED,       "DB->open called" },
00142                 { DB_RE_DELIMITER,      "recno:delimiter" },
00143                 { DB_RE_FIXEDLEN,       "recno:fixed-length" },
00144                 { DB_RE_PAD,            "recno:pad" },
00145                 { DB_RE_RENUMBER,       "recno:renumber" },
00146                 { DB_RE_SNAPSHOT,       "recno:snapshot" },
00147                 { 0,                    NULL }
00148         };
00149         static const FN bfn[] = {
00150                 { RECNO_MODIFIED,       "recno:modified" },
00151                 { RECNO_READFILE,       "recno:readfile" },
00152                 { 0,                    NULL }
00153         };
00154         BTREE *bt;
00155         HASH *h;
00156         QUEUE *q;
00157 
00158         COMPQUIET(flags, 0);
00159 
00160         fprintf(fp,
00161             "In-memory DB structure:\n%s: %#lx",
00162             __db_dbtype_to_string(dbp), (u_long)dbp->flags);
00163         CDB___db_prflags(dbp->flags, fn, fp);
00164         fprintf(fp, "\n");
00165 
00166         switch (dbp->type) {
00167         case DB_BTREE:
00168         case DB_RECNO:
00169                 bt = dbp->bt_internal;
00170                 fprintf(fp, "bt_lpgno: %lu\n", (u_long)bt->bt_lpgno);
00171                 fprintf(fp, "bt_meta: %lu: bt_root: %lu\n",
00172                     (u_long)bt->bt_meta, (u_long)bt->bt_root);
00173                 fprintf(fp, "bt_maxkey: %lu bt_minkey: %lu\n",
00174                     (u_long)bt->bt_maxkey, (u_long)bt->bt_minkey);
00175                 fprintf(fp, "bt_compare: %#lx bt_prefix: %#lx\n",
00176                     (u_long)bt->bt_compare, (u_long)bt->bt_prefix);
00177                 if (dbp->type == DB_RECNO) {
00178                         fprintf(fp,
00179                     "re_pad: %#lx re_delim: %#lx re_len: %lu re_source: %s\n",
00180                             (u_long)bt->re_pad, (u_long)bt->re_delim,
00181                             (u_long)bt->re_len,
00182                             bt->re_source == NULL ? "" : bt->re_source);
00183                         fprintf(fp, "re_last: %lu\n", (u_long)bt->re_last);
00184                         fprintf(fp,
00185                             "cmap: %#lx smap: %#lx emap: %#lx msize: %lu\n",
00186                             (u_long)bt->re_cmap, (u_long)bt->re_smap,
00187                             (u_long)bt->re_emap, (u_long)bt->re_msize);
00188                         fprintf(fp, "re_irec: %#lx\n", (u_long)bt->re_irec);
00189                 }
00190                 fprintf(fp, "flags: %#lx", (u_long)bt->flags);
00191                 CDB___db_prflags(bt->flags, bfn, fp);
00192                 fprintf(fp, "\n");
00193                 break;
00194         case DB_HASH:
00195                 h = dbp->h_internal;
00196                 fprintf(fp, "meta_pgno: %lu\n", (u_long)h->meta_pgno);
00197                 fprintf(fp, "h_ffactor: %lu\n", (u_long)h->h_ffactor);
00198                 fprintf(fp, "h_nelem: %lu\n", (u_long)h->h_nelem);
00199                 fprintf(fp, "h_hash: %#lx\n", (u_long)h->h_hash);
00200                 break;
00201         case DB_QUEUE:
00202                 q = dbp->q_internal;
00203                 fprintf(fp, "q_meta: %lu\n", (u_long)q->q_meta);
00204                 fprintf(fp, "q_root: %lu\n", (u_long)q->q_root);
00205                 fprintf(fp, "re_pad: %#lx re_len: %lu\n",
00206                     (u_long)q->re_pad, (u_long)q->re_len);
00207                 fprintf(fp, "rec_page: %lu\n", (u_long)q->rec_page);
00208                 break;
00209         default:
00210                 break;
00211         }
00212 }
00213 
00214 /*
00215  * __db_prtree --
00216  *      Print out the entire tree.
00217  */
00218 static int
00219 __db_prtree(dbp, flags)
00220         DB *dbp;
00221         u_int32_t flags;
00222 {
00223         PAGE *h;
00224         db_pgno_t i, last;
00225         int ret;
00226 
00227         if (set_psize == PSIZE_BOUNDARY)
00228                 __db_psize(dbp);
00229 
00230         /* Find out the page number of the last page in the database. */
00231         if ((ret = CDB_memp_fget(dbp->mpf, &last, DB_MPOOL_LAST, &h)) != 0)
00232                 return (ret);
00233         if ((ret = CDB_memp_fput(dbp->mpf, h, 0)) != 0)
00234                 return (ret);
00235 
00236         /* Dump each page. */
00237         for (i = 0; i <= last; ++i) {
00238                 if ((ret = CDB_memp_fget(dbp->mpf, &i, 0, &h)) != 0)
00239                         return (ret);
00240                 (void)CDB___db_prpage(dbp, h, flags);
00241                 if ((ret = CDB_memp_fput(dbp->mpf, h, 0)) != 0)
00242                         return (ret);
00243         }
00244 
00245         (void)fflush(__db_prinit(NULL));
00246         return (0);
00247 }
00248 
00249 /*
00250  * __db_meta --
00251  *      Print out common metadata information.
00252  */
00253 static void
00254 __db_meta(dbp, dbmeta, fp, fn, flags)
00255         DB *dbp;
00256         DBMETA *dbmeta;
00257         FILE *fp;
00258         FN const *fn;
00259         u_int32_t flags;
00260 {
00261         PAGE *h;
00262         int cnt;
00263         db_pgno_t pgno;
00264         u_int8_t *p;
00265         int ret;
00266         const char *sep;
00267 
00268         fprintf(fp, "\tmagic: %#lx\n", (u_long)dbmeta->magic);
00269         fprintf(fp, "\tversion: %lu\n", (u_long)dbmeta->version);
00270         fprintf(fp, "\tpagesize: %lu\n", (u_long)dbmeta->pagesize);
00271         fprintf(fp, "\ttype: %lu\n", (u_long)dbmeta->type);
00272         fprintf(fp, "\tkeys: %lu\trecords: %lu\n",
00273             (u_long)dbmeta->key_count, (u_long)dbmeta->record_count);
00274         fprintf(fp, "\talloc_lsn(lsn.file: %lu lsn.offset: %lu)\n",
00275             (u_long)dbmeta->alloc_lsn.file, (u_long)dbmeta->alloc_lsn.offset);
00276 
00277         if (!LF_ISSET(DB_PR_RECOVERYTEST)) {
00278                 /*
00279                  * If we're doing recovery testing, don't display the free
00280                  * list, it may have changed and that makes the dump diff
00281                  * not work.
00282                  */
00283                 fprintf(fp, "\tfree list: %lu", (u_long)dbmeta->free);
00284                 for (pgno = dbmeta->free,
00285                     cnt = 0, sep = ", "; pgno != PGNO_INVALID;) {
00286                         if ((ret = CDB_memp_fget(dbp->mpf, &pgno, 0, &h)) != 0) {
00287                                 fprintf(fp,
00288                             "Unable to retrieve free-list page: %lu: %s\n",
00289                                     (u_long)pgno, CDB_db_strerror(ret));
00290                                 break;
00291                         }
00292                         pgno = h->next_pgno;
00293                         (void)CDB_memp_fput(dbp->mpf, h, 0);
00294                         fprintf(fp, "%s%lu", sep, (u_long)pgno);
00295                         if (++cnt % 10 == 0) {
00296                                 fprintf(fp, "\n");
00297                                 cnt = 0;
00298                                 sep = "\t";
00299                         } else
00300                                 sep = ", ";
00301                 }
00302                 fprintf(fp, "\n");
00303         }
00304 
00305         if (fn != NULL) {
00306                 fprintf(fp, "\tflags: %#lx", (u_long)dbmeta->flags);
00307                 CDB___db_prflags(dbmeta->flags, fn, fp);
00308                 fprintf(fp, "\n");
00309         }
00310 
00311         fprintf(fp, "\tuid: ");
00312         for (p = (u_int8_t *)dbmeta->uid,
00313             cnt = 0; cnt < DB_FILE_ID_LEN; ++cnt) {
00314                 fprintf(fp, "%x", *p++);
00315                 if (cnt < DB_FILE_ID_LEN - 1)
00316                         fprintf(fp, " ");
00317         }
00318         fprintf(fp, "\n");
00319 }
00320 
00321 /*
00322  * __db_bmeta --
00323  *      Print out the btree meta-data page.
00324  */
00325 static int
00326 __db_bmeta(dbp, fp, h, flags)
00327         DB *dbp;
00328         FILE *fp;
00329         BTMETA *h;
00330         u_int32_t flags;
00331 {
00332         static const FN mfn[] = {
00333                 { BTM_DUP,      "duplicates" },
00334                 { BTM_RECNO,    "recno" },
00335                 { BTM_RECNUM,   "btree:recnum" },
00336                 { BTM_FIXEDLEN, "recno:fixed-length" },
00337                 { BTM_RENUMBER, "recno:renumber" },
00338                 { BTM_SUBDB,    "multiple-databases" },
00339                 { 0,            NULL }
00340         };
00341 
00342         __db_meta(dbp, (DBMETA *)h, fp, mfn, flags);
00343 
00344         fprintf(fp, "\tmaxkey: %lu minkey: %lu\n",
00345             (u_long)h->maxkey, (u_long)h->minkey);
00346         if (dbp->type == DB_RECNO)
00347                 fprintf(fp, "\tre_len: %#lx re_pad: %lu\n",
00348                     (u_long)h->re_len, (u_long)h->re_pad);
00349         fprintf(fp, "\troot: %lu\n", (u_long)h->root);
00350 
00351         return (0);
00352 }
00353 
00354 /*
00355  * __db_hmeta --
00356  *      Print out the hash meta-data page.
00357  */
00358 static int
00359 __db_hmeta(dbp, fp, h, flags)
00360         DB *dbp;
00361         FILE *fp;
00362         HMETA *h;
00363         u_int32_t flags;
00364 {
00365         static const FN mfn[] = {
00366                 { DB_HASH_DUP,   "duplicates" },
00367                 { DB_HASH_SUBDB, "multiple-databases" },
00368                 { 0,             NULL }
00369         };
00370         int i;
00371 
00372         __db_meta(dbp, (DBMETA *)h, fp, mfn, flags);
00373 
00374         fprintf(fp, "\tmax_bucket: %lu\n", (u_long)h->max_bucket);
00375         fprintf(fp, "\thigh_mask: %#lx\n", (u_long)h->high_mask);
00376         fprintf(fp, "\tlow_mask:  %#lx\n", (u_long)h->low_mask);
00377         fprintf(fp, "\tffactor: %lu\n", (u_long)h->ffactor);
00378         fprintf(fp, "\tnelem: %lu\n", (u_long)h->nelem);
00379         fprintf(fp, "\th_charkey: %#lx\n", (u_long)h->h_charkey);
00380         fprintf(fp, "\tspare points: ");
00381         for (i = 0; i < NCACHED; i++)
00382                 fprintf(fp, "%lu ", (u_long)h->spares[i]);
00383         fprintf(fp, "\n");
00384 
00385         return (0);
00386 }
00387 
00388 /*
00389  * __db_qmeta --
00390  *      Print out the queue meta-data page.
00391  */
00392 static int
00393 __db_qmeta(dbp, fp, h, flags)
00394         DB *dbp;
00395         FILE *fp;
00396         QMETA *h;
00397         u_int32_t flags;
00398 {
00399         __db_meta(dbp, (DBMETA *)h, fp, NULL, flags);
00400 
00401         fprintf(fp, "\tstart: %lu\n", (u_long)h->start);
00402         fprintf(fp, "\tfirst_recno: %lu\n", (u_long)h->first_recno);
00403         fprintf(fp, "\tcur_recno: %lu\n", (u_long)h->cur_recno);
00404         fprintf(fp, "\tre_len: %#lx re_pad: %lu\n",
00405             (u_long)h->re_len, (u_long)h->re_pad);
00406         fprintf(fp, "\trec_page: %lu\n", (u_long)h->rec_page);
00407 
00408         return (0);
00409 }
00410 
00411 /*
00412  * CDB___db_prnpage
00413  *      -- Print out a specific page.
00414  *
00415  * PUBLIC: int CDB___db_prnpage __P((DB *, db_pgno_t));
00416  */
00417 int
00418 CDB___db_prnpage(dbp, pgno)
00419         DB *dbp;
00420         db_pgno_t pgno;
00421 {
00422         PAGE *h;
00423         int ret;
00424 
00425         if (set_psize == PSIZE_BOUNDARY)
00426                 __db_psize(dbp);
00427 
00428         if ((ret = CDB_memp_fget(dbp->mpf, &pgno, 0, &h)) != 0)
00429                 return (ret);
00430 
00431         ret = CDB___db_prpage(dbp, h, DB_PR_PAGE);
00432         (void)fflush(__db_prinit(NULL));
00433 
00434         (void)CDB_memp_fput(dbp->mpf, h, 0);
00435         return (ret);
00436 }
00437 
00438 /*
00439  * CDB___db_prpage
00440  *      -- Print out a page.
00441  *
00442  * PUBLIC: int CDB___db_prpage __P((DB *, PAGE *, u_int32_t));
00443  */
00444 int
00445 CDB___db_prpage(dbp, h, flags)
00446         DB *dbp;
00447         PAGE *h;
00448         u_int32_t flags;
00449 {
00450         BINTERNAL *bi;
00451         BKEYDATA *bk;
00452         BTREE *t;
00453         FILE *fp;
00454         HOFFPAGE a_hkd;
00455         QAMDATA *qp, *qep;
00456         RINTERNAL *ri;
00457         db_indx_t dlen, len, i;
00458         db_pgno_t pgno;
00459         db_recno_t recno;
00460         int deleted, ret;
00461         const char *s;
00462         u_int32_t qlen;
00463         u_int8_t *ep, *hk, *p;
00464         void *sp;
00465 
00466         fp = __db_prinit(NULL);
00467 
00468         /*
00469          * If we're doing recovery testing and this page is P_INVALID,
00470          * assume it's a page that's on the free list, and don't display it.
00471          */
00472         if (LF_ISSET(DB_PR_RECOVERYTEST) && TYPE(h) == P_INVALID)
00473                 return (0);
00474 
00475         s = CDB___db_pagetype_to_string(TYPE(h));
00476         if (s == NULL) {
00477                 fprintf(fp, "ILLEGAL PAGE TYPE: page: %lu type: %lu\n",
00478                     (u_long)h->pgno, (u_long)TYPE(h));
00479                 return (1);
00480         }
00481 
00482         /* Page number, page type. */
00483         fprintf(fp, "page %lu: %s level: %lu",
00484             (u_long)h->pgno, s, (u_long)h->level);
00485 
00486         /* Record count. */
00487         if (TYPE(h) == P_IBTREE ||
00488             TYPE(h) == P_IRECNO || (TYPE(h) == P_LRECNO &&
00489             h->pgno == ((BTREE *)dbp->bt_internal)->bt_root))
00490                 fprintf(fp, " records: %lu", (u_long)RE_NREC(h));
00491 
00492         /* LSN. */
00493         fprintf(fp, " (lsn.file: %lu lsn.offset: %lu)\n",
00494             (u_long)LSN(h).file, (u_long)LSN(h).offset);
00495 
00496         switch (TYPE(h)) {
00497         case P_BTREEMETA:
00498                 return (__db_bmeta(dbp, fp, (BTMETA *)h, flags));
00499         case P_HASHMETA:
00500                 return (__db_hmeta(dbp, fp, (HMETA *)h, flags));
00501         case P_QAMMETA:
00502                 return (__db_qmeta(dbp, fp, (QMETA *)h, flags));
00503         case P_QAMDATA:                         /* Should be meta->start. */
00504                 if (!LF_ISSET(DB_PR_PAGE))
00505                         return (0);
00506 
00507                 qlen = ((QUEUE *)dbp->q_internal)->re_len;
00508                 recno = (h->pgno - 1) * QAM_RECNO_PER_PAGE(dbp) + 1;
00509                 i = 0;
00510                 qep = (QAMDATA *)((u_int8_t *)h + set_psize - qlen);
00511                 for (qp = QAM_GET_RECORD(dbp, h, i); qp < qep;
00512                     recno++, i++, qp = QAM_GET_RECORD(dbp, h, i)) {
00513                         if (!F_ISSET(qp, QAM_SET))
00514                                 continue;
00515 
00516                         fprintf(fp, "%s",
00517                             F_ISSET(qp, QAM_VALID) ? "\t" : "       D");
00518                         fprintf(fp, "[%03lu] %4lu ",
00519                             (u_long)recno, (u_long)qp - (u_long)h);
00520                         CDB___db_pr(qp->data, qlen);
00521                 }
00522                 return (0);
00523         }
00524 
00525         t = dbp->bt_internal;
00526 
00527         s = "\t";
00528         if (TYPE(h) != P_IBTREE && TYPE(h) != P_IRECNO) {
00529                 fprintf(fp, "%sprev: %4lu next: %4lu",
00530                     s, (u_long)PREV_PGNO(h), (u_long)NEXT_PGNO(h));
00531                 s = " ";
00532         }
00533         if (TYPE(h) == P_OVERFLOW) {
00534                 fprintf(fp, "%sref cnt: %4lu ", s, (u_long)OV_REF(h));
00535                 CDB___db_pr((u_int8_t *)h + P_OVERHEAD, OV_LEN(h));
00536                 return (0);
00537         }
00538         fprintf(fp, "%sentries: %4lu", s, (u_long)NUM_ENT(h));
00539         fprintf(fp, " offset: %4lu\n", (u_long)HOFFSET(h));
00540 
00541         if (TYPE(h) == P_INVALID || !LF_ISSET(DB_PR_PAGE))
00542                 return (0);
00543 
00544         ret = 0;
00545         for (i = 0; i < NUM_ENT(h); i++) {
00546                 if (P_ENTRY(h, i) - (u_int8_t *)h < P_OVERHEAD ||
00547                     (size_t)(P_ENTRY(h, i) - (u_int8_t *)h) >= set_psize) {
00548                         fprintf(fp,
00549                             "ILLEGAL PAGE OFFSET: indx: %lu of %lu\n",
00550                             (u_long)i, (u_long)h->inp[i]);
00551                         ret = EINVAL;
00552                         continue;
00553                 }
00554                 deleted = 0;
00555                 switch (TYPE(h)) {
00556                 case P_HASH:
00557                 case P_IBTREE:
00558                 case P_IRECNO:
00559                         sp = P_ENTRY(h, i);
00560                         break;
00561                 case P_LBTREE:
00562                         sp = P_ENTRY(h, i);
00563                         deleted = i % 2 == 0 &&
00564                             B_DISSET(GET_BKEYDATA(h, i + O_INDX)->type);
00565                         break;
00566                 case P_LDUP:
00567                 case P_LRECNO:
00568                         sp = P_ENTRY(h, i);
00569                         deleted = B_DISSET(GET_BKEYDATA(h, i)->type);
00570                         break;
00571                 default:
00572                         fprintf(fp,
00573                             "ILLEGAL PAGE ITEM: %lu\n", (u_long)TYPE(h));
00574                         ret = EINVAL;
00575                         continue;
00576                 }
00577                 fprintf(fp, "%s", deleted ? "       D" : "\t");
00578                 fprintf(fp, "[%03lu] %4lu ", (u_long)i, (u_long)h->inp[i]);
00579                 switch (TYPE(h)) {
00580                 case P_HASH:
00581                         hk = sp;
00582                         switch (HPAGE_PTYPE(hk)) {
00583                         case H_OFFDUP:
00584                                 memcpy(&pgno,
00585                                     HOFFDUP_PGNO(hk), sizeof(db_pgno_t));
00586                                 fprintf(fp,
00587                                     "%4lu [offpage dups]\n", (u_long)pgno);
00588                                 break;
00589                         case H_DUPLICATE:
00590                                 /*
00591                                  * If this is the first item on a page, then
00592                                  * we cannot figure out how long it is, so
00593                                  * we only print the first one in the duplicate
00594                                  * set.
00595                                  */
00596                                 if (i != 0)
00597                                         len = LEN_HKEYDATA(h, 0, i);
00598                                 else
00599                                         len = 1;
00600 
00601                                 fprintf(fp, "Duplicates:\n");
00602                                 for (p = HKEYDATA_DATA(hk),
00603                                     ep = p + len; p < ep;) {
00604                                         memcpy(&dlen, p, sizeof(db_indx_t));
00605                                         p += sizeof(db_indx_t);
00606                                         fprintf(fp, "\t\t");
00607                                         CDB___db_pr(p, dlen);
00608                                         p += sizeof(db_indx_t) + dlen;
00609                                 }
00610                                 break;
00611                         case H_KEYDATA:
00612                                 CDB___db_pr(HKEYDATA_DATA(hk),
00613                                     LEN_HKEYDATA(h, i == 0 ? set_psize : 0, i));
00614                                 break;
00615                         case H_OFFPAGE:
00616                                 memcpy(&a_hkd, hk, HOFFPAGE_SIZE);
00617                                 fprintf(fp,
00618                                     "overflow: total len: %4lu page: %4lu\n",
00619                                     (u_long)a_hkd.tlen, (u_long)a_hkd.pgno);
00620                                 break;
00621                         }
00622                         break;
00623                 case P_IBTREE:
00624                         bi = sp;
00625                         fprintf(fp, "count: %4lu pgno: %4lu type: %4lu",
00626                             (u_long)bi->nrecs, (u_long)bi->pgno, (u_long)bi->type);
00627                         switch (B_TYPE(bi->type)) {
00628                         case B_KEYDATA:
00629                                 CDB___db_pr(bi->data, bi->len);
00630                                 break;
00631                         case B_DUPLICATE:
00632                         case B_OVERFLOW:
00633                                 __db_proff(bi->data);
00634                                 break;
00635                         default:
00636                                 fprintf(fp, "ILLEGAL BINTERNAL TYPE: %lu\n",
00637                                     (u_long)B_TYPE(bi->type));
00638                                 ret = EINVAL;
00639                                 break;
00640                         }
00641                         break;
00642                 case P_IRECNO:
00643                         ri = sp;
00644                         fprintf(fp, "entries %4lu pgno %4lu\n",
00645                             (u_long)ri->nrecs, (u_long)ri->pgno);
00646                         break;
00647                 case P_LBTREE:
00648                 case P_LDUP:
00649                 case P_LRECNO:
00650                         bk = sp;
00651                         switch (B_TYPE(bk->type)) {
00652                         case B_KEYDATA:
00653                                 CDB___db_pr(bk->data, bk->len);
00654                                 break;
00655                         case B_DUPLICATE:
00656                         case B_OVERFLOW:
00657                                 __db_proff(bk);
00658                                 break;
00659                         default:
00660                                 fprintf(fp,
00661                             "ILLEGAL DUPLICATE/LBTREE/LRECNO TYPE: %lu\n",
00662                                     (u_long)B_TYPE(bk->type));
00663                                 ret = EINVAL;
00664                                 break;
00665                         }
00666                         break;
00667                 }
00668         }
00669         (void)fflush(fp);
00670         return (ret);
00671 }
00672 
00673 /*
00674  * CDB___db_pr --
00675  *      Print out a data element.
00676  *
00677  * PUBLIC: void CDB___db_pr __P((u_int8_t *, u_int32_t));
00678  */
00679 void
00680 CDB___db_pr(p, len)
00681         u_int8_t *p;
00682         u_int32_t len;
00683 {
00684         FILE *fp;
00685         u_int lastch;
00686         int i;
00687 
00688         fp = __db_prinit(NULL);
00689 
00690         fprintf(fp, "len: %3lu", (u_long)len);
00691         lastch = '.';
00692         if (len != 0) {
00693                 fprintf(fp, " data: ");
00694                 for (i = len <= 20 ? len : 20; i > 0; --i, ++p) {
00695                         lastch = *p;
00696                         if (isprint(*p) || *p == '\n')
00697                                 fprintf(fp, "%c", *p);
00698                         else
00699                                 fprintf(fp, "0x%.2x", (u_int)*p);
00700                 }
00701                 if (len > 20) {
00702                         fprintf(fp, "...");
00703                         lastch = '.';
00704                 }
00705         }
00706         if (lastch != '\n')
00707                 fprintf(fp, "\n");
00708 }
00709 
00710 /*
00711  * CDB___db_prdbt --
00712  *      Print out a DBT data element.
00713  *
00714  * PUBLIC: int CDB___db_prdbt __P((DBT *, int, const char *, void *,
00715  * PUBLIC:     int (*)(void *, const void *), int, VRFY_DBINFO *));
00716  */
00717 int
00718 CDB___db_prdbt(dbtp, checkprint, prefix, handle, callback, is_recno, vdp)
00719         DBT *dbtp;
00720         int checkprint;
00721         const char *prefix;
00722         void *handle;
00723         int (*callback) __P((void *, const void *));
00724         int is_recno;
00725         VRFY_DBINFO *vdp;
00726 {
00727         static const char hex[] = "0123456789abcdef";
00728 #define DBTBUFLEN       100
00729         char buf[DBTBUFLEN];
00730         db_recno_t recno;
00731         int ret;
00732         u_int32_t len;
00733         u_int8_t *p;
00734 
00735         if (vdp != NULL) {
00736                 /*
00737                  * If vdp is non-NULL, we might be the first key in the
00738                  * "fake" subdatabase used for key/data pairs we can't
00739                  * associate with a known subdb.
00740                  *
00741                  * Check and clear the SALVAGE_PRINTHEADER flag;  if
00742                  * it was set, print a subdatabase header.
00743                  */
00744                 if (F_ISSET(vdp, SALVAGE_PRINTHEADER))
00745                         (void)CDB___db_prheader(NULL, "__OTHER__", 0, 0,
00746                             handle, callback, vdp, 0);
00747                 F_CLR(vdp, SALVAGE_PRINTHEADER);
00748                 F_SET(vdp, SALVAGE_PRINTFOOTER);
00749         }
00750 
00751         /*
00752          * !!!
00753          * This routine is the routine that dumps out items in the format
00754          * used by db_dump(1) and db_load(1).  This means that the format
00755          * cannot change.
00756          */
00757         if (prefix != NULL && (ret = callback(handle, prefix)) != 0)
00758                 return (ret);
00759         if (is_recno) {
00760                 /*
00761                  * We're printing a record number, and this has to be done
00762                  * in a platform-independent way.  So we use the numeral in
00763                  * straight ASCII.
00764                  */
00765                 CDB___ua_memcpy(&recno, dbtp->data, sizeof(recno));
00766                 snprintf(buf, DBTBUFLEN, "%lu", (u_long)recno);
00767                 if ((ret = callback(handle, buf)) != 0)
00768                         return (ret);
00769         } else if (checkprint) {
00770                 for (len = dbtp->size, p = dbtp->data; len--; ++p)
00771                         if (isprint(*p)) {
00772                                 if (*p == '\\' &&
00773                                     (ret = callback(handle, "\\")) != 0)
00774                                         return (ret);
00775                                 snprintf(buf, DBTBUFLEN, "%c", *p);
00776                                 if ((ret = callback(handle, buf)) != 0)
00777                                         return (ret);
00778                         } else {
00779                                 snprintf(buf, DBTBUFLEN, "\\%c%c",
00780                                     hex[(u_int8_t)(*p & 0xf0) >> 4],
00781                                     hex[*p & 0x0f]);
00782                                 if ((ret = callback(handle, buf)) != 0)
00783                                         return (ret);
00784                         }
00785         } else
00786                 for (len = dbtp->size, p = dbtp->data; len--; ++p) {
00787                         snprintf(buf, DBTBUFLEN, "%c%c",
00788                             hex[(u_int8_t)(*p & 0xf0) >> 4],
00789                             hex[*p & 0x0f]);
00790                         if ((ret = callback(handle, buf)) != 0)
00791                                 return (ret);
00792                 }
00793 
00794         return (callback(handle, "\n"));
00795 }
00796 
00797 /*
00798  * __db_proff --
00799  *      Print out an off-page element.
00800  */
00801 static void
00802 __db_proff(vp)
00803         void *vp;
00804 {
00805         FILE *fp;
00806         BOVERFLOW *bo;
00807 
00808         fp = __db_prinit(NULL);
00809 
00810         bo = vp;
00811         switch (B_TYPE(bo->type)) {
00812         case B_OVERFLOW:
00813                 fprintf(fp, "overflow: total len: %4lu page: %4lu\n",
00814                     (u_long)bo->tlen, (u_long)bo->pgno);
00815                 break;
00816         case B_DUPLICATE:
00817                 fprintf(fp, "duplicate: page: %4lu\n", (u_long)bo->pgno);
00818                 break;
00819         }
00820 }
00821 
00822 /*
00823  * CDB___db_prflags --
00824  *      Print out flags values.
00825  *
00826  * PUBLIC: void CDB___db_prflags __P((u_int32_t, const FN *, FILE *));
00827  */
00828 void
00829 CDB___db_prflags(flags, fn, fp)
00830         u_int32_t flags;
00831         FN const *fn;
00832         FILE *fp;
00833 {
00834         const FN *fnp;
00835         int found;
00836         const char *sep;
00837 
00838         sep = " (";
00839         for (found = 0, fnp = fn; fnp->mask != 0; ++fnp)
00840                 if (LF_ISSET(fnp->mask)) {
00841                         fprintf(fp, "%s%s", sep, fnp->name);
00842                         sep = ", ";
00843                         found = 1;
00844                 }
00845         if (found)
00846                 fprintf(fp, ")");
00847 }
00848 
00849 /*
00850  * __db_prinit --
00851  *      Initialize tree printing routines.
00852  */
00853 static FILE *
00854 __db_prinit(fp)
00855         FILE *fp;
00856 {
00857         if (set_fp == NULL)
00858                 set_fp = fp == NULL ? stdout : fp;
00859         return (set_fp);
00860 }
00861 
00862 /*
00863  * __db_psize --
00864  *      Get the page size.
00865  */
00866 static void
00867 __db_psize(dbp)
00868         DB *dbp;
00869 {
00870         DBMETA *mp;
00871         db_pgno_t pgno;
00872 
00873         set_psize = PSIZE_BOUNDARY - 1;
00874 
00875         pgno = PGNO_BASE_MD;
00876         if (CDB_memp_fget(dbp->mpf, &pgno, 0, &mp) != 0)
00877                 return;
00878 
00879         switch (mp->magic) {
00880         case DB_BTREEMAGIC:
00881         case DB_HASHMAGIC:
00882         case DB_QAMMAGIC:
00883                 set_psize = mp->pagesize;
00884                 break;
00885         }
00886         (void)CDB_memp_fput(dbp->mpf, mp, 0);
00887 }
00888 
00889 /*
00890  * __db_dbtype_to_string --
00891  *      Return the name of the database type.
00892  */
00893 static const char *
00894 __db_dbtype_to_string(dbp)
00895         DB *dbp;
00896 {
00897         switch (dbp->type) {
00898         case DB_BTREE:
00899                 return ("btree");
00900         case DB_HASH:
00901                 return ("hash");
00902                 break;
00903         case DB_RECNO:
00904                 return ("recno");
00905                 break;
00906         case DB_QUEUE:
00907                 return ("queue");
00908         default:
00909                 return ("UNKNOWN TYPE");
00910         }
00911         /* NOTREACHED */
00912 }
00913 
00914 /*
00915  * CDB___db_pagetype_to_string --
00916  *      Return the name of the specified page type.
00917  *
00918  * PUBLIC: const char *CDB___db_pagetype_to_string __P((u_int32_t));
00919  */
00920 const char *
00921 CDB___db_pagetype_to_string(type)
00922         u_int32_t type;
00923 {
00924         char *s;
00925 
00926         s = NULL;
00927         switch (type) {
00928         case P_BTREEMETA:
00929                 s = "btree metadata";
00930                 break;
00931         case P_LDUP:
00932                 s = "duplicate";
00933                 break;
00934         case P_HASH:
00935                 s = "hash";
00936                 break;
00937         case P_HASHMETA:
00938                 s = "hash metadata";
00939                 break;
00940         case P_IBTREE:
00941                 s = "btree internal";
00942                 break;
00943         case P_INVALID:
00944                 s = "invalid";
00945                 break;
00946         case P_IRECNO:
00947                 s = "recno internal";
00948                 break;
00949         case P_LBTREE:
00950                 s = "btree leaf";
00951                 break;
00952         case P_LRECNO:
00953                 s = "recno leaf";
00954                 break;
00955         case P_OVERFLOW:
00956                 s = "overflow";
00957                 break;
00958         case P_QAMMETA:
00959                 s = "queue metadata";
00960                 break;
00961         case P_QAMDATA:
00962                 s = "queue";
00963                 break;
00964         default:
00965                 /* Just return a NULL. */
00966                 break;
00967         }
00968         return (s);
00969 }
00970 
00971 /*
00972  * CDB___db_prheader --
00973  *      Write out header information in the format expected by db_load.
00974  *
00975  * PUBLIC: int  CDB___db_prheader __P((DB *, char *, int, int, void *,
00976  * PUBLIC:     int (*)(void *, const void *), VRFY_DBINFO *, db_pgno_t));
00977  */
00978 int
00979 CDB___db_prheader(dbp, subname, pflag, keyflag, handle, callback, vdp, meta_pgno)
00980         DB *dbp;
00981         char *subname;
00982         int pflag, keyflag;
00983         void *handle;
00984         int (*callback) __P((void *, const void *));
00985         VRFY_DBINFO *vdp;
00986         db_pgno_t meta_pgno;
00987 {
00988         DB_BTREE_STAT *btsp;
00989         DB_ENV *dbenv;
00990         DB_HASH_STAT *hsp;
00991         DB_QUEUE_STAT *qsp;
00992         VRFY_PAGEINFO *pip;
00993         char *buf;
00994         int ret, t_ret, buflen;
00995         u_int32_t dbtype;
00996 
00997         btsp = NULL;
00998         hsp = NULL;
00999         qsp = NULL;
01000         ret = 0;
01001         buf = NULL;
01002         COMPQUIET(buflen, 0);
01003 
01004         if (dbp == NULL)
01005                 dbenv = NULL;
01006         else
01007                 dbenv = dbp->dbenv;
01008 
01009         /*
01010          * If we've been passed a verifier statistics object, use
01011          * that;  we're being called in a context where dbp->stat
01012          * is unsafe.
01013          */
01014         if (vdp != NULL) {
01015                 if ((ret = CDB___db_vrfy_getpageinfo(vdp, meta_pgno, &pip)) != 0)
01016                         return (ret);
01017         } else
01018                 pip = NULL;
01019 
01020         /*
01021          * If dbp is NULL, we're being called from inside CDB___db_prdbt,
01022          * and this is a special subdatabase for "lost" items.  Make it a btree.
01023          * Otherwise, set dbtype to the appropriate type for the specified
01024          * meta page, or the type of the dbp.
01025          */
01026         if (dbp == NULL)
01027                 dbtype = DB_BTREE;
01028         else if (pip != NULL)
01029                 switch (pip->type) {
01030                 case P_BTREEMETA:
01031                         if (F_ISSET(pip, VRFY_IS_RECNO))
01032                                 dbtype = DB_RECNO;
01033                         else
01034                                 dbtype = DB_BTREE;
01035                         break;
01036                 case P_HASHMETA:
01037                         dbtype = DB_HASH;
01038                         break;
01039                 default:
01040                         /* Shouldn't happen. */
01041                         DB_ASSERT(0);
01042                         ret = EINVAL;
01043                         goto err;
01044                 }
01045         else
01046                 dbtype = dbp->type;
01047 
01048         if ((ret = callback(handle, "VERSION=2\n")) != 0)
01049                 goto err;
01050         if (pflag) {
01051                 if ((ret = callback(handle, "format=print\n")) != 0)
01052                         goto err;
01053         } else if ((ret = callback(handle, "format=bytevalue\n")) != 0)
01054                 goto err;
01055 
01056         /*
01057          * 64 bytes is long enough, as a minimum bound, for any of the
01058          * fields besides subname.  Subname can be anything, and so
01059          * 64 + subname is big enough for all the things we need to print here.
01060          */
01061         buflen = 64 + ((subname != NULL) ? strlen(subname) : 0);
01062         if ((ret = CDB___os_malloc(dbenv, buflen, NULL, &buf)) != 0)
01063                 goto err;
01064         if (subname != NULL) {
01065                 snprintf(buf, buflen, "database=%s\n", subname);
01066                 if ((ret = callback(handle, buf)) != 0)
01067                         goto err;
01068         }
01069         switch (dbtype) {
01070         case DB_BTREE:
01071                 if ((ret = callback(handle, "type=btree\n")) != 0)
01072                         goto err;
01073                 if (pip != NULL) {
01074                         if (F_ISSET(pip, VRFY_HAS_RECNUMS))
01075                                 if ((ret =
01076                                     callback(handle, "recnum=1\n")) != 0)
01077                                         goto err;
01078                         if (pip->bt_maxkey != 0) {
01079                                 snprintf(buf, buflen, "bt_maxkey=%lu\n",
01080                                     (u_long)pip->bt_maxkey);
01081                                 if ((ret = callback(handle, buf)) != 0)
01082                                         goto err;
01083                         }
01084                         if (pip->bt_minkey != 0 &&
01085                             pip->bt_minkey != DEFMINKEYPAGE) {
01086                                 snprintf(buf, buflen, "bt_minkey=%lu\n",
01087                                     (u_long)pip->bt_minkey);
01088                                 if ((ret = callback(handle, buf)) != 0)
01089                                         goto err;
01090                         }
01091                         break;
01092                 }
01093                 if ((ret = dbp->stat(dbp, &btsp, NULL, 0)) != 0) {
01094                         dbp->err(dbp, ret, "DB->stat");
01095                         goto err;
01096                 }
01097                 if (F_ISSET(dbp, DB_BT_RECNUM))
01098                         if ((ret = callback(handle, "recnum=1\n")) != 0)
01099                                 goto err;
01100                 if (btsp->bt_maxkey != 0) {
01101                         snprintf(buf, buflen,
01102                             "bt_maxkey=%lu\n", (u_long)btsp->bt_maxkey);
01103                         if ((ret = callback(handle, buf)) != 0)
01104                                 goto err;
01105                 }
01106                 if (btsp->bt_minkey != 0 && btsp->bt_minkey != DEFMINKEYPAGE) {
01107                         snprintf(buf, buflen,
01108                             "bt_minkey=%lu\n", (u_long)btsp->bt_minkey);
01109                         if ((ret = callback(handle, buf)) != 0)
01110                                 goto err;
01111                 }
01112                 break;
01113         case DB_HASH:
01114                 if ((ret = callback(handle, "type=hash\n")) != 0)
01115                         goto err;
01116                 if (pip != NULL) {
01117                         if (pip->h_ffactor != 0) {
01118                                 snprintf(buf, buflen, "h_ffactor=%lu\n",
01119                                     (u_long)pip->h_ffactor);
01120                                 if ((ret = callback(handle, buf)) != 0)
01121                                         goto err;
01122                         }
01123                         if (pip->h_nelem != 0) {
01124                                 snprintf(buf, buflen, "h_nelem=%lu\n",
01125                                     (u_long)pip->h_nelem);
01126                                 if ((ret = callback(handle, buf)) != 0)
01127                                         goto err;
01128                         }
01129                         break;
01130                 }
01131                 if ((ret = dbp->stat(dbp, &hsp, NULL, 0)) != 0) {
01132                         dbp->err(dbp, ret, "DB->stat");
01133                         goto err;
01134                 }
01135                 if (hsp->hash_ffactor != 0) {
01136                         snprintf(buf, buflen,
01137                             "h_ffactor=%lu\n", (u_long)hsp->hash_ffactor);
01138                         if ((ret = callback(handle, buf)) != 0)
01139                                 goto err;
01140                 }
01141                 if (hsp->hash_nelem != 0 || hsp->hash_nkeys != 0) {
01142                         snprintf(buf, buflen, "h_nelem=%lu\n",
01143                             hsp->hash_nelem > hsp->hash_nkeys ?
01144                             (u_long)hsp->hash_nelem : (u_long)hsp->hash_nkeys);
01145                         if ((ret = callback(handle, buf)) != 0)
01146                                 goto err;
01147                 }
01148                 break;
01149         case DB_QUEUE:
01150                 if ((ret = callback(handle, "type=queue\n")) != 0)
01151                         goto err;
01152                 if (vdp != NULL) {
01153                         snprintf(buf,
01154                             buflen, "re_len=%lu\n", (u_long)vdp->re_len);
01155                         if ((ret = callback(handle, buf)) != 0)
01156                                 goto err;
01157                         break;
01158                 }
01159                 if ((ret = dbp->stat(dbp, &qsp, NULL, 0)) != 0) {
01160                         dbp->err(dbp, ret, "DB->stat");
01161                         goto err;
01162                 }
01163                 snprintf(buf, buflen, "re_len=%lu\n", (u_long)qsp->qs_re_len);
01164                 if (qsp->qs_re_pad != 0 && qsp->qs_re_pad != ' ') 
01165                         snprintf(buf, buflen, "re_pad=%#x\n", qsp->qs_re_pad);
01166                 if ((ret = callback(handle, buf)) != 0)
01167                         goto err;
01168                 break;
01169         case DB_RECNO:
01170                 if ((ret = callback(handle, "type=recno\n")) != 0)
01171                         goto err;
01172                 if (pip != NULL) {
01173                         if (F_ISSET(pip, VRFY_IS_RRECNO))
01174                                 if ((ret =
01175                                     callback(handle, "renumber=1\n")) != 0)
01176                                         goto err;
01177                         if (pip->re_len > 0) {
01178                                 snprintf(buf, buflen, "re_len=%lu\n",
01179                                     (u_long)pip->re_len);
01180                                 if ((ret = callback(handle, buf)) != 0)
01181                                         goto err;
01182                         }
01183                         break;
01184                 }
01185                 if ((ret = dbp->stat(dbp, &btsp, NULL, 0)) != 0) {
01186                         dbp->err(dbp, ret, "DB->stat");
01187                         goto err;
01188                 }
01189                 if (F_ISSET(dbp, DB_RE_RENUMBER))
01190                         if ((ret = callback(handle, "renumber=1\n")) != 0)
01191                                 goto err;
01192                 if (F_ISSET(dbp, DB_RE_FIXEDLEN)) {
01193                         snprintf(buf, buflen,
01194                             "re_len=%lu\n", (u_long)btsp->bt_re_len);
01195                         if ((ret = callback(handle, buf)) != 0)
01196                                 goto err;
01197                 }
01198                 if (btsp->bt_re_pad != 0 && btsp->bt_re_pad != ' ') {
01199                         snprintf(buf, buflen, "re_pad=%#x\n", btsp->bt_re_pad);
01200                         if ((ret = callback(handle, buf)) != 0)
01201                                 goto err;
01202                 }
01203                 break;
01204         case DB_UNKNOWN:
01205                 DB_ASSERT(0);                   /* Impossible. */
01206                 CDB___db_err(dbp->dbenv, "Impossible DB type in CDB___db_prheader");
01207                 ret = EINVAL;
01208                 goto err;
01209         }
01210 
01211         if (pip != NULL) {
01212                 if (F_ISSET(pip, VRFY_HAS_DUPS))
01213                         if ((ret = callback(handle, "duplicates=1\n")) != 0)
01214                                 goto err;
01215                 if (F_ISSET(pip, VRFY_HAS_DUPSORT))
01216                         if ((ret = callback(handle, "dupsort=1\n")) != 0)
01217                                 goto err;
01218                 /* We should handle page size. XXX */
01219         } else {
01220                 if (F_ISSET(dbp, DB_AM_DUP))
01221                         if ((ret = callback(handle, "duplicates=1\n")) != 0)
01222                                 goto err;
01223                 if (F_ISSET(dbp, DB_AM_DUPSORT))
01224                         if ((ret = callback(handle, "dupsort=1\n")) != 0)
01225                                 goto err;
01226                 if (!F_ISSET(dbp, DB_AM_PGDEF)) {
01227                         snprintf(buf, buflen, "db_pagesize=%lu\n",
01228                             (u_long)dbp->pgsize);
01229                         if ((ret = callback(handle, buf)) != 0)
01230                                 goto err;
01231                 }
01232         }
01233 
01234         if (keyflag)
01235                 if ((ret = callback(handle, "keys=1\n")) != 0)
01236                         goto err;
01237 
01238         ret = callback(handle, "HEADER=END\n");
01239 
01240 err:    if (pip != NULL &&
01241             (t_ret = CDB___db_vrfy_putpageinfo(vdp, pip)) != 0 && ret == 0)
01242                 ret = t_ret;
01243         if (btsp != NULL)
01244                 CDB___os_free(btsp, 0);
01245         if (hsp != NULL)
01246                 CDB___os_free(hsp, 0);
01247         if (qsp != NULL)
01248                 CDB___os_free(qsp, 0);
01249         if (buf != NULL)
01250                 CDB___os_free(buf, buflen);
01251 
01252         return (ret);
01253 }
01254 
01255 /*
01256  * CDB___db_prfooter --
01257  *      Print the footer that marks the end of a DB dump.  This is trivial,
01258  *      but for consistency's sake we don't want to put its literal contents
01259  *      in multiple places.
01260  *
01261  * PUBLIC: int CDB___db_prfooter __P((void *, int (*)(void *, const void *)));
01262  */
01263 int
01264 CDB___db_prfooter(handle, callback)
01265         void *handle;
01266         int (*callback) __P((void *, const void *));
01267 {
01268         return (callback(handle, "DATA=END\n"));
01269 }

Generated on Sun Jun 8 10:56:36 2008 for GNUmifluz by  doxygen 1.5.5