00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "db_config.h"
00011
00012 #ifndef NO_SYSTEM_INCLUDES
00013 #include <sys/types.h>
00014
00015 #include <string.h>
00016 #endif
00017
00018 #include "db_int.h"
00019 #include "dbinc/db_page.h"
00020 #include "dbinc/db_shash.h"
00021 #include "dbinc/db_swap.h"
00022 #include "dbinc/db_verify.h"
00023 #include "dbinc/btree.h"
00024 #include "dbinc/hash.h"
00025 #include "dbinc/lock.h"
00026 #include "dbinc/mp.h"
00027 #include "dbinc/qam.h"
00028 #include "dbinc/txn.h"
00029
00030
00031
00032
00033
00034
00035
00036
00037 static u_int __db_guesspgsize __P((DB_ENV *, DB_FH *));
00038 static int __db_is_valid_magicno __P((u_int32_t, DBTYPE *));
00039 static int __db_is_valid_pagetype __P((u_int32_t));
00040 static int __db_meta2pgset
00041 __P((DB *, VRFY_DBINFO *, db_pgno_t, u_int32_t, DB *));
00042 static int __db_salvage_subdbpg __P((DB *, VRFY_DBINFO *,
00043 PAGE *, void *, int (*)(void *, const void *), u_int32_t));
00044 static int __db_salvage_subdbs __P((DB *, VRFY_DBINFO *, void *,
00045 int(*)(void *, const void *), u_int32_t, int *));
00046 static int __db_salvage_unknowns __P((DB *, VRFY_DBINFO *, void *,
00047 int (*)(void *, const void *), u_int32_t));
00048 static int __db_verify __P((DB *, const char *, const char *,
00049 void *, int (*)(void *, const void *), u_int32_t));
00050 static int __db_verify_arg __P((DB *, const char *, void *, u_int32_t));
00051 static int __db_vrfy_freelist
00052 __P((DB *, VRFY_DBINFO *, db_pgno_t, u_int32_t));
00053 static int __db_vrfy_invalid
00054 __P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t, u_int32_t));
00055 static int __db_vrfy_orderchkonly __P((DB *,
00056 VRFY_DBINFO *, const char *, const char *, u_int32_t));
00057 static int __db_vrfy_pagezero __P((DB *, VRFY_DBINFO *, DB_FH *, u_int32_t));
00058 static int __db_vrfy_subdbs
00059 __P((DB *, VRFY_DBINFO *, const char *, u_int32_t));
00060 static int __db_vrfy_structure
00061 __P((DB *, VRFY_DBINFO *, const char *, db_pgno_t, u_int32_t));
00062 static int __db_vrfy_walkpages __P((DB *, VRFY_DBINFO *,
00063 void *, int (*)(void *, const void *), u_int32_t));
00064
00065 #define VERIFY_FLAGS \
00066 (DB_AGGRESSIVE | \
00067 DB_NOORDERCHK | DB_ORDERCHKONLY | DB_PRINTABLE | DB_SALVAGE | DB_UNREF)
00068
00069
00070
00071
00072
00073
00074
00075
00076 int
00077 __db_verify_pp(dbp, file, database, outfile, flags)
00078 DB *dbp;
00079 const char *file, *database;
00080 FILE *outfile;
00081 u_int32_t flags;
00082 {
00083
00084
00085
00086
00087 return (__db_verify_internal(dbp,
00088 file, database, outfile, __db_pr_callback, flags));
00089 }
00090
00091
00092
00093
00094
00095
00096
00097 int
00098 __db_verify_internal(dbp, fname, dname, handle, callback, flags)
00099 DB *dbp;
00100 const char *fname, *dname;
00101 void *handle;
00102 int (*callback) __P((void *, const void *));
00103 u_int32_t flags;
00104 {
00105 DB_ENV *dbenv;
00106 int ret, t_ret;
00107
00108 dbenv = dbp->dbenv;
00109
00110 PANIC_CHECK(dbenv);
00111 DB_ILLEGAL_AFTER_OPEN(dbp, "DB->verify");
00112
00113 #ifdef HAVE_FTRUNCATE
00114
00115
00116
00117
00118
00119 if (!LF_ISSET(DB_SALVAGE))
00120 LF_SET(DB_UNREF);
00121 #endif
00122
00123 if ((ret = __db_verify_arg(dbp, dname, handle, flags)) == 0)
00124 ret = __db_verify(dbp, fname, dname, handle, callback, flags);
00125
00126
00127 if ((t_ret = __db_close(dbp, NULL, 0)) != 0 && ret == 0)
00128 ret = t_ret;
00129
00130 return (ret);
00131 }
00132
00133
00134
00135
00136
00137 static int
00138 __db_verify_arg(dbp, dname, handle, flags)
00139 DB *dbp;
00140 const char *dname;
00141 void *handle;
00142 u_int32_t flags;
00143 {
00144 DB_ENV *dbenv;
00145 int ret;
00146
00147 dbenv = dbp->dbenv;
00148
00149 if ((ret = __db_fchk(dbenv, "DB->verify", flags, VERIFY_FLAGS)) != 0)
00150 return (ret);
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160 if (LF_ISSET(DB_SALVAGE)) {
00161 if (LF_ISSET(~(DB_AGGRESSIVE | DB_PRINTABLE | DB_SALVAGE)))
00162 return (__db_ferr(dbenv, "DB->verify", 1));
00163 if (handle == NULL) {
00164 __db_err(dbenv,
00165 "DB_SALVAGE requires a an output handle");
00166 return (EINVAL);
00167 }
00168 } else
00169 if (LF_ISSET(DB_AGGRESSIVE | DB_PRINTABLE))
00170 return (__db_ferr(dbenv, "DB->verify", 1));
00171
00172
00173
00174
00175
00176 if ((ret = __db_fcchk(dbenv, "DB->verify", flags,
00177 DB_ORDERCHKONLY, DB_SALVAGE | DB_NOORDERCHK)) != 0)
00178 return (ret);
00179 if (LF_ISSET(DB_ORDERCHKONLY) && dname == NULL) {
00180 __db_err(dbenv, "DB_ORDERCHKONLY requires a database name");
00181 return (EINVAL);
00182 }
00183 return (0);
00184 }
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200 static int
00201 __db_verify(dbp, name, subdb, handle, callback, flags)
00202 DB *dbp;
00203 const char *name, *subdb;
00204 void *handle;
00205 int (*callback) __P((void *, const void *));
00206 u_int32_t flags;
00207 {
00208 DB_ENV *dbenv;
00209 DB_FH *fhp;
00210 VRFY_DBINFO *vdp;
00211 int has_subdbs, isbad, ret, t_ret;
00212 char *real_name;
00213
00214 dbenv = dbp->dbenv;
00215 fhp = NULL;
00216 vdp = NULL;
00217 real_name = NULL;
00218 has_subdbs = isbad = ret = 0;
00219
00220 F_SET(dbp, DB_AM_VERIFYING);
00221
00222
00223 if (!LF_ISSET(DB_SALVAGE) && dbp->db_feedback != NULL)
00224 dbp->db_feedback(dbp, DB_VERIFY, 0);
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235 if ((ret = __db_vrfy_dbinfo_create(dbenv, 1024, &vdp)) != 0)
00236 goto err;
00237
00238
00239
00240
00241
00242
00243 if (LF_ISSET(DB_PRINTABLE))
00244 F_SET(vdp, SALVAGE_PRINTABLE);
00245
00246
00247 if ((ret = __db_appname(dbenv,
00248 DB_APP_DATA, name, 0, NULL, &real_name)) != 0)
00249 goto err;
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262 if ((ret = __os_open(dbenv, real_name, DB_OSO_RDONLY, 0, &fhp)) != 0)
00263 goto err;
00264
00265
00266 if ((ret = __db_vrfy_pagezero(dbp, vdp, fhp, flags)) != 0) {
00267 if (ret == DB_VERIFY_BAD)
00268 isbad = 1;
00269 else
00270 goto err;
00271 }
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285 if ((ret = __db_dbenv_setup(dbp, NULL,
00286 name, subdb, TXN_INVALID, DB_ODDFILESIZE | DB_RDONLY)) != 0)
00287 goto err;
00288
00289
00290
00291
00292
00293 if (dbp->type == DB_QUEUE &&
00294 (ret = __qam_set_ext_data(dbp, name)) != 0)
00295 goto err;
00296
00297
00298 F_SET(dbp, DB_AM_OPEN_CALLED);
00299
00300
00301 if ((ret = __memp_last_pgno(dbp->mpf, &vdp->last_pgno)) != 0)
00302 goto err;
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313 if (LF_ISSET(DB_ORDERCHKONLY)) {
00314 ret = __db_vrfy_orderchkonly(dbp, vdp, name, subdb, flags);
00315 goto done;
00316 }
00317
00318
00319
00320
00321
00322
00323
00324 if (LF_ISSET(DB_SALVAGE)) {
00325 if ((ret = __db_salvage_init(vdp)) != 0)
00326 goto err;
00327
00328
00329
00330
00331
00332
00333
00334
00335 if (!LF_ISSET(DB_AGGRESSIVE) && __db_salvage_subdbs(
00336 dbp, vdp, handle, callback, flags, &has_subdbs) != 0)
00337 isbad = 1;
00338
00339
00340
00341
00342
00343
00344 if (has_subdbs)
00345 F_SET(vdp, SALVAGE_PRINTHEADER);
00346 }
00347
00348 if ((ret =
00349 __db_vrfy_walkpages(dbp, vdp, handle, callback, flags)) != 0) {
00350 if (ret == DB_VERIFY_BAD)
00351 isbad = 1;
00352 else
00353 goto err;
00354 }
00355
00356
00357 if (!LF_ISSET(DB_SALVAGE) && isbad == 0)
00358 if ((ret =
00359 __db_vrfy_structure(dbp, vdp, name, 0, flags)) != 0) {
00360 if (ret == DB_VERIFY_BAD)
00361 isbad = 1;
00362 else
00363 goto err;
00364 }
00365
00366
00367
00368
00369
00370
00371 if (LF_ISSET(DB_SALVAGE)) {
00372 if ((ret = __db_salvage_unknowns(dbp,
00373 vdp, handle, callback, flags)) != 0)
00374 isbad = 1;
00375
00376 __db_salvage_destroy(vdp);
00377 }
00378
00379
00380 if (LF_ISSET(DB_SALVAGE) &&
00381 (!has_subdbs || F_ISSET(vdp, SALVAGE_PRINTFOOTER)))
00382 (void)__db_prfooter(handle, callback);
00383
00384 done: err:
00385
00386 if (!LF_ISSET(DB_SALVAGE) && dbp->db_feedback != NULL)
00387 dbp->db_feedback(dbp, DB_VERIFY, 100);
00388
00389 if (fhp != NULL &&
00390 (t_ret = __os_closehandle(dbenv, fhp)) != 0 && ret == 0)
00391 ret = t_ret;
00392 if (vdp != NULL &&
00393 (t_ret = __db_vrfy_dbinfo_destroy(dbenv, vdp)) != 0 && ret == 0)
00394 ret = t_ret;
00395 if (real_name != NULL)
00396 __os_free(dbenv, real_name);
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406 if (ret == DB_VERIFY_FATAL ||
00407 ret == DB_PAGE_NOTFOUND || (ret == 0 && isbad == 1))
00408 ret = DB_VERIFY_BAD;
00409
00410
00411 if (ret != 0)
00412 __db_err(dbenv, "%s: %s", name, db_strerror(ret));
00413
00414 return (ret);
00415 }
00416
00417
00418
00419
00420
00421
00422
00423
00424 static int
00425 __db_vrfy_pagezero(dbp, vdp, fhp, flags)
00426 DB *dbp;
00427 VRFY_DBINFO *vdp;
00428 DB_FH *fhp;
00429 u_int32_t flags;
00430 {
00431 DBMETA *meta;
00432 DB_ENV *dbenv;
00433 VRFY_PAGEINFO *pip;
00434 db_pgno_t freelist;
00435 size_t nr;
00436 int isbad, ret, swapped;
00437 u_int8_t mbuf[DBMETASIZE];
00438
00439 isbad = ret = swapped = 0;
00440 freelist = 0;
00441 dbenv = dbp->dbenv;
00442 meta = (DBMETA *)mbuf;
00443 dbp->type = DB_UNKNOWN;
00444
00445 if ((ret = __db_vrfy_getpageinfo(vdp, PGNO_BASE_MD, &pip)) != 0)
00446 return (ret);
00447
00448
00449
00450
00451
00452
00453
00454 if ((ret = __os_seek(dbenv, fhp, 0, 0, 0, 0, DB_OS_SEEK_SET)) != 0 ||
00455 (ret = __os_read(dbenv, fhp, mbuf, DBMETASIZE, &nr)) != 0) {
00456 __db_err(dbenv,
00457 "Metadata page %lu cannot be read: %s",
00458 (u_long)PGNO_BASE_MD, db_strerror(ret));
00459 return (ret);
00460 }
00461
00462 if (nr != DBMETASIZE) {
00463 EPRINT((dbenv,
00464 "Page %lu: Incomplete metadata page",
00465 (u_long)PGNO_BASE_MD));
00466 return (DB_VERIFY_FATAL);
00467 }
00468
00469 if ((ret = __db_chk_meta(dbenv, dbp, meta, 1)) != 0) {
00470 EPRINT((dbenv,
00471 "Page %lu: metadata page corrupted", (u_long)PGNO_BASE_MD));
00472 isbad = 1;
00473 if (ret != -1) {
00474 EPRINT((dbenv,
00475 "Page %lu: could not check metadata page",
00476 (u_long)PGNO_BASE_MD));
00477 return (DB_VERIFY_FATAL);
00478 }
00479 }
00480
00481
00482
00483
00484
00485
00486
00487 if (meta->pgno != PGNO_BASE_MD) {
00488 isbad = 1;
00489 EPRINT((dbenv, "Page %lu: pgno incorrectly set to %lu",
00490 (u_long)PGNO_BASE_MD, (u_long)meta->pgno));
00491 }
00492
00493
00494 if (__db_is_valid_magicno(meta->magic, &dbp->type))
00495 swapped = 0;
00496 else {
00497 M_32_SWAP(meta->magic);
00498 if (__db_is_valid_magicno(meta->magic,
00499 &dbp->type))
00500 swapped = 1;
00501 else {
00502 isbad = 1;
00503 EPRINT((dbenv,
00504 "Page %lu: bad magic number %lu",
00505 (u_long)PGNO_BASE_MD, (u_long)meta->magic));
00506 }
00507 }
00508
00509
00510
00511
00512
00513 if (swapped)
00514 M_32_SWAP(meta->version);
00515 if ((dbp->type == DB_BTREE &&
00516 (meta->version > DB_BTREEVERSION ||
00517 meta->version < DB_BTREEOLDVER)) ||
00518 (dbp->type == DB_HASH &&
00519 (meta->version > DB_HASHVERSION ||
00520 meta->version < DB_HASHOLDVER)) ||
00521 (dbp->type == DB_QUEUE &&
00522 (meta->version > DB_QAMVERSION ||
00523 meta->version < DB_QAMOLDVER))) {
00524 isbad = 1;
00525 EPRINT((dbenv,
00526 "Page %lu: unsupported DB version %lu; extraneous errors may result",
00527 (u_long)PGNO_BASE_MD, (u_long)meta->version));
00528 }
00529
00530
00531
00532
00533
00534 if (swapped)
00535 M_32_SWAP(meta->pagesize);
00536 if (IS_VALID_PAGESIZE(meta->pagesize))
00537 dbp->pgsize = meta->pagesize;
00538 else {
00539 isbad = 1;
00540 EPRINT((dbenv, "Page %lu: bad page size %lu",
00541 (u_long)PGNO_BASE_MD, (u_long)meta->pagesize));
00542
00543
00544
00545
00546
00547
00548 if (!IS_VALID_PAGESIZE(dbp->pgsize))
00549 dbp->pgsize = __db_guesspgsize(dbenv, fhp);
00550 }
00551
00552
00553
00554
00555
00556
00557 if ((dbp->type == DB_BTREE && meta->type != P_BTREEMETA) ||
00558 (dbp->type == DB_HASH && meta->type != P_HASHMETA) ||
00559 (dbp->type == DB_QUEUE && meta->type != P_QAMMETA)) {
00560 isbad = 1;
00561 EPRINT((dbenv, "Page %lu: bad page type %lu",
00562 (u_long)PGNO_BASE_MD, (u_long)meta->type));
00563 }
00564
00565
00566
00567
00568 if (meta->metaflags != 0) {
00569 if (meta->metaflags == DBMETA_CHKSUM)
00570 F_SET(pip, VRFY_HAS_CHKSUM);
00571 else {
00572 isbad = 1;
00573 EPRINT((dbenv,
00574 "Page %lu: bad meta-data flags value %#lx",
00575 (u_long)PGNO_BASE_MD, (u_long)meta->metaflags));
00576 }
00577 }
00578
00579
00580
00581
00582
00583
00584 if (swapped)
00585 M_32_SWAP(meta->free);
00586 freelist = meta->free;
00587
00588
00589
00590
00591
00592
00593 pip->pgno = PGNO_BASE_MD;
00594 pip->type = meta->type;
00595
00596
00597
00598
00599
00600 F_SET(pip, VRFY_INCOMPLETE);
00601
00602 pip->free = freelist;
00603
00604 if ((ret = __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0)
00605 return (ret);
00606
00607
00608 memcpy(dbp->fileid, meta->uid, DB_FILE_ID_LEN);
00609
00610 if (swapped == 1)
00611 F_SET(dbp, DB_AM_SWAP);
00612
00613 return (isbad ? DB_VERIFY_BAD : 0);
00614 }
00615
00616
00617
00618
00619
00620
00621 static int
00622 __db_vrfy_walkpages(dbp, vdp, handle, callback, flags)
00623 DB *dbp;
00624 VRFY_DBINFO *vdp;
00625 void *handle;
00626 int (*callback) __P((void *, const void *));
00627 u_int32_t flags;
00628 {
00629 DB_ENV *dbenv;
00630 DB_MPOOLFILE *mpf;
00631 PAGE *h;
00632 db_pgno_t i;
00633 int ret, t_ret, isbad;
00634
00635 dbenv = dbp->dbenv;
00636 mpf = dbp->mpf;
00637 h = NULL;
00638 ret = isbad = t_ret = 0;
00639
00640 for (i = 0; i <= vdp->last_pgno; i++) {
00641
00642
00643
00644
00645 if (LF_ISSET(DB_SALVAGE) && (__db_salvage_isdone(vdp, i) != 0))
00646 continue;
00647
00648
00649
00650
00651
00652 if ((t_ret = __memp_fget(mpf, &i, 0, &h)) != 0) {
00653 if (ret == 0)
00654 ret = t_ret;
00655 if (LF_ISSET(DB_SALVAGE))
00656 continue;
00657 return (ret);
00658 }
00659
00660 if (LF_ISSET(DB_SALVAGE)) {
00661
00662
00663
00664
00665
00666 if ((t_ret = __db_salvage(dbp,
00667 vdp, i, h, handle, callback, flags)) != 0) {
00668 if (ret == 0)
00669 ret = t_ret;
00670 isbad = 1;
00671 }
00672 } else {
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683 if (i != PGNO_BASE_MD) {
00684 ret = __db_vrfy_common(dbp, vdp, h, i, flags);
00685 if (ret == DB_VERIFY_BAD)
00686 isbad = 1;
00687 else if (ret != 0)
00688 goto err;
00689 }
00690
00691 switch (TYPE(h)) {
00692 case P_INVALID:
00693 ret = __db_vrfy_invalid(dbp, vdp, h, i, flags);
00694 break;
00695 case __P_DUPLICATE:
00696 isbad = 1;
00697 EPRINT((dbenv,
00698 "Page %lu: old-style duplicate page",
00699 (u_long)i));
00700 break;
00701 case P_HASH:
00702 ret = __ham_vrfy(dbp, vdp, h, i, flags);
00703 break;
00704 case P_IBTREE:
00705 case P_IRECNO:
00706 case P_LBTREE:
00707 case P_LDUP:
00708 ret = __bam_vrfy(dbp, vdp, h, i, flags);
00709 break;
00710 case P_LRECNO:
00711 ret = __ram_vrfy_leaf(dbp, vdp, h, i, flags);
00712 break;
00713 case P_OVERFLOW:
00714 ret = __db_vrfy_overflow(dbp, vdp, h, i, flags);
00715 break;
00716 case P_HASHMETA:
00717 ret = __ham_vrfy_meta(dbp,
00718 vdp, (HMETA *)h, i, flags);
00719 break;
00720 case P_BTREEMETA:
00721 ret = __bam_vrfy_meta(dbp,
00722 vdp, (BTMETA *)h, i, flags);
00723 break;
00724 case P_QAMMETA:
00725 ret = __qam_vrfy_meta(dbp,
00726 vdp, (QMETA *)h, i, flags);
00727 break;
00728 case P_QAMDATA:
00729 ret = __qam_vrfy_data(dbp,
00730 vdp, (QPAGE *)h, i, flags);
00731 break;
00732 default:
00733 EPRINT((dbenv,
00734 "Page %lu: unknown page type %lu",
00735 (u_long)i, (u_long)TYPE(h)));
00736 isbad = 1;
00737 break;
00738 }
00739
00740
00741
00742
00743 if (ret == DB_VERIFY_BAD)
00744 isbad = 1;
00745 else if (ret != 0)
00746 goto err;
00747
00748
00749
00750
00751
00752
00753
00754 if (dbp->db_feedback != NULL)
00755 dbp->db_feedback(dbp, DB_VERIFY,
00756 (int)((i + 1) * 50 / (vdp->last_pgno + 1)));
00757 }
00758
00759
00760
00761
00762
00763 if ((t_ret = __memp_fput(mpf, h, 0)) != 0) {
00764 if (ret == 0)
00765 ret = t_ret;
00766 if (!LF_ISSET(DB_SALVAGE))
00767 return (ret);
00768 }
00769 }
00770
00771
00772
00773
00774
00775 if (F_ISSET(vdp, VRFY_QMETA_SET) && (t_ret =
00776 __qam_vrfy_walkqueue(dbp, vdp, handle, callback, flags)) != 0) {
00777 if (ret == 0)
00778 ret = t_ret;
00779 if (t_ret == DB_VERIFY_BAD)
00780 isbad = 1;
00781 else if (!LF_ISSET(DB_SALVAGE))
00782 return (ret);
00783 }
00784
00785 if (0) {
00786 err: if (h != NULL && (t_ret = __memp_fput(mpf, h, 0)) != 0)
00787 return (ret == 0 ? t_ret : ret);
00788 }
00789
00790 return ((isbad == 1 && ret == 0) ? DB_VERIFY_BAD : ret);
00791 }
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802 static int
00803 __db_vrfy_structure(dbp, vdp, dbname, meta_pgno, flags)
00804 DB *dbp;
00805 VRFY_DBINFO *vdp;
00806 const char *dbname;
00807 db_pgno_t meta_pgno;
00808 u_int32_t flags;
00809 {
00810 DB *pgset;
00811 DB_ENV *dbenv;
00812 VRFY_PAGEINFO *pip;
00813 db_pgno_t i;
00814 int ret, isbad, hassubs, p;
00815
00816 isbad = 0;
00817 pip = NULL;
00818 dbenv = dbp->dbenv;
00819 pgset = vdp->pgset;
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835 if (dbp->db_feedback != NULL)
00836 vdp->pgs_remaining = vdp->last_pgno + 1;
00837
00838
00839
00840
00841 switch (dbp->type) {
00842 case DB_BTREE:
00843 case DB_RECNO:
00844 if ((ret = __bam_vrfy_structure(dbp, vdp, 0, flags)) != 0) {
00845 if (ret == DB_VERIFY_BAD)
00846 isbad = 1;
00847 else
00848 goto err;
00849 }
00850
00851
00852
00853
00854
00855
00856 if ((ret = __db_vrfy_getpageinfo(vdp, 0, &pip)) != 0)
00857 goto err;
00858 hassubs = F_ISSET(pip, VRFY_HAS_SUBDBS) ? 1 : 0;
00859 if ((ret = __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0)
00860 goto err;
00861 pip = NULL;
00862
00863 if (isbad == 0 && hassubs)
00864 if ((ret =
00865 __db_vrfy_subdbs(dbp, vdp, dbname, flags)) != 0) {
00866 if (ret == DB_VERIFY_BAD)
00867 isbad = 1;
00868 else
00869 goto err;
00870 }
00871 break;
00872 case DB_HASH:
00873 if ((ret = __ham_vrfy_structure(dbp, vdp, 0, flags)) != 0) {
00874 if (ret == DB_VERIFY_BAD)
00875 isbad = 1;
00876 else
00877 goto err;
00878 }
00879 break;
00880 case DB_QUEUE:
00881 if ((ret = __qam_vrfy_structure(dbp, vdp, flags)) != 0) {
00882 if (ret == DB_VERIFY_BAD)
00883 isbad = 1;
00884 }
00885
00886
00887
00888
00889
00890
00891
00892 goto err;
00893 case DB_UNKNOWN:
00894 default:
00895
00896 DB_ASSERT(0);
00897 ret = EINVAL;
00898 goto err;
00899 }
00900
00901
00902 if ((ret =
00903 __db_vrfy_freelist(dbp, vdp, meta_pgno, flags)) == DB_VERIFY_BAD)
00904 isbad = 1;
00905
00906
00907
00908
00909
00910
00911
00912
00913 if (ret != 0 || isbad == 1)
00914 goto err;
00915
00916
00917
00918
00919
00920
00921 for (i = 0; i < vdp->last_pgno + 1; i++) {
00922 if ((ret = __db_vrfy_getpageinfo(vdp, i, &pip)) != 0)
00923 goto err;
00924 if ((ret = __db_vrfy_pgset_get(pgset, i, &p)) != 0)
00925 goto err;
00926 if (pip->type == P_OVERFLOW) {
00927 if ((u_int32_t)p != pip->refcount) {
00928 EPRINT((dbenv,
00929 "Page %lu: overflow refcount %lu, referenced %lu times",
00930 (u_long)i,
00931 (u_long)pip->refcount, (u_long)p));
00932 isbad = 1;
00933 }
00934 } else if (p == 0 && LF_ISSET(DB_UNREF)) {
00935 EPRINT((dbenv,
00936 "Page %lu: unreferenced page", (u_long)i));
00937 isbad = 1;
00938 }
00939
00940 if (F_ISSET(pip, VRFY_IS_ALLZEROES)) {
00941 EPRINT((dbenv,
00942 "Page %lu: totally zeroed page", (u_long)i));
00943 isbad = 1;
00944 }
00945 if ((ret = __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0)
00946 goto err;
00947 pip = NULL;
00948 }
00949
00950 err: if (pip != NULL)
00951 (void)__db_vrfy_putpageinfo(dbenv, vdp, pip);
00952
00953 return ((isbad == 1 && ret == 0) ? DB_VERIFY_BAD : ret);
00954 }
00955
00956
00957
00958
00959 static int
00960 __db_is_valid_pagetype(type)
00961 u_int32_t type;
00962 {
00963 switch (type) {
00964 case P_INVALID:
00965 case P_HASH:
00966 case P_IBTREE:
00967 case P_IRECNO:
00968 case P_LBTREE:
00969 case P_LRECNO:
00970 case P_OVERFLOW:
00971 case P_HASHMETA:
00972 case P_BTREEMETA:
00973 case P_QAMMETA:
00974 case P_QAMDATA:
00975 case P_LDUP:
00976 return (1);
00977 default:
00978 break;
00979 }
00980 return (0);
00981 }
00982
00983
00984
00985
00986 static int
00987 __db_is_valid_magicno(magic, typep)
00988 u_int32_t magic;
00989 DBTYPE *typep;
00990 {
00991 switch (magic) {
00992 case DB_BTREEMAGIC:
00993 *typep = DB_BTREE;
00994 return (1);
00995 case DB_HASHMAGIC:
00996 *typep = DB_HASH;
00997 return (1);
00998 case DB_QAMMAGIC:
00999 *typep = DB_QUEUE;
01000 return (1);
01001 default:
01002 break;
01003 }
01004 *typep = DB_UNKNOWN;
01005 return (0);
01006 }
01007
01008
01009
01010
01011
01012
01013
01014
01015 int
01016 __db_vrfy_common(dbp, vdp, h, pgno, flags)
01017 DB *dbp;
01018 VRFY_DBINFO *vdp;
01019 PAGE *h;
01020 db_pgno_t pgno;
01021 u_int32_t flags;
01022 {
01023 DB_ENV *dbenv;
01024 VRFY_PAGEINFO *pip;
01025 int ret, t_ret;
01026 u_int8_t *p;
01027
01028 dbenv = dbp->dbenv;
01029
01030 if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
01031 return (ret);
01032
01033 pip->pgno = pgno;
01034 F_CLR(pip, VRFY_IS_ALLZEROES);
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044 if (pgno != 0 && PGNO(h) == 0) {
01045 for (p = (u_int8_t *)h; p < (u_int8_t *)h + dbp->pgsize; p++)
01046 if (*p != 0) {
01047 EPRINT((dbenv,
01048 "Page %lu: partially zeroed page",
01049 (u_long)pgno));
01050 ret = DB_VERIFY_BAD;
01051 goto err;
01052 }
01053
01054
01055
01056
01057
01058
01059 pip->type = P_HASH;
01060 F_SET(pip, VRFY_IS_ALLZEROES);
01061 ret = 0;
01062 goto err;
01063 }
01064
01065 if (PGNO(h) != pgno) {
01066 EPRINT((dbenv, "Page %lu: bad page number %lu",
01067 (u_long)pgno, (u_long)h->pgno));
01068 ret = DB_VERIFY_BAD;
01069 }
01070
01071 if (!__db_is_valid_pagetype(h->type)) {
01072 EPRINT((dbenv, "Page %lu: bad page type %lu",
01073 (u_long)pgno, (u_long)h->type));
01074 ret = DB_VERIFY_BAD;
01075 }
01076 pip->type = h->type;
01077
01078 err: if ((t_ret = __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0 && ret == 0)
01079 ret = t_ret;
01080
01081 return (ret);
01082 }
01083
01084
01085
01086
01087
01088
01089 static int
01090 __db_vrfy_invalid(dbp, vdp, h, pgno, flags)
01091 DB *dbp;
01092 VRFY_DBINFO *vdp;
01093 PAGE *h;
01094 db_pgno_t pgno;
01095 u_int32_t flags;
01096 {
01097 DB_ENV *dbenv;
01098 VRFY_PAGEINFO *pip;
01099 int ret, t_ret;
01100
01101 dbenv = dbp->dbenv;
01102
01103 if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
01104 return (ret);
01105 pip->next_pgno = pip->prev_pgno = 0;
01106
01107 if (!IS_VALID_PGNO(NEXT_PGNO(h))) {
01108 EPRINT((dbenv, "Page %lu: invalid next_pgno %lu",
01109 (u_long)pgno, (u_long)NEXT_PGNO(h)));
01110 ret = DB_VERIFY_BAD;
01111 } else
01112 pip->next_pgno = NEXT_PGNO(h);
01113
01114 if ((t_ret = __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0 && ret == 0)
01115 ret = t_ret;
01116 return (ret);
01117 }
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132 int
01133 __db_vrfy_datapage(dbp, vdp, h, pgno, flags)
01134 DB *dbp;
01135 VRFY_DBINFO *vdp;
01136 PAGE *h;
01137 db_pgno_t pgno;
01138 u_int32_t flags;
01139 {
01140 DB_ENV *dbenv;
01141 VRFY_PAGEINFO *pip;
01142 int isbad, ret, t_ret;
01143
01144 dbenv = dbp->dbenv;
01145
01146 if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
01147 return (ret);
01148 isbad = 0;
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158 if (TYPE(h) != P_IBTREE && TYPE(h) != P_IRECNO) {
01159 if (!IS_VALID_PGNO(PREV_PGNO(h)) || PREV_PGNO(h) == pip->pgno) {
01160 isbad = 1;
01161 EPRINT((dbenv, "Page %lu: invalid prev_pgno %lu",
01162 (u_long)pip->pgno, (u_long)PREV_PGNO(h)));
01163 }
01164 if (!IS_VALID_PGNO(NEXT_PGNO(h)) || NEXT_PGNO(h) == pip->pgno) {
01165 isbad = 1;
01166 EPRINT((dbenv, "Page %lu: invalid next_pgno %lu",
01167 (u_long)pip->pgno, (u_long)NEXT_PGNO(h)));
01168 }
01169 pip->prev_pgno = PREV_PGNO(h);
01170 pip->next_pgno = NEXT_PGNO(h);
01171 }
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181 if (TYPE(h) != P_OVERFLOW) {
01182 if (BKEYDATA_PSIZE(0) * NUM_ENT(h) > dbp->pgsize) {
01183 isbad = 1;
01184 EPRINT((dbenv, "Page %lu: too many entries: %lu",
01185 (u_long)pgno, (u_long)NUM_ENT(h)));
01186 }
01187 pip->entries = NUM_ENT(h);
01188 }
01189
01190
01191
01192
01193
01194
01195 switch (TYPE(h)) {
01196 case P_IBTREE:
01197 case P_IRECNO:
01198 if (LEVEL(h) < LEAFLEVEL + 1) {
01199 isbad = 1;
01200 EPRINT((dbenv, "Page %lu: bad btree level %lu",
01201 (u_long)pgno, (u_long)LEVEL(h)));
01202 }
01203 pip->bt_level = LEVEL(h);
01204 break;
01205 case P_LBTREE:
01206 case P_LDUP:
01207 case P_LRECNO:
01208 if (LEVEL(h) != LEAFLEVEL) {
01209 isbad = 1;
01210 EPRINT((dbenv,
01211 "Page %lu: btree leaf page has incorrect level %lu",
01212 (u_long)pgno, (u_long)LEVEL(h)));
01213 }
01214 break;
01215 default:
01216 if (LEVEL(h) != 0) {
01217 isbad = 1;
01218 EPRINT((dbenv,
01219 "Page %lu: nonzero level %lu in non-btree database",
01220 (u_long)pgno, (u_long)LEVEL(h)));
01221 }
01222 break;
01223 }
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233 if ((t_ret = __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0 && ret == 0)
01234 ret = t_ret;
01235
01236 return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
01237 }
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247 int
01248 __db_vrfy_meta(dbp, vdp, meta, pgno, flags)
01249 DB *dbp;
01250 VRFY_DBINFO *vdp;
01251 DBMETA *meta;
01252 db_pgno_t pgno;
01253 u_int32_t flags;
01254 {
01255 DB_ENV *dbenv;
01256 DBTYPE dbtype, magtype;
01257 VRFY_PAGEINFO *pip;
01258 int isbad, ret, t_ret;
01259
01260 isbad = 0;
01261 dbenv = dbp->dbenv;
01262
01263 if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
01264 return (ret);
01265
01266
01267 switch (meta->type) {
01268 case P_BTREEMETA:
01269 dbtype = DB_BTREE;
01270 break;
01271 case P_HASHMETA:
01272 dbtype = DB_HASH;
01273 break;
01274 case P_QAMMETA:
01275 dbtype = DB_QUEUE;
01276 break;
01277 default:
01278
01279 DB_ASSERT(0);
01280 ret = EINVAL;
01281 goto err;
01282 }
01283
01284
01285 if (!__db_is_valid_magicno(meta->magic, &magtype)) {
01286 isbad = 1;
01287 EPRINT((dbenv,
01288 "Page %lu: invalid magic number", (u_long)pgno));
01289 }
01290 if (magtype != dbtype) {
01291 isbad = 1;
01292 EPRINT((dbenv,
01293 "Page %lu: magic number does not match database type",
01294 (u_long)pgno));
01295 }
01296
01297
01298 if ((dbtype == DB_BTREE &&
01299 (meta->version > DB_BTREEVERSION ||
01300 meta->version < DB_BTREEOLDVER)) ||
01301 (dbtype == DB_HASH &&
01302 (meta->version > DB_HASHVERSION ||
01303 meta->version < DB_HASHOLDVER)) ||
01304 (dbtype == DB_QUEUE &&
01305 (meta->version > DB_QAMVERSION ||
01306 meta->version < DB_QAMOLDVER))) {
01307 isbad = 1;
01308 EPRINT((dbenv,
01309 "Page %lu: unsupported database version %lu; extraneous errors may result",
01310 (u_long)pgno, (u_long)meta->version));
01311 }
01312
01313
01314 if (meta->pagesize != dbp->pgsize) {
01315 isbad = 1;
01316 EPRINT((dbenv, "Page %lu: invalid pagesize %lu",
01317 (u_long)pgno, (u_long)meta->pagesize));
01318 }
01319
01320
01321 if (meta->metaflags != 0) {
01322 if (meta->metaflags == DBMETA_CHKSUM)
01323 F_SET(pip, VRFY_HAS_CHKSUM);
01324 else {
01325 isbad = 1;
01326 EPRINT((dbenv,
01327 "Page %lu: bad meta-data flags value %#lx",
01328 (u_long)PGNO_BASE_MD, (u_long)meta->metaflags));
01329 }
01330 }
01331
01332
01333
01334
01335
01336
01337
01338 if (pgno != PGNO_BASE_MD && meta->free != PGNO_INVALID) {
01339 isbad = 1;
01340 EPRINT((dbenv,
01341 "Page %lu: nonempty free list on subdatabase metadata page",
01342 (u_long)pgno));
01343 }
01344
01345
01346 if (meta->free != PGNO_INVALID && IS_VALID_PGNO(meta->free))
01347 pip->free = meta->free;
01348 else if (!IS_VALID_PGNO(meta->free)) {
01349 isbad = 1;
01350 EPRINT((dbenv,
01351 "Page %lu: nonsensical free list pgno %lu",
01352 (u_long)pgno, (u_long)meta->free));
01353 }
01354
01355
01356
01357
01358
01359 F_CLR(pip, VRFY_INCOMPLETE);
01360
01361 err: if ((t_ret = __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0 && ret == 0)
01362 ret = t_ret;
01363
01364 return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
01365 }
01366
01367
01368
01369
01370
01371
01372 static int
01373 __db_vrfy_freelist(dbp, vdp, meta, flags)
01374 DB *dbp;
01375 VRFY_DBINFO *vdp;
01376 db_pgno_t meta;
01377 u_int32_t flags;
01378 {
01379 DB *pgset;
01380 DB_ENV *dbenv;
01381 VRFY_PAGEINFO *pip;
01382 db_pgno_t cur_pgno, next_pgno;
01383 int p, ret, t_ret;
01384
01385 pgset = vdp->pgset;
01386 DB_ASSERT(pgset != NULL);
01387 dbenv = dbp->dbenv;
01388
01389 if ((ret = __db_vrfy_getpageinfo(vdp, meta, &pip)) != 0)
01390 return (ret);
01391 for (next_pgno = pip->free;
01392 next_pgno != PGNO_INVALID; next_pgno = pip->next_pgno) {
01393 cur_pgno = pip->pgno;
01394 if ((ret = __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0)
01395 return (ret);
01396
01397
01398 if (!IS_VALID_PGNO(next_pgno)) {
01399 EPRINT((dbenv,
01400 "Page %lu: invalid next_pgno %lu on free list page",
01401 (u_long)cur_pgno, (u_long)next_pgno));
01402 return (DB_VERIFY_BAD);
01403 }
01404
01405
01406 if ((ret = __db_vrfy_pgset_get(pgset, next_pgno, &p)) != 0)
01407 return (ret);
01408 if (p != 0) {
01409 EPRINT((dbenv,
01410 "Page %lu: page %lu encountered a second time on free list",
01411 (u_long)cur_pgno, (u_long)next_pgno));
01412 return (DB_VERIFY_BAD);
01413 }
01414 if ((ret = __db_vrfy_pgset_inc(pgset, next_pgno)) != 0)
01415 return (ret);
01416
01417 if ((ret = __db_vrfy_getpageinfo(vdp, next_pgno, &pip)) != 0)
01418 return (ret);
01419
01420 if (pip->type != P_INVALID) {
01421 EPRINT((dbenv,
01422 "Page %lu: non-invalid page %lu on free list",
01423 (u_long)cur_pgno, (u_long)next_pgno));
01424 ret = DB_VERIFY_BAD;
01425 break;
01426 }
01427 }
01428
01429 if ((t_ret = __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0)
01430 ret = t_ret;
01431 return (ret);
01432 }
01433
01434
01435
01436
01437
01438
01439 static int
01440 __db_vrfy_subdbs(dbp, vdp, dbname, flags)
01441 DB *dbp;
01442 VRFY_DBINFO *vdp;
01443 const char *dbname;
01444 u_int32_t flags;
01445 {
01446 DB *mdbp;
01447 DBC *dbc;
01448 DBT key, data;
01449 DB_ENV *dbenv;
01450 VRFY_PAGEINFO *pip;
01451 db_pgno_t meta_pgno;
01452 int ret, t_ret, isbad;
01453 u_int8_t type;
01454
01455 isbad = 0;
01456 dbc = NULL;
01457 dbenv = dbp->dbenv;
01458
01459 if ((ret =
01460 __db_master_open(dbp, NULL, dbname, DB_RDONLY, 0, &mdbp)) != 0)
01461 return (ret);
01462
01463 if ((ret = __db_cursor_int(mdbp,
01464 NULL, DB_BTREE, PGNO_INVALID, 0, DB_LOCK_INVALIDID, &dbc)) != 0)
01465 goto err;
01466
01467 memset(&key, 0, sizeof(key));
01468 memset(&data, 0, sizeof(data));
01469 while ((ret = __db_c_get(dbc, &key, &data, DB_NEXT)) == 0) {
01470 if (data.size != sizeof(db_pgno_t)) {
01471 EPRINT((dbenv,
01472 "Subdatabase entry not page-number size"));
01473 isbad = 1;
01474 goto err;
01475 }
01476 memcpy(&meta_pgno, data.data, data.size);
01477
01478
01479
01480
01481 DB_NTOHL(&meta_pgno);
01482 if (meta_pgno == PGNO_INVALID || meta_pgno > vdp->last_pgno) {
01483 EPRINT((dbenv,
01484 "Subdatabase entry references invalid page %lu",
01485 (u_long)meta_pgno));
01486 isbad = 1;
01487 goto err;
01488 }
01489 if ((ret = __db_vrfy_getpageinfo(vdp, meta_pgno, &pip)) != 0)
01490 goto err;
01491 type = pip->type;
01492 if ((ret = __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0)
01493 goto err;
01494 switch (type) {
01495 case P_BTREEMETA:
01496 if ((ret = __bam_vrfy_structure(
01497 dbp, vdp, meta_pgno, flags)) != 0) {
01498 if (ret == DB_VERIFY_BAD)
01499 isbad = 1;
01500 else
01501 goto err;
01502 }
01503 break;
01504 case P_HASHMETA:
01505 if ((ret = __ham_vrfy_structure(
01506 dbp, vdp, meta_pgno, flags)) != 0) {
01507 if (ret == DB_VERIFY_BAD)
01508 isbad = 1;
01509 else
01510 goto err;
01511 }
01512 break;
01513 case P_QAMMETA:
01514 default:
01515 EPRINT((dbenv,
01516 "Subdatabase entry references page %lu of invalid type %lu",
01517 (u_long)meta_pgno, (u_long)type));
01518 ret = DB_VERIFY_BAD;
01519 goto err;
01520 }
01521 }
01522
01523 if (ret == DB_NOTFOUND)
01524 ret = 0;
01525
01526 err: if (dbc != NULL && (t_ret = __db_c_close(dbc)) != 0 && ret == 0)
01527 ret = t_ret;
01528
01529 if ((t_ret = __db_close(mdbp, NULL, 0)) != 0 && ret == 0)
01530 ret = t_ret;
01531
01532 return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
01533 }
01534
01535
01536
01537
01538
01539
01540
01541
01542 void
01543 __db_vrfy_struct_feedback(dbp, vdp)
01544 DB *dbp;
01545 VRFY_DBINFO *vdp;
01546 {
01547 int progress;
01548
01549 if (dbp->db_feedback == NULL)
01550 return;
01551
01552 if (vdp->pgs_remaining > 0)
01553 vdp->pgs_remaining--;
01554
01555
01556 progress = 100 - (int)(vdp->pgs_remaining * 50 / (vdp->last_pgno + 1));
01557 dbp->db_feedback(dbp, DB_VERIFY, progress == 100 ? 99 : progress);
01558 }
01559
01560
01561
01562
01563
01564 static int
01565 __db_vrfy_orderchkonly(dbp, vdp, name, subdb, flags)
01566 DB *dbp;
01567 VRFY_DBINFO *vdp;
01568 const char *name, *subdb;
01569 u_int32_t flags;
01570 {
01571 BTMETA *btmeta;
01572 DB *mdbp, *pgset;
01573 DBC *pgsc;
01574 DBT key, data;
01575 DB_ENV *dbenv;
01576 DB_MPOOLFILE *mpf;
01577 HASH *h_internal;
01578 HMETA *hmeta;
01579 PAGE *h, *currpg;
01580 db_pgno_t meta_pgno, p, pgno;
01581 u_int32_t bucket;
01582 int t_ret, ret;
01583
01584 pgset = NULL;
01585 pgsc = NULL;
01586 dbenv = dbp->dbenv;
01587 mpf = dbp->mpf;
01588 currpg = h = NULL;
01589
01590 LF_CLR(DB_NOORDERCHK);
01591
01592
01593 if ((ret = __db_master_open(dbp, NULL, name, DB_RDONLY, 0, &mdbp)) != 0)
01594 goto err;
01595
01596 memset(&key, 0, sizeof(key));
01597 key.data = (void *)subdb;
01598 key.size = (u_int32_t)strlen(subdb);
01599 memset(&data, 0, sizeof(data));
01600 if ((ret = __db_get(mdbp, NULL, &key, &data, 0)) != 0)
01601 goto err;
01602
01603 if (data.size != sizeof(db_pgno_t)) {
01604 EPRINT((dbenv, "Subdatabase entry of invalid size"));
01605 ret = DB_VERIFY_BAD;
01606 goto err;
01607 }
01608
01609 memcpy(&meta_pgno, data.data, data.size);
01610
01611
01612
01613
01614
01615 DB_NTOHL(&meta_pgno);
01616
01617 if ((ret = __memp_fget(mpf, &meta_pgno, 0, &h)) != 0)
01618 goto err;
01619
01620 if ((ret = __db_vrfy_pgset(dbenv, dbp->pgsize, &pgset)) != 0)
01621 goto err;
01622
01623 switch (TYPE(h)) {
01624 case P_BTREEMETA:
01625 btmeta = (BTMETA *)h;
01626 if (F_ISSET(&btmeta->dbmeta, BTM_RECNO)) {
01627
01628 ret = 0;
01629 goto err;
01630 }
01631 if ((ret =
01632 __db_meta2pgset(dbp, vdp, meta_pgno, flags, pgset)) != 0)
01633 goto err;
01634 if ((ret = __db_cursor_int(pgset, NULL, dbp->type,
01635 PGNO_INVALID, 0, DB_LOCK_INVALIDID, &pgsc)) != 0)
01636 goto err;
01637 while ((ret = __db_vrfy_pgset_next(pgsc, &p)) == 0) {
01638 if ((ret = __memp_fget(mpf, &p, 0, &currpg)) != 0)
01639 goto err;
01640 if ((ret = __bam_vrfy_itemorder(dbp,
01641 NULL, currpg, p, NUM_ENT(currpg), 1,
01642 F_ISSET(&btmeta->dbmeta, BTM_DUP), flags)) != 0)
01643 goto err;
01644 if ((ret = __memp_fput(mpf, currpg, 0)) != 0)
01645 goto err;
01646 currpg = NULL;
01647 }
01648
01649
01650
01651
01652
01653
01654 if (ret == DB_NOTFOUND)
01655 ret = 0;
01656 break;
01657 case P_HASHMETA:
01658 hmeta = (HMETA *)h;
01659 h_internal = (HASH *)dbp->h_internal;
01660
01661
01662
01663 if (h_internal == NULL) {
01664 EPRINT((dbenv,
01665 "Page %lu: DB->h_internal field is NULL",
01666 (u_long)meta_pgno));
01667 ret = DB_VERIFY_BAD;
01668 goto err;
01669 }
01670 if (h_internal->h_hash == NULL)
01671 h_internal->h_hash = hmeta->dbmeta.version < 5
01672 ? __ham_func4 : __ham_func5;
01673 if (hmeta->h_charkey !=
01674 h_internal->h_hash(dbp, CHARKEY, sizeof(CHARKEY))) {
01675 EPRINT((dbenv,
01676 "Page %lu: incorrect hash function for database",
01677 (u_long)meta_pgno));
01678 ret = DB_VERIFY_BAD;
01679 goto err;
01680 }
01681
01682
01683
01684
01685
01686 for (bucket = 0; bucket <= hmeta->max_bucket; bucket++) {
01687 pgno = BS_TO_PAGE(bucket, hmeta->spares);
01688 while (pgno != PGNO_INVALID) {
01689 if ((ret = __memp_fget(mpf,
01690 &pgno, 0, &currpg)) != 0)
01691 goto err;
01692 if ((ret = __ham_vrfy_hashing(dbp,
01693 NUM_ENT(currpg), hmeta, bucket, pgno,
01694 flags, h_internal->h_hash)) != 0)
01695 goto err;
01696 pgno = NEXT_PGNO(currpg);
01697 if ((ret = __memp_fput(mpf, currpg, 0)) != 0)
01698 goto err;
01699 currpg = NULL;
01700 }
01701 }
01702 break;
01703 default:
01704 EPRINT((dbenv, "Page %lu: database metapage of bad type %lu",
01705 (u_long)meta_pgno, (u_long)TYPE(h)));
01706 ret = DB_VERIFY_BAD;
01707 break;
01708 }
01709
01710 err: if (pgsc != NULL && (t_ret = __db_c_close(pgsc)) != 0 && ret == 0)
01711 ret = t_ret;
01712 if (pgset != NULL &&
01713 (t_ret = __db_close(pgset, NULL, 0)) != 0 && ret == 0)
01714 ret = t_ret;
01715 if (h != NULL && (t_ret = __memp_fput(mpf, h, 0)) != 0)
01716 ret = t_ret;
01717 if (currpg != NULL && (t_ret = __memp_fput(mpf, currpg, 0)) != 0)
01718 ret = t_ret;
01719 if ((t_ret = __db_close(mdbp, NULL, 0)) != 0)
01720 ret = t_ret;
01721 return (ret);
01722 }
01723
01724
01725
01726
01727
01728
01729
01730
01731
01732 int
01733 __db_salvage(dbp, vdp, pgno, h, handle, callback, flags)
01734 DB *dbp;
01735 VRFY_DBINFO *vdp;
01736 db_pgno_t pgno;
01737 PAGE *h;
01738 void *handle;
01739 int (*callback) __P((void *, const void *));
01740 u_int32_t flags;
01741 {
01742 DB_ENV *dbenv;
01743 VRFY_PAGEINFO *pip;
01744 int keyflag, ret, t_ret;
01745
01746 DB_ASSERT(LF_ISSET(DB_SALVAGE));
01747
01748 dbenv = dbp->dbenv;
01749
01750
01751
01752
01753
01754
01755
01756
01757 keyflag = 0;
01758
01759
01760 if (__db_salvage_isdone(vdp, pgno))
01761 return (0);
01762
01763 switch (TYPE(h)) {
01764 case P_HASHMETA:
01765 ret = __ham_vrfy_meta(dbp, vdp, (HMETA *)h, pgno, flags);
01766 break;
01767 case P_BTREEMETA:
01768 ret = __bam_vrfy_meta(dbp, vdp, (BTMETA *)h, pgno, flags);
01769 break;
01770 case P_QAMMETA:
01771 keyflag = 1;
01772 ret = __qam_vrfy_meta(dbp, vdp, (QMETA *)h, pgno, flags);
01773 break;
01774 case P_HASH:
01775 return (__ham_salvage(
01776 dbp, vdp, pgno, h, handle, callback, flags));
01777 case P_LBTREE:
01778 return (__bam_salvage(dbp,
01779 vdp, pgno, P_LBTREE, h, handle, callback, NULL, flags));
01780 case P_LDUP:
01781 return (__db_salvage_markneeded(vdp, pgno, SALVAGE_LDUP));
01782 case P_OVERFLOW:
01783 return (__db_salvage_markneeded(vdp, pgno, SALVAGE_OVERFLOW));
01784 case P_LRECNO:
01785
01786
01787
01788
01789
01790
01791
01792
01793
01794
01795
01796
01797 return (__db_salvage_markneeded(vdp, pgno, SALVAGE_LRECNO));
01798 case P_QAMDATA:
01799 return (__qam_salvage(dbp,
01800 vdp, pgno, h, handle, callback, flags));
01801 case P_IBTREE:
01802 case P_INVALID:
01803 case P_IRECNO:
01804 case __P_DUPLICATE:
01805 default:
01806
01807 return (0);
01808 }
01809 if (ret != 0)
01810 return (ret);
01811
01812
01813
01814
01815
01816
01817
01818
01819 if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
01820 return (ret);
01821 if (!F_ISSET(pip, VRFY_HAS_SUBDBS))
01822 ret = __db_prheader(
01823 dbp, NULL, 0, keyflag, handle, callback, vdp, pgno);
01824 if ((t_ret = __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0 && ret == 0)
01825 ret = t_ret;
01826 return (ret);
01827 }
01828
01829
01830
01831
01832
01833
01834 static int
01835 __db_salvage_unknowns(dbp, vdp, handle, callback, flags)
01836 DB *dbp;
01837 VRFY_DBINFO *vdp;
01838 void *handle;
01839 int (*callback) __P((void *, const void *));
01840 u_int32_t flags;
01841 {
01842 DBC *dbc;
01843 DBT unkdbt, key, *dbt;
01844 DB_ENV *dbenv;
01845 DB_MPOOLFILE *mpf;
01846 PAGE *h;
01847 db_pgno_t pgno;
01848 u_int32_t pgtype;
01849 int ret, t_ret;
01850 void *ovflbuf;
01851
01852 dbc = NULL;
01853 dbenv = dbp->dbenv;
01854 mpf = dbp->mpf;
01855
01856 memset(&unkdbt, 0, sizeof(DBT));
01857 unkdbt.size = (u_int32_t)strlen("UNKNOWN") + 1;
01858 unkdbt.data = "UNKNOWN";
01859
01860 if ((ret = __os_malloc(dbenv, dbp->pgsize, &ovflbuf)) != 0)
01861 return (ret);
01862
01863
01864
01865
01866
01867
01868 while ((t_ret =
01869 __db_salvage_getnext(vdp, &dbc, &pgno, &pgtype, 1)) == 0) {
01870 if ((t_ret = __memp_fget(mpf, &pgno, 0, &h)) != 0) {
01871 if (ret == 0)
01872 ret = t_ret;
01873 continue;
01874 }
01875
01876 dbt = NULL;
01877 switch (pgtype) {
01878 case SALVAGE_LDUP:
01879 case SALVAGE_LRECNODUP:
01880 dbt = &unkdbt;
01881
01882 case SALVAGE_LBTREE:
01883 case SALVAGE_LRECNO:
01884 if ((t_ret = __bam_salvage(dbp, vdp, pgno, pgtype,
01885 h, handle, callback, dbt, flags)) != 0 && ret == 0)
01886 ret = t_ret;
01887 break;
01888 case SALVAGE_OVERFLOW:
01889 DB_ASSERT(0);
01890 break;
01891 case SALVAGE_HASH:
01892 if ((t_ret = __ham_salvage(dbp, vdp,
01893 pgno, h, handle, callback, flags)) != 0 && ret == 0)
01894 ret = t_ret;
01895 break;
01896 case SALVAGE_INVALID:
01897 case SALVAGE_IGNORE:
01898 default:
01899
01900
01901
01902
01903 DB_ASSERT(0);
01904 break;
01905 }
01906 if ((t_ret = __memp_fput(mpf, h, 0)) != 0 && ret == 0)
01907 ret = t_ret;
01908 }
01909
01910
01911 if (t_ret == DB_NOTFOUND)
01912 t_ret = 0;
01913 if (t_ret != 0 && ret == 0)
01914 ret = t_ret;
01915
01916
01917 if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
01918 ret = t_ret;
01919 dbc = NULL;
01920
01921
01922 while ((t_ret =
01923 __db_salvage_getnext(vdp, &dbc, &pgno, &pgtype, 0)) == 0) {
01924 if ((t_ret = __memp_fget(mpf, &pgno, 0, &h)) != 0) {
01925 if (ret == 0)
01926 ret = t_ret;
01927 continue;
01928 }
01929
01930 switch (pgtype) {
01931 case SALVAGE_OVERFLOW:
01932
01933
01934
01935
01936
01937 if ((t_ret = __db_safe_goff(dbp,
01938 vdp, pgno, &key, &ovflbuf, flags)) != 0 ||
01939 ((vdp->type == DB_BTREE || vdp->type == DB_HASH) &&
01940 (t_ret = __db_vrfy_prdbt(&unkdbt,
01941 0, " ", handle, callback, 0, vdp)) != 0) ||
01942 (t_ret = __db_vrfy_prdbt(
01943 &key, 0, " ", handle, callback, 0, vdp)) != 0)
01944 if (ret == 0)
01945 ret = t_ret;
01946 break;
01947 default:
01948 DB_ASSERT(0);
01949 break;
01950 }
01951 if ((t_ret = __memp_fput(mpf, h, 0)) != 0 && ret == 0)
01952 ret = t_ret;
01953 }
01954
01955
01956 if (t_ret == DB_NOTFOUND)
01957 t_ret = 0;
01958 if (t_ret != 0 && ret == 0)
01959 ret = t_ret;
01960
01961 if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
01962 ret = t_ret;
01963
01964 __os_free(dbenv, ovflbuf);
01965
01966 return (ret);
01967 }
01968
01969
01970
01971
01972
01973 #define INP_OFFSET(dbp, h, i) \
01974 ((db_indx_t)((u_int8_t *)((P_INP(dbp,(h))) + (i)) - (u_int8_t *)(h)))
01975
01976
01977
01978
01979
01980
01981
01982
01983
01984
01985
01986
01987
01988
01989
01990 int
01991 __db_vrfy_inpitem(dbp, h, pgno, i, is_btree, flags, himarkp, offsetp)
01992 DB *dbp;
01993 PAGE *h;
01994 db_pgno_t pgno;
01995 u_int32_t i;
01996 int is_btree;
01997 u_int32_t flags, *himarkp, *offsetp;
01998 {
01999 BKEYDATA *bk;
02000 DB_ENV *dbenv;
02001 db_indx_t *inp, offset, len;
02002
02003 dbenv = dbp->dbenv;
02004
02005 DB_ASSERT(himarkp != NULL);
02006 inp = P_INP(dbp, h);
02007
02008
02009
02010
02011
02012
02013 if (inp + i >= (db_indx_t *)((u_int8_t *)h + *himarkp)) {
02014
02015 EPRINT((dbenv, "Page %lu: entries listing %lu overlaps data",
02016 (u_long)pgno, (u_long)i));
02017 return (DB_VERIFY_FATAL);
02018 }
02019
02020 offset = inp[i];
02021
02022
02023
02024
02025
02026 if (offset <= INP_OFFSET(dbp, h, i) || offset > dbp->pgsize) {
02027 EPRINT((dbenv, "Page %lu: bad offset %lu at page index %lu",
02028 (u_long)pgno, (u_long)offset, (u_long)i));
02029 return (DB_VERIFY_BAD);
02030 }
02031
02032
02033 if (offset < *himarkp)
02034 *himarkp = offset;
02035
02036 if (is_btree) {
02037
02038
02039
02040
02041 if (offset != DB_ALIGN(offset, sizeof(u_int32_t))) {
02042 EPRINT((dbenv,
02043 "Page %lu: unaligned offset %lu at page index %lu",
02044 (u_long)pgno, (u_long)offset, (u_long)i));
02045 return (DB_VERIFY_BAD);
02046 }
02047
02048
02049
02050
02051 bk = GET_BKEYDATA(dbp, h, i);
02052
02053
02054
02055
02056
02057
02058
02059
02060 switch (B_TYPE(bk->type)) {
02061 case B_KEYDATA:
02062 len = bk->len;
02063 break;
02064 case B_DUPLICATE:
02065 case B_OVERFLOW:
02066 len = BOVERFLOW_SIZE;
02067 break;
02068 default:
02069 EPRINT((dbenv,
02070 "Page %lu: item %lu of unrecognizable type",
02071 (u_long)pgno, (u_long)i));
02072 return (DB_VERIFY_BAD);
02073 }
02074
02075 if ((size_t)(offset + len) > dbp->pgsize) {
02076 EPRINT((dbenv,
02077 "Page %lu: item %lu extends past page boundary",
02078 (u_long)pgno, (u_long)i));
02079 return (DB_VERIFY_BAD);
02080 }
02081 }
02082
02083 if (offsetp != NULL)
02084 *offsetp = offset;
02085 return (0);
02086 }
02087
02088
02089
02090
02091
02092
02093
02094
02095
02096
02097 int
02098 __db_vrfy_duptype(dbp, vdp, pgno, flags)
02099 DB *dbp;
02100 VRFY_DBINFO *vdp;
02101 db_pgno_t pgno;
02102 u_int32_t flags;
02103 {
02104 DB_ENV *dbenv;
02105 VRFY_PAGEINFO *pip;
02106 int ret, isbad;
02107
02108 dbenv = dbp->dbenv;
02109 isbad = 0;
02110
02111 if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
02112 return (ret);
02113
02114 switch (pip->type) {
02115 case P_IBTREE:
02116 case P_LDUP:
02117 if (!LF_ISSET(ST_DUPSORT)) {
02118 EPRINT((dbenv,
02119 "Page %lu: sorted duplicate set in unsorted-dup database",
02120 (u_long)pgno));
02121 isbad = 1;
02122 }
02123 break;
02124 case P_IRECNO:
02125 case P_LRECNO:
02126 if (LF_ISSET(ST_DUPSORT)) {
02127 EPRINT((dbenv,
02128 "Page %lu: unsorted duplicate set in sorted-dup database",
02129 (u_long)pgno));
02130 isbad = 1;
02131 }
02132 break;
02133 default:
02134
02135
02136
02137
02138
02139 if (F_ISSET(pip, VRFY_IS_ALLZEROES))
02140 ZEROPG_ERR_PRINT(dbenv, pgno, "duplicate page");
02141 else
02142 EPRINT((dbenv,
02143 "Page %lu: duplicate page of inappropriate type %lu",
02144 (u_long)pgno, (u_long)pip->type));
02145 isbad = 1;
02146 break;
02147 }
02148
02149 if ((ret = __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0)
02150 return (ret);
02151 return (isbad == 1 ? DB_VERIFY_BAD : 0);
02152 }
02153
02154
02155
02156
02157
02158
02159
02160
02161
02162
02163
02164
02165
02166
02167
02168
02169
02170
02171
02172
02173
02174
02175
02176
02177 int
02178 __db_salvage_duptree(dbp, vdp, pgno, key, handle, callback, flags)
02179 DB *dbp;
02180 VRFY_DBINFO *vdp;
02181 db_pgno_t pgno;
02182 DBT *key;
02183 void *handle;
02184 int (*callback) __P((void *, const void *));
02185 u_int32_t flags;
02186 {
02187 DB_MPOOLFILE *mpf;
02188 PAGE *h;
02189 int ret, t_ret;
02190
02191 mpf = dbp->mpf;
02192
02193 if (pgno == PGNO_INVALID || !IS_VALID_PGNO(pgno))
02194 return (DB_VERIFY_BAD);
02195
02196
02197 if ((ret = __memp_fget(mpf, &pgno, 0, &h)) != 0)
02198 return (ret);
02199
02200 switch (TYPE(h)) {
02201 case P_IBTREE:
02202 case P_IRECNO:
02203 if ((ret = __db_vrfy_common(dbp, vdp, h, pgno, flags)) != 0)
02204 goto err;
02205 if ((ret = __bam_vrfy(dbp,
02206 vdp, h, pgno, flags | DB_NOORDERCHK)) != 0 ||
02207 (ret = __db_salvage_markdone(vdp, pgno)) != 0)
02208 goto err;
02209
02210
02211
02212 if ((ret = __bam_salvage_walkdupint(dbp, vdp, h, key,
02213 handle, callback, flags)) != 0)
02214 goto err;
02215 break;
02216 case P_LRECNO:
02217 case P_LDUP:
02218 if ((ret = __bam_salvage(dbp,
02219 vdp, pgno, TYPE(h), h, handle, callback, key, flags)) != 0)
02220 goto err;
02221 break;
02222 default:
02223 ret = DB_VERIFY_BAD;
02224 goto err;
02225 }
02226
02227 err: if ((t_ret = __memp_fput(mpf, h, 0)) != 0 && ret == 0)
02228 ret = t_ret;
02229 return (ret);
02230 }
02231
02232
02233
02234
02235
02236
02237 static int
02238 __db_salvage_subdbs(dbp, vdp, handle, callback, flags, hassubsp)
02239 DB *dbp;
02240 VRFY_DBINFO *vdp;
02241 void *handle;
02242 int (*callback) __P((void *, const void *));
02243 u_int32_t flags;
02244 int *hassubsp;
02245 {
02246 DB *pgset;
02247 DBC *pgsc;
02248 DB_ENV *dbenv;
02249 DB_MPOOLFILE *mpf;
02250 PAGE *h;
02251 VRFY_PAGEINFO *pip;
02252 db_pgno_t p, meta_pgno;
02253 int ret, t_ret;
02254
02255 *hassubsp = 0;
02256
02257 dbenv = dbp->dbenv;
02258 pgset = NULL;
02259 pgsc = NULL;
02260 mpf = dbp->mpf;
02261 h = NULL;
02262 pip = NULL;
02263 ret = 0;
02264
02265
02266
02267
02268
02269 meta_pgno = PGNO_BASE_MD;
02270 if ((t_ret = __memp_fget(mpf, &meta_pgno, 0, &h)) == 0 &&
02271 (t_ret = __db_vrfy_common(dbp, vdp, h, PGNO_BASE_MD, flags)) == 0 &&
02272 (t_ret = __db_salvage(
02273 dbp, vdp, PGNO_BASE_MD, h, handle, callback, flags)) == 0 &&
02274 (t_ret = __db_vrfy_getpageinfo(vdp, 0, &pip)) == 0)
02275 if (F_ISSET(pip, VRFY_HAS_SUBDBS))
02276 *hassubsp = 1;
02277 if (pip != NULL &&
02278 (t_ret = __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0 && ret == 0)
02279 ret = t_ret;
02280 if (h != NULL) {
02281 if ((t_ret = __memp_fput(mpf, h, 0)) != 0 && ret == 0)
02282 ret = t_ret;
02283 h = NULL;
02284 }
02285 if (ret != 0 || *hassubsp == 0)
02286 return (ret);
02287
02288
02289
02290
02291
02292
02293
02294
02295 if ((ret = __db_vrfy_pgset(dbenv, dbp->pgsize, &pgset)) != 0)
02296 goto err;
02297 if ((ret = __db_meta2pgset(dbp, vdp, PGNO_BASE_MD, flags, pgset)) != 0)
02298 goto err;
02299 if ((ret = __db_cursor(pgset, NULL, &pgsc, 0)) != 0)
02300 goto err;
02301 while ((t_ret = __db_vrfy_pgset_next(pgsc, &p)) == 0) {
02302 if ((t_ret = __memp_fget(mpf, &p, 0, &h)) == 0 &&
02303 (t_ret = __db_vrfy_common(dbp, vdp, h, p, flags)) == 0 &&
02304 (t_ret =
02305 __bam_vrfy(dbp, vdp, h, p, flags | DB_NOORDERCHK)) == 0)
02306 t_ret = __db_salvage_subdbpg(
02307 dbp, vdp, h, handle, callback, flags);
02308 if (t_ret != 0 && ret == 0)
02309 ret = t_ret;
02310 if (h != NULL) {
02311 if ((t_ret = __memp_fput(mpf, h, 0)) != 0 && ret == 0)
02312 ret = t_ret;
02313 h = NULL;
02314 }
02315 }
02316
02317 if (t_ret != DB_NOTFOUND && ret == 0)
02318 ret = t_ret;
02319
02320 err: if (pgsc != NULL && (t_ret = __db_c_close(pgsc)) != 0 && ret == 0)
02321 ret = t_ret;
02322 if (pgset != NULL &&
02323 (t_ret = __db_close(pgset, NULL, 0)) != 0 && ret ==0)
02324 ret = t_ret;
02325 if (h != NULL && (t_ret = __memp_fput(mpf, h, 0)) != 0 && ret == 0)
02326 ret = t_ret;
02327 return (ret);
02328 }
02329
02330
02331
02332
02333
02334
02335 static int
02336 __db_salvage_subdbpg(dbp, vdp, master, handle, callback, flags)
02337 DB *dbp;
02338 VRFY_DBINFO *vdp;
02339 PAGE *master;
02340 void *handle;
02341 int (*callback) __P((void *, const void *));
02342 u_int32_t flags;
02343 {
02344 BKEYDATA *bkkey, *bkdata;
02345 BOVERFLOW *bo;
02346 DB *pgset;
02347 DBC *pgsc;
02348 DBT key;
02349 DB_ENV *dbenv;
02350 DB_MPOOLFILE *mpf;
02351 PAGE *subpg;
02352 db_indx_t i;
02353 db_pgno_t meta_pgno, p;
02354 int ret, err_ret, t_ret;
02355 char *subdbname;
02356
02357 dbenv = dbp->dbenv;
02358 mpf = dbp->mpf;
02359 ret = err_ret = 0;
02360 subdbname = NULL;
02361
02362 if ((ret = __db_vrfy_pgset(dbenv, dbp->pgsize, &pgset)) != 0)
02363 return (ret);
02364
02365
02366
02367
02368
02369 for (i = 0; i < NUM_ENT(master); i += P_INDX) {
02370 bkkey = GET_BKEYDATA(dbp, master, i);
02371 bkdata = GET_BKEYDATA(dbp, master, i + O_INDX);
02372
02373
02374 if (B_TYPE(bkkey->type) == B_OVERFLOW) {
02375
02376
02377
02378
02379 bo = (BOVERFLOW *)bkkey;
02380 if ((ret = __db_safe_goff(dbp, vdp,
02381 bo->pgno, &key, &subdbname, flags)) != 0) {
02382 err_ret = DB_VERIFY_BAD;
02383 continue;
02384 }
02385
02386
02387 if ((ret = __os_realloc(dbenv,
02388 key.size + 1, &subdbname)) != 0)
02389 goto err;
02390 subdbname[key.size] = '\0';
02391 } else if (B_TYPE(bkkey->type) == B_KEYDATA) {
02392 if ((ret = __os_realloc(dbenv,
02393 bkkey->len + 1, &subdbname)) != 0)
02394 goto err;
02395 memcpy(subdbname, bkkey->data, bkkey->len);
02396 subdbname[bkkey->len] = '\0';
02397 }
02398
02399
02400 if (bkdata->len != sizeof(db_pgno_t)) {
02401 err_ret = DB_VERIFY_BAD;
02402 continue;
02403 }
02404 memcpy(&meta_pgno,
02405 (db_pgno_t *)bkdata->data, sizeof(db_pgno_t));
02406
02407
02408
02409
02410
02411 DB_NTOHL(&meta_pgno);
02412
02413
02414 if (!IS_VALID_PGNO(meta_pgno) ||
02415 (ret = __memp_fget(mpf, &meta_pgno, 0, &subpg)) != 0) {
02416 err_ret = ret;
02417 continue;
02418 }
02419
02420
02421
02422
02423
02424
02425
02426
02427
02428 if ((ret =
02429 __db_vrfy_common(dbp, vdp, subpg, meta_pgno, flags)) != 0) {
02430 err_ret = ret;
02431 (void)__memp_fput(mpf, subpg, 0);
02432 continue;
02433 }
02434 switch (TYPE(subpg)) {
02435 case P_BTREEMETA:
02436 if ((ret = __bam_vrfy_meta(dbp,
02437 vdp, (BTMETA *)subpg, meta_pgno, flags)) != 0) {
02438 err_ret = ret;
02439 (void)__memp_fput(mpf, subpg, 0);
02440 continue;
02441 }
02442 break;
02443 case P_HASHMETA:
02444 if ((ret = __ham_vrfy_meta(dbp,
02445 vdp, (HMETA *)subpg, meta_pgno, flags)) != 0) {
02446 err_ret = ret;
02447 (void)__memp_fput(mpf, subpg, 0);
02448 continue;
02449 }
02450 break;
02451 default:
02452
02453 err_ret = DB_VERIFY_BAD;
02454 continue;
02455 }
02456
02457 if ((ret = __memp_fput(mpf, subpg, 0)) != 0) {
02458 err_ret = ret;
02459 continue;
02460 }
02461
02462
02463 if ((ret = __db_prheader(dbp,
02464 subdbname, 0, 0, handle, callback, vdp, meta_pgno)) != 0)
02465 goto err;
02466
02467 if ((ret = __db_meta2pgset(dbp, vdp, meta_pgno,
02468 flags, pgset)) != 0) {
02469 err_ret = ret;
02470 continue;
02471 }
02472
02473 if ((ret = __db_cursor(pgset, NULL, &pgsc, 0)) != 0)
02474 goto err;
02475 while ((ret = __db_vrfy_pgset_next(pgsc, &p)) == 0) {
02476 if ((ret = __memp_fget(mpf, &p, 0, &subpg)) != 0) {
02477 err_ret = ret;
02478 continue;
02479 }
02480 if ((ret = __db_salvage(dbp, vdp, p, subpg,
02481 handle, callback, flags)) != 0)
02482 err_ret = ret;
02483 if ((ret = __memp_fput(mpf, subpg, 0)) != 0)
02484 err_ret = ret;
02485 }
02486
02487 if (ret != DB_NOTFOUND)
02488 goto err;
02489
02490 if ((ret = __db_c_close(pgsc)) != 0)
02491 goto err;
02492 if ((ret = __db_prfooter(handle, callback)) != 0)
02493 goto err;
02494 }
02495 err: if (subdbname)
02496 __os_free(dbenv, subdbname);
02497
02498 if ((t_ret = __db_close(pgset, NULL, 0)) != 0)
02499 ret = t_ret;
02500
02501 if ((t_ret = __db_salvage_markdone(vdp, PGNO(master))) != 0)
02502 return (t_ret);
02503
02504 return ((err_ret != 0) ? err_ret : ret);
02505 }
02506
02507
02508
02509
02510
02511
02512
02513 static int
02514 __db_meta2pgset(dbp, vdp, pgno, flags, pgset)
02515 DB *dbp;
02516 VRFY_DBINFO *vdp;
02517 db_pgno_t pgno;
02518 u_int32_t flags;
02519 DB *pgset;
02520 {
02521 DB_MPOOLFILE *mpf;
02522 PAGE *h;
02523 int ret, t_ret;
02524
02525 mpf = dbp->mpf;
02526
02527 if ((ret = __memp_fget(mpf, &pgno, 0, &h)) != 0)
02528 return (ret);
02529
02530 switch (TYPE(h)) {
02531 case P_BTREEMETA:
02532 ret = __bam_meta2pgset(dbp, vdp, (BTMETA *)h, flags, pgset);
02533 break;
02534 case P_HASHMETA:
02535 ret = __ham_meta2pgset(dbp, vdp, (HMETA *)h, flags, pgset);
02536 break;
02537 default:
02538 ret = DB_VERIFY_BAD;
02539 break;
02540 }
02541
02542 if ((t_ret = __memp_fput(mpf, h, 0)) != 0)
02543 return (t_ret);
02544 return (ret);
02545 }
02546
02547
02548
02549
02550
02551
02552 static u_int
02553 __db_guesspgsize(dbenv, fhp)
02554 DB_ENV *dbenv;
02555 DB_FH *fhp;
02556 {
02557 db_pgno_t i;
02558 size_t nr;
02559 u_int32_t guess;
02560 u_int8_t type;
02561
02562 for (guess = DB_MAX_PGSIZE; guess >= DB_MIN_PGSIZE; guess >>= 1) {
02563
02564
02565
02566
02567
02568
02569
02570
02571
02572
02573
02574
02575 for (i = 1; i <= 3; i++) {
02576 if (__os_seek(dbenv, fhp, guess,
02577 i, SSZ(DBMETA, type), 0, DB_OS_SEEK_SET) != 0)
02578 break;
02579 if (__os_read(dbenv,
02580 fhp, &type, 1, &nr) != 0 || nr == 0)
02581 break;
02582 if (type == P_INVALID || type >= P_PAGETYPE_MAX)
02583 return (guess << 1);
02584 }
02585 }
02586
02587
02588
02589
02590
02591 return (DB_DEF_IOSIZE);
02592 }