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

📄 db_vrfy.c

📁 这是linux下运行的mysql软件包,可用于linux 下安装 php + mysql + apach 的网络配置
💻 C
📖 第 1 页 / 共 5 页
字号:
/*- * See the file LICENSE for redistribution information. * * Copyright (c) 2000-2002 *	Sleepycat Software.  All rights reserved. * * $Id: db_vrfy.c,v 1.107 2002/09/03 17:27:15 bostic Exp $ */#include "db_config.h"#ifndef lintstatic const char revid[] = "$Id: db_vrfy.c,v 1.107 2002/09/03 17:27:15 bostic Exp $";#endif /* not lint */#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/qam.h"#include "dbinc/txn.h"static 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 __P((DB *, VRFY_DBINFO *, db_pgno_t,		PAGE *, void *, int (*)(void *, const void *), u_int32_t));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_vrfy_common		__P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t, 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));/* * 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). *//* * __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). * *	__db_verify itself is simply a wrapper to __db_verify_internal, *	which lets us pass appropriate equivalents to FILE * in from the *	non-C APIs. * * PUBLIC: int __db_verify * PUBLIC:     __P((DB *, const char *, const char *, FILE *, u_int32_t)); */int__db_verify(dbp, file, database, outfile, flags)	DB *dbp;	const char *file, *database;	FILE *outfile;	u_int32_t flags;{	return (__db_verify_internal(dbp,	    file, database, outfile, __db_verify_callback, flags));}/* * __db_verify_callback -- *	Callback function for using pr_* functions from C. * * PUBLIC: int  __db_verify_callback __P((void *, const void *)); */int__db_verify_callback(handle, str_arg)	void *handle;	const void *str_arg;{	char *str;	FILE *f;	str = (char *)str_arg;	f = (FILE *)handle;	if (fprintf(f, "%s", str) != (int)strlen(str))		return (EIO);	return (0);}/* * __db_verify_internal -- *	Inner meat of __db_verify. * * 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_orig, name, subdb, handle, callback, flags)	DB *dbp_orig;	const char *name, *subdb;	void *handle;	int (*callback) __P((void *, const void *));	u_int32_t flags;{	DB *dbp;	DB_ENV *dbenv;	DB_FH fh, *fhp;	VRFY_DBINFO *vdp;	int has, ret, isbad;	char *real_name;	dbenv = dbp_orig->dbenv;	vdp = NULL;	real_name = NULL;	ret = isbad = 0;	memset(&fh, 0, sizeof(fh));	fhp = &fh;	PANIC_CHECK(dbenv);	DB_ILLEGAL_AFTER_OPEN(dbp_orig, "verify");#define	OKFLAGS (DB_AGGRESSIVE | DB_NOORDERCHK | DB_ORDERCHKONLY | \    DB_PRINTABLE | DB_SALVAGE)	if ((ret = __db_fchk(dbenv, "DB->verify", flags, OKFLAGS)) != 0)		return (ret);	/*	 * DB_SALVAGE is mutually exclusive with the other flags except	 * DB_AGGRESSIVE and DB_PRINTABLE.	 */	if (LF_ISSET(DB_SALVAGE) &&	    (flags & ~DB_AGGRESSIVE & ~DB_PRINTABLE) != DB_SALVAGE)		return (__db_ferr(dbenv, "__db_verify", 1));	/* DB_AGGRESSIVE and DB_PRINTABLE are only meaningful when salvaging. */	if ((LF_ISSET(DB_AGGRESSIVE) || LF_ISSET(DB_PRINTABLE)) &&	    !LF_ISSET(DB_SALVAGE))		return (__db_ferr(dbenv, "__db_verify", 1));	if (LF_ISSET(DB_ORDERCHKONLY) && flags != DB_ORDERCHKONLY)		return (__db_ferr(dbenv, "__db_verify", 1));	if (LF_ISSET(DB_ORDERCHKONLY) && subdb == NULL) {		__db_err(dbenv, "DB_ORDERCHKONLY requires a database name");		return (EINVAL);	}	/*	 * 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)) {		dbp_orig->errx(dbp_orig,	    "verify may not be used with transactions, logging, or locking");		return (EINVAL);		/* NOTREACHED */	}	/* Create a dbp to use internally, which we can close at our leisure. */	if ((ret = db_create(&dbp, dbenv, 0)) != 0)		goto err;	F_SET(dbp, DB_AM_VERIFYING);	/* Copy the supplied pagesize, which we use if the file one is bogus. */	if (dbp_orig->pgsize >= DB_MIN_PGSIZE &&	    dbp_orig->pgsize <= DB_MAX_PGSIZE)		dbp->set_pagesize(dbp, dbp_orig->pgsize);	/* Copy the feedback function, if present, and initialize it. */	if (!LF_ISSET(DB_SALVAGE) && dbp_orig->db_feedback != NULL) {		dbp->set_feedback(dbp, dbp_orig->db_feedback);		dbp->db_feedback(dbp, DB_VERIFY, 0);	}	/*	 * Copy the comparison and hashing functions.  Note that	 * even if the database is not a hash or btree, the respective	 * internal structures will have been initialized.	 */	if (dbp_orig->dup_compare != NULL &&	    (ret = dbp->set_dup_compare(dbp, dbp_orig->dup_compare)) != 0)		goto err;	if (((BTREE *)dbp_orig->bt_internal)->bt_compare != NULL &&	    (ret = dbp->set_bt_compare(dbp,	    ((BTREE *)dbp_orig->bt_internal)->bt_compare)) != 0)		goto err;	if (((HASH *)dbp_orig->h_internal)->h_hash != NULL &&	    (ret = dbp->set_h_hash(dbp,	    ((HASH *)dbp_orig->h_internal)->h_hash)) != 0)		goto err;	/*	 * 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, 0444, 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);	/* 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. */	dbp->mpf->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.		 */		has = 0;		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);		else if ((ret = __db_prheader(dbp,		    NULL, 0, 0, handle, callback, vdp, PGNO_BASE_MD)) != 0)			goto err;	}	if ((ret =	    __db_vrfy_walkpages(dbp, vdp, handle, callback, flags)) != 0) {		if (ret == DB_VERIFY_BAD)			isbad = 1;		else if (ret != 0)			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 if (ret != 0)				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);	}	if (0) {		/* Don't try to strerror() DB_VERIFY_FATAL;  it's private. */err:		if (ret == DB_VERIFY_FATAL)			ret = DB_VERIFY_BAD;		(void)__db_err(dbenv, "%s: %s", name, db_strerror(ret));	}	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 (F_ISSET(fhp, DB_FH_VALID))		(void)__os_closehandle(dbenv, fhp);	if (dbp)		(void)dbp->close(dbp, 0);	if (vdp)		(void)__db_vrfy_dbinfo_destroy(dbenv, vdp);	if (real_name)		__os_free(dbenv, real_name);	if ((ret == 0 && isbad == 1) || ret == DB_VERIFY_FATAL)		ret = DB_VERIFY_BAD;	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));	}	/* 12-15: Magic number.  Must be one of valid set. */	if (__db_is_valid_magicno(meta->magic, &dbp->type))		swapped = 0;	else {		M_32_SWAP(meta->magic);		if (__db_is_valid_magicno(meta->magic,		    &dbp->type))			swapped = 1;

⌨️ 快捷键说明

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