bt_verify.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:57k
源码类别:

MySQL数据库

开发平台:

Visual C++

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