dbe_vrfy.c

来自「db.* (pronounced dee-be star) is an adva」· C语言 代码 · 共 478 行

C
478
字号
/*************************************************************************** *                                                                         * * db.*                                                                    * * open source database, dbedit 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.                                      *  *                                                                         * **************************************************************************//*-----------------------------------------------------------------------    dbe_vrfy.c - DBEDIT, verify command    The verify command checks the consistency of one instance of a set.    The check is similar to that performed by DBCHECK, except that DBCHECK    reads through all records in the owner and member files, and also    performs other checks not done by verify (e.g. key files).-----------------------------------------------------------------------*/#include "db.star.h"#include "dbe_type.h"#include "dbe_str.h"#include "dbe_err.h"#include "dbe_ext.h"#include "dbe_io.h"/* ************************** FUNCTIONS ****************************** *//* Verify a set, i.e. check owner & member pointers.    First establish whether current record is the owner, or a member,    of the set to be checked. If it is neither, return an error.    If the current record is a member, find the owner, and check its    type.    The verify starts from the owner record. Its set pointers are    checked, and then the members are read sequentially (from first    to last), each previous pointer and owner pointer being tested for    consistency.*/int verify(DBE_TOK *tokens, int *tokenptr, DB_TCHAR *errstr, DB_TASK *task){    int         i, error, err, status, mt, token, first, last;    long        error_count;    char       *p;    short       own_fno;    short       own_type, curr_type, type, st;    DB_ADDR     own_dba = 0;    MEM_PTR     memptr;    DB_ULONG    own_rno;    int         hold = NOPGHOLD;    error = err = 0;    error_count = 0L;    own_fno = -1;    token = *tokenptr + 1;    st = (short) tokens[token].ival;    /* Test for valid current record */    if ((error = dbe_chkdba(task->curr_rec, task)) < 0)        return (error);    /* Get nextslot values for all files */    for (i = 0; i < task->size_ft; i++)    {        if (task->file_table[i].ft_type == DATA)            dio_pzread((FILE_NO) i, task);    }    /* Get current record type and owner record type */    memcpy(&curr_type, slot.buffer, sizeof(short));    if (curr_type & RLBMASK)        curr_type &= ~RLBMASK;    own_type = task->set_table[st].st_own_rt;    /* Is current record owner of set to be verified ? */    if (curr_type == own_type)    {        own_dba = task->curr_rec;        p = slot.buffer;    }    else    {        /* Current record is not owner - must find and read owner.           Is current record member of set to be verified ?        */        first = task->set_table[st].st_members;        last = first + task->set_table[st].st_memtot;        for (mt = first; mt < last; mt++)        {            if (curr_type == task->member_table[mt].mt_record)                break;        }        if (mt < last)        {            /* Current record is a member - find owner */            memcpy(&memptr, slot.buffer + task->member_table[mt].mt_mem_ptr,                   sizeof(MEM_PTR));            /* Check owner address is valid, and owner is in right file */            own_dba = memptr.owner;            d_decode_dba(own_dba, &own_fno, &own_rno);            if (vrfydba(own_dba, task)             || (own_fno != task->record_table[own_type].rt_file))            {                pr_error(0);                pr_errdba(BAD_OWNP, memptr.owner);                pr_ownmem(st, task->curr_rec, M_VRFYMA, task);                error_count++;            }            /* Read the owner record - hold it in cache while verifying */            status = dio_read(own_dba, &p, hold = PGHOLD , task);            if (status == S_OKAY && p != NULL)            {                /* Check type of record just read */                memcpy(&type, p, sizeof(short));                if (type & RLBMASK)                    type &= ~RLBMASK;                if (type != own_type)                {                    pr_error(0);                    pr_errtype(BAD_OWNT, (int) type);                    pr_ownmem(st, task->curr_rec, M_VRFYMA, task);                    error_count++;                }            }            else                error = ERR_READ;        }        else        {            /* Current record is neither owner nor member of set */            error = ERR_CSET;        }    }    /* Verify set owner pointers of owner record */    if (error >= 0 && !error_count)        error_count = chk_own(p, st, own_dba, task);    /* Finished verifying - release owner from cache, if held */    if (hold == PGHOLD)        dio_release(own_dba, PGFREE , task);    *tokenptr = ++token;    if (error >= 0)    {        pr_total(error_count);        if (err)            error = err;    }    if ((error == ERR_READ) || (error == ERR_OPN))    {        if (own_fno >= 0 && own_fno < task->size_ft)            vtstrcpy(errstr, task->file_table[own_fno].ft_name);    }    return (error);}/* ******************* Check owner pointers ************************** *//* chk_own - based on function of same name in setchk.c*/long chk_own(char *own_rec, short st, DB_ADDR own_dba, DB_TASK *task){    SET_PTR        setptr;    MEM_PTR        memptr;    DB_ADDR        mem_dba, prev_mem;    register int   mt;    short          fno;    char          *p;    short          type;    F_ADDR         mcount;    int            error, status;    long           error_count;    DB_ULONG       recNum;    error_count = 0L;    /* copy the set structure from the record */    memcpy(&setptr, own_rec + task->set_table[st].st_own_ptr, sizeof(SET_PTR));    /* check the validity of the first and last pointers */    if (vrfydba(setptr.last, task))    {        pr_error(0);        pr_errdba(BAD_LAST, setptr.last);        pr_ownmem(st, own_dba, M_VRFYOA, task);        error_count++;    }    if (vrfydba(setptr.first, task))    {        pr_error(0);        pr_errdba(BAD_FRST, setptr.first);        pr_ownmem(st, own_dba, M_VRFYOA, task);        error_count++;        return (error_count);      /* must have good first ptr to proceed */    }    /* get the DB_ADDR of the first member */    mem_dba = setptr.first;    mcount = 0;    prev_mem = NULL_DBA;    /* scan all members in this set */    while (mem_dba != NULL_DBA)    {        error = 0;        /* make sure is it a good database address */        if (vrfydba(mem_dba, task))        {            pr_error(error++);            pr_errdba(BAD_MEMP, mem_dba);            ++error_count;            return (error_count);        }        /* read the member record if necessary */        if (mem_dba == task->curr_rec)        {            p = slot.buffer;        }        else if (mem_dba == own_dba)        {            p = own_rec;        }        else        {            d_decode_dba(mem_dba, &fno, &recNum);            status = dio_read(mem_dba, &p, NOPGHOLD , task);            if (status != S_OKAY || p == NULL)            {                dbe_err(ERR_READ, task->file_table[fno].ft_name);                return (error_count);            }        }        /* obtain and validate the member type */        memcpy(&type, p, sizeof(short));        type &= ~RLBMASK;        if ((mt = val_mtype(st, type, task)) == -1)        {            pr_error(error++);            pr_errtype(BAD_MEMT, (int) type);        }        /* obtain the member pointers */        memcpy(&memptr, p + task->member_table[mt].mt_mem_ptr, sizeof(MEM_PTR));        mcount++;        /* if this is the first member, the PREV pointer must be null */        if (mem_dba == setptr.first)        {            if (memptr.prev != NULL_DBA)            {                pr_error(error++);                dbe_err(ERR_PNN, NULL);            }        }        /* if this is the last member, the NEXT pointer must be null */        if (mem_dba == setptr.last)        {            if (memptr.next != NULL_DBA)            {                pr_error(error++);                dbe_err(ERR_NNN, NULL);                ++error_count;                pr_ownmem(st, mem_dba, M_VRFYMA, task);                mem_dba = NULL_DBA;                continue;            }        }        /* If PREV pointer is null, must be first member of set */        if (memptr.prev == NULL_DBA)        {            if (mem_dba != setptr.first)            {                pr_error(error++);                dbe_err(ERR_PN, NULL);            }        }        /* If NEXT pointer is null, must be last member of set */        if (memptr.next == NULL_DBA)        {            if (mem_dba != setptr.last)            {                pr_error(error++);                dbe_err(ERR_NN, NULL);            }        }        /* make sure that the owner pointers match up */        if (memptr.owner != own_dba)        {            pr_error(error++);            dbe_err(ERR_MEMP, NULL);        }        /* the previous pointer should point the the previous member */        if (memptr.prev != prev_mem)        {            pr_error(error++);            dbe_err(ERR_PREV, NULL);        }        /* summarize any errors */        if (error)        {            ++error_count;            pr_ownmem(st, mem_dba, M_VRFYMA, task);        }        /* point to the next member */        prev_mem = mem_dba;        mem_dba = memptr.next;    }                                   /* end scan all members in this set */    /* verify the membership count */    if (mcount != setptr.total)    {        pr_error(0);        ++error_count;        pr_errcount(setptr.total, mcount);        pr_ownmem(st, own_dba, M_VRFYOA, task);    }    return (error_count);}/* locate the member table entry for this record type - copied from setchk.c*/int val_mtype(short st, short type, DB_TASK *task){    register short i;    for ( i = task->set_table[st].st_members;          i < task->set_table[st].st_members + task->set_table[st].st_memtot;          i++ )    {        if (task->member_table[i].mt_record == type)            return (i);    }    return (-1);}/* Print error, and address of record with bad set owner or member pointer*/int pr_ownmem(short st, DB_ADDR dba, int message, DB_TASK *task){    DB_TCHAR    line[LINELEN];    short       fno;    DB_ULONG    rno;    d_decode_dba(dba, &fno, &rno);    vstprintf(line,        decimal ? DB_TEXT("%s%s%s[%d:%lu]\n") : DB_TEXT("%s%s%s[%x:%lx]\n"),        dbe_getstr(M_VRFYST), task->set_names[st], dbe_getstr(message),        fno, rno);    dbe_out(line, STDERR);    return 0;}/* General function for printing error message with database address*/int pr_errdba(int error, DB_ADDR dba){    DB_TCHAR    buffer[32];    short       fno;    DB_ULONG    rno;    d_decode_dba(dba, &fno, &rno);    vstprintf(buffer, decimal ? DB_TEXT("[%d:%ld]") : DB_TEXT("[%x:%lx]"),              fno, rno);    dbe_err(error, buffer);    return 0;}/* Print bad record type error, with record type read from file*/int pr_errtype(int error, int type){    DB_TCHAR buffer[32];    vstprintf(buffer, decimal ? DB_TEXT("%d") : DB_TEXT("%x"), type);    dbe_err(error, buffer);    return 0;}/* Print bad membership count error, with actual and stored membership counts*/int pr_errcount(long stored, long actual){    DB_TCHAR line[LINELEN];    long     n1, n2;    n1 = stored;    n2 = actual;    vstprintf(line, DB_TEXT("%s%ld%s%ld\n"),              dbe_getstr(M_VRFYMM), n1,              dbe_getstr(M_VRFYAM), n2);    dbe_out(line, STDERR);    return 0;}/* Print total number of errors found*/int pr_total(long count){    DB_TCHAR line[LINELEN];    dbe_out(dbe_getstr(M_VRFYCO), STDERR);    vstprintf(line, DB_TEXT("%ld%s"),        count, dbe_getstr(count == 1L ? M_VRFY1E : M_VRFYER));    dbe_out(line, STDERR);    return 0;}/* Print opening error message, if this is the first error in this slot*/int pr_error(int count){    if (count == 0)        dbe_out(dbe_getstr(M_VRFYDE), STDERR);    return 0;}/* Check database address for validity*/int vrfydba(DB_ADDR dba, DB_TASK *task){    short    fno;    DB_ADDR  rno;    d_decode_dba(dba, &fno, &rno);    if ((fno < 0) || (fno >= task->size_ft))        return (BAD_DBA);    if (task->file_table[fno].ft_type == 'k')        return (BAD_DFIL);    if ((F_ADDR) rno < 0 || (F_ADDR) rno >= task->pgzero[fno].pz_next)        return (BAD_DBA);    return (0);}

⌨️ 快捷键说明

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