bt_verify.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:61k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*-
  2.  * See the file LICENSE for redistribution information.
  3.  *
  4.  * Copyright (c) 1999-2002
  5.  * Sleepycat Software.  All rights reserved.
  6.  *
  7.  * $Id: bt_verify.c,v 1.76 2002/07/03 19:03:51 bostic Exp $
  8.  */
  9. #include "db_config.h"
  10. #ifndef lint
  11. static const char revid[] = "$Id: bt_verify.c,v 1.76 2002/07/03 19:03:51 bostic Exp $";
  12. #endif /* not lint */
  13. #ifndef NO_SYSTEM_INCLUDES
  14. #include <sys/types.h>
  15. #include <string.h>
  16. #endif
  17. #include "db_int.h"
  18. #include "dbinc/db_page.h"
  19. #include "dbinc/db_verify.h"
  20. #include "dbinc/btree.h"
  21. static int __bam_safe_getdata __P((DB *, PAGE *, u_int32_t, int, DBT *, int *));
  22. static int __bam_vrfy_inp __P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t,
  23.     db_indx_t *, u_int32_t));
  24. static int __bam_vrfy_treeorder __P((DB *, db_pgno_t, PAGE *, BINTERNAL *,
  25.     BINTERNAL *, int (*)(DB *, const DBT *, const DBT *), u_int32_t));
  26. static int __ram_vrfy_inp __P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t,
  27.     db_indx_t *, u_int32_t));
  28. #define OKFLAGS (DB_AGGRESSIVE | DB_NOORDERCHK | DB_SALVAGE)
  29. /*
  30.  * __bam_vrfy_meta --
  31.  * Verify the btree-specific part of a metadata page.
  32.  *
  33.  * PUBLIC: int __bam_vrfy_meta __P((DB *, VRFY_DBINFO *, BTMETA *,
  34.  * PUBLIC:     db_pgno_t, u_int32_t));
  35.  */
  36. int
  37. __bam_vrfy_meta(dbp, vdp, meta, pgno, flags)
  38. DB *dbp;
  39. VRFY_DBINFO *vdp;
  40. BTMETA *meta;
  41. db_pgno_t pgno;
  42. u_int32_t flags;
  43. {
  44. VRFY_PAGEINFO *pip;
  45. int isbad, t_ret, ret;
  46. db_indx_t ovflsize;
  47. if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
  48. return (ret);
  49. isbad = 0;
  50. /*
  51.  * If VRFY_INCOMPLETE is not set, then we didn't come through
  52.  * __db_vrfy_pagezero and didn't incompletely
  53.  * check this page--we haven't checked it at all.
  54.  * Thus we need to call __db_vrfy_meta and check the common fields.
  55.  *
  56.  * If VRFY_INCOMPLETE is set, we've already done all the same work
  57.  * in __db_vrfy_pagezero, so skip the check.
  58.  */
  59. if (!F_ISSET(pip, VRFY_INCOMPLETE) &&
  60.     (ret = __db_vrfy_meta(dbp, vdp, &meta->dbmeta, pgno, flags)) != 0) {
  61. if (ret == DB_VERIFY_BAD)
  62. isbad = 1;
  63. else
  64. goto err;
  65. }
  66. /* bt_minkey:  must be >= 2; must produce sensible ovflsize */
  67. /* avoid division by zero */
  68. ovflsize = meta->minkey > 0 ?
  69.     B_MINKEY_TO_OVFLSIZE(dbp, meta->minkey, dbp->pgsize) : 0;
  70. if (meta->minkey < 2 ||
  71.     ovflsize > B_MINKEY_TO_OVFLSIZE(dbp, DEFMINKEYPAGE, dbp->pgsize)) {
  72. pip->bt_minkey = 0;
  73. isbad = 1;
  74. EPRINT((dbp->dbenv,
  75.     "Page %lu: nonsensical bt_minkey value %lu on metadata page",
  76.     (u_long)pgno, (u_long)meta->minkey));
  77. } else
  78. pip->bt_minkey = meta->minkey;
  79. /* bt_maxkey: no constraints (XXX: right?) */
  80. pip->bt_maxkey = meta->maxkey;
  81. /* re_len: no constraints on this (may be zero or huge--we make rope) */
  82. pip->re_len = meta->re_len;
  83. /*
  84.  * The root must not be current page or 0 and it must be within
  85.  * database.  If this metadata page is the master meta data page
  86.  * of the file, then the root page had better be page 1.
  87.  */
  88. pip->root = 0;
  89. if (meta->root == PGNO_INVALID ||
  90.     meta->root == pgno || !IS_VALID_PGNO(meta->root) ||
  91.     (pgno == PGNO_BASE_MD && meta->root != 1)) {
  92. isbad = 1;
  93. EPRINT((dbp->dbenv,
  94.     "Page %lu: nonsensical root page %lu on metadata page",
  95.     (u_long)pgno, (u_long)meta->root));
  96. } else
  97. pip->root = meta->root;
  98. /* Flags. */
  99. if (F_ISSET(&meta->dbmeta, BTM_RENUMBER))
  100. F_SET(pip, VRFY_IS_RRECNO);
  101. if (F_ISSET(&meta->dbmeta, BTM_SUBDB)) {
  102. /*
  103.  * If this is a master db meta page, it had better not have
  104.  * duplicates.
  105.  */
  106. if (F_ISSET(&meta->dbmeta, BTM_DUP) && pgno == PGNO_BASE_MD) {
  107. isbad = 1;
  108. EPRINT((dbp->dbenv,
  109. "Page %lu: Btree metadata page has both duplicates and multiple databases",
  110.     (u_long)pgno));
  111. }
  112. F_SET(pip, VRFY_HAS_SUBDBS);
  113. }
  114. if (F_ISSET(&meta->dbmeta, BTM_DUP))
  115. F_SET(pip, VRFY_HAS_DUPS);
  116. if (F_ISSET(&meta->dbmeta, BTM_DUPSORT))
  117. F_SET(pip, VRFY_HAS_DUPSORT);
  118. if (F_ISSET(&meta->dbmeta, BTM_RECNUM))
  119. F_SET(pip, VRFY_HAS_RECNUMS);
  120. if (F_ISSET(pip, VRFY_HAS_RECNUMS) && F_ISSET(pip, VRFY_HAS_DUPS)) {
  121. EPRINT((dbp->dbenv,
  122.     "Page %lu: Btree metadata page illegally has both recnums and dups",
  123.     (u_long)pgno));
  124. isbad = 1;
  125. }
  126. if (F_ISSET(&meta->dbmeta, BTM_RECNO)) {
  127. F_SET(pip, VRFY_IS_RECNO);
  128. dbp->type = DB_RECNO;
  129. } else if (F_ISSET(pip, VRFY_IS_RRECNO)) {
  130. isbad = 1;
  131. EPRINT((dbp->dbenv,
  132.     "Page %lu: metadata page has renumber flag set but is not recno",
  133.     (u_long)pgno));
  134. }
  135. if (F_ISSET(pip, VRFY_IS_RECNO) && F_ISSET(pip, VRFY_HAS_DUPS)) {
  136. EPRINT((dbp->dbenv,
  137.     "Page %lu: recno metadata page specifies duplicates",
  138.     (u_long)pgno));
  139. isbad = 1;
  140. }
  141. if (F_ISSET(&meta->dbmeta, BTM_FIXEDLEN))
  142. F_SET(pip, VRFY_IS_FIXEDLEN);
  143. else if (pip->re_len > 0) {
  144. /*
  145.  * It's wrong to have an re_len if it's not a fixed-length
  146.  * database
  147.  */
  148. isbad = 1;
  149. EPRINT((dbp->dbenv,
  150.     "Page %lu: re_len of %lu in non-fixed-length database",
  151.     (u_long)pgno, (u_long)pip->re_len));
  152. }
  153. /*
  154.  * We do not check that the rest of the page is 0, because it may
  155.  * not be and may still be correct.
  156.  */
  157. err: if ((t_ret =
  158.     __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 && ret == 0)
  159. ret = t_ret;
  160. return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
  161. }
  162. /*
  163.  * __ram_vrfy_leaf --
  164.  * Verify a recno leaf page.
  165.  *
  166.  * PUBLIC: int __ram_vrfy_leaf __P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t,
  167.  * PUBLIC:     u_int32_t));
  168.  */
  169. int
  170. __ram_vrfy_leaf(dbp, vdp, h, pgno, flags)
  171. DB *dbp;
  172. VRFY_DBINFO *vdp;
  173. PAGE *h;
  174. db_pgno_t pgno;
  175. u_int32_t flags;
  176. {
  177. BKEYDATA *bk;
  178. VRFY_PAGEINFO *pip;
  179. db_indx_t i;
  180. int ret, t_ret, isbad;
  181. u_int32_t re_len_guess, len;
  182. isbad = 0;
  183. if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
  184. return (ret);
  185. if ((ret = __db_fchk(dbp->dbenv,
  186.     "__ram_vrfy_leaf", flags, OKFLAGS)) != 0)
  187. goto err;
  188. if (TYPE(h) != P_LRECNO) {
  189. /* We should not have been called. */
  190. TYPE_ERR_PRINT(dbp->dbenv, "__ram_vrfy_leaf", pgno, TYPE(h));
  191. DB_ASSERT(0);
  192. ret = EINVAL;
  193. goto err;
  194. }
  195. /*
  196.  * Verify (and, if relevant, save off) page fields common to
  197.  * all PAGEs.
  198.  */
  199. if ((ret = __db_vrfy_datapage(dbp, vdp, h, pgno, flags)) != 0) {
  200. if (ret == DB_VERIFY_BAD)
  201. isbad = 1;
  202. else
  203. goto err;
  204. }
  205. /*
  206.  * Verify inp[].  Return immediately if it returns DB_VERIFY_BAD;
  207.  * further checks are dangerous.
  208.  */
  209. if ((ret = __bam_vrfy_inp(dbp,
  210.     vdp, h, pgno, &pip->entries, flags)) != 0)
  211. goto err;
  212. if (F_ISSET(pip, VRFY_HAS_DUPS)) {
  213. EPRINT((dbp->dbenv,
  214.     "Page %lu: Recno database has dups", (u_long)pgno));
  215. ret = DB_VERIFY_BAD;
  216. goto err;
  217. }
  218. /*
  219.  * Walk through inp and see if the lengths of all the records are the
  220.  * same--if so, this may be a fixed-length database, and we want to
  221.  * save off this value.  We know inp to be safe if we've gotten this
  222.  * far.
  223.  */
  224. re_len_guess = 0;
  225. for (i = 0; i < NUM_ENT(h); i++) {
  226. bk = GET_BKEYDATA(dbp, h, i);
  227. /* KEYEMPTY.  Go on. */
  228. if (B_DISSET(bk->type))
  229. continue;
  230. if (bk->type == B_OVERFLOW)
  231. len = ((BOVERFLOW *)bk)->tlen;
  232. else if (bk->type == B_KEYDATA)
  233. len = bk->len;
  234. else {
  235. isbad = 1;
  236. EPRINT((dbp->dbenv,
  237.     "Page %lu: nonsensical type for item %lu",
  238.     (u_long)pgno, (u_long)i));
  239. continue;
  240. }
  241. if (re_len_guess == 0)
  242. re_len_guess = len;
  243. /*
  244.  * Is this item's len the same as the last one's?  If not,
  245.  * reset to 0 and break--we don't have a single re_len.
  246.  * Otherwise, go on to the next item.
  247.  */
  248. if (re_len_guess != len) {
  249. re_len_guess = 0;
  250. break;
  251. }
  252. }
  253. pip->re_len = re_len_guess;
  254. /* Save off record count. */
  255. pip->rec_cnt = NUM_ENT(h);
  256. err: if ((t_ret =
  257.     __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 && ret == 0)
  258. ret = t_ret;
  259. return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
  260. }
  261. /*
  262.  * __bam_vrfy --
  263.  * Verify a btree leaf or internal page.
  264.  *
  265.  * PUBLIC: int __bam_vrfy __P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t,
  266.  * PUBLIC:     u_int32_t));
  267.  */
  268. int
  269. __bam_vrfy(dbp, vdp, h, pgno, flags)
  270. DB *dbp;
  271. VRFY_DBINFO *vdp;
  272. PAGE *h;
  273. db_pgno_t pgno;
  274. u_int32_t flags;
  275. {
  276. VRFY_PAGEINFO *pip;
  277. int ret, t_ret, isbad;
  278. isbad = 0;
  279. if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
  280. return (ret);
  281. switch (TYPE(h)) {
  282. case P_IBTREE:
  283. case P_IRECNO:
  284. case P_LBTREE:
  285. case P_LDUP:
  286. break;
  287. default:
  288. TYPE_ERR_PRINT(dbp->dbenv, "__bam_vrfy", pgno, TYPE(h));
  289. DB_ASSERT(0);
  290. ret = EINVAL;
  291. goto err;
  292. }
  293. /*
  294.  * Verify (and, if relevant, save off) page fields common to
  295.  * all PAGEs.
  296.  */
  297. if ((ret = __db_vrfy_datapage(dbp, vdp, h, pgno, flags)) != 0) {
  298. if (ret == DB_VERIFY_BAD)
  299. isbad = 1;
  300. else
  301. goto err;
  302. }
  303. /*
  304.  * The record count is, on internal pages, stored in an overloaded
  305.  * next_pgno field.  Save it off;  we'll verify it when we check
  306.  * overall database structure.  We could overload the field
  307.  * in VRFY_PAGEINFO, too, but this seems gross, and space
  308.  * is not at such a premium.
  309.  */
  310. pip->rec_cnt = RE_NREC(h);
  311. /*
  312.  * Verify inp[].
  313.  */
  314. if (TYPE(h) == P_IRECNO) {
  315. if ((ret = __ram_vrfy_inp(dbp,
  316.     vdp, h, pgno, &pip->entries, flags)) != 0)
  317. goto err;
  318. } else if ((ret = __bam_vrfy_inp(dbp,
  319.     vdp, h, pgno, &pip->entries, flags)) != 0) {
  320. if (ret == DB_VERIFY_BAD)
  321. isbad = 1;
  322. else
  323. goto err;
  324. EPRINT((dbp->dbenv,
  325.     "Page %lu: item order check unsafe: skipping",
  326.     (u_long)pgno));
  327. } else if (!LF_ISSET(DB_NOORDERCHK) && (ret =
  328.     __bam_vrfy_itemorder(dbp, vdp, h, pgno, 0, 0, 0, flags)) != 0) {
  329. /*
  330.  * We know that the elements of inp are reasonable.
  331.  *
  332.  * Check that elements fall in the proper order.
  333.  */
  334. if (ret == DB_VERIFY_BAD)
  335. isbad = 1;
  336. else
  337. goto err;
  338. }
  339. err: if ((t_ret =
  340.     __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 && ret == 0)
  341. ret = t_ret;
  342. return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
  343. }
  344. /*
  345.  * __ram_vrfy_inp --
  346.  * Verify that all entries in a P_IRECNO inp[] array are reasonable,
  347.  * and count them.  Note that P_LRECNO uses __bam_vrfy_inp;
  348.  * P_IRECNOs are a special, and simpler, case, since they have
  349.  * RINTERNALs rather than BKEYDATA/BINTERNALs.
  350.  */
  351. static int
  352. __ram_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
  353. DB *dbp;
  354. VRFY_DBINFO *vdp;
  355. PAGE *h;
  356. db_pgno_t pgno;
  357. db_indx_t *nentriesp;
  358. u_int32_t flags;
  359. {
  360. RINTERNAL *ri;
  361. VRFY_CHILDINFO child;
  362. VRFY_PAGEINFO *pip;
  363. int ret, t_ret, isbad;
  364. u_int32_t himark, i, offset, nentries;
  365. db_indx_t *inp;
  366. u_int8_t *pagelayout, *p;
  367. isbad = 0;
  368. memset(&child, 0, sizeof(VRFY_CHILDINFO));
  369. nentries = 0;
  370. pagelayout = NULL;
  371. if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
  372. return (ret);
  373. if (TYPE(h) != P_IRECNO) {
  374. TYPE_ERR_PRINT(dbp->dbenv, "__ram_vrfy_inp", pgno, TYPE(h));
  375. DB_ASSERT(0);
  376. ret = EINVAL;
  377. goto err;
  378. }
  379. himark = dbp->pgsize;
  380. if ((ret =
  381.     __os_malloc(dbp->dbenv, dbp->pgsize, &pagelayout)) != 0)
  382. goto err;
  383. memset(pagelayout, 0, dbp->pgsize);
  384. inp = P_INP(dbp, h);
  385. for (i = 0; i < NUM_ENT(h); i++) {
  386. if ((u_int8_t *)inp + i >= (u_int8_t *)h + himark) {
  387. EPRINT((dbp->dbenv,
  388.     "Page %lu: entries listing %lu overlaps data",
  389.     (u_long)pgno, (u_long)i));
  390. ret = DB_VERIFY_BAD;
  391. goto err;
  392. }
  393. offset = inp[i];
  394. /*
  395.  * Check that the item offset is reasonable:  it points
  396.  * somewhere after the inp array and before the end of the
  397.  * page.
  398.  */
  399. if (offset <= (u_int32_t)((u_int8_t *)inp + i -
  400.     (u_int8_t *)h) ||
  401.     offset > (u_int32_t)(dbp->pgsize - RINTERNAL_SIZE)) {
  402. isbad = 1;
  403. EPRINT((dbp->dbenv,
  404.     "Page %lu: bad offset %lu at index %lu",
  405.     (u_long)pgno, (u_long)offset, (u_long)i));
  406. continue;
  407. }
  408. /* Update the high-water mark (what HOFFSET should be) */
  409. if (offset < himark)
  410. himark = offset;
  411. nentries++;
  412. /* Make sure this RINTERNAL is not multiply referenced. */
  413. ri = GET_RINTERNAL(dbp, h, i);
  414. if (pagelayout[offset] == 0) {
  415. pagelayout[offset] = 1;
  416. child.pgno = ri->pgno;
  417. child.type = V_RECNO;
  418. child.nrecs = ri->nrecs;
  419. if ((ret = __db_vrfy_childput(vdp, pgno, &child)) != 0)
  420. goto err;
  421. } else {
  422. EPRINT((dbp->dbenv,
  423. "Page %lu: RINTERNAL structure at offset %lu referenced twice",
  424.     (u_long)pgno, (u_long)offset));
  425. isbad = 1;
  426. }
  427. }
  428. for (p = pagelayout + himark;
  429.     p < pagelayout + dbp->pgsize;
  430.     p += RINTERNAL_SIZE)
  431. if (*p != 1) {
  432. EPRINT((dbp->dbenv,
  433.     "Page %lu: gap between items at offset %lu",
  434.     (u_long)pgno, (u_long)(p - pagelayout)));
  435. isbad = 1;
  436. }
  437. if ((db_indx_t)himark != HOFFSET(h)) {
  438. EPRINT((dbp->dbenv,
  439.     "Page %lu: bad HOFFSET %lu, appears to be %lu",
  440.     (u_long)pgno, (u_long)(HOFFSET(h)), (u_long)himark));
  441. isbad = 1;
  442. }
  443. *nentriesp = nentries;
  444. err: if ((t_ret =
  445.     __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 && ret == 0)
  446. ret = t_ret;
  447. if (pagelayout != NULL)
  448. __os_free(dbp->dbenv, pagelayout);
  449. return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
  450. }
  451. /*
  452.  * __bam_vrfy_inp --
  453.  * Verify that all entries in inp[] array are reasonable;
  454.  * count them.
  455.  */
  456. static int
  457. __bam_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags)
  458. DB *dbp;
  459. VRFY_DBINFO *vdp;
  460. PAGE *h;
  461. db_pgno_t pgno;
  462. db_indx_t *nentriesp;
  463. u_int32_t flags;
  464. {
  465. BKEYDATA *bk;
  466. BOVERFLOW *bo;
  467. VRFY_CHILDINFO child;
  468. VRFY_PAGEINFO *pip;
  469. int isbad, initem, isdupitem, ret, t_ret;
  470. u_int32_t himark, offset; /* These would be db_indx_ts but for algnmt.*/
  471. u_int32_t i, endoff, nentries;
  472. u_int8_t *pagelayout;
  473. isbad = isdupitem = 0;
  474. nentries = 0;
  475. memset(&child, 0, sizeof(VRFY_CHILDINFO));
  476. if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
  477. return (ret);
  478. switch (TYPE(h)) {
  479. case P_IBTREE:
  480. case P_LBTREE:
  481. case P_LDUP:
  482. case P_LRECNO:
  483. break;
  484. default:
  485. /*
  486.  * In the salvager, we might call this from a page which
  487.  * we merely suspect is a btree page.  Otherwise, it
  488.  * shouldn't get called--if it is, that's a verifier bug.
  489.  */
  490. if (LF_ISSET(DB_SALVAGE))
  491. break;
  492. TYPE_ERR_PRINT(dbp->dbenv, "__bam_vrfy_inp", pgno, TYPE(h));
  493. DB_ASSERT(0);
  494. ret = EINVAL;
  495. goto err;
  496. }
  497. /*
  498.  * Loop through inp[], the array of items, until we either
  499.  * run out of entries or collide with the data.  Keep track
  500.  * of h_offset in himark.
  501.  *
  502.  * For each element in inp[i], make sure it references a region
  503.  * that starts after the end of the inp array (as defined by
  504.  * NUM_ENT(h)), ends before the beginning of the page, doesn't
  505.  * overlap any other regions, and doesn't have a gap between
  506.  * it and the region immediately after it.
  507.  */
  508. himark = dbp->pgsize;
  509. if ((ret = __os_malloc(dbp->dbenv, dbp->pgsize, &pagelayout)) != 0)
  510. goto err;
  511. memset(pagelayout, 0, dbp->pgsize);
  512. for (i = 0; i < NUM_ENT(h); i++) {
  513. switch (ret = __db_vrfy_inpitem(dbp,
  514.     h, pgno, i, 1, flags, &himark, &offset)) {
  515. case 0:
  516. break;
  517. case DB_VERIFY_BAD:
  518. isbad = 1;
  519. continue;
  520. case DB_VERIFY_FATAL:
  521. isbad = 1;
  522. goto err;
  523. default:
  524. DB_ASSERT(ret != 0);
  525. break;
  526. }
  527. /*
  528.  * We now have a plausible beginning for the item, and we know
  529.  * its length is safe.
  530.  *
  531.  * Mark the beginning and end in pagelayout so we can make sure
  532.  * items have no overlaps or gaps.
  533.  */
  534. bk = GET_BKEYDATA(dbp, h, i);
  535. #define ITEM_BEGIN 1
  536. #define ITEM_END 2
  537. if (pagelayout[offset] == 0)
  538. pagelayout[offset] = ITEM_BEGIN;
  539. else if (pagelayout[offset] == ITEM_BEGIN) {
  540. /*
  541.  * Having two inp entries that point at the same patch
  542.  * of page is legal if and only if the page is
  543.  * a btree leaf and they're onpage duplicate keys--
  544.  * that is, if (i % P_INDX) == 0.
  545.  */
  546. if ((i % P_INDX == 0) && (TYPE(h) == P_LBTREE)) {
  547. /* Flag for later. */
  548. F_SET(pip, VRFY_HAS_DUPS);
  549. /* Bump up nentries so we don't undercount. */
  550. nentries++;
  551. /*
  552.  * We'll check to make sure the end is
  553.  * equal, too.
  554.  */
  555. isdupitem = 1;
  556. } else {
  557. isbad = 1;
  558. EPRINT((dbp->dbenv,
  559.     "Page %lu: duplicated item %lu",
  560.     (u_long)pgno, (u_long)i));
  561. }
  562. }
  563. /*
  564.  * Mark the end.  Its location varies with the page type
  565.  * and the item type.
  566.  *
  567.  * If the end already has a sign other than 0, do nothing--
  568.  * it's an overlap that we'll catch later.
  569.  */
  570. switch(B_TYPE(bk->type)) {
  571. case B_KEYDATA:
  572. if (TYPE(h) == P_IBTREE)
  573. /* It's a BINTERNAL. */
  574. endoff = offset + BINTERNAL_SIZE(bk->len) - 1;
  575. else
  576. endoff = offset + BKEYDATA_SIZE(bk->len) - 1;
  577. break;
  578. case B_DUPLICATE:
  579. /*
  580.  * Flag that we have dups; we'll check whether
  581.  * that's okay during the structure check.
  582.  */
  583. F_SET(pip, VRFY_HAS_DUPS);
  584. /* FALLTHROUGH */
  585. case B_OVERFLOW:
  586. /*
  587.  * Overflow entries on internal pages are stored
  588.  * as the _data_ of a BINTERNAL;  overflow entries
  589.  * on leaf pages are stored as the entire entry.
  590.  */
  591. endoff = offset +
  592.     ((TYPE(h) == P_IBTREE) ?
  593.     BINTERNAL_SIZE(BOVERFLOW_SIZE) :
  594.     BOVERFLOW_SIZE) - 1;
  595. break;
  596. default:
  597. /*
  598.  * We'll complain later;  for now, just mark
  599.  * a minimum.
  600.  */
  601. endoff = offset + BKEYDATA_SIZE(0) - 1;
  602. break;
  603. }
  604. /*
  605.  * If this is an onpage duplicate key we've seen before,
  606.  * the end had better coincide too.
  607.  */
  608. if (isdupitem && pagelayout[endoff] != ITEM_END) {
  609. EPRINT((dbp->dbenv,
  610.     "Page %lu: duplicated item %lu",
  611.     (u_long)pgno, (u_long)i));
  612. isbad = 1;
  613. } else if (pagelayout[endoff] == 0)
  614. pagelayout[endoff] = ITEM_END;
  615. isdupitem = 0;
  616. /*
  617.  * There should be no deleted items in a quiescent tree,
  618.  * except in recno.
  619.  */
  620. if (B_DISSET(bk->type) && TYPE(h) != P_LRECNO) {
  621. isbad = 1;
  622. EPRINT((dbp->dbenv,
  623.     "Page %lu: item %lu marked deleted",
  624.     (u_long)pgno, (u_long)i));
  625. }
  626. /*
  627.  * Check the type and such of bk--make sure it's reasonable
  628.  * for the pagetype.
  629.  */
  630. switch (B_TYPE(bk->type)) {
  631. case B_KEYDATA:
  632. /*
  633.  * This is a normal, non-overflow BKEYDATA or BINTERNAL.
  634.  * The only thing to check is the len, and that's
  635.  * already been done.
  636.  */
  637. break;
  638. case B_DUPLICATE:
  639. if (TYPE(h) == P_IBTREE) {
  640. isbad = 1;
  641. EPRINT((dbp->dbenv,
  642.     "Page %lu: duplicate page referenced by internal btree page at item %lu",
  643.     (u_long)pgno, (u_long)i));
  644. break;
  645. } else if (TYPE(h) == P_LRECNO) {
  646. isbad = 1;
  647. EPRINT((dbp->dbenv,
  648. "Page %lu: duplicate page referenced by recno page at item %lu",
  649.     (u_long)pgno, (u_long)i));
  650. break;
  651. }
  652. /* FALLTHROUGH */
  653. case B_OVERFLOW:
  654. bo = (TYPE(h) == P_IBTREE) ?
  655.     (BOVERFLOW *)(((BINTERNAL *)bk)->data) :
  656.     (BOVERFLOW *)bk;
  657. if (B_TYPE(bk->type) == B_OVERFLOW)
  658. /* Make sure tlen is reasonable. */
  659. if (bo->tlen > dbp->pgsize * vdp->last_pgno) {
  660. isbad = 1;
  661. EPRINT((dbp->dbenv,
  662. "Page %lu: impossible tlen %lu, item %lu",
  663.     (u_long)pgno,
  664.     (u_long)bo->tlen, (u_long)i));
  665. /* Don't save as a child. */
  666. break;
  667. }
  668. if (!IS_VALID_PGNO(bo->pgno) || bo->pgno == pgno ||
  669.     bo->pgno == PGNO_INVALID) {
  670. isbad = 1;
  671. EPRINT((dbp->dbenv,
  672.     "Page %lu: offpage item %lu has bad pgno %lu",
  673.     (u_long)pgno, (u_long)i, (u_long)bo->pgno));
  674. /* Don't save as a child. */
  675. break;
  676. }
  677. child.pgno = bo->pgno;
  678. child.type = (B_TYPE(bk->type) == B_OVERFLOW ?
  679.     V_OVERFLOW : V_DUPLICATE);
  680. child.tlen = bo->tlen;
  681. if ((ret = __db_vrfy_childput(vdp, pgno, &child)) != 0)
  682. goto err;
  683. break;
  684. default:
  685. isbad = 1;
  686. EPRINT((dbp->dbenv,
  687.     "Page %lu: item %lu of invalid type %lu",
  688.     (u_long)pgno, (u_long)i));
  689. break;
  690. }
  691. }
  692. /*
  693.  * Now, loop through and make sure the items are contiguous and
  694.  * non-overlapping.
  695.  */
  696. initem = 0;
  697. for (i = himark; i < dbp->pgsize; i++)
  698. if (initem == 0)
  699. switch (pagelayout[i]) {
  700. case 0:
  701. /* May be just for alignment. */
  702. if (i != ALIGN(i, sizeof(u_int32_t)))
  703. continue;
  704. isbad = 1;
  705. EPRINT((dbp->dbenv,
  706.     "Page %lu: gap between items at offset %lu",
  707.     (u_long)pgno, (u_long)i));
  708. /* Find the end of the gap */
  709. for ( ; pagelayout[i + 1] == 0 &&
  710.     (size_t)(i + 1) < dbp->pgsize; i++)
  711. ;
  712. break;
  713. case ITEM_BEGIN:
  714. /* We've found an item. Check its alignment. */
  715. if (i != ALIGN(i, sizeof(u_int32_t))) {
  716. isbad = 1;
  717. EPRINT((dbp->dbenv,
  718.     "Page %lu: offset %lu unaligned",
  719.     (u_long)pgno, (u_long)i));
  720. }
  721. initem = 1;
  722. nentries++;
  723. break;
  724. case ITEM_END:
  725. /*
  726.  * We've hit the end of an item even though
  727.  * we don't think we're in one;  must
  728.  * be an overlap.
  729.  */
  730. isbad = 1;
  731. EPRINT((dbp->dbenv,
  732.     "Page %lu: overlapping items at offset %lu",
  733.     (u_long)pgno, (u_long)i));
  734. break;
  735. default:
  736. /* Should be impossible. */
  737. DB_ASSERT(0);
  738. ret = EINVAL;
  739. goto err;
  740. }
  741. else
  742. switch (pagelayout[i]) {
  743. case 0:
  744. /* In the middle of an item somewhere. Okay. */
  745. break;
  746. case ITEM_END:
  747. /* End of an item; switch to out-of-item mode.*/
  748. initem = 0;
  749. break;
  750. case ITEM_BEGIN:
  751. /*
  752.  * Hit a second item beginning without an
  753.  * end.  Overlap.
  754.  */
  755. isbad = 1;
  756. EPRINT((dbp->dbenv,
  757.     "Page %lu: overlapping items at offset %lu",
  758.     (u_long)pgno, (u_long)i));
  759. break;
  760. }
  761. (void)__os_free(dbp->dbenv, pagelayout);
  762. /* Verify HOFFSET. */
  763. if ((db_indx_t)himark != HOFFSET(h)) {
  764. EPRINT((dbp->dbenv,
  765.     "Page %lu: bad HOFFSET %lu, appears to be %lu",
  766.     (u_long)pgno, (u_long)HOFFSET(h), (u_long)himark));
  767. isbad = 1;
  768. }
  769. err: if (nentriesp != NULL)
  770. *nentriesp = nentries;
  771. if ((t_ret =
  772.     __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 && ret == 0)
  773. ret = t_ret;
  774. return ((isbad == 1 && ret == 0) ? DB_VERIFY_BAD : ret);
  775. }
  776. /*
  777.  * __bam_vrfy_itemorder --
  778.  * Make sure the items on a page sort correctly.
  779.  *
  780.  * Assumes that NUM_ENT(h) and inp[0]..inp[NUM_ENT(h) - 1] are
  781.  * reasonable;  be sure that __bam_vrfy_inp has been called first.
  782.  *
  783.  * If ovflok is set, it also assumes that overflow page chains
  784.  * hanging off the current page have been sanity-checked, and so we
  785.  * can use __bam_cmp to verify their ordering.  If it is not set,
  786.  * and we run into an overflow page, carp and return DB_VERIFY_BAD;
  787.  * we shouldn't be called if any exist.
  788.  *
  789.  * PUBLIC: int __bam_vrfy_itemorder __P((DB *, VRFY_DBINFO *, PAGE *,
  790.  * PUBLIC:     db_pgno_t, u_int32_t, int, int, u_int32_t));
  791.  */
  792. int
  793. __bam_vrfy_itemorder(dbp, vdp, h, pgno, nentries, ovflok, hasdups, flags)
  794. DB *dbp;
  795. VRFY_DBINFO *vdp;
  796. PAGE *h;
  797. db_pgno_t pgno;
  798. u_int32_t nentries;
  799. int ovflok, hasdups;
  800. u_int32_t flags;
  801. {
  802. DBT dbta, dbtb, dup_1, dup_2, *p1, *p2, *tmp;
  803. BTREE *bt;
  804. BINTERNAL *bi;
  805. BKEYDATA *bk;
  806. BOVERFLOW *bo;
  807. VRFY_PAGEINFO *pip;
  808. db_indx_t i;
  809. int cmp, freedup_1, freedup_2, isbad, ret, t_ret;
  810. int (*dupfunc) __P((DB *, const DBT *, const DBT *));
  811. int (*func) __P((DB *, const DBT *, const DBT *));
  812. void *buf1, *buf2, *tmpbuf;
  813. /*
  814.  * We need to work in the ORDERCHKONLY environment where we might
  815.  * not have a pip, but we also may need to work in contexts where
  816.  * NUM_ENT isn't safe.
  817.  */
  818. if (vdp != NULL) {
  819. if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
  820. return (ret);
  821. nentries = pip->entries;
  822. } else
  823. pip = NULL;
  824. ret = isbad = 0;
  825. bo = NULL; /* Shut up compiler. */
  826. memset(&dbta, 0, sizeof(DBT));
  827. F_SET(&dbta, DB_DBT_REALLOC);
  828. memset(&dbtb, 0, sizeof(DBT));
  829. F_SET(&dbtb, DB_DBT_REALLOC);
  830. buf1 = buf2 = NULL;
  831. DB_ASSERT(!LF_ISSET(DB_NOORDERCHK));
  832. dupfunc = (dbp->dup_compare == NULL) ? __bam_defcmp : dbp->dup_compare;
  833. if (TYPE(h) == P_LDUP)
  834. func = dupfunc;
  835. else {
  836. func = __bam_defcmp;
  837. if (dbp->bt_internal != NULL) {
  838. bt = (BTREE *)dbp->bt_internal;
  839. if (bt->bt_compare != NULL)
  840. func = bt->bt_compare;
  841. }
  842. }
  843. /*
  844.  * We alternate our use of dbta and dbtb so that we can walk
  845.  * through the page key-by-key without copying a dbt twice.
  846.  * p1 is always the dbt for index i - 1, and p2 for index i.
  847.  */
  848. p1 = &dbta;
  849. p2 = &dbtb;
  850. /*
  851.  * Loop through the entries.  nentries ought to contain the
  852.  * actual count, and so is a safe way to terminate the loop;  whether
  853.  * we inc. by one or two depends on whether we're a leaf page--
  854.  * on a leaf page, we care only about keys.  On internal pages
  855.  * and LDUP pages, we want to check the order of all entries.
  856.  *
  857.  * Note that on IBTREE pages, we start with item 1, since item
  858.  * 0 doesn't get looked at by __bam_cmp.
  859.  */
  860. for (i = (TYPE(h) == P_IBTREE) ? 1 : 0; i < nentries;
  861.     i += (TYPE(h) == P_LBTREE) ? P_INDX : O_INDX) {
  862. /*
  863.  * Put key i-1, now in p2, into p1, by swapping DBTs and bufs.
  864.  */
  865. tmp = p1;
  866. p1 = p2;
  867. p2 = tmp;
  868. tmpbuf = buf1;
  869. buf1 = buf2;
  870. buf2 = tmpbuf;
  871. /*
  872.  * Get key i into p2.
  873.  */
  874. switch (TYPE(h)) {
  875. case P_IBTREE:
  876. bi = GET_BINTERNAL(dbp, h, i);
  877. if (B_TYPE(bi->type) == B_OVERFLOW) {
  878. bo = (BOVERFLOW *)(bi->data);
  879. goto overflow;
  880. } else {
  881. p2->data = bi->data;
  882. p2->size = bi->len;
  883. }
  884. /*
  885.  * The leftmost key on an internal page must be
  886.  * len 0, since it's just a placeholder and
  887.  * automatically sorts less than all keys.
  888.  *
  889.  * XXX
  890.  * This criterion does not currently hold!
  891.  * See todo list item #1686.  Meanwhile, it's harmless
  892.  * to just not check for it.
  893.  */
  894. #if 0
  895. if (i == 0 && bi->len != 0) {
  896. isbad = 1;
  897. EPRINT((dbp->dbenv,
  898. "Page %lu: lowest key on internal page of nonzero length",
  899.     (u_long)pgno));
  900. }
  901. #endif
  902. break;
  903. case P_LBTREE:
  904. case P_LDUP:
  905. bk = GET_BKEYDATA(dbp, h, i);
  906. if (B_TYPE(bk->type) == B_OVERFLOW) {
  907. bo = (BOVERFLOW *)bk;
  908. goto overflow;
  909. } else {
  910. p2->data = bk->data;
  911. p2->size = bk->len;
  912. }
  913. break;
  914. default:
  915. /*
  916.  * This means our caller screwed up and sent us
  917.  * an inappropriate page.
  918.  */
  919. TYPE_ERR_PRINT(dbp->dbenv,
  920.     "__bam_vrfy_itemorder", pgno, TYPE(h))
  921. DB_ASSERT(0);
  922. ret = EINVAL;
  923. goto err;
  924. }
  925. if (0) {
  926. /*
  927.  * If ovflok != 1, we can't safely go chasing
  928.  * overflow pages with the normal routines now;
  929.  * they might be unsafe or nonexistent.  Mark this
  930.  * page as incomplete and return.
  931.  *
  932.  * Note that we don't need to worry about freeing
  933.  * buffers, since they can't have been allocated
  934.  * if overflow items are unsafe.
  935.  */
  936. overflow: if (!ovflok) {
  937. F_SET(pip, VRFY_INCOMPLETE);
  938. goto err;
  939. }
  940. /*
  941.  * Overflow items are safe to chase.  Do so.
  942.  * Fetch the overflow item into p2->data,
  943.  * NULLing it or reallocing it as appropriate.
  944.  *
  945.  * (We set p2->data to buf2 before the call
  946.  * so we're sure to realloc if we can and if p2
  947.  * was just pointing at a non-overflow item.)
  948.  */
  949. p2->data = buf2;
  950. if ((ret = __db_goff(dbp,
  951.     p2, bo->tlen, bo->pgno, NULL, NULL)) != 0) {
  952. isbad = 1;
  953. EPRINT((dbp->dbenv,
  954.     "Page %lu: error %lu in fetching overflow item %lu",
  955.     (u_long)pgno, (u_long)ret, (u_long)i));
  956. }
  957. /* In case it got realloc'ed and thus changed. */
  958. buf2 = p2->data;
  959. }
  960. /* Compare with the last key. */
  961. if (p1->data != NULL && p2->data != NULL) {
  962. cmp = func(dbp, p1, p2);
  963. /* comparison succeeded */
  964. if (cmp > 0) {
  965. isbad = 1;
  966. EPRINT((dbp->dbenv,
  967.     "Page %lu: out-of-order key at entry %lu",
  968.     (u_long)pgno, (u_long)i));
  969. /* proceed */
  970. } else if (cmp == 0) {
  971. /*
  972.  * If they compared equally, this
  973.  * had better be a (sub)database with dups.
  974.  * Mark it so we can check during the
  975.  * structure check.
  976.  */
  977. if (pip != NULL)
  978. F_SET(pip, VRFY_HAS_DUPS);
  979. else if (hasdups == 0) {
  980. isbad = 1;
  981. EPRINT((dbp->dbenv,
  982. "Page %lu: database with no duplicates has duplicated keys",
  983.     (u_long)pgno));
  984. }
  985. /*
  986.  * If we're a btree leaf, check to see
  987.  * if the data items of these on-page dups are
  988.  * in sorted order.  If not, flag this, so
  989.  * that we can make sure during the
  990.  * structure checks that the DUPSORT flag
  991.  * is unset.
  992.  *
  993.  * At this point i points to a duplicate key.
  994.  * Compare the datum before it (same key)
  995.  * to the datum after it, i.e. i-1 to i+1.
  996.  */
  997. if (TYPE(h) == P_LBTREE) {
  998. /*
  999.  * Unsafe;  continue and we'll pick
  1000.  * up the bogus nentries later.
  1001.  */
  1002. if (i + 1 >= (db_indx_t)nentries)
  1003. continue;
  1004. /*
  1005.  * We don't bother with clever memory
  1006.  * management with on-page dups,
  1007.  * as it's only really a big win
  1008.  * in the overflow case, and overflow
  1009.  * dups are probably (?) rare.
  1010.  */
  1011. if (((ret = __bam_safe_getdata(dbp,
  1012.     h, i - 1, ovflok, &dup_1,
  1013.     &freedup_1)) != 0) ||
  1014.     ((ret = __bam_safe_getdata(dbp,
  1015.     h, i + 1, ovflok, &dup_2,
  1016.     &freedup_2)) != 0))
  1017. goto err;
  1018. /*
  1019.  * If either of the data are NULL,
  1020.  * it's because they're overflows and
  1021.  * it's not safe to chase them now.
  1022.  * Mark an incomplete and return.
  1023.  */
  1024. if (dup_1.data == NULL ||
  1025.     dup_2.data == NULL) {
  1026. DB_ASSERT(!ovflok);
  1027. F_SET(pip, VRFY_INCOMPLETE);
  1028. goto err;
  1029. }
  1030. /*
  1031.  * If the dups are out of order,
  1032.  * flag this.  It's not an error
  1033.  * until we do the structure check
  1034.  * and see whether DUPSORT is set.
  1035.  */
  1036. if (dupfunc(dbp, &dup_1, &dup_2) > 0)
  1037. F_SET(pip, VRFY_DUPS_UNSORTED);
  1038. if (freedup_1)
  1039. __os_ufree(dbp->dbenv,
  1040.     dup_1.data);
  1041. if (freedup_2)
  1042. __os_ufree(dbp->dbenv,
  1043.     dup_2.data);
  1044. }
  1045. }
  1046. }
  1047. }
  1048. err: if (pip != NULL && ((t_ret =
  1049.     __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0) && ret == 0)
  1050. ret = t_ret;
  1051. if (buf1 != NULL)
  1052. __os_ufree(dbp->dbenv, buf1);
  1053. if (buf2 != NULL)
  1054. __os_ufree(dbp->dbenv, buf2);
  1055. return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
  1056. }
  1057. /*
  1058.  * __bam_vrfy_structure --
  1059.  * Verify the tree structure of a btree database (including the master
  1060.  * database containing subdbs).
  1061.  *
  1062.  * PUBLIC: int __bam_vrfy_structure __P((DB *, VRFY_DBINFO *, db_pgno_t,
  1063.  * PUBLIC:     u_int32_t));
  1064.  */
  1065. int
  1066. __bam_vrfy_structure(dbp, vdp, meta_pgno, flags)
  1067. DB *dbp;
  1068. VRFY_DBINFO *vdp;
  1069. db_pgno_t meta_pgno;
  1070. u_int32_t flags;
  1071. {
  1072. DB *pgset;
  1073. VRFY_PAGEINFO *mip, *rip;
  1074. db_pgno_t root, p;
  1075. int t_ret, ret;
  1076. u_int32_t nrecs, level, relen, stflags;
  1077. mip = rip = 0;
  1078. pgset = vdp->pgset;
  1079. if ((ret = __db_vrfy_getpageinfo(vdp, meta_pgno, &mip)) != 0)
  1080. return (ret);
  1081. if ((ret = __db_vrfy_pgset_get(pgset, meta_pgno, (int *)&p)) != 0)
  1082. goto err;
  1083. if (p != 0) {
  1084. EPRINT((dbp->dbenv,
  1085.     "Page %lu: btree metadata page observed twice",
  1086.     (u_long)meta_pgno));
  1087. ret = DB_VERIFY_BAD;
  1088. goto err;
  1089. }
  1090. if ((ret = __db_vrfy_pgset_inc(pgset, meta_pgno)) != 0)
  1091. goto err;
  1092. root = mip->root;
  1093. if (root == 0) {
  1094. EPRINT((dbp->dbenv,
  1095.     "Page %lu: btree metadata page has no root",
  1096.     (u_long)meta_pgno));
  1097. ret = DB_VERIFY_BAD;
  1098. goto err;
  1099. }
  1100. if ((ret = __db_vrfy_getpageinfo(vdp, root, &rip)) != 0)
  1101. goto err;
  1102. switch (rip->type) {
  1103. case P_IBTREE:
  1104. case P_LBTREE:
  1105. stflags = flags | ST_TOPLEVEL;
  1106. if (F_ISSET(mip, VRFY_HAS_DUPS))
  1107. stflags |= ST_DUPOK;
  1108. if (F_ISSET(mip, VRFY_HAS_DUPSORT))
  1109. stflags |= ST_DUPSORT;
  1110. if (F_ISSET(mip, VRFY_HAS_RECNUMS))
  1111. stflags |= ST_RECNUM;
  1112. ret = __bam_vrfy_subtree(dbp,
  1113.     vdp, root, NULL, NULL, stflags, NULL, NULL, NULL);
  1114. break;
  1115. case P_IRECNO:
  1116. case P_LRECNO:
  1117. stflags = flags | ST_RECNUM | ST_IS_RECNO | ST_TOPLEVEL;
  1118. if (mip->re_len > 0)
  1119. stflags |= ST_RELEN;
  1120. if ((ret = __bam_vrfy_subtree(dbp, vdp,
  1121.     root, NULL, NULL, stflags, &level, &nrecs, &relen)) != 0)
  1122. goto err;
  1123. /*
  1124.  * Even if mip->re_len > 0, re_len may come back zero if the
  1125.  * tree is empty.  It should be okay to just skip the check in
  1126.  * this case, as if there are any non-deleted keys at all,
  1127.  * that should never happen.
  1128.  */
  1129. if (mip->re_len > 0 && relen > 0 && mip->re_len != relen) {
  1130. EPRINT((dbp->dbenv,
  1131.     "Page %lu: recno database has bad re_len %lu",
  1132.     (u_long)meta_pgno, (u_long)relen));
  1133. ret = DB_VERIFY_BAD;
  1134. goto err;
  1135. }
  1136. ret = 0;
  1137. break;
  1138. case P_LDUP:
  1139. EPRINT((dbp->dbenv,
  1140.     "Page %lu: duplicate tree referenced from metadata page",
  1141.     (u_long)meta_pgno));
  1142. ret = DB_VERIFY_BAD;
  1143. break;
  1144. default:
  1145. EPRINT((dbp->dbenv,
  1146.     "Page %lu: btree root of incorrect type %lu on metadata page",
  1147.     (u_long)meta_pgno, (u_long)rip->type));
  1148. ret = DB_VERIFY_BAD;
  1149. break;
  1150. }
  1151. err: if (mip != NULL && ((t_ret =
  1152.     __db_vrfy_putpageinfo(dbp->dbenv, vdp, mip)) != 0) && ret == 0)
  1153. ret = t_ret;
  1154. if (rip != NULL && ((t_ret =
  1155.     __db_vrfy_putpageinfo(dbp->dbenv, vdp, rip)) != 0) && ret == 0)
  1156. ret = t_ret;
  1157. return (ret);
  1158. }
  1159. /*
  1160.  * __bam_vrfy_subtree--
  1161.  * Verify a subtree (or entire) btree with specified root.
  1162.  *
  1163.  * Note that this is public because it must be called to verify
  1164.  * offpage dup trees, including from hash.
  1165.  *
  1166.  * PUBLIC: int __bam_vrfy_subtree __P((DB *, VRFY_DBINFO *, db_pgno_t, void *,
  1167.  * PUBLIC:     void *, u_int32_t, u_int32_t *, u_int32_t *, u_int32_t *));
  1168.  */
  1169. int
  1170. __bam_vrfy_subtree(dbp,
  1171.     vdp, pgno, l, r, flags, levelp, nrecsp, relenp)
  1172. DB *dbp;
  1173. VRFY_DBINFO *vdp;
  1174. db_pgno_t pgno;
  1175. void *l, *r;
  1176. u_int32_t flags, *levelp, *nrecsp, *relenp;
  1177. {
  1178. BINTERNAL *li, *ri, *lp, *rp;
  1179. DB *pgset;
  1180. DB_MPOOLFILE *mpf;
  1181. DBC *cc;
  1182. PAGE *h;
  1183. VRFY_CHILDINFO *child;
  1184. VRFY_PAGEINFO *pip;
  1185. db_indx_t i;
  1186. db_pgno_t next_pgno, prev_pgno;
  1187. db_recno_t child_nrecs, nrecs;
  1188. u_int32_t child_level, child_relen, level, relen, stflags;
  1189. u_int8_t leaf_type;
  1190. int (*func) __P((DB *, const DBT *, const DBT *));
  1191. int isbad, p, ret, t_ret, toplevel;
  1192. mpf = dbp->mpf;
  1193. ret = isbad = 0;
  1194. nrecs = 0;
  1195. h = NULL;
  1196. relen = 0;
  1197. leaf_type = P_INVALID;
  1198. next_pgno = prev_pgno = PGNO_INVALID;
  1199. rp = (BINTERNAL *)r;
  1200. lp = (BINTERNAL *)l;
  1201. /* Provide feedback on our progress to the application. */
  1202. if (!LF_ISSET(DB_SALVAGE))
  1203. __db_vrfy_struct_feedback(dbp, vdp);
  1204. if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
  1205. return (ret);
  1206. cc = NULL;
  1207. level = pip->bt_level;
  1208. toplevel = LF_ISSET(ST_TOPLEVEL) ? 1 : 0;
  1209. LF_CLR(ST_TOPLEVEL);
  1210. /*
  1211.  * If this is the root, initialize the vdp's prev- and next-pgno
  1212.  * accounting.
  1213.  *
  1214.  * For each leaf page we hit, we'll want to make sure that
  1215.  * vdp->prev_pgno is the same as pip->prev_pgno and vdp->next_pgno is
  1216.  * our page number.  Then, we'll set vdp->next_pgno to pip->next_pgno
  1217.  * and vdp->prev_pgno to our page number, and the next leaf page in
  1218.  * line should be able to do the same verification.
  1219.  */
  1220. if (toplevel) {
  1221. /*
  1222.  * Cache the values stored in the vdp so that if we're an
  1223.  * auxiliary tree such as an off-page duplicate set, our
  1224.  * caller's leaf page chain doesn't get lost.
  1225.  */
  1226. prev_pgno = vdp->prev_pgno;
  1227. next_pgno = vdp->next_pgno;
  1228. leaf_type = vdp->leaf_type;
  1229. vdp->next_pgno = vdp->prev_pgno = PGNO_INVALID;
  1230. vdp->leaf_type = P_INVALID;
  1231. }
  1232. /*
  1233.  * We are recursively descending a btree, starting from the root
  1234.  * and working our way out to the leaves.
  1235.  *
  1236.  * There are four cases we need to deal with:
  1237.  * 1. pgno is a recno leaf page.  Any children are overflows.
  1238.  * 2. pgno is a duplicate leaf page.  Any children
  1239.  *    are overflow pages;  traverse them, and then return
  1240.  *    level and nrecs.
  1241.  * 3. pgno is an ordinary leaf page.  Check whether dups are
  1242.  *    allowed, and if so, traverse any off-page dups or
  1243.  *    overflows.  Then return nrecs and level.
  1244.  * 4. pgno is a recno internal page.  Recursively check any
  1245.  *    child pages, making sure their levels are one lower
  1246.  *    and their nrecs sum to ours.
  1247.  * 5. pgno is a btree internal page.  Same as #4, plus we
  1248.  *    must verify that for each pair of BINTERNAL entries
  1249.  *    N and N+1, the leftmost item on N's child sorts
  1250.  *    greater than N, and the rightmost item on N's child
  1251.  *    sorts less than N+1.
  1252.  *
  1253.  * Furthermore, in any sorted page type (P_LDUP, P_LBTREE, P_IBTREE),
  1254.  * we need to verify the internal sort order is correct if,
  1255.  * due to overflow items, we were not able to do so earlier.
  1256.  */
  1257. switch (pip->type) {
  1258. case P_LRECNO:
  1259. case P_LDUP:
  1260. case P_LBTREE:
  1261. /*
  1262.  * Cases 1, 2 and 3.
  1263.  *
  1264.  * We're some sort of leaf page;  verify
  1265.  * that our linked list of leaves is consistent.
  1266.  */
  1267. if (vdp->leaf_type == P_INVALID) {
  1268. /*
  1269.  * First leaf page.  Set the type that all its
  1270.  * successors should be, and verify that our prev_pgno
  1271.  * is PGNO_INVALID.
  1272.  */
  1273. vdp->leaf_type = pip->type;
  1274. if (pip->prev_pgno != PGNO_INVALID)
  1275. goto bad_prev;
  1276. } else {
  1277. /*
  1278.  * Successor leaf page. Check our type, the previous
  1279.  * page's next_pgno, and our prev_pgno.
  1280.  */
  1281. if (pip->type != vdp->leaf_type) {
  1282. EPRINT((dbp->dbenv,
  1283. "Page %lu: unexpected page type %lu found in leaf chain (expected %lu)",
  1284.     (u_long)pip->pgno, (u_long)pip->type,
  1285.     (u_long)vdp->leaf_type));
  1286. isbad = 1;
  1287. }
  1288. if (pip->pgno != vdp->next_pgno) {
  1289. EPRINT((dbp->dbenv,
  1290. "Page %lu: incorrect next_pgno %lu found in leaf chain (should be %lu)",
  1291.     (u_long)vdp->prev_pgno,
  1292.     (u_long)vdp->next_pgno, (u_long)pip->pgno));
  1293. isbad = 1;
  1294. }
  1295. if (pip->prev_pgno != vdp->prev_pgno) {
  1296. bad_prev: EPRINT((dbp->dbenv,
  1297. "Page %lu: incorrect prev_pgno %lu found in leaf chain (should be %lu)",
  1298.     (u_long)pip->pgno, (u_long)pip->prev_pgno,
  1299.     (u_long)vdp->prev_pgno));
  1300. isbad = 1;
  1301. }
  1302. }
  1303. vdp->prev_pgno = pip->pgno;
  1304. vdp->next_pgno = pip->next_pgno;
  1305. /*
  1306.  * Overflow pages are common to all three leaf types;
  1307.  * traverse the child list, looking for overflows.
  1308.  */
  1309. if ((ret = __db_vrfy_childcursor(vdp, &cc)) != 0)
  1310. goto err;
  1311. for (ret = __db_vrfy_ccset(cc, pgno, &child); ret == 0;
  1312.     ret = __db_vrfy_ccnext(cc, &child))
  1313. if (child->type == V_OVERFLOW &&
  1314.     (ret = __db_vrfy_ovfl_structure(dbp, vdp,
  1315.     child->pgno, child->tlen,
  1316.     flags | ST_OVFL_LEAF)) != 0) {
  1317. if (ret == DB_VERIFY_BAD)
  1318. isbad = 1;
  1319. else
  1320. goto done;
  1321. }
  1322. if ((ret = __db_vrfy_ccclose(cc)) != 0)
  1323. goto err;
  1324. cc = NULL;
  1325. /* Case 1 */
  1326. if (pip->type == P_LRECNO) {
  1327. if (!LF_ISSET(ST_IS_RECNO) &&
  1328.     !(LF_ISSET(ST_DUPOK) && !LF_ISSET(ST_DUPSORT))) {
  1329. isbad = 1;
  1330. EPRINT((dbp->dbenv,
  1331.     "Page %lu: recno leaf page non-recno tree",
  1332.     (u_long)pgno));
  1333. goto done;
  1334. }
  1335. goto leaf;
  1336. } else if (LF_ISSET(ST_IS_RECNO)) {
  1337. /*
  1338.  * It's a non-recno leaf.  Had better not be a recno
  1339.  * subtree.
  1340.  */
  1341. isbad = 1;
  1342. EPRINT((dbp->dbenv,
  1343.     "Page %lu: non-recno leaf page in recno tree",
  1344.     (u_long)pgno));
  1345. goto done;
  1346. }
  1347. /* Case 2--no more work. */
  1348. if (pip->type == P_LDUP)
  1349. goto leaf;
  1350. /* Case 3 */
  1351. /* Check if we have any dups. */
  1352. if (F_ISSET(pip, VRFY_HAS_DUPS)) {
  1353. /* If dups aren't allowed in this btree, trouble. */
  1354. if (!LF_ISSET(ST_DUPOK)) {
  1355. isbad = 1;
  1356. EPRINT((dbp->dbenv,
  1357.     "Page %lu: duplicates in non-dup btree",
  1358.     (u_long)pgno));
  1359. } else {
  1360. /*
  1361.  * We correctly have dups.  If any are off-page,
  1362.  * traverse those btrees recursively.
  1363.  */
  1364. if ((ret =
  1365.     __db_vrfy_childcursor(vdp, &cc)) != 0)
  1366. goto err;
  1367. for (ret = __db_vrfy_ccset(cc, pgno, &child);
  1368.     ret == 0;
  1369.     ret = __db_vrfy_ccnext(cc, &child)) {
  1370. stflags = flags | ST_RECNUM | ST_DUPSET;
  1371. /* Skip any overflow entries. */
  1372. if (child->type == V_DUPLICATE) {
  1373. if ((ret = __db_vrfy_duptype(
  1374.     dbp, vdp, child->pgno,
  1375.     stflags)) != 0) {
  1376. isbad = 1;
  1377. /* Next child. */
  1378. continue;
  1379. }
  1380. if ((ret = __bam_vrfy_subtree(
  1381.     dbp, vdp, child->pgno, NULL,
  1382.     NULL, stflags | ST_TOPLEVEL,
  1383.     NULL, NULL, NULL)) != 0) {
  1384. if (ret !=
  1385.     DB_VERIFY_BAD)
  1386. goto err;
  1387. else
  1388. isbad = 1;
  1389. }
  1390. }
  1391. }
  1392. if ((ret = __db_vrfy_ccclose(cc)) != 0)
  1393. goto err;
  1394. cc = NULL;
  1395. /*
  1396.  * If VRFY_DUPS_UNSORTED is set,
  1397.  * ST_DUPSORT had better not be.
  1398.  */
  1399. if (F_ISSET(pip, VRFY_DUPS_UNSORTED) &&
  1400.     LF_ISSET(ST_DUPSORT)) {
  1401. EPRINT((dbp->dbenv,
  1402.     "Page %lu: unsorted duplicate set in sorted-dup database",
  1403.     (u_long)pgno));
  1404. isbad = 1;
  1405. }
  1406. }
  1407. }
  1408. goto leaf;
  1409. case P_IBTREE:
  1410. case P_IRECNO:
  1411. /* We handle these below. */
  1412. break;
  1413. default:
  1414. /*
  1415.  * If a P_IBTREE or P_IRECNO contains a reference to an
  1416.  * invalid page, we'll wind up here;  handle it gracefully.
  1417.  * Note that the code at the "done" label assumes that the
  1418.  * current page is a btree/recno one of some sort;  this
  1419.  * is not the case here, so we goto err.
  1420.  *
  1421.  * If the page is entirely zeroed, its pip->type will be a lie
  1422.  * (we assumed it was a hash page, as they're allowed to be
  1423.  * zeroed);  handle this case specially.
  1424.  */
  1425. if (F_ISSET(pip, VRFY_IS_ALLZEROES))
  1426. ZEROPG_ERR_PRINT(dbp->dbenv,
  1427.     pgno, "btree or recno page");
  1428. else
  1429. EPRINT((dbp->dbenv,
  1430.     "Page %lu: btree or recno page is of inappropriate type %lu",
  1431.     (u_long)pgno, (u_long)pip->type));
  1432. ret = DB_VERIFY_BAD;
  1433. goto err;
  1434. }
  1435. /*
  1436.  * Cases 4 & 5: This is a btree or recno internal page.  For each child,
  1437.  * recurse, keeping a running count of nrecs and making sure the level
  1438.  * is always reasonable.
  1439.  */
  1440. if ((ret = __db_vrfy_childcursor(vdp, &cc)) != 0)
  1441. goto err;
  1442. for (ret = __db_vrfy_ccset(cc, pgno, &child); ret == 0;
  1443.     ret = __db_vrfy_ccnext(cc, &child))
  1444. if (child->type == V_RECNO) {
  1445. if (pip->type != P_IRECNO) {
  1446. TYPE_ERR_PRINT(dbp->dbenv, "__bam_vrfy_subtree",
  1447.     pgno, pip->type);
  1448. DB_ASSERT(0);
  1449. ret = EINVAL;
  1450. goto err;
  1451. }
  1452. if ((ret = __bam_vrfy_subtree(dbp, vdp, child->pgno,
  1453.     NULL, NULL, flags, &child_level, &child_nrecs,
  1454.     &child_relen)) != 0) {
  1455. if (ret != DB_VERIFY_BAD)
  1456. goto done;
  1457. else
  1458. isbad = 1;
  1459. }
  1460. if (LF_ISSET(ST_RELEN)) {
  1461. if (relen == 0)
  1462. relen = child_relen;
  1463. /*
  1464.  * child_relen may be zero if the child subtree
  1465.  * is empty.
  1466.  */
  1467. else if (child_relen > 0 &&
  1468.     relen != child_relen) {
  1469. isbad = 1;
  1470. EPRINT((dbp->dbenv,
  1471.    "Page %lu: recno page returned bad re_len %lu",
  1472.     (u_long)child->pgno,
  1473.     (u_long)child_relen));
  1474. }
  1475. if (relenp)
  1476. *relenp = relen;
  1477. }
  1478. if (LF_ISSET(ST_RECNUM))
  1479. nrecs += child_nrecs;
  1480. if (level != child_level + 1) {
  1481. isbad = 1;
  1482.    EPRINT((dbp->dbenv, "Page %lu: recno level incorrect: got %lu, expected %lu",
  1483.     (u_long)child->pgno, (u_long)child_level,
  1484.     (u_long)(level - 1)));
  1485. }
  1486. } else if (child->type == V_OVERFLOW &&
  1487.     (ret = __db_vrfy_ovfl_structure(dbp, vdp,
  1488.     child->pgno, child->tlen, flags)) != 0) {
  1489. if (ret == DB_VERIFY_BAD)
  1490. isbad = 1;
  1491. else
  1492. goto done;
  1493. }
  1494. if ((ret = __db_vrfy_ccclose(cc)) != 0)
  1495. goto err;
  1496. cc = NULL;
  1497. /* We're done with case 4. */
  1498. if (pip->type == P_IRECNO)
  1499. goto done;
  1500. /*
  1501.  * Case 5.  Btree internal pages.
  1502.  * As described above, we need to iterate through all the
  1503.  * items on the page and make sure that our children sort appropriately
  1504.  * with respect to them.
  1505.  *
  1506.  * For each entry, li will be the "left-hand" key for the entry
  1507.  * itself, which must sort lower than all entries on its child;
  1508.  * ri will be the key to its right, which must sort greater.
  1509.  */
  1510. if (h == NULL && (ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
  1511. goto err;
  1512. for (i = 0; i < pip->entries; i += O_INDX) {
  1513. li = GET_BINTERNAL(dbp, h, i);
  1514. ri = (i + O_INDX < pip->entries) ?
  1515.     GET_BINTERNAL(dbp, h, i + O_INDX) : NULL;
  1516. /*
  1517.  * The leftmost key is forcibly sorted less than all entries,
  1518.  * so don't bother passing it.
  1519.  */
  1520. if ((ret = __bam_vrfy_subtree(dbp, vdp, li->pgno,
  1521.     i == 0 ? NULL : li, ri, flags, &child_level,
  1522.     &child_nrecs, NULL)) != 0) {
  1523. if (ret != DB_VERIFY_BAD)
  1524. goto done;
  1525. else
  1526. isbad = 1;
  1527. }
  1528. if (LF_ISSET(ST_RECNUM)) {
  1529. /*
  1530.  * Keep a running tally on the actual record count so
  1531.  * we can return it to our parent (if we have one) or
  1532.  * compare it to the NRECS field if we're a root page.
  1533.  */
  1534. nrecs += child_nrecs;
  1535. /*
  1536.  * Make sure the actual record count of the child
  1537.  * is equal to the value in the BINTERNAL structure.
  1538.  */
  1539. if (li->nrecs != child_nrecs) {
  1540. isbad = 1;
  1541. EPRINT((dbp->dbenv,
  1542. "Page %lu: item %lu has incorrect record count of %lu, should be %lu",
  1543.     (u_long)pgno, (u_long)i, (u_long)li->nrecs,
  1544.     (u_long)child_nrecs));
  1545. }
  1546. }
  1547. if (level != child_level + 1) {
  1548. isbad = 1;
  1549. EPRINT((dbp->dbenv,
  1550. "Page %lu: Btree level incorrect: got %lu, expected %lu",
  1551.     (u_long)li->pgno,
  1552.     (u_long)child_level, (u_long)(level - 1)));
  1553. }
  1554. }
  1555. if (0) {
  1556. leaf: level = LEAFLEVEL;
  1557. if (LF_ISSET(ST_RECNUM))
  1558. nrecs = pip->rec_cnt;
  1559. /* XXX
  1560.  * We should verify that the record count on a leaf page
  1561.  * is the sum of the number of keys and the number of
  1562.  * records in its off-page dups.  This requires looking
  1563.  * at the page again, however, and it may all be changing
  1564.  * soon, so for now we don't bother.
  1565.  */
  1566. if (LF_ISSET(ST_RELEN) && relenp)
  1567. *relenp = pip->re_len;
  1568. }
  1569. done: if (F_ISSET(pip, VRFY_INCOMPLETE) && isbad == 0 && ret == 0) {
  1570. /*
  1571.  * During the page-by-page pass, item order verification was
  1572.  * not finished due to the presence of overflow items.  If
  1573.  * isbad == 0, though, it's now safe to do so, as we've
  1574.  * traversed any child overflow pages.  Do it.
  1575.  */
  1576. if (h == NULL && (ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
  1577. goto err;
  1578. if ((ret = __bam_vrfy_itemorder(dbp,
  1579.     vdp, h, pgno, 0, 1, 0, flags)) != 0)
  1580. goto err;
  1581. F_CLR(pip, VRFY_INCOMPLETE);
  1582. }
  1583. /*
  1584.  * It's possible to get to this point with a page that has no
  1585.  * items, but without having detected any sort of failure yet.
  1586.  * Having zero items is legal if it's a leaf--it may be the
  1587.  * root page in an empty tree, or the tree may have been
  1588.  * modified with the DB_REVSPLITOFF flag set (there's no way
  1589.  * to tell from what's on disk).  For an internal page,
  1590.  * though, having no items is a problem (all internal pages
  1591.  * must have children).
  1592.  */
  1593. if (isbad == 0 && ret == 0) {
  1594. if (h == NULL && (ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
  1595. goto err;
  1596. if (NUM_ENT(h) == 0 && ISINTERNAL(h)) {
  1597. EPRINT((dbp->dbenv,
  1598.     "Page %lu: internal page is empty and should not be",
  1599.     (u_long)pgno));
  1600. isbad = 1;
  1601. goto err;
  1602. }
  1603. }
  1604. /*
  1605.  * Our parent has sent us BINTERNAL pointers to parent records
  1606.  * so that we can verify our place with respect to them.  If it's
  1607.  * appropriate--we have a default sort function--verify this.
  1608.  */
  1609. if (isbad == 0 && ret == 0 && !LF_ISSET(DB_NOORDERCHK) && lp != NULL) {
  1610. if (h == NULL && (ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
  1611. goto err;
  1612. /*
  1613.  * __bam_vrfy_treeorder needs to know what comparison function
  1614.  * to use.  If ST_DUPSET is set, we're in a duplicate tree
  1615.  * and we use the duplicate comparison function;  otherwise,
  1616.  * use the btree one.  If unset, use the default, of course.
  1617.  */
  1618. func = LF_ISSET(ST_DUPSET) ? dbp->dup_compare :
  1619.     ((BTREE *)dbp->bt_internal)->bt_compare;
  1620. if (func == NULL)
  1621. func = __bam_defcmp;
  1622. if ((ret = __bam_vrfy_treeorder(
  1623.     dbp, pgno, h, lp, rp, func, flags)) != 0) {
  1624. if (ret == DB_VERIFY_BAD)
  1625. isbad = 1;
  1626. else
  1627. goto err;
  1628. }
  1629. }
  1630. /*
  1631.  * This is guaranteed to succeed for leaf pages, but no harm done.
  1632.  *
  1633.  * Internal pages below the top level do not store their own
  1634.  * record numbers, so we skip them.
  1635.  */
  1636. if (LF_ISSET(ST_RECNUM) && nrecs != pip->rec_cnt && toplevel) {
  1637. isbad = 1;
  1638. EPRINT((dbp->dbenv,
  1639.     "Page %lu: bad record count: has %lu records, claims %lu",
  1640.     (u_long)pgno, (u_long)nrecs, (u_long)pip->rec_cnt));
  1641. }
  1642. if (levelp)
  1643. *levelp = level;
  1644. if (nrecsp)
  1645. *nrecsp = nrecs;
  1646. pgset = vdp->pgset;
  1647. if ((ret = __db_vrfy_pgset_get(pgset, pgno, &p)) != 0)
  1648. goto err;
  1649. if (p != 0) {
  1650. isbad = 1;
  1651. EPRINT((dbp->dbenv, "Page %lu: linked twice", (u_long)pgno));
  1652. } else if ((ret = __db_vrfy_pgset_inc(pgset, pgno)) != 0)
  1653. goto err;
  1654. if (toplevel)
  1655. /*
  1656.  * The last page's next_pgno in the leaf chain should have been
  1657.  * PGNO_INVALID.
  1658.  */
  1659. if (vdp->next_pgno != PGNO_INVALID) {
  1660. EPRINT((dbp->dbenv, "Page %lu: unterminated leaf chain",
  1661.     (u_long)vdp->prev_pgno));
  1662. isbad = 1;
  1663. }
  1664. err: if (toplevel) {
  1665. /* Restore our caller's settings. */
  1666. vdp->next_pgno = next_pgno;
  1667. vdp->prev_pgno = prev_pgno;
  1668. vdp->leaf_type = leaf_type;
  1669. }
  1670. if (h != NULL && (t_ret = mpf->put(mpf, h, 0)) != 0 && ret == 0)
  1671. ret = t_ret;
  1672. if ((t_ret =
  1673.     __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 && ret == 0)
  1674. ret = t_ret;
  1675. if (cc != NULL && ((t_ret = __db_vrfy_ccclose(cc)) != 0) && ret == 0)
  1676. ret = t_ret;
  1677. return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
  1678. }
  1679. /*
  1680.  * __bam_vrfy_treeorder --
  1681.  * Verify that the lowest key on a page sorts greater than the
  1682.  * BINTERNAL which points to it (lp), and the highest key
  1683.  * sorts less than the BINTERNAL above that (rp).
  1684.  *
  1685.  * If lp is NULL, this means that it was the leftmost key on the
  1686.  * parent, which (regardless of sort function) sorts less than
  1687.  * all keys.  No need to check it.
  1688.  *
  1689.  * If rp is NULL, lp was the highest key on the parent, so there's
  1690.  * no higher key we must sort less than.
  1691.  */
  1692. static int
  1693. __bam_vrfy_treeorder(dbp, pgno, h, lp, rp, func, flags)
  1694. DB *dbp;
  1695. db_pgno_t pgno;
  1696. PAGE *h;
  1697. BINTERNAL *lp, *rp;
  1698. int (*func) __P((DB *, const DBT *, const DBT *));
  1699. u_int32_t flags;
  1700. {
  1701. BOVERFLOW *bo;
  1702. DBT dbt;
  1703. db_indx_t last;
  1704. int ret, cmp;
  1705. memset(&dbt, 0, sizeof(DBT));
  1706. F_SET(&dbt, DB_DBT_MALLOC);
  1707. ret = 0;
  1708. /*
  1709.  * Empty pages are sorted correctly by definition.  We check
  1710.  * to see whether they ought to be empty elsewhere;  leaf
  1711.  * pages legally may be.
  1712.  */
  1713. if (NUM_ENT(h) == 0)
  1714. return (0);
  1715. switch (TYPE(h)) {
  1716. case P_IBTREE:
  1717. case P_LDUP:
  1718. last = NUM_ENT(h) - O_INDX;
  1719. break;
  1720. case P_LBTREE:
  1721. last = NUM_ENT(h) - P_INDX;
  1722. break;
  1723. default:
  1724. TYPE_ERR_PRINT(dbp->dbenv,
  1725.     "__bam_vrfy_treeorder", pgno, TYPE(h));
  1726. DB_ASSERT(0);
  1727. return (EINVAL);
  1728. }
  1729. /*
  1730.  * The key on page h, the child page, is more likely to be
  1731.  * an overflow page, so we pass its offset, rather than lp/rp's,
  1732.  * into __bam_cmp.  This will take advantage of __db_moff.
  1733.  */
  1734. /*
  1735.  * Skip first-item check if we're an internal page--the first
  1736.  * entry on an internal page is treated specially by __bam_cmp,
  1737.  * so what's on the page shouldn't matter.  (Plus, since we're passing
  1738.  * our page and item 0 as to __bam_cmp, we'll sort before our
  1739.  * parent and falsely report a failure.)
  1740.  */
  1741. if (lp != NULL && TYPE(h) != P_IBTREE) {
  1742. if (lp->type == B_KEYDATA) {
  1743. dbt.data = lp->data;
  1744. dbt.size = lp->len;
  1745. } else if (lp->type == B_OVERFLOW) {
  1746. bo = (BOVERFLOW *)lp->data;
  1747. if ((ret = __db_goff(dbp, &dbt, bo->tlen, bo->pgno,
  1748.     NULL, NULL)) != 0)
  1749. return (ret);
  1750. } else {
  1751. DB_ASSERT(0);
  1752. EPRINT((dbp->dbenv,
  1753.     "Page %lu: unknown type for internal record",
  1754.     (u_long)PGNO(h)));
  1755. return (EINVAL);
  1756. }
  1757. /* On error, fall through, free if neeeded, and return. */
  1758. if ((ret = __bam_cmp(dbp, &dbt, h, 0, func, &cmp)) == 0) {
  1759. if (cmp > 0) {
  1760. EPRINT((dbp->dbenv,
  1761.     "Page %lu: first item on page sorted greater than parent entry",
  1762.     (u_long)PGNO(h)));
  1763. ret = DB_VERIFY_BAD;
  1764. }
  1765. } else
  1766. EPRINT((dbp->dbenv,
  1767.     "Page %lu: first item on page had comparison error",
  1768.     (u_long)PGNO(h)));
  1769. if (dbt.data != lp->data)
  1770. __os_ufree(dbp->dbenv, dbt.data);
  1771. if (ret != 0)
  1772. return (ret);
  1773. }
  1774. if (rp != NULL) {
  1775. if (rp->type == B_KEYDATA) {
  1776. dbt.data = rp->data;
  1777. dbt.size = rp->len;
  1778. } else if (rp->type == B_OVERFLOW) {
  1779. bo = (BOVERFLOW *)rp->data;
  1780. if ((ret = __db_goff(dbp, &dbt, bo->tlen, bo->pgno,
  1781.     NULL, NULL)) != 0)
  1782. return (ret);
  1783. } else {
  1784. DB_ASSERT(0);
  1785. EPRINT((dbp->dbenv,
  1786.     "Page %lu: unknown type for internal record",
  1787.     (u_long)PGNO(h)));
  1788. return (EINVAL);
  1789. }
  1790. /* On error, fall through, free if neeeded, and return. */
  1791. if ((ret = __bam_cmp(dbp, &dbt, h, last, func, &cmp)) == 0) {
  1792. if (cmp < 0) {
  1793. EPRINT((dbp->dbenv,
  1794.     "Page %lu: last item on page sorted greater than parent entry",
  1795.     (u_long)PGNO(h)));
  1796. ret = DB_VERIFY_BAD;
  1797. }
  1798. } else
  1799. EPRINT((dbp->dbenv,
  1800.     "Page %lu: last item on page had comparison error",
  1801.     (u_long)PGNO(h)));
  1802. if (dbt.data != rp->data)
  1803. __os_ufree(dbp->dbenv, dbt.data);
  1804. }
  1805. return (ret);
  1806. }
  1807. /*
  1808.  * __bam_salvage --
  1809.  * Safely dump out anything that looks like a key on an alleged
  1810.  * btree leaf page.
  1811.  *
  1812.  * PUBLIC: int __bam_salvage __P((DB *, VRFY_DBINFO *, db_pgno_t, u_int32_t,
  1813.  * PUBLIC:     PAGE *, void *, int (*)(void *, const void *), DBT *,
  1814.  * PUBLIC:     u_int32_t));
  1815.  */
  1816. int
  1817. __bam_salvage(dbp, vdp, pgno, pgtype, h, handle, callback, key, flags)
  1818. DB *dbp;
  1819. VRFY_DBINFO *vdp;
  1820. db_pgno_t pgno;
  1821. u_int32_t pgtype;
  1822. PAGE *h;
  1823. void *handle;
  1824. int (*callback) __P((void *, const void *));
  1825. DBT *key;
  1826. u_int32_t flags;
  1827. {
  1828. DBT dbt, unkdbt;
  1829. BKEYDATA *bk;
  1830. BOVERFLOW *bo;
  1831. db_indx_t i, beg, end, *inp;
  1832. u_int32_t himark;
  1833. u_int8_t *pgmap;
  1834. void *ovflbuf;
  1835. int t_ret, ret, err_ret;
  1836. /* Shut up lint. */
  1837. COMPQUIET(end, 0);
  1838. ovflbuf = pgmap = NULL;
  1839. err_ret = ret = 0;
  1840. inp = P_INP(dbp, h);
  1841. memset(&dbt, 0, sizeof(DBT));
  1842. dbt.flags = DB_DBT_REALLOC;
  1843. memset(&unkdbt, 0, sizeof(DBT));
  1844. unkdbt.size = (u_int32_t)(strlen("UNKNOWN") + 1);
  1845. unkdbt.data = "UNKNOWN";
  1846. /*
  1847.  * Allocate a buffer for overflow items.  Start at one page;
  1848.  * __db_safe_goff will realloc as needed.
  1849.  */
  1850. if ((ret = __os_malloc(dbp->dbenv, dbp->pgsize, &ovflbuf)) != 0)
  1851. return (ret);
  1852. if (LF_ISSET(DB_AGGRESSIVE)) {
  1853. if ((ret =
  1854.     __os_malloc(dbp->dbenv, dbp->pgsize, &pgmap)) != 0)
  1855. goto err;
  1856. memset(pgmap, 0, dbp->pgsize);
  1857. }
  1858. /*
  1859.  * Loop through the inp array, spitting out key/data pairs.
  1860.  *
  1861.  * If we're salvaging normally, loop from 0 through NUM_ENT(h).
  1862.  * If we're being aggressive, loop until we hit the end of the page--
  1863.  * NUM_ENT() may be bogus.
  1864.  */
  1865. himark = dbp->pgsize;
  1866. for (i = 0;; i += O_INDX) {
  1867. /* If we're not aggressive, break when we hit NUM_ENT(h). */
  1868. if (!LF_ISSET(DB_AGGRESSIVE) && i >= NUM_ENT(h))
  1869. break;
  1870. /* Verify the current item. */
  1871. ret = __db_vrfy_inpitem(dbp,
  1872.     h, pgno, i, 1, flags, &himark, NULL);
  1873. /* If this returned a fatality, it's time to break. */
  1874. if (ret == DB_VERIFY_FATAL) {
  1875. /*
  1876.  * Don't return DB_VERIFY_FATAL;  it's private
  1877.  * and means only that we can't go on with this
  1878.  * page, not with the whole database.  It's
  1879.  * not even an error if we've run into it
  1880.  * after NUM_ENT(h).
  1881.  */
  1882. ret = (i < NUM_ENT(h)) ? DB_VERIFY_BAD : 0;
  1883. break;
  1884. }
  1885. /*
  1886.  * If this returned 0, it's safe to print or (carefully)
  1887.  * try to fetch.
  1888.  */
  1889. if (ret == 0) {
  1890. /*
  1891.  * We only want to print deleted items if
  1892.  * DB_AGGRESSIVE is set.
  1893.  */
  1894. bk = GET_BKEYDATA(dbp, h, i);
  1895. if (!LF_ISSET(DB_AGGRESSIVE) && B_DISSET(bk->type))
  1896. continue;
  1897. /*
  1898.  * We're going to go try to print the next item.  If
  1899.  * key is non-NULL, we're a dup page, so we've got to
  1900.  * print the key first, unless SA_SKIPFIRSTKEY is set
  1901.  * and we're on the first entry.
  1902.  */
  1903. if (key != NULL &&
  1904.     (i != 0 || !LF_ISSET(SA_SKIPFIRSTKEY)))
  1905. if ((ret = __db_prdbt(key,
  1906.     0, " ", handle, callback, 0, vdp)) != 0)
  1907. err_ret = ret;
  1908. beg = inp[i];
  1909. switch (B_TYPE(bk->type)) {
  1910. case B_DUPLICATE:
  1911. end = beg + BOVERFLOW_SIZE - 1;
  1912. /*
  1913.  * If we're not on a normal btree leaf page,
  1914.  * there shouldn't be off-page
  1915.  * dup sets.  Something's confused;  just
  1916.  * drop it, and the code to pick up unlinked
  1917.  * offpage dup sets will print it out
  1918.  * with key "UNKNOWN" later.
  1919.  */
  1920. if (pgtype != P_LBTREE)
  1921. break;
  1922. bo = (BOVERFLOW *)bk;
  1923. /*
  1924.  * If the page number is unreasonable, or
  1925.  * if this is supposed to be a key item,
  1926.  * just spit out "UNKNOWN"--the best we
  1927.  * can do is run into the data items in the
  1928.  * unlinked offpage dup pass.
  1929.  */
  1930. if (!IS_VALID_PGNO(bo->pgno) ||
  1931.     (i % P_INDX == 0)) {
  1932. /* Not much to do on failure. */
  1933. if ((ret = __db_prdbt(&unkdbt, 0, " ",
  1934.     handle, callback, 0, vdp)) != 0)
  1935. err_ret = ret;
  1936. break;
  1937. }
  1938. if ((ret = __db_salvage_duptree(dbp,
  1939.     vdp, bo->pgno, &dbt, handle, callback,
  1940.     flags | SA_SKIPFIRSTKEY)) != 0)
  1941. err_ret = ret;
  1942. break;
  1943. case B_KEYDATA:
  1944. end =
  1945.     ALIGN(beg + bk->len, sizeof(u_int32_t)) - 1;
  1946. dbt.data = bk->data;
  1947. dbt.size = bk->len;
  1948. if ((ret = __db_prdbt(&dbt,
  1949.     0, " ", handle, callback, 0, vdp)) != 0)
  1950. err_ret = ret;
  1951. break;
  1952. case B_OVERFLOW:
  1953. end = beg + BOVERFLOW_SIZE - 1;
  1954. bo = (BOVERFLOW *)bk;
  1955. if ((ret = __db_safe_goff(dbp, vdp,
  1956.     bo->pgno, &dbt, &ovflbuf, flags)) != 0) {
  1957. err_ret = ret;
  1958. /* We care about err_ret more. */
  1959. (void)__db_prdbt(&unkdbt, 0, " ",
  1960.     handle, callback, 0, vdp);
  1961. break;
  1962. }
  1963. if ((ret = __db_prdbt(&dbt,
  1964.     0, " ", handle, callback, 0, vdp)) != 0)
  1965. err_ret = ret;
  1966. break;
  1967. default:
  1968. /*
  1969.  * We should never get here;  __db_vrfy_inpitem
  1970.  * should not be returning 0 if bk->type
  1971.  * is unrecognizable.
  1972.  */
  1973. DB_ASSERT(0);
  1974. return (EINVAL);
  1975. }
  1976. /*
  1977.  * If we're being aggressive, mark the beginning
  1978.  * and end of the item;  we'll come back and print
  1979.  * whatever "junk" is in the gaps in case we had
  1980.  * any bogus inp elements and thereby missed stuff.
  1981.  */
  1982. if (LF_ISSET(DB_AGGRESSIVE)) {
  1983. pgmap[beg] = ITEM_BEGIN;
  1984. pgmap[end] = ITEM_END;
  1985. }
  1986. }
  1987. }
  1988. /*
  1989.  * If i is odd and this is a btree leaf, we've printed out a key but not
  1990.  * a datum; fix this imbalance by printing an "UNKNOWN".
  1991.  */
  1992. if (pgtype == P_LBTREE && (i % P_INDX == 1) && ((ret =
  1993.     __db_prdbt(&unkdbt, 0, " ", handle, callback, 0, vdp)) != 0))
  1994. err_ret = ret;
  1995. err: if (pgmap != NULL)
  1996. __os_free(dbp->dbenv, pgmap);
  1997. __os_free(dbp->dbenv, ovflbuf);
  1998. /* Mark this page as done. */
  1999. if ((t_ret = __db_salvage_markdone(vdp, pgno)) != 0)
  2000. return (t_ret);
  2001. return ((err_ret != 0) ? err_ret : ret);
  2002. }
  2003. /*
  2004.  * __bam_salvage_walkdupint --
  2005.  * Walk a known-good btree or recno internal page which is part of
  2006.  * a dup tree, calling __db_salvage_duptree on each child page.
  2007.  *
  2008.  * PUBLIC: int __bam_salvage_walkdupint __P((DB *, VRFY_DBINFO *, PAGE *,
  2009.  * PUBLIC:     DBT *, void *, int (*)(void *, const void *), u_int32_t));
  2010.  */
  2011. int
  2012. __bam_salvage_walkdupint(dbp, vdp, h, key, handle, callback, flags)
  2013. DB *dbp;
  2014. VRFY_DBINFO *vdp;
  2015. PAGE *h;
  2016. DBT *key;
  2017. void *handle;
  2018. int (*callback) __P((void *, const void *));
  2019. u_int32_t flags;
  2020. {
  2021. RINTERNAL *ri;
  2022. BINTERNAL *bi;
  2023. int ret, t_ret;
  2024. db_indx_t i;
  2025. ret = 0;
  2026. for (i = 0; i < NUM_ENT(h); i++) {
  2027. switch (TYPE(h)) {
  2028. case P_IBTREE:
  2029. bi = GET_BINTERNAL(dbp, h, i);
  2030. if ((t_ret = __db_salvage_duptree(dbp,
  2031.     vdp, bi->pgno, key, handle, callback, flags)) != 0)
  2032. ret = t_ret;
  2033. break;
  2034. case P_IRECNO:
  2035. ri = GET_RINTERNAL(dbp, h, i);
  2036. if ((t_ret = __db_salvage_duptree(dbp,
  2037.     vdp, ri->pgno, key, handle, callback, flags)) != 0)
  2038. ret = t_ret;
  2039. break;
  2040. default:
  2041. __db_err(dbp->dbenv,
  2042.     "__bam_salvage_walkdupint called on non-int. page");
  2043. DB_ASSERT(0);
  2044. return (EINVAL);
  2045. }
  2046. /* Pass SA_SKIPFIRSTKEY, if set, on to the 0th child only. */
  2047. flags &= ~LF_ISSET(SA_SKIPFIRSTKEY);
  2048. }
  2049. return (ret);
  2050. }
  2051. /*
  2052.  * __bam_meta2pgset --
  2053.  * Given a known-good meta page, return in pgsetp a 0-terminated list of
  2054.  * db_pgno_t's corresponding to the pages in the btree.
  2055.  *
  2056.  * We do this by a somewhat sleazy method, to avoid having to traverse the
  2057.  * btree structure neatly:  we walk down the left side to the very
  2058.  * first leaf page, then we mark all the pages in the chain of
  2059.  * NEXT_PGNOs (being wary of cycles and invalid ones), then we
  2060.  * consolidate our scratch array into a nice list, and return.  This
  2061.  * avoids the memory management hassles of recursion and the
  2062.  * trouble of walking internal pages--they just don't matter, except
  2063.  * for the left branch.
  2064.  *
  2065.  * PUBLIC: int __bam_meta2pgset __P((DB *, VRFY_DBINFO *, BTMETA *,
  2066.  * PUBLIC:     u_int32_t, DB *));
  2067.  */
  2068. int
  2069. __bam_meta2pgset(dbp, vdp, btmeta, flags, pgset)
  2070. DB *dbp;
  2071. VRFY_DBINFO *vdp;
  2072. BTMETA *btmeta;
  2073. u_int32_t flags;
  2074. DB *pgset;
  2075. {
  2076. BINTERNAL *bi;
  2077. DB_MPOOLFILE *mpf;
  2078. PAGE *h;
  2079. RINTERNAL *ri;
  2080. db_pgno_t current, p;
  2081. int err_ret, ret;
  2082. mpf = dbp->mpf;
  2083. h = NULL;
  2084. ret = err_ret = 0;
  2085. DB_ASSERT(pgset != NULL);
  2086. for (current = btmeta->root;;) {
  2087. if (!IS_VALID_PGNO(current) || current == PGNO(btmeta)) {
  2088. err_ret = DB_VERIFY_BAD;
  2089. goto err;
  2090. }
  2091. if ((ret = mpf->get(mpf, &current, 0, &h)) != 0) {
  2092. err_ret = ret;
  2093. goto err;
  2094. }
  2095. switch (TYPE(h)) {
  2096. case P_IBTREE:
  2097. case P_IRECNO:
  2098. if ((ret = __bam_vrfy(dbp,
  2099.     vdp, h, current, flags | DB_NOORDERCHK)) != 0) {
  2100. err_ret = ret;
  2101. goto err;
  2102. }
  2103. if (TYPE(h) == P_IBTREE) {
  2104. bi = GET_BINTERNAL(dbp, h, 0);
  2105. current = bi->pgno;
  2106. } else { /* P_IRECNO */
  2107. ri = GET_RINTERNAL(dbp, h, 0);
  2108. current = ri->pgno;
  2109. }
  2110. break;
  2111. case P_LBTREE:
  2112. case P_LRECNO:
  2113. goto traverse;
  2114. default:
  2115. err_ret = DB_VERIFY_BAD;
  2116. goto err;
  2117. }
  2118. if ((ret = mpf->put(mpf, h, 0)) != 0)
  2119. err_ret = ret;
  2120. h = NULL;
  2121. }
  2122. /*
  2123.  * At this point, current is the pgno of leaf page h, the 0th in the
  2124.  * tree we're concerned with.
  2125.  */
  2126. traverse:
  2127. while (IS_VALID_PGNO(current) && current != PGNO_INVALID) {
  2128. if (h == NULL && (ret = mpf->get(mpf, &current, 0, &h)) != 0) {
  2129. err_ret = ret;
  2130. break;
  2131. }
  2132. if ((ret = __db_vrfy_pgset_get(pgset, current, (int *)&p)) != 0)
  2133. goto err;
  2134. if (p != 0) {
  2135. /*
  2136.  * We've found a cycle.  Return success anyway--
  2137.  * our caller may as well use however much of
  2138.  * the pgset we've come up with.
  2139.  */
  2140. break;
  2141. }
  2142. if ((ret = __db_vrfy_pgset_inc(pgset, current)) != 0)
  2143. goto err;
  2144. current = NEXT_PGNO(h);
  2145. if ((ret = mpf->put(mpf, h, 0)) != 0)
  2146. err_ret = ret;
  2147. h = NULL;
  2148. }
  2149. err: if (h != NULL)
  2150. (void)mpf->put(mpf, h, 0);
  2151. return (ret == 0 ? err_ret : ret);
  2152. }
  2153. /*
  2154.  * __bam_safe_getdata --
  2155.  *
  2156.  * Utility function for __bam_vrfy_itemorder.  Safely gets the datum at
  2157.  * index i, page h, and sticks it in DBT dbt.  If ovflok is 1 and i's an
  2158.  * overflow item, we do a safe_goff to get the item and signal that we need
  2159.  * to free dbt->data;  if ovflok is 0, we leaves the DBT zeroed.
  2160.  */
  2161. static int
  2162. __bam_safe_getdata(dbp, h, i, ovflok, dbt, freedbtp)
  2163. DB *dbp;
  2164. PAGE *h;
  2165. u_int32_t i;
  2166. int ovflok;
  2167. DBT *dbt;
  2168. int *freedbtp;
  2169. {
  2170. BKEYDATA *bk;
  2171. BOVERFLOW *bo;
  2172. memset(dbt, 0, sizeof(DBT));
  2173. *freedbtp = 0;
  2174. bk = GET_BKEYDATA(dbp, h, i);
  2175. if (B_TYPE(bk->type) == B_OVERFLOW) {
  2176. if (!ovflok)
  2177. return (0);
  2178. bo = (BOVERFLOW *)bk;
  2179. F_SET(dbt, DB_DBT_MALLOC);
  2180. *freedbtp = 1;
  2181. return (__db_goff(dbp, dbt, bo->tlen, bo->pgno, NULL, NULL));
  2182. } else {
  2183. dbt->data = bk->data;
  2184. dbt->size = bk->len;
  2185. }
  2186. return (0);
  2187. }