00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 #include "db_config.h"
00046
00047 #ifndef NO_SYSTEM_INCLUDES
00048 #include <sys/types.h>
00049 #include <string.h>
00050 #endif
00051
00052 #include "db_int.h"
00053 #include "dbinc/db_page.h"
00054 #include "dbinc/db_shash.h"
00055 #include "dbinc/db_am.h"
00056 #include "dbinc/db_verify.h"
00057 #include "dbinc/mp.h"
00058
00059
00060
00061
00062
00063
00064
00065
00066 int
00067 __db_vrfy_overflow(dbp, vdp, h, pgno, flags)
00068 DB *dbp;
00069 VRFY_DBINFO *vdp;
00070 PAGE *h;
00071 db_pgno_t pgno;
00072 u_int32_t flags;
00073 {
00074 VRFY_PAGEINFO *pip;
00075 int isbad, ret, t_ret;
00076
00077 isbad = 0;
00078 if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
00079 return (ret);
00080
00081 if ((ret = __db_vrfy_datapage(dbp, vdp, h, pgno, flags)) != 0) {
00082 if (ret == DB_VERIFY_BAD)
00083 isbad = 1;
00084 else
00085 goto err;
00086 }
00087
00088 pip->refcount = OV_REF(h);
00089 if (pip->refcount < 1) {
00090 EPRINT((dbp->dbenv,
00091 "Page %lu: overflow page has zero reference count",
00092 (u_long)pgno));
00093 isbad = 1;
00094 }
00095
00096
00097 pip->olen = HOFFSET(h);
00098
00099 err: if ((t_ret = __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0)
00100 ret = t_ret;
00101 return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
00102 }
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 int
00113 __db_vrfy_ovfl_structure(dbp, vdp, pgno, tlen, flags)
00114 DB *dbp;
00115 VRFY_DBINFO *vdp;
00116 db_pgno_t pgno;
00117 u_int32_t tlen;
00118 u_int32_t flags;
00119 {
00120 DB *pgset;
00121 VRFY_PAGEINFO *pip;
00122 db_pgno_t next, prev;
00123 int isbad, ret, seen_cnt, t_ret;
00124 u_int32_t refcount;
00125
00126 pgset = vdp->pgset;
00127 DB_ASSERT(pgset != NULL);
00128 isbad = 0;
00129
00130
00131 if (!IS_VALID_PGNO(pgno))
00132 return (DB_VERIFY_BAD);
00133
00134
00135
00136
00137
00138 if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)
00139 return (ret);
00140
00141
00142 refcount = pip->refcount;
00143
00144 if (pip->type != P_OVERFLOW) {
00145 EPRINT((dbp->dbenv,
00146 "Page %lu: overflow page of invalid type %lu",
00147 (u_long)pgno, (u_long)pip->type));
00148 ret = DB_VERIFY_BAD;
00149 goto err;
00150 }
00151
00152 prev = pip->prev_pgno;
00153 if (prev != PGNO_INVALID) {
00154 EPRINT((dbp->dbenv,
00155 "Page %lu: first page in overflow chain has a prev_pgno %lu",
00156 (u_long)pgno, (u_long)prev));
00157 isbad = 1;
00158 }
00159
00160 for (;;) {
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170 if ((ret = __db_vrfy_pgset_get(pgset, pgno, &seen_cnt)) != 0)
00171 goto err;
00172 if ((u_int32_t)seen_cnt > refcount) {
00173 EPRINT((dbp->dbenv,
00174 "Page %lu: encountered too many times in overflow traversal",
00175 (u_long)pgno));
00176 ret = DB_VERIFY_BAD;
00177 goto err;
00178 }
00179 if ((ret = __db_vrfy_pgset_inc(pgset, pgno)) != 0)
00180 goto err;
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206 if (LF_ISSET(ST_OVFL_LEAF)) {
00207 if (F_ISSET(pip, VRFY_OVFL_LEAFSEEN)) {
00208 EPRINT((dbp->dbenv,
00209 "Page %lu: overflow page linked twice from leaf or data page",
00210 (u_long)pgno));
00211 ret = DB_VERIFY_BAD;
00212 goto err;
00213 }
00214 F_SET(pip, VRFY_OVFL_LEAFSEEN);
00215 }
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 if (seen_cnt == 0) {
00228
00229
00230
00231
00232 tlen -= pip->olen;
00233
00234
00235 if (!LF_ISSET(DB_SALVAGE))
00236 __db_vrfy_struct_feedback(dbp, vdp);
00237 } else
00238 goto done;
00239
00240 next = pip->next_pgno;
00241
00242
00243 if (next == PGNO_INVALID)
00244 break;
00245
00246
00247
00248
00249
00250 if (!IS_VALID_PGNO(next)) {
00251 DB_ASSERT(0);
00252 EPRINT((dbp->dbenv,
00253 "Page %lu: bad next_pgno %lu on overflow page",
00254 (u_long)pgno, (u_long)next));
00255 ret = DB_VERIFY_BAD;
00256 goto err;
00257 }
00258
00259 if ((ret = __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 ||
00260 (ret = __db_vrfy_getpageinfo(vdp, next, &pip)) != 0)
00261 return (ret);
00262 if (pip->prev_pgno != pgno) {
00263 EPRINT((dbp->dbenv,
00264 "Page %lu: bad prev_pgno %lu on overflow page (should be %lu)",
00265 (u_long)next, (u_long)pip->prev_pgno,
00266 (u_long)pgno));
00267 isbad = 1;
00268
00269
00270
00271
00272 }
00273
00274 pgno = next;
00275 }
00276
00277 if (tlen > 0) {
00278 isbad = 1;
00279 EPRINT((dbp->dbenv,
00280 "Page %lu: overflow item incomplete", (u_long)pgno));
00281 }
00282
00283 done:
00284 err: if ((t_ret =
00285 __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 && ret == 0)
00286 ret = t_ret;
00287 return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);
00288 }
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298 int
00299 __db_safe_goff(dbp, vdp, pgno, dbt, buf, flags)
00300 DB *dbp;
00301 VRFY_DBINFO *vdp;
00302 db_pgno_t pgno;
00303 DBT *dbt;
00304 void *buf;
00305 u_int32_t flags;
00306 {
00307 DB_MPOOLFILE *mpf;
00308 PAGE *h;
00309 int ret, t_ret;
00310 u_int32_t bytesgot, bytes;
00311 u_int8_t *src, *dest;
00312
00313 mpf = dbp->mpf;
00314 h = NULL;
00315 ret = t_ret = 0;
00316 bytesgot = bytes = 0;
00317
00318 while ((pgno != PGNO_INVALID) && (IS_VALID_PGNO(pgno))) {
00319
00320
00321
00322
00323 if ((ret = __db_salvage_markdone(vdp, pgno)) != 0)
00324 break;
00325
00326 if ((ret = __memp_fget(mpf, &pgno, 0, &h)) != 0)
00327 break;
00328
00329
00330
00331
00332
00333 if (!LF_ISSET(DB_AGGRESSIVE) && TYPE(h) != P_OVERFLOW) {
00334 ret = DB_VERIFY_BAD;
00335 break;
00336 }
00337
00338 src = (u_int8_t *)h + P_OVERHEAD(dbp);
00339 bytes = OV_LEN(h);
00340
00341 if (bytes + P_OVERHEAD(dbp) > dbp->pgsize)
00342 bytes = dbp->pgsize - P_OVERHEAD(dbp);
00343
00344 if ((ret = __os_realloc(dbp->dbenv,
00345 bytesgot + bytes, buf)) != 0)
00346 break;
00347
00348 dest = *(u_int8_t **)buf + bytesgot;
00349 bytesgot += bytes;
00350
00351 memcpy(dest, src, bytes);
00352
00353 pgno = NEXT_PGNO(h);
00354
00355 if ((ret = __memp_fput(mpf, h, 0)) != 0)
00356 break;
00357 h = NULL;
00358 }
00359
00360
00361
00362
00363
00364 if (ret == 0 || LF_ISSET(DB_AGGRESSIVE)) {
00365 dbt->size = bytesgot;
00366 dbt->data = *(void **)buf;
00367 }
00368
00369
00370 if (h != NULL && (t_ret = __memp_fput(mpf, h, 0)) != 0 && ret == 0)
00371 ret = t_ret;
00372
00373 return (ret);
00374 }