dbcheck.c
来自「db.* (pronounced dee-be star) is an adva」· C语言 代码 · 共 2,087 行 · 第 1/5 页
C
2,087 行
/*************************************************************************** * * * db.* * * open source database, dbcheck utility * * * * Copyright (c) 2000 Centura Software Corporation. All rights reserved. * * * * Use of this software, whether in source code format, or in executable, * * binary object code form, is governed by the CENTURA OPEN SOURCE LICENSE * * which is fully described in the LICENSE.TXT file, included within this * * distribution of source code files. * * * **************************************************************************//*----------------------------------------------------------------------- dbcheck - db.* Database Consistency Check Utility To execute: dbcheck [-options] dbname [dbfile(s)] Options: [-s] [-k] [-dk] [-kd] [-ts] [-a] [-r#] [p#] [-f#] [-t] [-c] [-sg [<mode>,]<password>] Where: -s = Perform complete set consistency check -k = Perform key file structure consistency check -dk = Perform key access consistency check from data files -kd = Perform key data consisteny check from key files -ts = Perform time stamp checks for records and sets -a = Does -s -dk -kd -ts -nk = Disables -k, -dk, -kd, and causes key files to be ignored -r# = Report every # percent to stderr -p# = Number of pages for db.* to allocate to its page cache -f# = Number of open files db.* is allowed to have -t = Print a traceback of the b-tree at the first sign of disorder -c = Print counts of objects scanned in the check -sg = Specifies the SafeGarde encryption information dbname = Name of database to be checked dbfile(s) = If specified check only these files If no "-" options are specified, dbcheck merely checks the delete chains and verifies that the ids and addresses in each slot are sane. The "-" options perform better integrity checks, but can add significant run time. The -r option is useful when you have a huge database, and you want to keep tabs in how far dbcheck has progressed. The -f and -p options can improve speed, at the cost of extra memory. The -t option is used to quickly inspect the tree to find out why it is disordered. The -c option can be useful to determine if the database has application level integrity.-----------------------------------------------------------------------*//*********************** INCLUDE FILES ******************************/#define MOD dbcheck#include "db.star.h"#include "dbcache.h"#include "version.h"#define DBCHECK#include "cnvfld.h"#define ERR_DEFINE#include "dbcheck.h"#define MAXTEXT 1600/* ********************** EXTERNAL VARIABLE DECLARATIONS ************* */extern char etext, edata, end;/* ********************** LOCAL FUNCTION DECLARATIONS **************** */static void flush(void);void EXTERNAL_FCN dbcheck_dberr(int errnum, DB_TCHAR *errmsg){ vtprintf(DB_TEXT("\n%s (errnum = %d)\n"), errmsg, errnum);}/***************************************************************************//***************************************************************************//* Main Processing *//***************************************************************************//***************************************************************************/int MAIN(int argc, DB_TCHAR *argv[]){ int status = S_OKAY; long tot_err_cnt = 0; char *pgbuf = NULL; CHKOPTS *opts = NULL; DBINFO *dbi = NULL; DB_TASK *task = NULL; /* dberr and other macros reference a pointer called 'task' */ setvbuf( stdout, NULL, _IONBF, 0 ); setvbuf( stderr, NULL, _IONBF, 0 ); vtprintf(DBSTAR_UTIL_DESC(DB_TEXT("Database Consistency Check"))); psp_init(); if ((status = parse_args(argc, argv, &opts)) != S_OKAY) { psp_term(); return 1; } fflush(stdout); psp_handleInterrupt(flush); if ((status = d_opentask(&task)) == S_OKAY) { if ((status = d_set_dberr(dbcheck_dberr, task)) == S_OKAY) { if ((status = setup(&pgbuf, opts, &dbi, task)) == S_OKAY) status = scan(pgbuf, dbi, task); fflush(stdout); pr_stat(status, dbi); if (status == S_OKAY) pr_counts(dbi, task); if (dbi) /* allocated in setup_db */ { if (dbi->errinfo) tot_err_cnt += dbi->errinfo->tot_err_cnt; free_dbinfo(dbi); } if (pgbuf) /* allocated in setup_db */ psp_freeMemory(pgbuf, 0); d_close(task); /* database opened in setup() */ } d_closetask(task); } psp_handleInterrupt(NULL); if (status != S_OKAY) tot_err_cnt++; if (opts) /* allocated in parse_args */ { if (opts->fnames) psp_freeMemory(opts->fnames, 0); psp_freeMemory(opts, 0); } psp_term(); return(tot_err_cnt != 0);}/************************************************************************* Parse the argument vector*/ static int parse_args(int argc, DB_TCHAR **argv, CHKOPTS **ppopts){ register int i; CHKOPTS *opts;#if defined(SAFEGARDE) DB_TCHAR *cp; DB_TCHAR *password; int mode;#endif if (argc < 2) { usage(); return(S_UNAVAIL); } opts = (CHKOPTS *) psp_cGetMemory(sizeof(CHKOPTS), 0); if (!opts) return(S_NOMEMORY); opts->report = -1; opts->numpages = 64; opts->fnames = (DB_TCHAR **) psp_cGetMemory(argc * sizeof(DB_TCHAR *), 0); if (opts->fnames == NULL) { psp_freeMemory(opts, 0); return(S_NOMEMORY); } /* process the options */ for (i = 1; i < argc; i++) { if (vtstricmp(argv[i], DB_TEXT("-s")) == 0) opts->setscan = TRUE; else if (vtstricmp(argv[i], DB_TEXT("-k")) == 0) opts->keyscan = TRUE; else if (vtstricmp(argv[i], DB_TEXT("-dk")) == 0) opts->datkey = TRUE; else if (vtstricmp(argv[i], DB_TEXT("-kd")) == 0) opts->keydat = TRUE; else if (vtstricmp(argv[i], DB_TEXT("-ts")) == 0) opts->timestmp = TRUE; else if (vtstricmp(argv[i], DB_TEXT("-nk")) == 0) opts->ignorekey = TRUE; else if (vtstrnicmp(argv[i], DB_TEXT("-r"), 2) == 0) opts->report = (short) vttoi(argv[i] + 2); else if (vtstrnicmp(argv[i], DB_TEXT("-p"), 2) == 0) opts->numpages = (short) vttoi(argv[i] + 2); else if (vtstrnicmp(argv[i], DB_TEXT("-f"), 2) == 0) opts->numfiles = (short) vttoi(argv[i] + 2); else if (vtstricmp(argv[i], DB_TEXT("-t")) == 0) opts->treetrace = TRUE; else if (vtstricmp(argv[i], DB_TEXT("-c")) == 0) opts->counts = TRUE; else if (vtstricmp(argv[i], DB_TEXT("-a")) == 0) { opts->keyscan = opts->setscan = opts->datkey = opts->keydat = opts->timestmp = TRUE; } else if (vtstricmp(argv[i], DB_TEXT("-sg")) == 0) { if (i == argc - 1) { vftprintf(stderr, DB_TEXT("dbcheck: no password specified\n")); usage(); return S_UNAVAIL; }#if defined(SAFEGARDE) if ((cp = vtstrchr(argv[++i], DB_TEXT(','))) != NULL) *cp++ = DB_TEXT('\0'); if (cp) { if (vtstricmp(argv[i], "low") == 0) mode = LOW_ENC; else if (vtstricmp(argv[i], "med") == 0) mode = MED_ENC; else if (vtstricmp(argv[i], "high") == 0) mode = HIGH_ENC; else { vftprintf(stderr, DB_TEXT("dbcheck: invalid encryption mode\n")); usage(); return S_UNAVAIL; } password = cp; } else { mode = MED_ENC; password = argv[i]; } if ((opts->sg = sg_create(mode, password)) == NULL) { vftprintf(stderr, DB_TEXT("dbcheck: Could not create SafeGarde context\n")); return S_UNAVAIL; }#else vftprintf(stderr, DB_TEXT("dbcheck: SafeGarde is not available in this version\n")); return S_UNAVAIL;#endif } else if (argv[i][0] == DB_TEXT('-')) { vftprintf(stderr, DB_TEXT("dbcheck: invalid option: %s\n"), argv[i]); usage(); return(S_UNAVAIL); } else if (opts->dbname == NULL) opts->dbname = argv[i]; /* first non-option string is db name */ else opts->fnames[opts->nfnames++] = argv[i]; } if (opts->dbname == NULL) { usage(); return(S_UNAVAIL); } if (opts->ignorekey == TRUE) { opts->keyscan = opts->datkey = opts->keydat = FALSE; } *ppopts = opts; return(S_OKAY);}/*************************************************************************** Print a usage message*/static void usage(){ vtprintf(DB_TEXT("usage: dbcheck [-options] dbname [dbfile(s)]\n")); vtprintf(DB_TEXT("options: [-s] [-k] [-dk] [-kd] [-a] [-nk] [-ts] [-r#] [-p#] [-f#] [-t] [-c]\n")); vtprintf(DB_TEXT(" [-sg [<mode>,]password]\n\n")); vtprintf(DB_TEXT(" -s = Perform complete set consistency check\n")); vtprintf(DB_TEXT(" -k = Perform key file structure consistency check\n")); vtprintf(DB_TEXT(" -dk = Perform key access consistency check from data to key files\n")); vtprintf(DB_TEXT(" -kd = Perform key data consistency check from key to data files\n")); vtprintf(DB_TEXT(" -a = Does -s -dk -kd -ts\n")); vtprintf(DB_TEXT(" -nk = Disables -k, -dk, -kd, and causes key files to be ignored\n")); vtprintf(DB_TEXT(" -ts = Perform time stamp checks for records and sets\n")); vtprintf(DB_TEXT(" -r# = Report every # percent to stderr\n")); vtprintf(DB_TEXT(" -p# = Max number of pages for its page cache\n")); vtprintf(DB_TEXT(" -f# = Max number of open files allowed to have open at once\n")); vtprintf(DB_TEXT(" -t = Print a traceback of the b-tree at the first sign of disorder\n")); vtprintf(DB_TEXT(" -c = Print counts of objects scanned in the check\n")); vtprintf(DB_TEXT(" -sg = Specifies SafeGarde encryption information\n")); vtprintf(DB_TEXT(" <mode> can be 'low', 'med' (default), or 'high'\n")); vtprintf(DB_TEXT("\n"));}/*************************************************************************** Flush the stdout buffer in case only a few errors were found.*/static void flush(void){ DB_TCHAR ch; fflush(stdout); vtprintf(DB_TEXT("[INTERRUPT] Terminate? (y/n) ")); do { ch = vgettchar(); if (ch == DB_TEXT('y') || ch == DB_TEXT('Y')) exit(1); } while (ch != DB_TEXT('\n') && ch != DB_TEOF); vtprintf(DB_TEXT("Continuing execution\n"));}/************************************************************************** returns dbd_ver of DBD*/static int get_dbd_ver(DB_TCHAR *dbname, char *dbd_ver, DB_TASK *task){ DB_TCHAR dbfile[FILENMLEN] = DB_TEXT(""); PSP_FH dbf; int stat = S_OKAY; /* form database dictionary name */ if (vtstrlen(dbname) + vtstrlen(DB_REF(db_name)) >= FILENMLEN + 4) return (dberr(S_NAMELEN)); vtstrcpy(dbfile, dbname); vtstrcat(dbfile, DB_TEXT(".dbd")); if ((dbf = psp_fileOpen(dbfile, O_RDONLY, PSP_FLAG_DENYNO)) == NULL) return (dberr(S_INVDB)); if (psp_fileRead(dbf, (void *) dbd_ver, DBD_COMPAT_LEN) != DBD_COMPAT_LEN) stat = S_OKAY; psp_fileClose(dbf); if (stat != S_OKAY) dberr(stat); return(stat);}/************************************************************************** Setup structures used later*/static int setup( char **ppbuf, CHKOPTS *opts, DBINFO **ppdb, DB_TASK *task){ int status = S_OKAY; if ((status = setup_db(ppbuf, opts, ppdb, task)) == S_OKAY) { if ((status = setup_keys(*ppdb, task)) == S_OKAY) { if ((status = setup_sets(*ppdb, task)) == S_OKAY) { if ((status = setup_tots(*ppdb, task)) == S_OKAY) { if ((status = setup_cnts(*ppdb, task)) == S_OKAY) status = setup_temp_files(*ppdb, task); } } } } return status;}/*************************************************************************** Open the database and read the data dictionary*/static int setup_db( char **ppbuf, CHKOPTS *opts, DBINFO **ppdb, DB_TASK *task){ int i, j, status = S_OKAY; DB_TCHAR dbfile[FILENMLEN]; PSP_FH dbf; DB_TCHAR filnam[FILENMLEN]; DBINFO *dbi;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?