⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 db_ovfl_vrfy.c

📁 这是国外的resip协议栈
💻 C
字号:
/*- * See the file LICENSE for redistribution information. * * Copyright (c) 1996-2004 *	Sleepycat Software.  All rights reserved. *//* * Copyright (c) 1990, 1993, 1994, 1995, 1996 *	Keith Bostic.  All rights reserved. *//* * Copyright (c) 1990, 1993, 1994, 1995 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * Mike Olson. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: db_ovfl_vrfy.c,v 11.56 2004/01/28 03:35:57 bostic Exp $ */#include "db_config.h"#ifndef NO_SYSTEM_INCLUDES#include <sys/types.h>#include <string.h>#endif#include "db_int.h"#include "dbinc/db_page.h"#include "dbinc/db_shash.h"#include "dbinc/db_am.h"#include "dbinc/db_verify.h"#include "dbinc/mp.h"/* * __db_vrfy_overflow -- *	Verify overflow page. * * PUBLIC: int __db_vrfy_overflow __P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t, * PUBLIC:     u_int32_t)); */int__db_vrfy_overflow(dbp, vdp, h, pgno, flags)	DB *dbp;	VRFY_DBINFO *vdp;	PAGE *h;	db_pgno_t pgno;	u_int32_t flags;{	VRFY_PAGEINFO *pip;	int isbad, ret, t_ret;	isbad = 0;	if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)		return (ret);	if ((ret = __db_vrfy_datapage(dbp, vdp, h, pgno, flags)) != 0) {		if (ret == DB_VERIFY_BAD)			isbad = 1;		else			goto err;	}	pip->refcount = OV_REF(h);	if (pip->refcount < 1) {		EPRINT((dbp->dbenv,		    "Page %lu: overflow page has zero reference count",		    (u_long)pgno));		isbad = 1;	}	/* Just store for now. */	pip->olen = HOFFSET(h);err:	if ((t_ret = __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0)		ret = t_ret;	return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);}/* * __db_vrfy_ovfl_structure -- *	Walk a list of overflow pages, avoiding cycles and marking *	pages seen. * * PUBLIC: int __db_vrfy_ovfl_structure * PUBLIC:     __P((DB *, VRFY_DBINFO *, db_pgno_t, u_int32_t, u_int32_t)); */int__db_vrfy_ovfl_structure(dbp, vdp, pgno, tlen, flags)	DB *dbp;	VRFY_DBINFO *vdp;	db_pgno_t pgno;	u_int32_t tlen;	u_int32_t flags;{	DB *pgset;	VRFY_PAGEINFO *pip;	db_pgno_t next, prev;	int isbad, ret, seen_cnt, t_ret;	u_int32_t refcount;	pgset = vdp->pgset;	DB_ASSERT(pgset != NULL);	isbad = 0;	/* This shouldn't happen, but just to be sure. */	if (!IS_VALID_PGNO(pgno))		return (DB_VERIFY_BAD);	/*	 * Check the first prev_pgno;  it ought to be PGNO_INVALID,	 * since there's no prev page.	 */	if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0)		return (ret);	/* The refcount is stored on the first overflow page. */	refcount = pip->refcount;	if (pip->type != P_OVERFLOW) {		EPRINT((dbp->dbenv,		    "Page %lu: overflow page of invalid type %lu",		    (u_long)pgno, (u_long)pip->type));		ret = DB_VERIFY_BAD;		goto err;		/* Unsafe to continue. */	}	prev = pip->prev_pgno;	if (prev != PGNO_INVALID) {		EPRINT((dbp->dbenv,	    "Page %lu: first page in overflow chain has a prev_pgno %lu",		    (u_long)pgno, (u_long)prev));		isbad = 1;	}	for (;;) {		/*		 * We may have seen this page elsewhere, if the overflow entry		 * has been promoted to an internal page;  we just want to		 * make sure that each overflow page is seen exactly as many		 * times as its refcount dictates.		 *		 * Note that this code also serves to keep us from looping		 * infinitely if there's a cycle in an overflow chain.		 */		if ((ret = __db_vrfy_pgset_get(pgset, pgno, &seen_cnt)) != 0)			goto err;		if ((u_int32_t)seen_cnt > refcount) {			EPRINT((dbp->dbenv,		"Page %lu: encountered too many times in overflow traversal",			    (u_long)pgno));			ret = DB_VERIFY_BAD;			goto err;		}		if ((ret = __db_vrfy_pgset_inc(pgset, pgno)) != 0)			goto err;		/*		 * Each overflow page can be referenced multiple times,		 * because it's possible for overflow Btree keys to get		 * promoted to internal pages.  We want to make sure that		 * each page is referenced from a Btree leaf (or Hash data		 * page, which we consider a "leaf" here) exactly once; if		 * the parent was a leaf, set a flag to indicate that we've		 * seen this page in a leaf context.		 *		 * If the parent is not a leaf--in which case it's a Btree		 * internal page--we don't need to bother doing any further		 * verification, as we'll do it when we hit the leaf (or		 * complain that we never saw the leaf).  Only the first		 * page in an overflow chain should ever have a refcount		 * greater than 1, and the combination of the LEAFSEEN check		 * and the fact that we bail after the first page for		 * non-leaves should ensure this.		 *		 * Note that each "child" of a page, such as an overflow page,		 * is stored and verified in a structure check exactly once,		 * so this code does not need to contend with the fact that		 * overflow chains used as Btree duplicate keys may be		 * referenced multiply from a single Btree leaf page.		 */		if (LF_ISSET(ST_OVFL_LEAF)) {			if (F_ISSET(pip, VRFY_OVFL_LEAFSEEN)) {				EPRINT((dbp->dbenv,		"Page %lu: overflow page linked twice from leaf or data page",				    (u_long)pgno));				ret = DB_VERIFY_BAD;				goto err;			}			F_SET(pip, VRFY_OVFL_LEAFSEEN);		}		/*		 * We want to verify each overflow chain only once, and		 * although no chain should be linked more than once from a		 * leaf page, we can't guarantee that it'll be linked that		 * once if it's linked from an internal page and the key		 * is gone.		 *		 * seen_cnt is the number of times we'd encountered this page		 * before calling this function.		 */		if (seen_cnt == 0) {			/*			 * Keep a running tab on how much of the item we've			 * seen.			 */			tlen -= pip->olen;			/* Send the application feedback about our progress. */			if (!LF_ISSET(DB_SALVAGE))				__db_vrfy_struct_feedback(dbp, vdp);		} else			goto done;		next = pip->next_pgno;		/* Are we there yet? */		if (next == PGNO_INVALID)			break;		/*		 * We've already checked this when we saved it, but just		 * to be sure...		 */		if (!IS_VALID_PGNO(next)) {			DB_ASSERT(0);			EPRINT((dbp->dbenv,			    "Page %lu: bad next_pgno %lu on overflow page",			    (u_long)pgno, (u_long)next));			ret = DB_VERIFY_BAD;			goto err;		}		if ((ret = __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 ||		    (ret = __db_vrfy_getpageinfo(vdp, next, &pip)) != 0)			return (ret);		if (pip->prev_pgno != pgno) {			EPRINT((dbp->dbenv,		"Page %lu: bad prev_pgno %lu on overflow page (should be %lu)",			    (u_long)next, (u_long)pip->prev_pgno,			    (u_long)pgno));			isbad = 1;			/*			 * It's safe to continue because we have separate			 * cycle detection.			 */		}		pgno = next;	}	if (tlen > 0) {		isbad = 1;		EPRINT((dbp->dbenv,		    "Page %lu: overflow item incomplete", (u_long)pgno));	}done:err:	if ((t_ret =	    __db_vrfy_putpageinfo(dbp->dbenv, vdp, pip)) != 0 && ret == 0)		ret = t_ret;	return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret);}/* * __db_safe_goff -- *	Get an overflow item, very carefully, from an untrusted database, *	in the context of the salvager. * * PUBLIC: int __db_safe_goff __P((DB *, VRFY_DBINFO *, db_pgno_t, * PUBLIC:     DBT *, void *, u_int32_t)); */int__db_safe_goff(dbp, vdp, pgno, dbt, buf, flags)	DB *dbp;	VRFY_DBINFO *vdp;	db_pgno_t pgno;	DBT *dbt;	void *buf;	u_int32_t flags;{	DB_MPOOLFILE *mpf;	PAGE *h;	int ret, t_ret;	u_int32_t bytesgot, bytes;	u_int8_t *src, *dest;	mpf = dbp->mpf;	h = NULL;	ret = t_ret = 0;	bytesgot = bytes = 0;	while ((pgno != PGNO_INVALID) && (IS_VALID_PGNO(pgno))) {		/*		 * Mark that we're looking at this page;  if we've seen it		 * already, quit.		 */		if ((ret = __db_salvage_markdone(vdp, pgno)) != 0)			break;		if ((ret = __memp_fget(mpf, &pgno, 0, &h)) != 0)			break;		/*		 * Make sure it's really an overflow page, unless we're		 * being aggressive, in which case we pretend it is.		 */		if (!LF_ISSET(DB_AGGRESSIVE) && TYPE(h) != P_OVERFLOW) {			ret = DB_VERIFY_BAD;			break;		}		src = (u_int8_t *)h + P_OVERHEAD(dbp);		bytes = OV_LEN(h);		if (bytes + P_OVERHEAD(dbp) > dbp->pgsize)			bytes = dbp->pgsize - P_OVERHEAD(dbp);		if ((ret = __os_realloc(dbp->dbenv,		    bytesgot + bytes, buf)) != 0)			break;		dest = *(u_int8_t **)buf + bytesgot;		bytesgot += bytes;		memcpy(dest, src, bytes);		pgno = NEXT_PGNO(h);		if ((ret = __memp_fput(mpf, h, 0)) != 0)			break;		h = NULL;	}	/*	 * If we're being aggressive, salvage a partial datum if there	 * was an error somewhere along the way.	 */	if (ret == 0 || LF_ISSET(DB_AGGRESSIVE)) {		dbt->size = bytesgot;		dbt->data = *(void **)buf;	}	/* If we broke out on error, don't leave pages pinned. */	if (h != NULL && (t_ret = __memp_fput(mpf, h, 0)) != 0 && ret == 0)		ret = t_ret;	return (ret);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -