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

📄 db_vrfy.c

📁 这是国外的resip协议栈
💻 C
📖 第 1 页 / 共 5 页
字号:
/*- * See the file LICENSE for redistribution information. * * Copyright (c) 2000-2004 *	Sleepycat Software.  All rights reserved. * * $Id: db_vrfy.c,v 1.138 2004/10/11 18:47:50 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_swap.h"#include "dbinc/db_verify.h"#include "dbinc/btree.h"#include "dbinc/hash.h"#include "dbinc/lock.h"#include "dbinc/mp.h"#include "dbinc/qam.h"#include "dbinc/txn.h"/* * This is the code for DB->verify, the DB database consistency checker. * For now, it checks all subdatabases in a database, and verifies * everything it knows how to (i.e. it's all-or-nothing, and one can't * check only for a subset of possible problems). */static u_int __db_guesspgsize __P((DB_ENV *, DB_FH *));static int   __db_is_valid_magicno __P((u_int32_t, DBTYPE *));static int   __db_is_valid_pagetype __P((u_int32_t));static int   __db_meta2pgset		__P((DB *, VRFY_DBINFO *, db_pgno_t, u_int32_t, DB *));static int   __db_salvage_subdbpg __P((DB *, VRFY_DBINFO *,		PAGE *, void *, int (*)(void *, const void *), u_int32_t));static int   __db_salvage_subdbs __P((DB *, VRFY_DBINFO *, void *,		int(*)(void *, const void *), u_int32_t, int *));static int   __db_salvage_unknowns __P((DB *, VRFY_DBINFO *, void *,		int (*)(void *, const void *), u_int32_t));static int   __db_verify __P((DB *, const char *, const char *,		void *, int (*)(void *, const void *), u_int32_t));static int   __db_verify_arg __P((DB *, const char *, void *, u_int32_t));static int   __db_vrfy_freelist		__P((DB *, VRFY_DBINFO *, db_pgno_t, u_int32_t));static int   __db_vrfy_invalid		__P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t, u_int32_t));static int   __db_vrfy_orderchkonly __P((DB *,		VRFY_DBINFO *, const char *, const char *, u_int32_t));static int   __db_vrfy_pagezero __P((DB *, VRFY_DBINFO *, DB_FH *, u_int32_t));static int   __db_vrfy_subdbs		__P((DB *, VRFY_DBINFO *, const char *, u_int32_t));static int   __db_vrfy_structure		__P((DB *, VRFY_DBINFO *, const char *, db_pgno_t, u_int32_t));static int   __db_vrfy_walkpages __P((DB *, VRFY_DBINFO *,		void *, int (*)(void *, const void *), u_int32_t));#define	VERIFY_FLAGS							\    (DB_AGGRESSIVE |							\     DB_NOORDERCHK | DB_ORDERCHKONLY | DB_PRINTABLE | DB_SALVAGE | DB_UNREF)/* * __db_verify_pp -- *	DB->verify public interface. * * PUBLIC: int __db_verify_pp * PUBLIC:     __P((DB *, const char *, const char *, FILE *, u_int32_t)); */int__db_verify_pp(dbp, file, database, outfile, flags)	DB *dbp;	const char *file, *database;	FILE *outfile;	u_int32_t flags;{	/*	 * __db_verify_pp is a wrapper to __db_verify_internal, which lets	 * us pass appropriate equivalents to FILE * in from the non-C APIs.	 */	return (__db_verify_internal(dbp,	    file, database, outfile, __db_pr_callback, flags));}/* * __db_verify_internal -- * * PUBLIC: int __db_verify_internal __P((DB *, const char *, * PUBLIC:     const char *, void *, int (*)(void *, const void *), u_int32_t)); */int__db_verify_internal(dbp, fname, dname, handle, callback, flags)	DB *dbp;	const char *fname, *dname;	void *handle;	int (*callback) __P((void *, const void *));	u_int32_t flags;{	DB_ENV *dbenv;	int ret, t_ret;	dbenv = dbp->dbenv;	PANIC_CHECK(dbenv);	DB_ILLEGAL_AFTER_OPEN(dbp, "DB->verify");#ifdef HAVE_FTRUNCATE	/*	 * If we're using ftruncate to abort page-allocation functions, there	 * should never be unreferenced pages.  Always check for unreferenced	 * pages on those systems.	 */	if (!LF_ISSET(DB_SALVAGE))		LF_SET(DB_UNREF);#endif	if ((ret = __db_verify_arg(dbp, dname, handle, flags)) != 0)		goto err;	/*	 * Forbid working in an environment that uses transactions or	 * locking;  we're going to be looking at the file freely,	 * and while we're not going to modify it, we aren't obeying	 * locking conventions either.	 */	if (TXN_ON(dbenv) || LOCKING_ON(dbenv) || LOGGING_ON(dbenv)) {		__db_err(dbenv,    "DB->verify may not be used with transactions, logging, or locking");		ret = EINVAL;		goto err;	}	ret = __db_verify(dbp, fname, dname, handle, callback, flags);	/* Db.verify is a DB handle destructor. */err:	if ((t_ret = __db_close(dbp, NULL, 0)) != 0 && ret == 0)		ret = t_ret;	return (ret);}/* * __db_verify_arg -- *	Check DB->verify arguments. */static int__db_verify_arg(dbp, dname, handle, flags)	DB *dbp;	const char *dname;	void *handle;	u_int32_t flags;{	DB_ENV *dbenv;	int ret;	dbenv = dbp->dbenv;	if ((ret = __db_fchk(dbenv, "DB->verify", flags, VERIFY_FLAGS)) != 0)		return (ret);	/*	 * DB_SALVAGE is mutually exclusive with the other flags except	 * DB_AGGRESSIVE, DB_PRINTABLE.	 *	 * DB_AGGRESSIVE and DB_PRINTABLE are only meaningful when salvaging.	 *	 * DB_SALVAGE requires an output stream.	 */	if (LF_ISSET(DB_SALVAGE)) {		if (LF_ISSET(~(DB_AGGRESSIVE | DB_PRINTABLE | DB_SALVAGE)))			return (__db_ferr(dbenv, "DB->verify", 1));		if (handle == NULL) {			__db_err(dbenv,			    "DB_SALVAGE requires a an output handle");			return (EINVAL);		}	} else		if (LF_ISSET(DB_AGGRESSIVE | DB_PRINTABLE))			return (__db_ferr(dbenv, "DB->verify", 1));	/* 	 * DB_ORDERCHKONLY is mutually exclusive with DB_SALVAGE and	 * DB_NOORDERCHK, and requires a database name.	 */	if ((ret = __db_fcchk(dbenv, "DB->verify", flags,	    DB_ORDERCHKONLY, DB_SALVAGE | DB_NOORDERCHK)) != 0)		return (ret);	if (LF_ISSET(DB_ORDERCHKONLY) && dname == NULL) {		__db_err(dbenv, "DB_ORDERCHKONLY requires a database name");		return (EINVAL);	}	return (0);}/* * __db_verify -- *	Walk the entire file page-by-page, either verifying with or without *	dumping in db_dump -d format, or DB_SALVAGE-ing whatever key/data *	pairs can be found and dumping them in standard (db_load-ready) *	dump format. * *	(Salvaging isn't really a verification operation, but we put it *	here anyway because it requires essentially identical top-level *	code.) * *	flags may be 0, DB_NOORDERCHK, DB_ORDERCHKONLY, or DB_SALVAGE *	(and optionally DB_AGGRESSIVE). */static int__db_verify(dbp, name, subdb, handle, callback, flags)	DB *dbp;	const char *name, *subdb;	void *handle;	int (*callback) __P((void *, const void *));	u_int32_t flags;{	DB_ENV *dbenv;	DB_FH *fhp;	VRFY_DBINFO *vdp;	int has, isbad, ret, t_ret;	char *real_name;	dbenv = dbp->dbenv;	fhp = NULL;	vdp = NULL;	real_name = NULL;	has = ret = isbad = 0;	F_SET(dbp, DB_AM_VERIFYING);	/* Initialize any feedback function. */	if (!LF_ISSET(DB_SALVAGE) && dbp->db_feedback != NULL)		dbp->db_feedback(dbp, DB_VERIFY, 0);	/*	 * We don't know how large the cache is, and if the database	 * in question uses a small page size--which we don't know	 * yet!--it may be uncomfortably small for the default page	 * size [#2143].  However, the things we need temporary	 * databases for in dbinfo are largely tiny, so using a	 * 1024-byte pagesize is probably not going to be a big hit,	 * and will make us fit better into small spaces.	 */	if ((ret = __db_vrfy_dbinfo_create(dbenv, 1024, &vdp)) != 0)		goto err;	/*	 * Note whether the user has requested that we use printable	 * chars where possible.  We won't get here with this flag if	 * we're not salvaging.	 */	if (LF_ISSET(DB_PRINTABLE))		F_SET(vdp, SALVAGE_PRINTABLE);	/* Find the real name of the file. */	if ((ret = __db_appname(dbenv,	    DB_APP_DATA, name, 0, NULL, &real_name)) != 0)		goto err;	/*	 * Our first order of business is to verify page 0, which is	 * the metadata page for the master database of subdatabases	 * or of the only database in the file.  We want to do this by hand	 * rather than just calling __db_open in case it's corrupt--various	 * things in __db_open might act funny.	 *	 * Once we know the metadata page is healthy, I believe that it's	 * safe to open the database normally and then use the page swapping	 * code, which makes life easier.	 */	if ((ret = __os_open(dbenv, real_name, DB_OSO_RDONLY, 0, &fhp)) != 0)		goto err;	/* Verify the metadata page 0; set pagesize and type. */	if ((ret = __db_vrfy_pagezero(dbp, vdp, fhp, flags)) != 0) {		if (ret == DB_VERIFY_BAD)			isbad = 1;		else			goto err;	}	/*	 * We can assume at this point that dbp->pagesize and dbp->type are	 * set correctly, or at least as well as they can be, and that	 * locking, logging, and txns are not in use.  Thus we can trust	 * the memp code not to look at the page, and thus to be safe	 * enough to use.	 *	 * The dbp is not open, but the file is open in the fhp, and we	 * cannot assume that __db_open is safe.  Call __db_dbenv_setup,	 * the [safe] part of __db_open that initializes the environment--	 * and the mpool--manually.	 */	if ((ret = __db_dbenv_setup(dbp, NULL,	    name, TXN_INVALID, DB_ODDFILESIZE | DB_RDONLY)) != 0)		return (ret);	/*	 * Set our name in the Queue subsystem;  we may need it later	 * to deal with extents.	 */	if (dbp->type == DB_QUEUE &&	    (ret = __qam_set_ext_data(dbp, name)) != 0)		return (ret);	/* Mark the dbp as opened, so that we correctly handle its close. */	F_SET(dbp, DB_AM_OPEN_CALLED);	/* Find out the page number of the last page in the database. */	__memp_last_pgno(dbp->mpf, &vdp->last_pgno);	/*	 * DB_ORDERCHKONLY is a special case;  our file consists of	 * several subdatabases, which use different hash, bt_compare,	 * and/or dup_compare functions.  Consequently, we couldn't verify	 * sorting and hashing simply by calling DB->verify() on the file.	 * DB_ORDERCHKONLY allows us to come back and check those things;  it	 * requires a subdatabase, and assumes that everything but that	 * database's sorting/hashing is correct.	 */	if (LF_ISSET(DB_ORDERCHKONLY)) {		ret = __db_vrfy_orderchkonly(dbp, vdp, name, subdb, flags);		goto done;	}	/*	 * When salvaging, we use a db to keep track of whether we've seen a	 * given overflow or dup page in the course of traversing normal data.	 * If in the end we have not, we assume its key got lost and print it	 * with key "UNKNOWN".	 */	if (LF_ISSET(DB_SALVAGE)) {		if ((ret = __db_salvage_init(vdp)) != 0)			return (ret);		/*		 * If we're not being aggressive, attempt to crack subdbs.		 * "has" will indicate whether the attempt has succeeded		 * (even in part), meaning that we have some semblance of		 * subdbs;  on the walkpages pass, we print out		 * whichever data pages we have not seen.		 */		if (!LF_ISSET(DB_AGGRESSIVE) && (__db_salvage_subdbs(dbp,		    vdp, handle, callback, flags, &has)) != 0)			isbad = 1;		/*		 * If we have subdatabases, we need to signal that if		 * any keys are found that don't belong to a subdatabase,		 * they'll need to have an "__OTHER__" subdatabase header		 * printed first.  Flag this.  Else, print a header for		 * the normal, non-subdb database.		 */		if (has == 1)			F_SET(vdp, SALVAGE_PRINTHEADER);	}	if ((ret =	    __db_vrfy_walkpages(dbp, vdp, handle, callback, flags)) != 0) {		if (ret == DB_VERIFY_BAD)			isbad = 1;		else			goto err;	}	/* If we're verifying, verify inter-page structure. */	if (!LF_ISSET(DB_SALVAGE) && isbad == 0)		if ((ret =		    __db_vrfy_structure(dbp, vdp, name, 0, flags)) != 0) {			if (ret == DB_VERIFY_BAD)				isbad = 1;			else				goto err;		}	/*	 * If we're salvaging, output with key UNKNOWN any overflow or dup pages	 * we haven't been able to put in context.  Then destroy the salvager's	 * state-saving database.	 */	if (LF_ISSET(DB_SALVAGE)) {		if ((ret = __db_salvage_unknowns(dbp,		    vdp, handle, callback, flags)) != 0)			isbad = 1;		/* No return value, since there's little we can do. */		__db_salvage_destroy(vdp);	}err:	if (LF_ISSET(DB_SALVAGE) &&	    (has == 0 || F_ISSET(vdp, SALVAGE_PRINTFOOTER)))		(void)__db_prfooter(handle, callback);	/* Send feedback that we're done. */done:	if (!LF_ISSET(DB_SALVAGE) && dbp->db_feedback != NULL)		dbp->db_feedback(dbp, DB_VERIFY, 100);	if (fhp != NULL &&	    (t_ret = __os_closehandle(dbenv, fhp)) != 0 && ret == 0)		ret = t_ret;	if (vdp != NULL &&	    (t_ret = __db_vrfy_dbinfo_destroy(dbenv, vdp)) != 0 && ret == 0)		ret = t_ret;	if (real_name != NULL)		__os_free(dbenv, real_name);	/*	 * DB_VERIFY_FATAL is a private error, translate to a public one.	 *	 * If we didn't find a page, it's probably a page number was corrupted.	 * Return the standard corruption error.	 *	 * Otherwise, if we found corruption along the way, set the return.	 */	if (ret == DB_VERIFY_FATAL ||	    ret == DB_PAGE_NOTFOUND || (ret == 0 && isbad == 1))		ret = DB_VERIFY_BAD;	/* Make sure there's a public complaint if we found corruption. */	if (ret != 0)		__db_err(dbenv, "%s: %s", name, db_strerror(ret));	return (ret);}/* * __db_vrfy_pagezero -- *	Verify the master metadata page.  Use seek, read, and a local buffer *	rather than the DB paging code, for safety. * *	Must correctly (or best-guess) set dbp->type and dbp->pagesize. */static int__db_vrfy_pagezero(dbp, vdp, fhp, flags)	DB *dbp;	VRFY_DBINFO *vdp;	DB_FH *fhp;	u_int32_t flags;{	DBMETA *meta;	DB_ENV *dbenv;	VRFY_PAGEINFO *pip;	db_pgno_t freelist;	size_t nr;	int isbad, ret, swapped;	u_int8_t mbuf[DBMETASIZE];	isbad = ret = swapped = 0;	freelist = 0;	dbenv = dbp->dbenv;	meta = (DBMETA *)mbuf;	dbp->type = DB_UNKNOWN;	/*	 * Seek to the metadata page.	 * Note that if we're just starting a verification, dbp->pgsize	 * may be zero;  this is okay, as we want page zero anyway and	 * 0*0 == 0.	 */	if ((ret = __os_seek(dbenv, fhp, 0, 0, 0, 0, DB_OS_SEEK_SET)) != 0 ||	    (ret = __os_read(dbenv, fhp, mbuf, DBMETASIZE, &nr)) != 0) {		__db_err(dbenv,		    "Metadata page %lu cannot be read: %s",		    (u_long)PGNO_BASE_MD, db_strerror(ret));		return (ret);	}	if (nr != DBMETASIZE) {		EPRINT((dbenv,		    "Page %lu: Incomplete metadata page",		    (u_long)PGNO_BASE_MD));		return (DB_VERIFY_FATAL);	}	if ((ret = __db_chk_meta(dbenv, dbp, meta, 1)) != 0) {		EPRINT((dbenv,		    "Page %lu: metadata page corrupted", (u_long)PGNO_BASE_MD));		isbad = 1;		if (ret != -1) {			EPRINT((dbenv,			    "Page %lu: could not check metadata page",			    (u_long)PGNO_BASE_MD));			return (DB_VERIFY_FATAL);		}	}	/*	 * Check all of the fields that we can.	 *	 * 08-11: Current page number.  Must == pgno.	 * Note that endianness doesn't matter--it's zero.	 */	if (meta->pgno != PGNO_BASE_MD) {		isbad = 1;		EPRINT((dbenv, "Page %lu: pgno incorrectly set to %lu",		    (u_long)PGNO_BASE_MD, (u_long)meta->pgno));	}

⌨️ 快捷键说明

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