~ubuntu-branches/ubuntu/edgy/rpm/edgy

« back to all changes in this revision

Viewing changes to db/db/db_vrfy.c-DEBUG

  • Committer: Bazaar Package Importer
  • Author(s): Joey Hess
  • Date: 2002-01-22 20:56:57 UTC
  • Revision ID: james.westby@ubuntu.com-20020122205657-l74j50mr9z8ofcl5
Tags: upstream-4.0.3
ImportĀ upstreamĀ versionĀ 4.0.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-
 
2
 * See the file LICENSE for redistribution information.
 
3
 *
 
4
 * Copyright (c) 2000-2001
 
5
 *      Sleepycat Software.  All rights reserved.
 
6
 *
 
7
 * $Id: db_vrfy.c,v 1.67 2001/07/11 21:12:17 krinsky Exp $
 
8
 */
 
9
 
 
10
#include "db_config.h"
 
11
 
 
12
#ifndef lint
 
13
static const char revid[] = "$Id: db_vrfy.c,v 1.67 2001/07/11 21:12:17 krinsky Exp $";
 
14
#endif /* not lint */
 
15
 
 
16
#ifndef NO_SYSTEM_INCLUDES
 
17
#include <sys/types.h>
 
18
 
 
19
#include <string.h>
 
20
#endif
 
21
 
 
22
#include "db_int.h"
 
23
#include "db_page.h"
 
24
#include "db_shash.h"
 
25
#include "db_swap.h"
 
26
#include "db_verify.h"
 
27
#include "btree.h"
 
28
#include "hash.h"
 
29
#include "qam.h"
 
30
#include "lock.h"
 
31
#include "mp.h"
 
32
 
 
33
static int  __db_guesspgsize __P((DB_ENV *, DB_FH *));
 
34
static int  __db_is_valid_magicno __P((u_int32_t, DBTYPE *));
 
35
static int  __db_is_valid_pagetype __P((u_int32_t));
 
36
static int  __db_meta2pgset
 
37
                __P((DB *, VRFY_DBINFO *, db_pgno_t, u_int32_t, DB *));
 
38
static int __db_salvage __P((DB *, VRFY_DBINFO *, db_pgno_t,
 
39
                PAGE *, void *, int (*)(void *, const void *), u_int32_t));
 
40
static int __db_salvage_subdbpg __P((DB *, VRFY_DBINFO *,
 
41
                PAGE *, void *, int (*)(void *, const void *), u_int32_t));
 
42
static int  __db_salvage_subdbs
 
43
                __P((DB *, VRFY_DBINFO *, void *,
 
44
                int(*)(void *, const void *), u_int32_t, int *));
 
45
static int  __db_salvage_unknowns
 
46
                __P((DB *, VRFY_DBINFO *, void *,
 
47
                int (*)(void *, const void *), u_int32_t));
 
48
static int  __db_vrfy_common
 
49
                __P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t, u_int32_t));
 
50
static int  __db_vrfy_freelist __P((DB *, VRFY_DBINFO *, db_pgno_t, u_int32_t));
 
51
static int  __db_vrfy_invalid
 
52
                __P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t, u_int32_t));
 
53
static int  __db_vrfy_orderchkonly __P((DB *,
 
54
                VRFY_DBINFO *, const char *, const char *, u_int32_t));
 
55
static int  __db_vrfy_pagezero __P((DB *, VRFY_DBINFO *, DB_FH *, u_int32_t));
 
56
static int  __db_vrfy_subdbs
 
57
                __P((DB *, VRFY_DBINFO *, const char *, u_int32_t));
 
58
static int  __db_vrfy_structure
 
59
                __P((DB *, VRFY_DBINFO *, const char *, db_pgno_t, u_int32_t));
 
60
static int  __db_vrfy_walkpages
 
61
                __P((DB *, VRFY_DBINFO *, void *, int (*)(void *, const void *),
 
62
                u_int32_t));
 
63
 
 
64
/*
 
65
 * This is the code for DB->verify, the DB database consistency checker.
 
66
 * For now, it checks all subdatabases in a database, and verifies
 
67
 * everything it knows how to (i.e. it's all-or-nothing, and one can't
 
68
 * check only for a subset of possible problems).
 
69
 */
 
70
 
 
71
/*
 
72
 * __db_verify --
 
73
 *      Walk the entire file page-by-page, either verifying with or without
 
74
 *      dumping in db_dump -d format, or DB_SALVAGE-ing whatever key/data
 
75
 *      pairs can be found and dumping them in standard (db_load-ready)
 
76
 *      dump format.
 
77
 *
 
78
 *      (Salvaging isn't really a verification operation, but we put it
 
79
 *      here anyway because it requires essentially identical top-level
 
80
 *      code.)
 
81
 *
 
82
 *      flags may be 0, DB_NOORDERCHK, DB_ORDERCHKONLY, or DB_SALVAGE
 
83
 *      (and optionally DB_AGGRESSIVE).
 
84
 *
 
85
 *      __db_verify itself is simply a wrapper to __db_verify_internal,
 
86
 *      which lets us pass appropriate equivalents to FILE * in from the
 
87
 *      non-C APIs.
 
88
 *
 
89
 * PUBLIC: int __db_verify
 
90
 * PUBLIC:     __P((DB *, const char *, const char *, FILE *, u_int32_t));
 
91
 */
 
92
int
 
93
__db_verify(dbp, file, database, outfile, flags)
 
94
        DB *dbp;
 
95
        const char *file, *database;
 
96
        FILE *outfile;
 
97
        u_int32_t flags;
 
98
{
 
99
 
 
100
        return (__db_verify_internal(dbp,
 
101
            file, database, outfile, __db_verify_callback, flags));
 
102
}
 
103
 
 
104
/*
 
105
 * __db_verify_callback --
 
106
 *      Callback function for using pr_* functions from C.
 
107
 *
 
108
 * PUBLIC: int  __db_verify_callback __P((void *, const void *));
 
109
 */
 
110
int
 
111
__db_verify_callback(handle, str_arg)
 
112
        void *handle;
 
113
        const void *str_arg;
 
114
{
 
115
        char *str;
 
116
        FILE *f;
 
117
 
 
118
        str = (char *)str_arg;
 
119
        f = (FILE *)handle;
 
120
 
 
121
        if (fprintf(f, "%s", str) != (int)strlen(str))
 
122
                return (EIO);
 
123
 
 
124
        return (0);
 
125
}
 
126
 
 
127
/*
 
128
 * __db_verify_internal --
 
129
 *      Inner meat of __db_verify.
 
130
 *
 
131
 * PUBLIC: int __db_verify_internal __P((DB *, const char *,
 
132
 * PUBLIC:     const char *, void *, int (*)(void *, const void *), u_int32_t));
 
133
 */
 
134
int
 
135
__db_verify_internal(dbp_orig, name, subdb, handle, callback, flags)
 
136
        DB *dbp_orig;
 
137
        const char *name, *subdb;
 
138
        void *handle;
 
139
        int (*callback) __P((void *, const void *));
 
140
        u_int32_t flags;
 
141
{
 
142
        DB *dbp;
 
143
        DB_ENV *dbenv;
 
144
        DB_FH fh, *fhp;
 
145
        VRFY_DBINFO *vdp;
 
146
        int has, ret, isbad;
 
147
        char *real_name;
 
148
 
 
149
        dbenv = dbp_orig->dbenv;
 
150
        vdp = NULL;
 
151
        real_name = NULL;
 
152
        ret = isbad = 0;
 
153
 
 
154
        memset(&fh, 0, sizeof(fh));
 
155
        fhp = &fh;
 
156
 
 
157
        PANIC_CHECK(dbenv);
 
158
        DB_ILLEGAL_AFTER_OPEN(dbp_orig, "verify");
 
159
 
 
160
#define OKFLAGS (DB_AGGRESSIVE | DB_NOORDERCHK | DB_ORDERCHKONLY | DB_SALVAGE)
 
161
        if ((ret = __db_fchk(dbenv, "DB->verify", flags, OKFLAGS)) != 0)
 
162
                return (ret);
 
163
 
 
164
        /*
 
165
         * DB_SALVAGE is mutually exclusive with the other flags except
 
166
         * DB_AGGRESSIVE.
 
167
         */
 
168
        if (LF_ISSET(DB_SALVAGE) &&
 
169
            (flags & ~DB_AGGRESSIVE) != DB_SALVAGE)
 
170
                return (__db_ferr(dbenv, "__db_verify", 1));
 
171
 
 
172
        if (LF_ISSET(DB_ORDERCHKONLY) && flags != DB_ORDERCHKONLY)
 
173
                return (__db_ferr(dbenv, "__db_verify", 1));
 
174
 
 
175
        if (LF_ISSET(DB_ORDERCHKONLY) && subdb == NULL) {
 
176
                __db_err(dbenv, "DB_ORDERCHKONLY requires a database name");
 
177
                return (EINVAL);
 
178
        }
 
179
 
 
180
        /*
 
181
         * Forbid working in an environment that uses transactions or
 
182
         * locking;  we're going to be looking at the file freely,
 
183
         * and while we're not going to modify it, we aren't obeying
 
184
         * locking conventions either.
 
185
         */
 
186
        if (TXN_ON(dbenv) || LOCKING_ON(dbenv) || LOGGING_ON(dbenv)) {
 
187
                dbp_orig->errx(dbp_orig,
 
188
            "verify may not be used with transactions, logging, or locking");
 
189
                return (EINVAL);
 
190
                /* NOTREACHED */
 
191
        }
 
192
 
 
193
        /* Create a dbp to use internally, which we can close at our leisure. */
 
194
        if ((ret = db_create(&dbp, dbenv, 0)) != 0)
 
195
                goto err;
 
196
 
 
197
        F_SET(dbp, DB_AM_VERIFYING);
 
198
 
 
199
        /* Copy the supplied pagesize, which we use if the file one is bogus. */
 
200
        if (dbp_orig->pgsize >= DB_MIN_PGSIZE &&
 
201
            dbp_orig->pgsize <= DB_MAX_PGSIZE)
 
202
                dbp->set_pagesize(dbp, dbp_orig->pgsize);
 
203
 
 
204
        /* Copy the feedback function, if present, and initialize it. */
 
205
        if (!LF_ISSET(DB_SALVAGE) && dbp_orig->db_feedback != NULL) {
 
206
                dbp->set_feedback(dbp, dbp_orig->db_feedback);
 
207
                dbp->db_feedback(dbp, DB_VERIFY, 0);
 
208
        }
 
209
 
 
210
        /*
 
211
         * Copy the comparison and hashing functions.  Note that
 
212
         * even if the database is not a hash or btree, the respective
 
213
         * internal structures will have been initialized.
 
214
         */
 
215
        if (dbp_orig->dup_compare != NULL &&
 
216
            (ret = dbp->set_dup_compare(dbp, dbp_orig->dup_compare)) != 0)
 
217
                goto err;
 
218
        if (((BTREE *)dbp_orig->bt_internal)->bt_compare != NULL &&
 
219
            (ret = dbp->set_bt_compare(dbp,
 
220
            ((BTREE *)dbp_orig->bt_internal)->bt_compare)) != 0)
 
221
                goto err;
 
222
        if (((HASH *)dbp_orig->h_internal)->h_hash != NULL &&
 
223
            (ret = dbp->set_h_hash(dbp,
 
224
            ((HASH *)dbp_orig->h_internal)->h_hash)) != 0)
 
225
                goto err;
 
226
 
 
227
        /*
 
228
         * We don't know how large the cache is, and if the database
 
229
         * in question uses a small page size--which we don't know
 
230
         * yet!--it may be uncomfortably small for the default page
 
231
         * size [#2143].  However, the things we need temporary
 
232
         * databases for in dbinfo are largely tiny, so using a
 
233
         * 1024-byte pagesize is probably not going to be a big hit,
 
234
         * and will make us fit better into small spaces.
 
235
         */
 
236
        if ((ret = __db_vrfy_dbinfo_create(dbenv, 1024, &vdp)) != 0)
 
237
                goto err;
 
238
 
 
239
        /* Find the real name of the file. */
 
240
        if ((ret = __db_appname(dbenv,
 
241
            DB_APP_DATA, NULL, name, 0, NULL, &real_name)) != 0)
 
242
                goto err;
 
243
 
 
244
        /*
 
245
         * Our first order of business is to verify page 0, which is
 
246
         * the metadata page for the master database of subdatabases
 
247
         * or of the only database in the file.  We want to do this by hand
 
248
         * rather than just calling __db_open in case it's corrupt--various
 
249
         * things in __db_open might act funny.
 
250
         *
 
251
         * Once we know the metadata page is healthy, I believe that it's
 
252
         * safe to open the database normally and then use the page swapping
 
253
         * code, which makes life easier.
 
254
         */
 
255
        if ((ret = __os_open(dbenv, real_name, DB_OSO_RDONLY, 0444, fhp)) != 0)
 
256
                goto err;
 
257
 
 
258
        /* Verify the metadata page 0; set pagesize and type. */
 
259
        if ((ret = __db_vrfy_pagezero(dbp, vdp, fhp, flags)) != 0) {
 
260
                if (ret == DB_VERIFY_BAD)
 
261
                        isbad = 1;
 
262
                else
 
263
                        goto err;
 
264
        }
 
265
 
 
266
        /*
 
267
         * We can assume at this point that dbp->pagesize and dbp->type are
 
268
         * set correctly, or at least as well as they can be, and that
 
269
         * locking, logging, and txns are not in use.  Thus we can trust
 
270
         * the memp code not to look at the page, and thus to be safe
 
271
         * enough to use.
 
272
         *
 
273
         * The dbp is not open, but the file is open in the fhp, and we
 
274
         * cannot assume that __db_open is safe.  Call __db_dbenv_setup,
 
275
         * the [safe] part of __db_open that initializes the environment--
 
276
         * and the mpool--manually.
 
277
         */
 
278
        if ((ret = __db_dbenv_setup(dbp,
 
279
            name, DB_ODDFILESIZE | DB_RDONLY)) != 0)
 
280
                return (ret);
 
281
 
 
282
        /* Mark the dbp as opened, so that we correctly handle its close. */
 
283
        F_SET(dbp, DB_OPEN_CALLED);
 
284
 
 
285
        /* Find out the page number of the last page in the database. */
 
286
        __memp_lastpgno(dbp->mpf, &vdp->last_pgno);
 
287
 
 
288
        /*
 
289
         * DB_ORDERCHKONLY is a special case;  our file consists of
 
290
         * several subdatabases, which use different hash, bt_compare,
 
291
         * and/or dup_compare functions.  Consequently, we couldn't verify
 
292
         * sorting and hashing simply by calling DB->verify() on the file.
 
293
         * DB_ORDERCHKONLY allows us to come back and check those things;  it
 
294
         * requires a subdatabase, and assumes that everything but that
 
295
         * database's sorting/hashing is correct.
 
296
         */
 
297
        if (LF_ISSET(DB_ORDERCHKONLY)) {
 
298
                ret = __db_vrfy_orderchkonly(dbp, vdp, name, subdb, flags);
 
299
                goto done;
 
300
        }
 
301
 
 
302
        /*
 
303
         * When salvaging, we use a db to keep track of whether we've seen a
 
304
         * given overflow or dup page in the course of traversing normal data.
 
305
         * If in the end we have not, we assume its key got lost and print it
 
306
         * with key "UNKNOWN".
 
307
         */
 
308
        if (LF_ISSET(DB_SALVAGE)) {
 
309
                if ((ret = __db_salvage_init(vdp)) != 0)
 
310
                        return (ret);
 
311
 
 
312
                /*
 
313
                 * If we're not being aggressive, attempt to crack subdbs.
 
314
                 * "has" will indicate whether the attempt has succeeded
 
315
                 * (even in part), meaning that we have some semblance of
 
316
                 * subdbs;  on the walkpages pass, we print out
 
317
                 * whichever data pages we have not seen.
 
318
                 */
 
319
                has = 0;
 
320
                if (!LF_ISSET(DB_AGGRESSIVE) && (__db_salvage_subdbs(dbp,
 
321
                    vdp, handle, callback, flags, &has)) != 0)
 
322
                        isbad = 1;
 
323
 
 
324
                /*
 
325
                 * If we have subdatabases, we need to signal that if
 
326
                 * any keys are found that don't belong to a subdatabase,
 
327
                 * they'll need to have an "__OTHER__" subdatabase header
 
328
                 * printed first.  Flag this.  Else, print a header for
 
329
                 * the normal, non-subdb database.
 
330
                 */
 
331
                if (has == 1)
 
332
                        F_SET(vdp, SALVAGE_PRINTHEADER);
 
333
                else if ((ret = __db_prheader(dbp,
 
334
                    NULL, 0, 0, handle, callback, vdp, PGNO_BASE_MD)) != 0)
 
335
                        goto err;
 
336
        }
 
337
 
 
338
        if ((ret =
 
339
            __db_vrfy_walkpages(dbp, vdp, handle, callback, flags)) != 0) {
 
340
                if (ret == DB_VERIFY_BAD)
 
341
                        isbad = 1;
 
342
                else if (ret != 0)
 
343
                        goto err;
 
344
        }
 
345
 
 
346
        /* If we're verifying, verify inter-page structure. */
 
347
        if (!LF_ISSET(DB_SALVAGE) && isbad == 0)
 
348
                if ((ret =
 
349
                    __db_vrfy_structure(dbp, vdp, name, 0, flags)) != 0) {
 
350
                        if (ret == DB_VERIFY_BAD)
 
351
                                isbad = 1;
 
352
                        else if (ret != 0)
 
353
                                goto err;
 
354
                }
 
355
 
 
356
        /*
 
357
         * If we're salvaging, output with key UNKNOWN any overflow or dup pages
 
358
         * we haven't been able to put in context.  Then destroy the salvager's
 
359
         * state-saving database.
 
360
         */
 
361
        if (LF_ISSET(DB_SALVAGE)) {
 
362
                if ((ret = __db_salvage_unknowns(dbp,
 
363
                    vdp, handle, callback, flags)) != 0)
 
364
                        isbad = 1;
 
365
                /* No return value, since there's little we can do. */
 
366
                __db_salvage_destroy(vdp);
 
367
        }
 
368
 
 
369
        if (0) {
 
370
err:            (void)__db_err(dbenv, "%s: %s", name, db_strerror(ret));
 
371
        }
 
372
 
 
373
        if (LF_ISSET(DB_SALVAGE) &&
 
374
            (has == 0 || F_ISSET(vdp, SALVAGE_PRINTFOOTER)))
 
375
                (void)__db_prfooter(handle, callback);
 
376
 
 
377
        /* Send feedback that we're done. */
 
378
done:   if (!LF_ISSET(DB_SALVAGE) && dbp->db_feedback != NULL)
 
379
                dbp->db_feedback(dbp, DB_VERIFY, 100);
 
380
 
 
381
        if (F_ISSET(fhp, DB_FH_VALID))
 
382
                (void)__os_closehandle(fhp);
 
383
        if (dbp)
 
384
                (void)dbp->close(dbp, 0);
 
385
        if (vdp)
 
386
                (void)__db_vrfy_dbinfo_destroy(dbenv, vdp);
 
387
        if (real_name)
 
388
                __os_freestr(dbenv, real_name);
 
389
 
 
390
        if ((ret == 0 && isbad == 1) || ret == DB_VERIFY_FATAL)
 
391
                ret = DB_VERIFY_BAD;
 
392
 
 
393
        return (ret);
 
394
}
 
395
 
 
396
/*
 
397
 * __db_vrfy_pagezero --
 
398
 *      Verify the master metadata page.  Use seek, read, and a local buffer
 
399
 *      rather than the DB paging code, for safety.
 
400
 *
 
401
 *      Must correctly (or best-guess) set dbp->type and dbp->pagesize.
 
402
 */
 
403
static int
 
404
__db_vrfy_pagezero(dbp, vdp, fhp, flags)
 
405
        DB *dbp;
 
406
        VRFY_DBINFO *vdp;
 
407
        DB_FH *fhp;
 
408
        u_int32_t flags;
 
409
{
 
410
        DBMETA *meta;
 
411
        DB_ENV *dbenv;
 
412
        VRFY_PAGEINFO *pip;
 
413
        db_pgno_t freelist;
 
414
        size_t nr;
 
415
        int isbad, ret, swapped;
 
416
        u_int8_t mbuf[DBMETASIZE];
 
417
 
 
418
        isbad = ret = swapped = 0;
 
419
        freelist = 0;
 
420
        dbenv = dbp->dbenv;
 
421
        meta = (DBMETA *)mbuf;
 
422
        dbp->type = DB_UNKNOWN;
 
423
 
 
424
        /*
 
425
         * Seek to the metadata page.
 
426
         * Note that if we're just starting a verification, dbp->pgsize
 
427
         * may be zero;  this is okay, as we want page zero anyway and
 
428
         * 0*0 == 0.
 
429
         */
 
430
        if ((ret = __os_seek(dbenv, fhp, 0, 0, 0, 0, DB_OS_SEEK_SET)) != 0 ||
 
431
            (ret = __os_read(dbenv, fhp, mbuf, DBMETASIZE, &nr)) != 0) {
 
432
                __db_err(dbenv, 
 
433
                    "Metadata page %lu cannot be read: %s", 
 
434
                    (u_long)PGNO_BASE_MD, db_strerror(ret));
 
435
                return (ret);
 
436
        }
 
437
 
 
438
        if (nr != DBMETASIZE) {
 
439
                EPRINT((dbp->dbenv,
 
440
                    "Incomplete metadata page %lu", (u_long)PGNO_BASE_MD));
 
441
                return (DB_VERIFY_FATAL);
 
442
        }
 
443
 
 
444
        /*
 
445
         * Check all of the fields that we can.
 
446
         */
 
447
 
 
448
        /* 08-11: Current page number.  Must == pgno. */
 
449
        /* Note that endianness doesn't matter--it's zero. */
 
450
        if (meta->pgno != PGNO_BASE_MD) {
 
451
                isbad = 1;
 
452
                EPRINT((dbp->dbenv, "Bad pgno: was %lu, should be %lu",
 
453
                    (u_long)meta->pgno, (u_long)PGNO_BASE_MD));
 
454
        }
 
455
 
 
456
        /* 12-15: Magic number.  Must be one of valid set. */
 
457
        if (__db_is_valid_magicno(meta->magic, &dbp->type))
 
458
                swapped = 0;
 
459
        else {
 
460
                M_32_SWAP(meta->magic);
 
461
                if (__db_is_valid_magicno(meta->magic,
 
462
                    &dbp->type))
 
463
                        swapped = 1;
 
464
                else {
 
465
                        isbad = 1;
 
466
                        EPRINT((dbp->dbenv,
 
467
                            "Bad magic number: %lu", (u_long)meta->magic));
 
468
                }
 
469
        }
 
470
 
 
471
        /*
 
472
         * 16-19: Version.  Must be current;  for now, we
 
473
         * don't support verification of old versions.
 
474
         */
 
475
        if (swapped)
 
476
                M_32_SWAP(meta->version);
 
477
        if ((dbp->type == DB_BTREE && meta->version != DB_BTREEVERSION) ||
 
478
            (dbp->type == DB_HASH && meta->version != DB_HASHVERSION) ||
 
479
            (dbp->type == DB_QUEUE && meta->version != DB_QAMVERSION)) {
 
480
                isbad = 1;
 
481
                EPRINT((dbp->dbenv, "%s%s", "Old or incorrect DB ",
 
482
                    "version; extraneous errors may result"));
 
483
        }
 
484
 
 
485
        /*
 
486
         * 20-23: Pagesize.  Must be power of two,
 
487
         * greater than 512, and less than 64K.
 
488
         */
 
489
        if (swapped)
 
490
                M_32_SWAP(meta->pagesize);
 
491
        if (IS_VALID_PAGESIZE(meta->pagesize))
 
492
                dbp->pgsize = meta->pagesize;
 
493
        else {
 
494
                isbad = 1;
 
495
                EPRINT((dbp->dbenv,
 
496
                    "Bad page size: %lu", (u_long)meta->pagesize));
 
497
 
 
498
                /*
 
499
                 * Now try to settle on a pagesize to use.
 
500
                 * If the user-supplied one is reasonable,
 
501
                 * use it;  else, guess.
 
502
                 */
 
503
                if (!IS_VALID_PAGESIZE(dbp->pgsize))
 
504
                        dbp->pgsize = __db_guesspgsize(dbenv, fhp);
 
505
        }
 
506
 
 
507
        /*
 
508
         * 25: Page type.  Must be correct for dbp->type,
 
509
         * which is by now set as well as it can be.
 
510
         */
 
511
        /* Needs no swapping--only one byte! */
 
512
        if ((dbp->type == DB_BTREE && meta->type != P_BTREEMETA) ||
 
513
            (dbp->type == DB_HASH && meta->type != P_HASHMETA) ||
 
514
            (dbp->type == DB_QUEUE && meta->type != P_QAMMETA)) {
 
515
                isbad = 1;
 
516
                EPRINT((dbp->dbenv, "Bad page type: %lu", (u_long)meta->type));
 
517
        }
 
518
 
 
519
        /*
 
520
         * 28-31: Free list page number.
 
521
         * We'll verify its sensibility when we do inter-page
 
522
         * verification later;  for now, just store it.
 
523
         */
 
524
        if (swapped)
 
525
            M_32_SWAP(meta->free);
 
526
        freelist = meta->free;
 
527
 
 
528
        /*
 
529
         * Initialize vdp->pages to fit a single pageinfo structure for
 
530
         * this one page.  We'll realloc later when we know how many
 
531
         * pages there are.
 
532
         */
 
533
        if ((ret = __db_vrfy_getpageinfo(vdp, PGNO_BASE_MD, &pip)) != 0)
 
534
                return (ret);
 
535
        pip->pgno = PGNO_BASE_MD;
 
536
        pip->type = meta->type;
 
537
 
 
538
        /*
 
539
         * Signal that we still have to check the info specific to
 
540
         * a given type of meta page.
 
541
         */
 
542
        F_SET(pip, VRFY_INCOMPLETE);
 
543
 
 
544
        pip->free = freelist;
 
545
 
 
546
        if ((ret = __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0)
 
547
                return (ret);
 
548
 
 
549
        /* Set up the dbp's fileid.  We don't use the regular open path. */
 
550
        memcpy(dbp->fileid, meta->uid, DB_FILE_ID_LEN);
 
551
 
 
552
        if (swapped == 1)
 
553
                F_SET(dbp, DB_AM_SWAP);
 
554
 
 
555
        return (isbad ? DB_VERIFY_BAD : 0);
 
556
}
 
557
 
 
558
/*
 
559
 * __db_vrfy_walkpages --
 
560
 *      Main loop of the verifier/salvager.  Walks through,
 
561
 *      page by page, and verifies all pages and/or prints all data pages.
 
562
 */
 
563
static int
 
564
__db_vrfy_walkpages(dbp, vdp, handle, callback, flags)
 
565
        DB *dbp;
 
566
        VRFY_DBINFO *vdp;
 
567
        void *handle;
 
568
        int (*callback) __P((void *, const void *));
 
569
        u_int32_t flags;
 
570
{
 
571
        DB_ENV *dbenv;
 
572
        PAGE *h;
 
573
        db_pgno_t i;
 
574
        int ret, t_ret, isbad;
 
575
 
 
576
        ret = isbad = t_ret = 0;
 
577
        dbenv = dbp->dbenv;
 
578
 
 
579
        if ((ret = __db_fchk(dbenv,
 
580
            "__db_vrfy_walkpages", flags, OKFLAGS)) != 0)
 
581
                return (ret);
 
582
 
 
583
        for (i = 0; i <= vdp->last_pgno; i++) {
 
584
                /*
 
585
                 * If DB_SALVAGE is set, we inspect our database of
 
586
                 * completed pages, and skip any we've already printed in
 
587
                 * the subdb pass.
 
588
                 */
 
589
                if (LF_ISSET(DB_SALVAGE) && (__db_salvage_isdone(vdp, i) != 0))
 
590
                        continue;
 
591
 
 
592
                /* If an individual page get fails, keep going. */
 
593
                if ((t_ret = memp_fget(dbp->mpf, &i, 0, &h)) != 0) {
 
594
                        if (ret == 0)
 
595
                                ret = t_ret;
 
596
if (t_ret) fprintf(stderr, "\tmemp_fget %d\n", i);
 
597
                        continue;
 
598
                }
 
599
 
 
600
                if (LF_ISSET(DB_SALVAGE)) {
 
601
                        /*
 
602
                         * We pretty much don't want to quit unless a
 
603
                         * bomb hits.  May as well return that something
 
604
                         * was screwy, however.
 
605
                         */
 
606
                        if ((t_ret = __db_salvage(dbp,
 
607
                            vdp, i, h, handle, callback, flags)) != 0) {
 
608
                                if (ret == 0)
 
609
                                        ret = t_ret;
 
610
                                isbad = 1;
 
611
                        }
 
612
                } else {
 
613
                        /*
 
614
                         * Verify info common to all page
 
615
                         * types.
 
616
                         */
 
617
                        if (i != PGNO_BASE_MD)
 
618
                                if ((t_ret = __db_vrfy_common(dbp,
 
619
                                    vdp, h, i, flags)) == DB_VERIFY_BAD)
 
620
                                        isbad = 1;
 
621
 
 
622
                        switch (TYPE(h)) {
 
623
                        case P_INVALID:
 
624
                                t_ret = __db_vrfy_invalid(dbp,
 
625
                                    vdp, h, i, flags);
 
626
if (t_ret) fprintf(stderr, "\tP_INVALID %d\n", i);
 
627
                                break;
 
628
                        case __P_DUPLICATE:
 
629
                                isbad = 1;
 
630
                                EPRINT((dbp->dbenv,
 
631
                                    "Old-style duplicate page: %lu",
 
632
                                    (u_long)i));
 
633
                                break;
 
634
                        case P_HASH:
 
635
                                t_ret = __ham_vrfy(dbp,
 
636
                                    vdp, h, i, flags);
 
637
if (t_ret) fprintf(stderr, "\tP_HASH %d\n", i);
 
638
                                break;
 
639
                        case P_IBTREE:
 
640
                        case P_IRECNO:
 
641
                        case P_LBTREE:
 
642
                        case P_LDUP:
 
643
                                t_ret = __bam_vrfy(dbp,
 
644
                                    vdp, h, i, flags);
 
645
                                break;
 
646
                        case P_LRECNO:
 
647
                                t_ret = __ram_vrfy_leaf(dbp,
 
648
                                    vdp, h, i, flags);
 
649
                                break;
 
650
                        case P_OVERFLOW:
 
651
                                t_ret = __db_vrfy_overflow(dbp,
 
652
                                    vdp, h, i, flags);
 
653
if (t_ret) fprintf(stderr, "\tP_OVERFLOW %d\n", i);
 
654
                                break;
 
655
                        case P_HASHMETA:
 
656
                                t_ret = __ham_vrfy_meta(dbp,
 
657
                                    vdp, (HMETA *)h, i, flags);
 
658
if (t_ret) fprintf(stderr, "\tP_HASHMETA %d\n", i);
 
659
                                break;
 
660
                        case P_BTREEMETA:
 
661
                                t_ret = __bam_vrfy_meta(dbp,
 
662
                                    vdp, (BTMETA *)h, i, flags);
 
663
                                break;
 
664
                        case P_QAMMETA:
 
665
                                t_ret = __qam_vrfy_meta(dbp,
 
666
                                    vdp, (QMETA *)h, i, flags);
 
667
                                break;
 
668
                        case P_QAMDATA:
 
669
                                t_ret = __qam_vrfy_data(dbp,
 
670
                                    vdp, (QPAGE *)h, i, flags);
 
671
                                break;
 
672
                        default:
 
673
                                EPRINT((dbp->dbenv,
 
674
                                    "Unknown page type: %lu", (u_long)TYPE(h)));
 
675
                                isbad = 1;
 
676
                                break;
 
677
                        }
 
678
 
 
679
                        /*
 
680
                         * Set up error return.
 
681
                         */
 
682
                        if (t_ret == DB_VERIFY_BAD)
 
683
                                isbad = 1;
 
684
                        else if (t_ret == DB_VERIFY_FATAL)
 
685
                                goto err;
 
686
                        else
 
687
                                ret = t_ret;
 
688
 
 
689
                        /*
 
690
                         * Provide feedback to the application about our
 
691
                         * progress.  The range 0-50% comes from the fact
 
692
                         * that this is the first of two passes through the
 
693
                         * database (front-to-back, then top-to-bottom).
 
694
                         */
 
695
                        if (dbp->db_feedback != NULL)
 
696
                                dbp->db_feedback(dbp, DB_VERIFY,
 
697
                                    (i + 1) * 50 / (vdp->last_pgno + 1));
 
698
                }
 
699
 
 
700
                if ((t_ret = memp_fput(dbp->mpf, h, 0)) != 0 && ret == 0)
 
701
                        ret = t_ret;
 
702
        }
 
703
 
 
704
        if (0) {
 
705
err:            if ((t_ret = memp_fput(dbp->mpf, h, 0)) != 0)
 
706
                        return (ret == 0 ? t_ret : ret);
 
707
                return (DB_VERIFY_BAD);
 
708
        }
 
709
 
 
710
        return ((isbad == 1 && ret == 0) ? DB_VERIFY_BAD : ret);
 
711
}
 
712
 
 
713
/*
 
714
 * __db_vrfy_structure--
 
715
 *      After a beginning-to-end walk through the database has been
 
716
 *      completed, put together the information that has been collected
 
717
 *      to verify the overall database structure.
 
718
 *
 
719
 *      Should only be called if we want to do a database verification,
 
720
 *      i.e. if DB_SALVAGE is not set.
 
721
 */
 
722
static int
 
723
__db_vrfy_structure(dbp, vdp, dbname, meta_pgno, flags)
 
724
        DB *dbp;
 
725
        VRFY_DBINFO *vdp;
 
726
        const char *dbname;
 
727
        db_pgno_t meta_pgno;
 
728
        u_int32_t flags;
 
729
{
 
730
        DB *pgset;
 
731
        DB_ENV *dbenv;
 
732
        VRFY_PAGEINFO *pip;
 
733
        db_pgno_t i;
 
734
        int ret, isbad, hassubs, p;
 
735
 
 
736
        isbad = 0;
 
737
        pip = NULL;
 
738
        dbenv = dbp->dbenv;
 
739
        pgset = vdp->pgset;
 
740
 
 
741
        if ((ret = __db_fchk(dbenv, "DB->verify", flags, OKFLAGS)) != 0)
 
742
                return (ret);
 
743
        if (LF_ISSET(DB_SALVAGE)) {
 
744
                __db_err(dbenv, "__db_vrfy_structure called with DB_SALVAGE");
 
745
                return (EINVAL);
 
746
        }
 
747
 
 
748
        /*
 
749
         * Providing feedback here is tricky;  in most situations,
 
750
         * we fetch each page one more time, but we do so in a top-down
 
751
         * order that depends on the access method.  Worse, we do this
 
752
         * recursively in btree, such that on any call where we're traversing
 
753
         * a subtree we don't know where that subtree is in the whole database;
 
754
         * worse still, any given database may be one of several subdbs.
 
755
         *
 
756
         * The solution is to decrement a counter vdp->pgs_remaining each time
 
757
         * we verify (and call feedback on) a page.  We may over- or
 
758
         * under-count, but the structure feedback function will ensure that we
 
759
         * never give a percentage under 50 or over 100.  (The first pass
 
760
         * covered the range 0-50%.)
 
761
         */
 
762
        if (dbp->db_feedback != NULL)
 
763
                vdp->pgs_remaining = vdp->last_pgno + 1;
 
764
 
 
765
        /*
 
766
         * Call the appropriate function to downwards-traverse the db type.
 
767
         */
 
768
        switch(dbp->type) {
 
769
        case DB_BTREE:
 
770
        case DB_RECNO:
 
771
                if ((ret = __bam_vrfy_structure(dbp, vdp, 0, flags)) != 0) {
 
772
                        if (ret == DB_VERIFY_BAD)
 
773
                                isbad = 1;
 
774
                        else
 
775
                                goto err;
 
776
                }
 
777
 
 
778
                /*
 
779
                 * If we have subdatabases and we know that the database is,
 
780
                 * thus far, sound, it's safe to walk the tree of subdatabases.
 
781
                 * Do so, and verify the structure of the databases within.
 
782
                 */
 
783
                if ((ret = __db_vrfy_getpageinfo(vdp, 0, &pip)) != 0)
 
784
                        goto err;
 
785
                hassubs = F_ISSET(pip, VRFY_HAS_SUBDBS) ? 1 : 0;
 
786
                if ((ret = __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0)
 
787
                        goto err;
 
788
 
 
789
                if (isbad == 0 && hassubs)
 
790
                        if ((ret =
 
791
                            __db_vrfy_subdbs(dbp, vdp, dbname, flags)) != 0) {
 
792
                                if (ret == DB_VERIFY_BAD)
 
793
                                        isbad = 1;
 
794
                                else
 
795
                                        goto err;
 
796
                        }
 
797
                break;
 
798
        case DB_HASH:
 
799
                if ((ret = __ham_vrfy_structure(dbp, vdp, 0, flags)) != 0) {
 
800
                        if (ret == DB_VERIFY_BAD)
 
801
                                isbad = 1;
 
802
                        else
 
803
                                goto err;
 
804
                }
 
805
                break;
 
806
        case DB_QUEUE:
 
807
                if ((ret = __qam_vrfy_structure(dbp, vdp, flags)) != 0) {
 
808
                        if (ret == DB_VERIFY_BAD)
 
809
                                isbad = 1;
 
810
                }
 
811
 
 
812
                /*
 
813
                 * Queue pages may be unreferenced and totally zeroed, if
 
814
                 * they're empty;  queue doesn't have much structure, so
 
815
                 * this is unlikely to be wrong in any troublesome sense.
 
816
                 * Skip to "err".
 
817
                 */
 
818
                goto err;
 
819
                /* NOTREACHED */
 
820
        default:
 
821
                /* This should only happen if the verifier is somehow broken. */
 
822
                DB_ASSERT(0);
 
823
                ret = EINVAL;
 
824
                goto err;
 
825
                /* NOTREACHED */
 
826
        }
 
827
 
 
828
        /* Walk free list. */
 
829
        if ((ret =
 
830
            __db_vrfy_freelist(dbp, vdp, meta_pgno, flags)) == DB_VERIFY_BAD)
 
831
                isbad = 1;
 
832
 
 
833
        /*
 
834
         * If structure checks up until now have failed, it's likely that
 
835
         * checking what pages have been missed will result in oodles of
 
836
         * extraneous error messages being EPRINTed.  Skip to the end
 
837
         * if this is the case;  we're going to be printing at least one
 
838
         * error anyway, and probably all the more salient ones.
 
839
         */
 
840
        if (ret != 0 || isbad == 1)
 
841
                goto err;
 
842
 
 
843
        /*
 
844
         * Make sure no page has been missed and that no page is still marked
 
845
         * "all zeroes" (only certain hash pages can be, and they're unmarked
 
846
         * in __ham_vrfy_structure).
 
847
         */
 
848
        for (i = 0; i < vdp->last_pgno + 1; i++) {
 
849
                if ((ret = __db_vrfy_getpageinfo(vdp, i, &pip)) != 0)
 
850
                        goto err;
 
851
                if ((ret = __db_vrfy_pgset_get(pgset, i, &p)) != 0)
 
852
                        goto err;
 
853
                if (p == 0) {
 
854
                        EPRINT((dbp->dbenv,
 
855
                            "Unreferenced page %lu", (u_long)i));
 
856
                        isbad = 1;
 
857
                }
 
858
 
 
859
                if (F_ISSET(pip, VRFY_IS_ALLZEROES)) {
 
860
                        EPRINT((dbp->dbenv,
 
861
                            "Totally zeroed page %lu", (u_long)i));
 
862
                        isbad = 1;
 
863
                }
 
864
                if ((ret = __db_vrfy_putpageinfo(dbenv, vdp, pip)) != 0)
 
865
                        goto err;
 
866
                pip = NULL;
 
867
        }
 
868
 
 
869
err:    if (pip != NULL)
 
870
                (void)__db_vrfy_putpageinfo(dbenv, vdp, pip);
 
871
 
 
872
        return ((isbad == 1 && ret == 0) ? DB_VERIFY_BAD : ret);
 
873
}
 
874
 
 
875
/*
 
876
 * __db_is_valid_pagetype
 
877
 */
 
878
static int
 
879
__db_is_valid_pagetype(type)
 
880
        u_int32_t type;
 
881
{
 
882
        switch (type) {
 
883
        case P_INVALID:                 /* Order matches ordinal value. */
 
884
        case P_HASH:
 
885
        case P_IBTREE:
 
886
        case P_IRECNO:
 
887
        case P_LBTREE:
 
888
        case P_LRECNO:
 
889
        case P_OVERFLOW:
 
890
        case P_HASHMETA:
 
891
        case P_BTREEMETA:
 
892
        case P_QAMMETA:
 
893
        case P_QAMDATA:
 
894
        case P_LDUP:
 
895
                return (1);
 
896
        }
 
897
        return (0);
 
898
}
 
899
 
 
900
/*
 
901
 * __db_is_valid_magicno
 
902
 */
 
903
static int
 
904
__db_is_valid_magicno(magic, typep)
 
905
        u_int32_t magic;
 
906
        DBTYPE *typep;
 
907
{
 
908
        switch (magic) {
 
909
        case DB_BTREEMAGIC:
 
910
                *typep = DB_BTREE;
 
911
                return (1);
 
912
        case DB_HASHMAGIC:
 
913
                *typep = DB_HASH;
 
914
                return (1);
 
915
        case DB_QAMMAGIC:
 
916
                *typep = DB_QUEUE;
 
917
                return (1);
 
918
        }
 
919
        *typep = DB_UNKNOWN;
 
920
        return (0);
 
921
}
 
922
 
 
923
/*
 
924
 * __db_vrfy_common --
 
925
 *      Verify info common to all page types.
 
926
 */
 
927
static int
 
928
__db_vrfy_common(dbp, vdp, h, pgno, flags)
 
929
        DB *dbp;
 
930
        VRFY_DBINFO *vdp;
 
931
        PAGE *h;
 
932
        db_pgno_t pgno;
 
933
        u_int32_t flags;
 
934
{
 
935
        VRFY_PAGEINFO *pip;
 
936
        int ret, t_ret;
 
937
        u_int8_t *p;
 
938
 
 
939
        if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
 
940
                return (ret);
 
941
 
 
942
        pip->pgno = pgno;
 
943
        F_CLR(pip, VRFY_IS_ALLZEROES);
 
944
 
 
945
        /*
 
946
         * Hash expands the table by leaving some pages between the
 
947
         * old last and the new last totally zeroed.  Its pgin function
 
948
         * should fix things, but we might not be using that (e.g. if
 
949
         * we're a subdatabase).
 
950
         *
 
951
         * Queue will create sparse files if sparse record numbers are used.
 
952
         */
 
953
        if (pgno != 0 && PGNO(h) == 0) {
 
954
                for (p = (u_int8_t *)h; p < (u_int8_t *)h + dbp->pgsize; p++)
 
955
                        if (*p != 0) {
 
956
                                EPRINT((dbp->dbenv,
 
957
                                    "Page %lu should be zeroed and is not",
 
958
                                    (u_long)pgno));
 
959
                                ret = DB_VERIFY_BAD;
 
960
                                goto err;
 
961
                        }
 
962
                /*
 
963
                 * It's totally zeroed;  mark it as a hash, and we'll
 
964
                 * check that that makes sense structurally later.
 
965
                 * (The queue verification doesn't care, since queues
 
966
                 * don't really have much in the way of structure.)
 
967
                 */
 
968
                pip->type = P_HASH;
 
969
                F_SET(pip, VRFY_IS_ALLZEROES);
 
970
                ret = 0;
 
971
                goto err;       /* well, not really an err. */
 
972
        }
 
973
 
 
974
        if (PGNO(h) != pgno) {
 
975
                EPRINT((dbp->dbenv,
 
976
                    "Bad page number: %lu should be %lu",
 
977
                    (u_long)h->pgno, (u_long)pgno));
 
978
                ret = DB_VERIFY_BAD;
 
979
        }
 
980
 
 
981
        if (!__db_is_valid_pagetype(h->type)) {
 
982
                EPRINT((dbp->dbenv, "Bad page type: %lu", (u_long)h->type));
 
983
                ret = DB_VERIFY_BAD;
 
984
        }
 
985
        pip->type = h->type;
 
986
 
 
987
err:    if ((t_ret =
 
988
            __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 && ret == 0)
 
989
                ret = t_ret;
 
990
 
 
991
        return (ret);
 
992
}
 
993
 
 
994
/*
 
995
 * __db_vrfy_invalid --
 
996
 *      Verify P_INVALID page.
 
997
 *      (Yes, there's not much to do here.)
 
998
 */
 
999
static int
 
1000
__db_vrfy_invalid(dbp, vdp, h, pgno, flags)
 
1001
        DB *dbp;
 
1002
        VRFY_DBINFO *vdp;
 
1003
        PAGE *h;
 
1004
        db_pgno_t pgno;
 
1005
        u_int32_t flags;
 
1006
{
 
1007
        VRFY_PAGEINFO *pip;
 
1008
        int ret, t_ret;
 
1009
 
 
1010
        if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
 
1011
                return (ret);
 
1012
        pip->next_pgno = pip->prev_pgno = 0;
 
1013
 
 
1014
        if (!IS_VALID_PGNO(NEXT_PGNO(h))) {
 
1015
                EPRINT((dbp->dbenv,
 
1016
                    "Invalid next_pgno %lu on page %lu",
 
1017
                    (u_long)NEXT_PGNO(h), (u_long)pgno));
 
1018
                ret = DB_VERIFY_BAD;
 
1019
        } else
 
1020
                pip->next_pgno = NEXT_PGNO(h);
 
1021
 
 
1022
        if ((t_ret =
 
1023
            __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 && ret == 0)
 
1024
                ret = t_ret;
 
1025
        return (ret);
 
1026
}
 
1027
 
 
1028
/*
 
1029
 * __db_vrfy_datapage --
 
1030
 *      Verify elements common to data pages (P_HASH, P_LBTREE,
 
1031
 *      P_IBTREE, P_IRECNO, P_LRECNO, P_OVERFLOW, P_DUPLICATE)--i.e.,
 
1032
 *      those defined in the PAGE structure.
 
1033
 *
 
1034
 *      Called from each of the per-page routines, after the
 
1035
 *      all-page-type-common elements of pip have been verified and filled
 
1036
 *      in.
 
1037
 *
 
1038
 * PUBLIC: int __db_vrfy_datapage
 
1039
 * PUBLIC:     __P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t, u_int32_t));
 
1040
 */
 
1041
int
 
1042
__db_vrfy_datapage(dbp, vdp, h, pgno, flags)
 
1043
        DB *dbp;
 
1044
        VRFY_DBINFO *vdp;
 
1045
        PAGE *h;
 
1046
        db_pgno_t pgno;
 
1047
        u_int32_t flags;
 
1048
{
 
1049
        VRFY_PAGEINFO *pip;
 
1050
        int isbad, ret, t_ret;
 
1051
 
 
1052
        if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
 
1053
                return (ret);
 
1054
        isbad = 0;
 
1055
 
 
1056
        /*
 
1057
         * prev_pgno and next_pgno:  store for inter-page checks,
 
1058
         * verify that they point to actual pages and not to self.
 
1059
         *
 
1060
         * !!!
 
1061
         * Internal btree pages do not maintain these fields (indeed,
 
1062
         * they overload them).  Skip.
 
1063
         */
 
1064
        if (TYPE(h) != P_IBTREE && TYPE(h) != P_IRECNO) {
 
1065
                if (!IS_VALID_PGNO(PREV_PGNO(h)) || PREV_PGNO(h) == pip->pgno) {
 
1066
                        isbad = 1;
 
1067
                        EPRINT((dbp->dbenv, "Page %lu: Invalid prev_pgno %lu",
 
1068
                            (u_long)pip->pgno, (u_long)PREV_PGNO(h)));
 
1069
                }
 
1070
                if (!IS_VALID_PGNO(NEXT_PGNO(h)) || NEXT_PGNO(h) == pip->pgno) {
 
1071
                        isbad = 1;
 
1072
                        EPRINT((dbp->dbenv, "Page %lu: Invalid next_pgno %lu",
 
1073
                            (u_long)pip->pgno, (u_long)NEXT_PGNO(h)));
 
1074
                }
 
1075
                pip->prev_pgno = PREV_PGNO(h);
 
1076
                pip->next_pgno = NEXT_PGNO(h);
 
1077
        }
 
1078
 
 
1079
        /*
 
1080
         * Verify the number of entries on the page.
 
1081
         * There is no good way to determine if this is accurate;  the
 
1082
         * best we can do is verify that it's not more than can, in theory,
 
1083
         * fit on the page.  Then, we make sure there are at least
 
1084
         * this many valid elements in inp[], and hope that this catches
 
1085
         * most cases.
 
1086
         */
 
1087
        if (TYPE(h) != P_OVERFLOW) {
 
1088
                if (BKEYDATA_PSIZE(0) * NUM_ENT(h) > dbp->pgsize) {
 
1089
                        isbad = 1;
 
1090
                        EPRINT((dbp->dbenv,
 
1091
                            "Page %lu: Too many entries: %lu",
 
1092
                            (u_long)pgno, (u_long)NUM_ENT(h)));
 
1093
                }
 
1094
                pip->entries = NUM_ENT(h);
 
1095
        }
 
1096
 
 
1097
        /*
 
1098
         * btree level.  Should be zero unless we're a btree;
 
1099
         * if we are a btree, should be between LEAFLEVEL and MAXBTREELEVEL,
 
1100
         * and we need to save it off.
 
1101
         */
 
1102
        switch (TYPE(h)) {
 
1103
        case P_IBTREE:
 
1104
        case P_IRECNO:
 
1105
                if (LEVEL(h) < LEAFLEVEL + 1 || LEVEL(h) > MAXBTREELEVEL) {
 
1106
                        isbad = 1;
 
1107
                        EPRINT((dbp->dbenv, "Bad btree level %lu on page %lu",
 
1108
                            (u_long)LEVEL(h), (u_long)pgno));
 
1109
                }
 
1110
                pip->bt_level = LEVEL(h);
 
1111
                break;
 
1112
        case P_LBTREE:
 
1113
        case P_LDUP:
 
1114
        case P_LRECNO:
 
1115
                if (LEVEL(h) != LEAFLEVEL) {
 
1116
                        isbad = 1;
 
1117
                        EPRINT((dbp->dbenv,
 
1118
                            "Btree leaf page %lu has incorrect level %lu",
 
1119
                            (u_long)pgno, (u_long)LEVEL(h)));
 
1120
                }
 
1121
                break;
 
1122
        default:
 
1123
                if (LEVEL(h) != 0) {
 
1124
                        isbad = 1;
 
1125
                        EPRINT((dbp->dbenv,
 
1126
                            "Nonzero level %lu in non-btree database page %lu",
 
1127
                            (u_long)LEVEL(h), (u_long)pgno));
 
1128
                }
 
1129
                break;
 
1130
        }
 
1131
 
 
1132
        /*
 
1133
         * Even though inp[] occurs in all PAGEs, we look at it in the
 
1134
         * access-method-specific code, since btree and hash treat
 
1135
         * item lengths very differently, and one of the most important
 
1136
         * things we want to verify is that the data--as specified
 
1137
         * by offset and length--cover the right part of the page
 
1138
         * without overlaps, gaps, or violations of the page boundary.
 
1139
         */
 
1140
        if ((t_ret =
 
1141
            __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 && ret == 0)
 
1142
                ret = t_ret;
 
1143
 
 
1144
        return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
 
1145
}
 
1146
 
 
1147
/*
 
1148
 * __db_vrfy_meta--
 
1149
 *      Verify the access-method common parts of a meta page, using
 
1150
 *      normal mpool routines.
 
1151
 *
 
1152
 * PUBLIC: int __db_vrfy_meta
 
1153
 * PUBLIC:     __P((DB *, VRFY_DBINFO *, DBMETA *, db_pgno_t, u_int32_t));
 
1154
 */
 
1155
int
 
1156
__db_vrfy_meta(dbp, vdp, meta, pgno, flags)
 
1157
        DB *dbp;
 
1158
        VRFY_DBINFO *vdp;
 
1159
        DBMETA *meta;
 
1160
        db_pgno_t pgno;
 
1161
        u_int32_t flags;
 
1162
{
 
1163
        DBTYPE dbtype, magtype;
 
1164
        VRFY_PAGEINFO *pip;
 
1165
        int isbad, ret, t_ret;
 
1166
 
 
1167
        isbad = 0;
 
1168
        if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
 
1169
                return (ret);
 
1170
 
 
1171
        /* type plausible for a meta page */
 
1172
        switch (meta->type) {
 
1173
        case P_BTREEMETA:
 
1174
                dbtype = DB_BTREE;
 
1175
                break;
 
1176
        case P_HASHMETA:
 
1177
                dbtype = DB_HASH;
 
1178
                break;
 
1179
        case P_QAMMETA:
 
1180
                dbtype = DB_QUEUE;
 
1181
                break;
 
1182
        default:
 
1183
                /* The verifier should never let us get here. */
 
1184
                DB_ASSERT(0);
 
1185
                ret = EINVAL;
 
1186
                goto err;
 
1187
        }
 
1188
 
 
1189
        /* magic number valid */
 
1190
        if (!__db_is_valid_magicno(meta->magic, &magtype)) {
 
1191
                isbad = 1;
 
1192
                EPRINT((dbp->dbenv,
 
1193
                    "Magic number invalid on page %lu", (u_long)pgno));
 
1194
        }
 
1195
        if (magtype != dbtype) {
 
1196
                isbad = 1;
 
1197
                EPRINT((dbp->dbenv,
 
1198
                    "Magic number does not match type of page %lu",
 
1199
                    (u_long)pgno));
 
1200
        }
 
1201
 
 
1202
        /* version */
 
1203
        if ((dbtype == DB_BTREE && meta->version != DB_BTREEVERSION) ||
 
1204
            (dbtype == DB_HASH && meta->version != DB_HASHVERSION) ||
 
1205
            (dbtype == DB_QUEUE && meta->version != DB_QAMVERSION)) {
 
1206
                isbad = 1;
 
1207
                EPRINT((dbp->dbenv, "%s%s", "Old of incorrect DB ",
 
1208
                    "version; extraneous errors may result"));
 
1209
        }
 
1210
 
 
1211
        /* pagesize */
 
1212
        if (meta->pagesize != dbp->pgsize) {
 
1213
                isbad = 1;
 
1214
                EPRINT((dbp->dbenv,
 
1215
                    "Invalid pagesize %lu on page %lu",
 
1216
                    (u_long)meta->pagesize, (u_long)pgno));
 
1217
        }
 
1218
 
 
1219
        /* free list */
 
1220
        /*
 
1221
         * If this is not the main, master-database meta page, it
 
1222
         * should not have a free list.
 
1223
         */
 
1224
        if (pgno != PGNO_BASE_MD && meta->free != PGNO_INVALID) {
 
1225
                isbad = 1;
 
1226
                EPRINT((dbp->dbenv,
 
1227
                    "Nonempty free list on subdatabase metadata page %lu",
 
1228
                    pgno));
 
1229
        }
 
1230
 
 
1231
        /* Can correctly be PGNO_INVALID--that's just the end of the list. */
 
1232
        if (meta->free != PGNO_INVALID && IS_VALID_PGNO(meta->free))
 
1233
                pip->free = meta->free;
 
1234
        else if (!IS_VALID_PGNO(meta->free)) {
 
1235
                isbad = 1;
 
1236
                EPRINT((dbp->dbenv,
 
1237
                    "Nonsensical free list pgno %lu on page %lu",
 
1238
                    (u_long)meta->free, (u_long)pgno));
 
1239
        }
 
1240
 
 
1241
        /*
 
1242
         * We have now verified the common fields of the metadata page.
 
1243
         * Clear the flag that told us they had been incompletely checked.
 
1244
         */
 
1245
        F_CLR(pip, VRFY_INCOMPLETE);
 
1246
 
 
1247
err:    if ((t_ret =
 
1248
            __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 && ret == 0)
 
1249
                ret = t_ret;
 
1250
 
 
1251
        return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
 
1252
}
 
1253
 
 
1254
/*
 
1255
 * __db_vrfy_freelist --
 
1256
 *      Walk free list, checking off pages and verifying absence of
 
1257
 *      loops.
 
1258
 */
 
1259
static int
 
1260
__db_vrfy_freelist(dbp, vdp, meta, flags)
 
1261
        DB *dbp;
 
1262
        VRFY_DBINFO *vdp;
 
1263
        db_pgno_t meta;
 
1264
        u_int32_t flags;
 
1265
{
 
1266
        DB *pgset;
 
1267
        VRFY_PAGEINFO *pip;
 
1268
        db_pgno_t pgno;
 
1269
        int p, ret, t_ret;
 
1270
 
 
1271
        pgset = vdp->pgset;
 
1272
        DB_ASSERT(pgset != NULL);
 
1273
 
 
1274
        if ((ret = __db_vrfy_getpageinfo(vdp, meta, &pip)) != 0)
 
1275
                return (ret);
 
1276
        for (pgno = pip->free; pgno != PGNO_INVALID; pgno = pip->next_pgno) {
 
1277
                if ((ret = __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0)
 
1278
                        return (ret);
 
1279
 
 
1280
                /* This shouldn't happen, but just in case. */
 
1281
                if (!IS_VALID_PGNO(pgno)) {
 
1282
                        EPRINT((dbp->dbenv,
 
1283
                            "Invalid next_pgno on free list page %lu",
 
1284
                            (u_long)pgno));
 
1285
                        return (DB_VERIFY_BAD);
 
1286
                }
 
1287
 
 
1288
                /* Detect cycles. */
 
1289
                if ((ret = __db_vrfy_pgset_get(pgset, pgno, &p)) != 0)
 
1290
                        return (ret);
 
1291
                if (p != 0) {
 
1292
                        EPRINT((dbp->dbenv,
 
1293
                            "Page %lu encountered a second time on free list",
 
1294
                            (u_long)pgno));
 
1295
                        return (DB_VERIFY_BAD);
 
1296
                }
 
1297
                if ((ret = __db_vrfy_pgset_inc(pgset, pgno)) != 0)
 
1298
                        return (ret);
 
1299
 
 
1300
                if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
 
1301
                        return (ret);
 
1302
 
 
1303
                if (pip->type != P_INVALID) {
 
1304
                        EPRINT((dbp->dbenv,
 
1305
                            "Non-invalid page %lu on free list", (u_long)pgno));
 
1306
                        ret = DB_VERIFY_BAD;      /* unsafe to continue */
 
1307
                        break;
 
1308
                }
 
1309
        }
 
1310
 
 
1311
        if ((t_ret = __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0)
 
1312
                ret = t_ret;
 
1313
        return (ret);
 
1314
}
 
1315
 
 
1316
/*
 
1317
 * __db_vrfy_subdbs --
 
1318
 *      Walk the known-safe master database of subdbs with a cursor,
 
1319
 *      verifying the structure of each subdatabase we encounter.
 
1320
 */
 
1321
static int
 
1322
__db_vrfy_subdbs(dbp, vdp, dbname, flags)
 
1323
        DB *dbp;
 
1324
        VRFY_DBINFO *vdp;
 
1325
        const char *dbname;
 
1326
        u_int32_t flags;
 
1327
{
 
1328
        DB *mdbp;
 
1329
        DBC *dbc;
 
1330
        DBT key, data;
 
1331
        VRFY_PAGEINFO *pip;
 
1332
        db_pgno_t meta_pgno;
 
1333
        int ret, t_ret, isbad;
 
1334
        u_int8_t type;
 
1335
 
 
1336
        isbad = 0;
 
1337
        dbc = NULL;
 
1338
 
 
1339
        if ((ret = __db_master_open(dbp, dbname, DB_RDONLY, 0, &mdbp)) != 0)
 
1340
                return (ret);
 
1341
 
 
1342
        if ((ret = __db_icursor(mdbp,
 
1343
            NULL, DB_BTREE, PGNO_INVALID, 0, DB_LOCK_INVALIDID, &dbc)) != 0)
 
1344
                goto err;
 
1345
 
 
1346
        memset(&key, 0, sizeof(key));
 
1347
        memset(&data, 0, sizeof(data));
 
1348
        while ((ret = dbc->c_get(dbc, &key, &data, DB_NEXT)) == 0) {
 
1349
                if (data.size != sizeof(db_pgno_t)) {
 
1350
                        EPRINT((dbp->dbenv, "Database entry of invalid size"));
 
1351
                        isbad = 1;
 
1352
                        goto err;
 
1353
                }
 
1354
                memcpy(&meta_pgno, data.data, data.size);
 
1355
                /*
 
1356
                 * Subdatabase meta pgnos are stored in network byte
 
1357
                 * order for cross-endian compatibility.  Swap if appropriate.
 
1358
                 */
 
1359
                DB_NTOHL(&meta_pgno);
 
1360
                if (meta_pgno == PGNO_INVALID || meta_pgno > vdp->last_pgno) {
 
1361
                        EPRINT((dbp->dbenv,
 
1362
                            "Database entry references invalid page %lu",
 
1363
                            (u_long)meta_pgno));
 
1364
                        isbad = 1;
 
1365
                        goto err;
 
1366
                }
 
1367
                if ((ret = __db_vrfy_getpageinfo(vdp, meta_pgno, &pip)) != 0)
 
1368
                        goto err;
 
1369
                type = pip->type;
 
1370
                if ((ret = __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0)
 
1371
                        goto err;
 
1372
                switch (type) {
 
1373
                case P_BTREEMETA:
 
1374
                        if ((ret = __bam_vrfy_structure(
 
1375
                            dbp, vdp, meta_pgno, flags)) != 0) {
 
1376
                                if (ret == DB_VERIFY_BAD)
 
1377
                                        isbad = 1;
 
1378
                                else
 
1379
                                        goto err;
 
1380
                        }
 
1381
                        break;
 
1382
                case P_HASHMETA:
 
1383
                        if ((ret = __ham_vrfy_structure(
 
1384
                            dbp, vdp, meta_pgno, flags)) != 0) {
 
1385
                                if (ret == DB_VERIFY_BAD)
 
1386
                                        isbad = 1;
 
1387
                                else
 
1388
                                        goto err;
 
1389
                        }
 
1390
                        break;
 
1391
                case P_QAMMETA:
 
1392
                default:
 
1393
                        EPRINT((dbp->dbenv,
 
1394
            "Database entry references page %lu of invalid type %lu",
 
1395
                            (u_long)meta_pgno, (u_long)type));
 
1396
                        ret = DB_VERIFY_BAD;
 
1397
                        goto err;
 
1398
                        /* NOTREACHED */
 
1399
                }
 
1400
        }
 
1401
 
 
1402
        if (ret == DB_NOTFOUND)
 
1403
                ret = 0;
 
1404
 
 
1405
err:    if (dbc != NULL && (t_ret = __db_c_close(dbc)) != 0 && ret == 0)
 
1406
                ret = t_ret;
 
1407
 
 
1408
        if ((t_ret = mdbp->close(mdbp, 0)) != 0 && ret == 0)
 
1409
                ret = t_ret;
 
1410
 
 
1411
        return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
 
1412
}
 
1413
 
 
1414
/*
 
1415
 * __db_vrfy_struct_feedback --
 
1416
 *      Provide feedback during top-down database structure traversal.
 
1417
 *      (See comment at the beginning of __db_vrfy_structure.)
 
1418
 *
 
1419
 * PUBLIC: void __db_vrfy_struct_feedback __P((DB *, VRFY_DBINFO *));
 
1420
 */
 
1421
void
 
1422
__db_vrfy_struct_feedback(dbp, vdp)
 
1423
        DB *dbp;
 
1424
        VRFY_DBINFO *vdp;
 
1425
{
 
1426
        int progress;
 
1427
 
 
1428
        if (dbp->db_feedback == NULL)
 
1429
                return;
 
1430
 
 
1431
        if (vdp->pgs_remaining > 0)
 
1432
                vdp->pgs_remaining--;
 
1433
 
 
1434
        /* Don't allow a feedback call of 100 until we're really done. */
 
1435
        progress = 100 - (vdp->pgs_remaining * 50 / (vdp->last_pgno + 1));
 
1436
        dbp->db_feedback(dbp, DB_VERIFY, progress == 100 ? 99 : progress);
 
1437
}
 
1438
 
 
1439
/*
 
1440
 * __db_vrfy_orderchkonly --
 
1441
 *      Do an sort-order/hashing check on a known-otherwise-good subdb.
 
1442
 */
 
1443
static int
 
1444
__db_vrfy_orderchkonly(dbp, vdp, name, subdb, flags)
 
1445
        DB *dbp;
 
1446
        VRFY_DBINFO *vdp;
 
1447
        const char *name, *subdb;
 
1448
        u_int32_t flags;
 
1449
{
 
1450
        BTMETA *btmeta;
 
1451
        DB *mdbp, *pgset;
 
1452
        DBC *pgsc;
 
1453
        DBT key, data;
 
1454
        HASH *h_internal;
 
1455
        HMETA *hmeta;
 
1456
        PAGE *h, *currpg;
 
1457
        db_pgno_t meta_pgno, p, pgno;
 
1458
        u_int32_t bucket;
 
1459
        int t_ret, ret;
 
1460
 
 
1461
        currpg = h = NULL;
 
1462
        pgsc = NULL;
 
1463
        pgset = NULL;
 
1464
 
 
1465
        LF_CLR(DB_NOORDERCHK);
 
1466
 
 
1467
        /* Open the master database and get the meta_pgno for the subdb. */
 
1468
        if ((ret = db_create(&mdbp, NULL, 0)) != 0)
 
1469
                return (ret);
 
1470
        if ((ret = __db_master_open(dbp, name, DB_RDONLY, 0, &mdbp)) != 0)
 
1471
                goto err;
 
1472
 
 
1473
        memset(&key, 0, sizeof(key));
 
1474
        key.data = (void *)subdb;
 
1475
        memset(&data, 0, sizeof(data));
 
1476
        if ((ret = dbp->get(dbp, NULL, &key, &data, 0)) != 0)
 
1477
                goto err;
 
1478
 
 
1479
        if (data.size != sizeof(db_pgno_t)) {
 
1480
                EPRINT((dbp->dbenv, "Database entry of invalid size"));
 
1481
                ret = DB_VERIFY_BAD;
 
1482
                goto err;
 
1483
        }
 
1484
 
 
1485
        memcpy(&meta_pgno, data.data, data.size);
 
1486
 
 
1487
        if ((ret = memp_fget(dbp->mpf, &meta_pgno, 0, &h)) != 0)
 
1488
                goto err;
 
1489
 
 
1490
        if ((ret = __db_vrfy_pgset(dbp->dbenv, dbp->pgsize, &pgset)) != 0)
 
1491
                goto err;
 
1492
 
 
1493
        switch (TYPE(h)) {
 
1494
        case P_BTREEMETA:
 
1495
                btmeta = (BTMETA *)h;
 
1496
                if (F_ISSET(&btmeta->dbmeta, BTM_RECNO)) {
 
1497
                        /* Recnos have no order to check. */
 
1498
                        ret = 0;
 
1499
                        goto err;
 
1500
                }
 
1501
                if ((ret =
 
1502
                    __db_meta2pgset(dbp, vdp, meta_pgno, flags, pgset)) != 0)
 
1503
                        goto err;
 
1504
                if ((ret = pgset->cursor(pgset, NULL, &pgsc, 0)) != 0)
 
1505
                        goto err;
 
1506
                while ((ret = __db_vrfy_pgset_next(pgsc, &p)) == 0) {
 
1507
                        if ((ret = memp_fget(dbp->mpf, &p, 0, &currpg)) != 0)
 
1508
                                goto err;
 
1509
                        if ((ret = __bam_vrfy_itemorder(dbp,
 
1510
                            NULL, currpg, p, NUM_ENT(currpg), 1,
 
1511
                            F_ISSET(&btmeta->dbmeta, BTM_DUP), flags)) != 0)
 
1512
                                goto err;
 
1513
                        if ((ret = memp_fput(dbp->mpf, currpg, 0)) != 0)
 
1514
                                goto err;
 
1515
                        currpg = NULL;
 
1516
                }
 
1517
                if ((ret = pgsc->c_close(pgsc)) != 0)
 
1518
                        goto err;
 
1519
                break;
 
1520
        case P_HASHMETA:
 
1521
                hmeta = (HMETA *)h;
 
1522
                h_internal = (HASH *)dbp->h_internal;
 
1523
                /*
 
1524
                 * Make sure h_charkey is right.
 
1525
                 */
 
1526
                if (h_internal == NULL || h_internal->h_hash == NULL) {
 
1527
                        EPRINT((dbp->dbenv,
 
1528
                    "DB_ORDERCHKONLY requires that a hash function be set"));
 
1529
                        ret = DB_VERIFY_BAD;
 
1530
                        goto err;
 
1531
                }
 
1532
                if (hmeta->h_charkey !=
 
1533
                    h_internal->h_hash(dbp, CHARKEY, sizeof(CHARKEY))) {
 
1534
                        EPRINT((dbp->dbenv,
 
1535
                            "Incorrect hash function for database"));
 
1536
                        ret = DB_VERIFY_BAD;
 
1537
                        goto err;
 
1538
                }
 
1539
 
 
1540
                /*
 
1541
                 * Foreach bucket, verify hashing on each page in the
 
1542
                 * corresponding chain of pages.
 
1543
                 */
 
1544
                for (bucket = 0; bucket <= hmeta->max_bucket; bucket++) {
 
1545
                        pgno = BS_TO_PAGE(bucket, hmeta->spares);
 
1546
                        while (pgno != PGNO_INVALID) {
 
1547
                                if ((ret = memp_fget(dbp->mpf,
 
1548
                                    &pgno, 0, &currpg)) != 0)
 
1549
                                        goto err;
 
1550
                                if ((ret = __ham_vrfy_hashing(dbp,
 
1551
                                    NUM_ENT(currpg),hmeta, bucket, pgno,
 
1552
                                    flags, h_internal->h_hash)) != 0)
 
1553
                                        goto err;
 
1554
                                pgno = NEXT_PGNO(currpg);
 
1555
                                if ((ret = memp_fput(dbp->mpf, currpg, 0)) != 0)
 
1556
                                        goto err;
 
1557
                                currpg = NULL;
 
1558
                        }
 
1559
                }
 
1560
                break;
 
1561
        default:
 
1562
                EPRINT((dbp->dbenv, "Database meta page %lu of bad type %lu",
 
1563
                    (u_long)meta_pgno, (u_long)TYPE(h)));
 
1564
                ret = DB_VERIFY_BAD;
 
1565
                break;
 
1566
        }
 
1567
 
 
1568
err:    if (pgsc != NULL)
 
1569
                (void)pgsc->c_close(pgsc);
 
1570
        if (pgset != NULL)
 
1571
                (void)pgset->close(pgset, 0);
 
1572
        if (h != NULL && (t_ret = memp_fput(dbp->mpf, h, 0)) != 0)
 
1573
                ret = t_ret;
 
1574
        if (currpg != NULL && (t_ret = memp_fput(dbp->mpf, currpg, 0)) != 0)
 
1575
                ret = t_ret;
 
1576
        if ((t_ret = mdbp->close(mdbp, 0)) != 0)
 
1577
                ret = t_ret;
 
1578
        return (ret);
 
1579
}
 
1580
 
 
1581
/*
 
1582
 * __db_salvage --
 
1583
 *      Walk through a page, salvaging all likely or plausible (w/
 
1584
 *      DB_AGGRESSIVE) key/data pairs.
 
1585
 */
 
1586
static int
 
1587
__db_salvage(dbp, vdp, pgno, h, handle, callback, flags)
 
1588
        DB *dbp;
 
1589
        VRFY_DBINFO *vdp;
 
1590
        db_pgno_t pgno;
 
1591
        PAGE *h;
 
1592
        void *handle;
 
1593
        int (*callback) __P((void *, const void *));
 
1594
        u_int32_t flags;
 
1595
{
 
1596
        DB_ASSERT(LF_ISSET(DB_SALVAGE));
 
1597
 
 
1598
        /* If we got this page in the subdb pass, we can safely skip it. */
 
1599
        if (__db_salvage_isdone(vdp, pgno))
 
1600
                return (0);
 
1601
 
 
1602
        switch (TYPE(h)) {
 
1603
        case P_HASH:
 
1604
                return (__ham_salvage(dbp,
 
1605
                    vdp, pgno, h, handle, callback, flags));
 
1606
                /* NOTREACHED */
 
1607
        case P_LBTREE:
 
1608
                return (__bam_salvage(dbp,
 
1609
                    vdp, pgno, P_LBTREE, h, handle, callback, NULL, flags));
 
1610
                /* NOTREACHED */
 
1611
        case P_LDUP:
 
1612
                return (__db_salvage_markneeded(vdp, pgno, SALVAGE_LDUP));
 
1613
                /* NOTREACHED */
 
1614
        case P_OVERFLOW:
 
1615
                return (__db_salvage_markneeded(vdp, pgno, SALVAGE_OVERFLOW));
 
1616
                /* NOTREACHED */
 
1617
        case P_LRECNO:
 
1618
                /*
 
1619
                 * Recnos are tricky -- they may represent dup pages, or
 
1620
                 * they may be subdatabase/regular database pages in their
 
1621
                 * own right.  If the former, they need to be printed with a
 
1622
                 * key, preferably when we hit the corresponding datum in
 
1623
                 * a btree/hash page.  If the latter, there is no key.
 
1624
                 *
 
1625
                 * If a database is sufficiently frotzed, we're not going
 
1626
                 * to be able to get this right, so we best-guess:  just
 
1627
                 * mark it needed now, and if we're really a normal recno
 
1628
                 * database page, the "unknowns" pass will pick us up.
 
1629
                 */
 
1630
                return (__db_salvage_markneeded(vdp, pgno, SALVAGE_LRECNO));
 
1631
                /* NOTREACHED */
 
1632
        case P_IBTREE:
 
1633
        case P_INVALID:
 
1634
        case P_IRECNO:
 
1635
        case __P_DUPLICATE:
 
1636
        default:
 
1637
                /* XXX: Should we be more aggressive here? */
 
1638
                break;
 
1639
        }
 
1640
        return (0);
 
1641
}
 
1642
 
 
1643
/*
 
1644
 * __db_salvage_unknowns --
 
1645
 *      Walk through the salvager database, printing with key "UNKNOWN"
 
1646
 *      any pages we haven't dealt with.
 
1647
 */
 
1648
static int
 
1649
__db_salvage_unknowns(dbp, vdp, handle, callback, flags)
 
1650
        DB *dbp;
 
1651
        VRFY_DBINFO *vdp;
 
1652
        void *handle;
 
1653
        int (*callback) __P((void *, const void *));
 
1654
        u_int32_t flags;
 
1655
{
 
1656
        DBT unkdbt, key, *dbt;
 
1657
        PAGE *h;
 
1658
        db_pgno_t pgno;
 
1659
        u_int32_t pgtype;
 
1660
        int ret, err_ret;
 
1661
        void *ovflbuf;
 
1662
 
 
1663
        memset(&unkdbt, 0, sizeof(DBT));
 
1664
        unkdbt.size = strlen("UNKNOWN") + 1;
 
1665
        unkdbt.data = "UNKNOWN";
 
1666
 
 
1667
        if ((ret = __os_malloc(dbp->dbenv, dbp->pgsize, &ovflbuf)) != 0)
 
1668
                return (ret);
 
1669
 
 
1670
        err_ret = 0;
 
1671
        while ((ret = __db_salvage_getnext(vdp, &pgno, &pgtype)) == 0) {
 
1672
                dbt = NULL;
 
1673
 
 
1674
                if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0) {
 
1675
                        err_ret = ret;
 
1676
                        continue;
 
1677
                }
 
1678
 
 
1679
                switch (pgtype) {
 
1680
                case SALVAGE_LDUP:
 
1681
                case SALVAGE_LRECNODUP:
 
1682
                        dbt = &unkdbt;
 
1683
                        /* FALLTHROUGH */
 
1684
                case SALVAGE_LBTREE:
 
1685
                case SALVAGE_LRECNO:
 
1686
                        if ((ret = __bam_salvage(dbp, vdp, pgno, pgtype,
 
1687
                            h, handle, callback, dbt, flags)) != 0)
 
1688
                                err_ret = ret;
 
1689
                        break;
 
1690
                case SALVAGE_OVERFLOW:
 
1691
                        /*
 
1692
                         * XXX:
 
1693
                         * This may generate multiple "UNKNOWN" keys in
 
1694
                         * a database with no dups.  What to do?
 
1695
                         */
 
1696
                        if ((ret = __db_safe_goff(dbp,
 
1697
                            vdp, pgno, &key, &ovflbuf, flags)) != 0) {
 
1698
                                err_ret = ret;
 
1699
                                continue;
 
1700
                        }
 
1701
                        if ((ret = __db_prdbt(&key,
 
1702
                            0, " ", handle, callback, 0, NULL)) != 0) {
 
1703
                                err_ret = ret;
 
1704
                                continue;
 
1705
                        }
 
1706
                        if ((ret = __db_prdbt(&unkdbt,
 
1707
                                0, " ", handle, callback, 0, NULL)) != 0)
 
1708
                                err_ret = ret;
 
1709
                        break;
 
1710
                case SALVAGE_HASH:
 
1711
                        if ((ret = __ham_salvage(
 
1712
                            dbp, vdp, pgno, h, handle, callback, flags)) != 0)
 
1713
                                err_ret = ret;
 
1714
                        break;
 
1715
                case SALVAGE_INVALID:
 
1716
                case SALVAGE_IGNORE:
 
1717
                default:
 
1718
                        /*
 
1719
                         * Shouldn't happen, but if it does, just do what the
 
1720
                         * nice man says.
 
1721
                         */
 
1722
                        DB_ASSERT(0);
 
1723
                        break;
 
1724
                }
 
1725
                if ((ret = memp_fput(dbp->mpf, h, 0)) != 0)
 
1726
                        err_ret = ret;
 
1727
        }
 
1728
 
 
1729
        __os_free(dbp->dbenv, ovflbuf, 0);
 
1730
 
 
1731
        if (err_ret != 0 && ret == 0)
 
1732
                ret = err_ret;
 
1733
 
 
1734
        return (ret == DB_NOTFOUND ? 0 : ret);
 
1735
}
 
1736
 
 
1737
/*
 
1738
 * Offset of the ith inp array entry, which we can compare to the offset
 
1739
 * the entry stores.
 
1740
 */
 
1741
#define INP_OFFSET(h, i)        \
 
1742
    ((db_indx_t)((u_int8_t *)(h)->inp + (i) - (u_int8_t *)(h)))
 
1743
 
 
1744
/*
 
1745
 * __db_vrfy_inpitem --
 
1746
 *      Verify that a single entry in the inp array is sane, and update
 
1747
 *      the high water mark and current item offset.  (The former of these is
 
1748
 *      used for state information between calls, and is required;  it must
 
1749
 *      be initialized to the pagesize before the first call.)
 
1750
 *
 
1751
 *      Returns DB_VERIFY_FATAL if inp has collided with the data,
 
1752
 *      since verification can't continue from there;  returns DB_VERIFY_BAD
 
1753
 *      if anything else is wrong.
 
1754
 *
 
1755
 * PUBLIC: int __db_vrfy_inpitem __P((DB *, PAGE *,
 
1756
 * PUBLIC:     db_pgno_t, u_int32_t, int, u_int32_t, u_int32_t *, u_int32_t *));
 
1757
 */
 
1758
int
 
1759
__db_vrfy_inpitem(dbp, h, pgno, i, is_btree, flags, himarkp, offsetp)
 
1760
        DB *dbp;
 
1761
        PAGE *h;
 
1762
        db_pgno_t pgno;
 
1763
        u_int32_t i;
 
1764
        int is_btree;
 
1765
        u_int32_t flags, *himarkp, *offsetp;
 
1766
{
 
1767
        BKEYDATA *bk;
 
1768
        db_indx_t offset, len;
 
1769
 
 
1770
        DB_ASSERT(himarkp != NULL);
 
1771
 
 
1772
        /*
 
1773
         * Check that the inp array, which grows from the beginning of the
 
1774
         * page forward, has not collided with the data, which grow from the
 
1775
         * end of the page backward.
 
1776
         */
 
1777
        if (h->inp + i >= (db_indx_t *)((u_int8_t *)h + *himarkp)) {
 
1778
                /* We've collided with the data.  We need to bail. */
 
1779
                EPRINT((dbp->dbenv,
 
1780
                    "Page %lu entries listing %lu overlaps data",
 
1781
                    (u_long)pgno, (u_long)i));
 
1782
                return (DB_VERIFY_FATAL);
 
1783
        }
 
1784
 
 
1785
        offset = h->inp[i];
 
1786
 
 
1787
        /*
 
1788
         * Check that the item offset is reasonable:  it points somewhere
 
1789
         * after the inp array and before the end of the page.
 
1790
         */
 
1791
        if (offset <= INP_OFFSET(h, i) || offset > dbp->pgsize) {
 
1792
                EPRINT((dbp->dbenv,
 
1793
                    "Bad offset %lu at page %lu index %lu",
 
1794
                    (u_long)offset, (u_long)pgno, (u_long)i));
 
1795
                return (DB_VERIFY_BAD);
 
1796
        }
 
1797
 
 
1798
        /* Update the high-water mark (what HOFFSET should be) */
 
1799
        if (offset < *himarkp)
 
1800
                *himarkp = offset;
 
1801
 
 
1802
        if (is_btree) {
 
1803
                /*
 
1804
                 * Check that the item length remains on-page.
 
1805
                 */
 
1806
                bk = GET_BKEYDATA(h, i);
 
1807
 
 
1808
                /*
 
1809
                 * We need to verify the type of the item here;
 
1810
                 * we can't simply assume that it will be one of the
 
1811
                 * expected three.  If it's not a recognizable type,
 
1812
                 * it can't be considered to have a verifiable
 
1813
                 * length, so it's not possible to certify it as safe.
 
1814
                 */
 
1815
                switch (B_TYPE(bk->type)) {
 
1816
                case B_KEYDATA:
 
1817
                        len = bk->len;
 
1818
                        break;
 
1819
                case B_DUPLICATE:
 
1820
                case B_OVERFLOW:
 
1821
                        len = BOVERFLOW_SIZE;
 
1822
                        break;
 
1823
                default:
 
1824
                        EPRINT((dbp->dbenv,
 
1825
                            "Item %lu on page %lu of unrecognizable type",
 
1826
                            i, pgno));
 
1827
                        return (DB_VERIFY_BAD);
 
1828
                }
 
1829
 
 
1830
                if ((size_t)(offset + len) > dbp->pgsize) {
 
1831
                        EPRINT((dbp->dbenv,
 
1832
                            "Item %lu on page %lu extends past page boundary",
 
1833
                            (u_long)i, (u_long)pgno));
 
1834
                        return (DB_VERIFY_BAD);
 
1835
                }
 
1836
        }
 
1837
 
 
1838
        if (offsetp != NULL)
 
1839
                *offsetp = offset;
 
1840
        return (0);
 
1841
}
 
1842
 
 
1843
/*
 
1844
 * __db_vrfy_duptype--
 
1845
 *      Given a page number and a set of flags to __bam_vrfy_subtree,
 
1846
 *      verify that the dup tree type is correct--i.e., it's a recno
 
1847
 *      if DUPSORT is not set and a btree if it is.
 
1848
 *
 
1849
 * PUBLIC: int __db_vrfy_duptype
 
1850
 * PUBLIC:     __P((DB *, VRFY_DBINFO *, db_pgno_t, u_int32_t));
 
1851
 */
 
1852
int
 
1853
__db_vrfy_duptype(dbp, vdp, pgno, flags)
 
1854
        DB *dbp;
 
1855
        VRFY_DBINFO *vdp;
 
1856
        db_pgno_t pgno;
 
1857
        u_int32_t flags;
 
1858
{
 
1859
        VRFY_PAGEINFO *pip;
 
1860
        int ret, isbad;
 
1861
 
 
1862
        isbad = 0;
 
1863
 
 
1864
        if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
 
1865
                return (ret);
 
1866
 
 
1867
        switch (pip->type) {
 
1868
        case P_IBTREE:
 
1869
        case P_LDUP:
 
1870
                if (!LF_ISSET(ST_DUPSORT)) {
 
1871
                        EPRINT((dbp->dbenv,
 
1872
            "Sorted duplicate set at page %lu in unsorted-dup database",
 
1873
                            (u_long)pgno));
 
1874
                        isbad = 1;
 
1875
                }
 
1876
                break;
 
1877
        case P_IRECNO:
 
1878
        case P_LRECNO:
 
1879
                if (LF_ISSET(ST_DUPSORT)) {
 
1880
                        EPRINT((dbp->dbenv,
 
1881
            "Unsorted duplicate set at page %lu in sorted-dup database",
 
1882
                            (u_long)pgno));
 
1883
                        isbad = 1;
 
1884
                }
 
1885
                break;
 
1886
        default:
 
1887
                EPRINT((dbp->dbenv,
 
1888
                    "Duplicate page %lu of inappropriate type %lu",
 
1889
                    (u_long)pgno, (u_long)pip->type));
 
1890
                isbad = 1;
 
1891
                break;
 
1892
        }
 
1893
 
 
1894
        if ((ret = __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0)
 
1895
                return (ret);
 
1896
        return (isbad == 1 ? DB_VERIFY_BAD : 0);
 
1897
}
 
1898
 
 
1899
/*
 
1900
 * __db_salvage_duptree --
 
1901
 *      Attempt to salvage a given duplicate tree, given its alleged root.
 
1902
 *
 
1903
 *      The key that corresponds to this dup set has been passed to us
 
1904
 *      in DBT *key.  Because data items follow keys, though, it has been
 
1905
 *      printed once already.
 
1906
 *
 
1907
 *      The basic idea here is that pgno ought to be a P_LDUP, a P_LRECNO, a
 
1908
 *      P_IBTREE, or a P_IRECNO.  If it's an internal page, use the verifier
 
1909
 *      functions to make sure it's safe;  if it's not, we simply bail and the
 
1910
 *      data will have to be printed with no key later on.  if it is safe,
 
1911
 *      recurse on each of its children.
 
1912
 *
 
1913
 *      Whether or not it's safe, if it's a leaf page, __bam_salvage it.
 
1914
 *
 
1915
 *      At all times, use the DB hanging off vdp to mark and check what we've
 
1916
 *      done, so each page gets printed exactly once and we don't get caught
 
1917
 *      in any cycles.
 
1918
 *
 
1919
 * PUBLIC: int __db_salvage_duptree __P((DB *, VRFY_DBINFO *, db_pgno_t,
 
1920
 * PUBLIC:     DBT *, void *, int (*)(void *, const void *), u_int32_t));
 
1921
 */
 
1922
int
 
1923
__db_salvage_duptree(dbp, vdp, pgno, key, handle, callback, flags)
 
1924
        DB *dbp;
 
1925
        VRFY_DBINFO *vdp;
 
1926
        db_pgno_t pgno;
 
1927
        DBT *key;
 
1928
        void *handle;
 
1929
        int (*callback) __P((void *, const void *));
 
1930
        u_int32_t flags;
 
1931
{
 
1932
        PAGE *h;
 
1933
        int ret, t_ret;
 
1934
 
 
1935
        if (pgno == PGNO_INVALID || !IS_VALID_PGNO(pgno))
 
1936
                return (DB_VERIFY_BAD);
 
1937
 
 
1938
        /* We have a plausible page.  Try it. */
 
1939
        if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0)
 
1940
                return (ret);
 
1941
 
 
1942
        switch (TYPE(h)) {
 
1943
        case P_IBTREE:
 
1944
        case P_IRECNO:
 
1945
                if ((ret = __db_vrfy_common(dbp, vdp, h, pgno, flags)) != 0)
 
1946
                        goto err;
 
1947
                if ((ret = __bam_vrfy(dbp,
 
1948
                    vdp, h, pgno, flags | DB_NOORDERCHK)) != 0 ||
 
1949
                    (ret = __db_salvage_markdone(vdp, pgno)) != 0)
 
1950
                        goto err;
 
1951
                /*
 
1952
                 * We have a known-healthy internal page.  Walk it.
 
1953
                 */
 
1954
                if ((ret = __bam_salvage_walkdupint(dbp, vdp, h, key,
 
1955
                    handle, callback, flags)) != 0)
 
1956
                        goto err;
 
1957
                break;
 
1958
        case P_LRECNO:
 
1959
        case P_LDUP:
 
1960
                if ((ret = __bam_salvage(dbp,
 
1961
                    vdp, pgno, TYPE(h), h, handle, callback, key, flags)) != 0)
 
1962
                        goto err;
 
1963
                break;
 
1964
        default:
 
1965
                ret = DB_VERIFY_BAD;
 
1966
                goto err;
 
1967
                /* NOTREACHED */
 
1968
        }
 
1969
 
 
1970
err:    if ((t_ret = memp_fput(dbp->mpf, h, 0)) != 0 && ret == 0)
 
1971
                ret = t_ret;
 
1972
        return (ret);
 
1973
}
 
1974
 
 
1975
/*
 
1976
 * __db_salvage_subdbs --
 
1977
 *      Check and see if this database has subdbs;  if so, try to salvage
 
1978
 *      them independently.
 
1979
 */
 
1980
static int
 
1981
__db_salvage_subdbs(dbp, vdp, handle, callback, flags, hassubsp)
 
1982
        DB *dbp;
 
1983
        VRFY_DBINFO *vdp;
 
1984
        void *handle;
 
1985
        int (*callback) __P((void *, const void *));
 
1986
        u_int32_t flags;
 
1987
        int *hassubsp;
 
1988
{
 
1989
        BTMETA *btmeta;
 
1990
        DB *pgset;
 
1991
        DBC *pgsc;
 
1992
        PAGE *h;
 
1993
        db_pgno_t p, meta_pgno;
 
1994
        int ret, err_ret;
 
1995
 
 
1996
        err_ret = 0;
 
1997
        pgsc = NULL;
 
1998
        pgset = NULL;
 
1999
 
 
2000
        meta_pgno = PGNO_BASE_MD;
 
2001
        if ((ret = memp_fget(dbp->mpf, &meta_pgno, 0, &h)) != 0)
 
2002
                return (ret);
 
2003
 
 
2004
        if (TYPE(h) == P_BTREEMETA)
 
2005
                btmeta = (BTMETA *)h;
 
2006
        else {
 
2007
                /* Not a btree metadata, ergo no subdbs, so just return. */
 
2008
                ret = 0;
 
2009
                goto err;
 
2010
        }
 
2011
 
 
2012
        /* If it's not a safe page, bail on the attempt. */
 
2013
        if ((ret = __db_vrfy_common(dbp, vdp, h, PGNO_BASE_MD, flags)) != 0 ||
 
2014
           (ret = __bam_vrfy_meta(dbp, vdp, btmeta, PGNO_BASE_MD, flags)) != 0)
 
2015
                goto err;
 
2016
 
 
2017
        if (!F_ISSET(&btmeta->dbmeta, BTM_SUBDB)) {
 
2018
                /* No subdbs, just return. */
 
2019
                ret = 0;
 
2020
                goto err;
 
2021
        }
 
2022
 
 
2023
        /* We think we've got subdbs.  Mark it so. */
 
2024
        *hassubsp = 1;
 
2025
 
 
2026
        if ((ret = memp_fput(dbp->mpf, h, 0)) != 0)
 
2027
                return (ret);
 
2028
 
 
2029
        /*
 
2030
         * We have subdbs.  Try to crack them.
 
2031
         *
 
2032
         * To do so, get a set of leaf pages in the master
 
2033
         * database, and then walk each of the valid ones, salvaging
 
2034
         * subdbs as we go.  If any prove invalid, just drop them;  we'll
 
2035
         * pick them up on a later pass.
 
2036
         */
 
2037
        if ((ret = __db_vrfy_pgset(dbp->dbenv, dbp->pgsize, &pgset)) != 0)
 
2038
                return (ret);
 
2039
        if ((ret =
 
2040
            __db_meta2pgset(dbp, vdp, PGNO_BASE_MD, flags, pgset)) != 0)
 
2041
                goto err;
 
2042
 
 
2043
        if ((ret = pgset->cursor(pgset, NULL, &pgsc, 0)) != 0)
 
2044
                goto err;
 
2045
        while ((ret = __db_vrfy_pgset_next(pgsc, &p)) == 0) {
 
2046
                if ((ret = memp_fget(dbp->mpf, &p, 0, &h)) != 0) {
 
2047
                        err_ret = ret;
 
2048
                        continue;
 
2049
                }
 
2050
                if ((ret = __db_vrfy_common(dbp, vdp, h, p, flags)) != 0 ||
 
2051
                    (ret = __bam_vrfy(dbp,
 
2052
                    vdp, h, p, flags | DB_NOORDERCHK)) != 0)
 
2053
                        goto nextpg;
 
2054
                if (TYPE(h) != P_LBTREE)
 
2055
                        goto nextpg;
 
2056
                else if ((ret = __db_salvage_subdbpg(
 
2057
                    dbp, vdp, h, handle, callback, flags)) != 0)
 
2058
                        err_ret = ret;
 
2059
nextpg:         if ((ret = memp_fput(dbp->mpf, h, 0)) != 0)
 
2060
                        err_ret = ret;
 
2061
        }
 
2062
 
 
2063
        if (ret != DB_NOTFOUND)
 
2064
                goto err;
 
2065
        if ((ret = pgsc->c_close(pgsc)) != 0)
 
2066
                goto err;
 
2067
 
 
2068
        ret = pgset->close(pgset, 0);
 
2069
        return ((ret == 0 && err_ret != 0) ? err_ret : ret);
 
2070
 
 
2071
        /* NOTREACHED */
 
2072
 
 
2073
err:    if (pgsc != NULL)
 
2074
                (void)pgsc->c_close(pgsc);
 
2075
        if (pgset != NULL)
 
2076
                (void)pgset->close(pgset, 0);
 
2077
        (void)memp_fput(dbp->mpf, h, 0);
 
2078
        return (ret);
 
2079
}
 
2080
 
 
2081
/*
 
2082
 * __db_salvage_subdbpg --
 
2083
 *      Given a known-good leaf page in the master database, salvage all
 
2084
 *      leaf pages corresponding to each subdb.
 
2085
 */
 
2086
static int
 
2087
__db_salvage_subdbpg(dbp, vdp, master, handle, callback, flags)
 
2088
        DB *dbp;
 
2089
        VRFY_DBINFO *vdp;
 
2090
        PAGE *master;
 
2091
        void *handle;
 
2092
        int (*callback) __P((void *, const void *));
 
2093
        u_int32_t flags;
 
2094
{
 
2095
        BKEYDATA *bkkey, *bkdata;
 
2096
        BOVERFLOW *bo;
 
2097
        DB *pgset;
 
2098
        DBC *pgsc;
 
2099
        DBT key;
 
2100
        PAGE *subpg;
 
2101
        db_indx_t i;
 
2102
        db_pgno_t meta_pgno, p;
 
2103
        int ret, err_ret, t_ret;
 
2104
        char *subdbname;
 
2105
 
 
2106
        ret = err_ret = 0;
 
2107
        subdbname = NULL;
 
2108
 
 
2109
        if ((ret = __db_vrfy_pgset(dbp->dbenv, dbp->pgsize, &pgset)) != 0)
 
2110
                return (ret);
 
2111
 
 
2112
        /*
 
2113
         * For each entry, get and salvage the set of pages
 
2114
         * corresponding to that entry.
 
2115
         */
 
2116
        for (i = 0; i < NUM_ENT(master); i += P_INDX) {
 
2117
                bkkey = GET_BKEYDATA(master, i);
 
2118
                bkdata = GET_BKEYDATA(master, i + O_INDX);
 
2119
 
 
2120
                /* Get the subdatabase name. */
 
2121
                if (B_TYPE(bkkey->type) == B_OVERFLOW) {
 
2122
                        /*
 
2123
                         * We can, in principle anyway, have a subdb
 
2124
                         * name so long it overflows.  Ick.
 
2125
                         */
 
2126
                        bo = (BOVERFLOW *)bkkey;
 
2127
                        if ((ret = __db_safe_goff(dbp, vdp, bo->pgno, &key,
 
2128
                            (void **)&subdbname, flags)) != 0) {
 
2129
                                err_ret = DB_VERIFY_BAD;
 
2130
                                continue;
 
2131
                        }
 
2132
 
 
2133
                        /* Nul-terminate it. */
 
2134
                        if ((ret = __os_realloc(dbp->dbenv,
 
2135
                            key.size + 1, &subdbname)) != 0)
 
2136
                                goto err;
 
2137
                        subdbname[key.size] = '\0';
 
2138
                } else if (B_TYPE(bkkey->type == B_KEYDATA)) {
 
2139
                        if ((ret = __os_realloc(dbp->dbenv,
 
2140
                            bkkey->len + 1, &subdbname)) != 0)
 
2141
                                goto err;
 
2142
                        memcpy(subdbname, bkkey->data, bkkey->len);
 
2143
                        subdbname[bkkey->len] = '\0';
 
2144
                }
 
2145
 
 
2146
                /* Get the corresponding pgno. */
 
2147
                if (bkdata->len != sizeof(db_pgno_t)) {
 
2148
                        err_ret = DB_VERIFY_BAD;
 
2149
                        continue;
 
2150
                }
 
2151
                memcpy(&meta_pgno, bkdata->data, sizeof(db_pgno_t));
 
2152
 
 
2153
                /* If we can't get the subdb meta page, just skip the subdb. */
 
2154
                if (!IS_VALID_PGNO(meta_pgno) ||
 
2155
                    (ret = memp_fget(dbp->mpf, &meta_pgno, 0, &subpg)) != 0) {
 
2156
                        err_ret = ret;
 
2157
                        continue;
 
2158
                }
 
2159
 
 
2160
                /*
 
2161
                 * Verify the subdatabase meta page.  This has two functions.
 
2162
                 * First, if it's bad, we have no choice but to skip the subdb
 
2163
                 * and let the pages just get printed on a later pass.  Second,
 
2164
                 * the access-method-specific meta verification routines record
 
2165
                 * the various state info (such as the presence of dups)
 
2166
                 * that we need for __db_prheader().
 
2167
                 */
 
2168
                if ((ret =
 
2169
                    __db_vrfy_common(dbp, vdp, subpg, meta_pgno, flags)) != 0) {
 
2170
                        err_ret = ret;
 
2171
                        (void)memp_fput(dbp->mpf, subpg, 0);
 
2172
                        continue;
 
2173
                }
 
2174
                switch (TYPE(subpg)) {
 
2175
                case P_BTREEMETA:
 
2176
                        if ((ret = __bam_vrfy_meta(dbp,
 
2177
                            vdp, (BTMETA *)subpg, meta_pgno, flags)) != 0) {
 
2178
                                err_ret = ret;
 
2179
                                (void)memp_fput(dbp->mpf, subpg, 0);
 
2180
                                continue;
 
2181
                        }
 
2182
                        break;
 
2183
                case P_HASHMETA:
 
2184
                        if ((ret = __ham_vrfy_meta(dbp,
 
2185
                            vdp, (HMETA *)subpg, meta_pgno, flags)) != 0) {
 
2186
                                err_ret = ret;
 
2187
                                (void)memp_fput(dbp->mpf, subpg, 0);
 
2188
                                continue;
 
2189
                        }
 
2190
                        break;
 
2191
                default:
 
2192
                        /* This isn't an appropriate page;  skip this subdb. */
 
2193
                        err_ret = DB_VERIFY_BAD;
 
2194
                        continue;
 
2195
                        /* NOTREACHED */
 
2196
                }
 
2197
 
 
2198
                if ((ret = memp_fput(dbp->mpf, subpg, 0)) != 0) {
 
2199
                        err_ret = ret;
 
2200
                        continue;
 
2201
                }
 
2202
 
 
2203
                /* Print a subdatabase header. */
 
2204
                if ((ret = __db_prheader(dbp,
 
2205
                    subdbname, 0, 0, handle, callback, vdp, meta_pgno)) != 0)
 
2206
                        goto err;
 
2207
 
 
2208
                if ((ret = __db_meta2pgset(dbp, vdp, meta_pgno,
 
2209
                    flags, pgset)) != 0) {
 
2210
                        err_ret = ret;
 
2211
                        continue;
 
2212
                }
 
2213
 
 
2214
                if ((ret = pgset->cursor(pgset, NULL, &pgsc, 0)) != 0)
 
2215
                        goto err;
 
2216
                while ((ret = __db_vrfy_pgset_next(pgsc, &p)) == 0) {
 
2217
                        if ((ret = memp_fget(dbp->mpf, &p, 0, &subpg)) != 0) {
 
2218
                                err_ret = ret;
 
2219
                                continue;
 
2220
                        }
 
2221
                        if ((ret = __db_salvage(dbp, vdp, p, subpg,
 
2222
                            handle, callback, flags)) != 0)
 
2223
                                err_ret = ret;
 
2224
                        if ((ret = memp_fput(dbp->mpf, subpg, 0)) != 0)
 
2225
                                err_ret = ret;
 
2226
                }
 
2227
 
 
2228
                if (ret != DB_NOTFOUND)
 
2229
                        goto err;
 
2230
 
 
2231
                if ((ret = pgsc->c_close(pgsc)) != 0)
 
2232
                        goto err;
 
2233
                if ((ret = __db_prfooter(handle, callback)) != 0)
 
2234
                        goto err;
 
2235
        }
 
2236
err:    if (subdbname)
 
2237
                __os_free(dbp->dbenv, subdbname, 0);
 
2238
 
 
2239
        if ((t_ret = pgset->close(pgset, 0)) != 0)
 
2240
                ret = t_ret;
 
2241
 
 
2242
        if ((t_ret = __db_salvage_markdone(vdp, PGNO(master))) != 0)
 
2243
                return (t_ret);
 
2244
 
 
2245
        return ((err_ret != 0) ? err_ret : ret);
 
2246
}
 
2247
 
 
2248
/*
 
2249
 * __db_meta2pgset --
 
2250
 *      Given a known-safe meta page number, return the set of pages
 
2251
 *      corresponding to the database it represents.  Return DB_VERIFY_BAD if
 
2252
 *      it's not a suitable meta page or is invalid.
 
2253
 */
 
2254
static int
 
2255
__db_meta2pgset(dbp, vdp, pgno, flags, pgset)
 
2256
        DB *dbp;
 
2257
        VRFY_DBINFO *vdp;
 
2258
        db_pgno_t pgno;
 
2259
        u_int32_t flags;
 
2260
        DB *pgset;
 
2261
{
 
2262
        PAGE *h;
 
2263
        int ret, t_ret;
 
2264
 
 
2265
        if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0)
 
2266
                return (ret);
 
2267
 
 
2268
        switch (TYPE(h)) {
 
2269
        case P_BTREEMETA:
 
2270
                ret = __bam_meta2pgset(dbp, vdp, (BTMETA *)h, flags, pgset);
 
2271
                break;
 
2272
        case P_HASHMETA:
 
2273
                ret = __ham_meta2pgset(dbp, vdp, (HMETA *)h, flags, pgset);
 
2274
                break;
 
2275
        default:
 
2276
                ret = DB_VERIFY_BAD;
 
2277
                break;
 
2278
        }
 
2279
 
 
2280
        if ((t_ret = memp_fput(dbp->mpf, h, 0)) != 0)
 
2281
                return (t_ret);
 
2282
        return (ret);
 
2283
}
 
2284
 
 
2285
/*
 
2286
 * __db_guesspgsize --
 
2287
 *      Try to guess what the pagesize is if the one on the meta page
 
2288
 *      and the one in the db are invalid.
 
2289
 */
 
2290
static int
 
2291
__db_guesspgsize(dbenv, fhp)
 
2292
        DB_ENV *dbenv;
 
2293
        DB_FH *fhp;
 
2294
{
 
2295
        db_pgno_t i;
 
2296
        size_t nr;
 
2297
        u_int32_t guess;
 
2298
        u_int8_t type;
 
2299
 
 
2300
        for (guess = DB_MAX_PGSIZE; guess >= DB_MIN_PGSIZE; guess >>= 1) {
 
2301
                /*
 
2302
                 * We try to read three pages ahead after the first one
 
2303
                 * and make sure we have plausible types for all of them.
 
2304
                 * If the seeks fail, continue with a smaller size;
 
2305
                 * we're probably just looking past the end of the database.
 
2306
                 * If they succeed and the types are reasonable, also continue
 
2307
                 * with a size smaller;  we may be looking at pages N,
 
2308
                 * 2N, and 3N for some N > 1.
 
2309
                 *
 
2310
                 * As soon as we hit an invalid type, we stop and return
 
2311
                 * our previous guess; that last one was probably the page size.
 
2312
                 */
 
2313
                for (i = 1; i <= 3; i++) {
 
2314
                        if (__os_seek(dbenv, fhp, guess,
 
2315
                            i, SSZ(DBMETA, type), 0, DB_OS_SEEK_SET) != 0)
 
2316
                                break;
 
2317
                        if (__os_read(dbenv,
 
2318
                            fhp, &type, 1, &nr) != 0 || nr == 0)
 
2319
                                break;
 
2320
                        if (type == P_INVALID || type >= P_PAGETYPE_MAX)
 
2321
                                return (guess << 1);
 
2322
                }
 
2323
        }
 
2324
 
 
2325
        /*
 
2326
         * If we're just totally confused--the corruption takes up most of the
 
2327
         * beginning pages of the database--go with the default size.
 
2328
         */
 
2329
        return (DB_DEF_IOSIZE);
 
2330
}