00001 /*- 00002 * See the file LICENSE for redistribution information. 00003 * 00004 * Copyright (c) 1999, 2000 00005 * Sleepycat Software. All rights reserved. 00006 */ 00007 00008 #include "config.h" 00009 00010 #ifndef lint 00011 static const char revid[] = "$Id: qam__verify_8c-source.html,v 1.1 2008年06月08日 10:21:47 sebdiaz Exp $"; 00012 #endif /* not lint */ 00013 00014 #ifndef NO_SYSTEM_INCLUDES 00015 #include <sys/types.h> 00016 00017 #endif 00018 00019 #include "db_int.h" 00020 #include "db_page.h" 00021 #include "db_verify.h" 00022 #include "qam.h" 00023 #include "db_ext.h" 00024 00025 /* 00026 * CDB___qam_vrfy_meta -- 00027 * Verify the queue-specific part of a metadata page. 00028 * 00029 * PUBLIC: int CDB___qam_vrfy_meta __P((DB *, VRFY_DBINFO *, QMETA *, 00030 * PUBLIC: db_pgno_t, u_int32_t)); 00031 */ 00032 int 00033 CDB___qam_vrfy_meta(dbp, vdp, meta, pgno, flags) 00034 DB *dbp; 00035 VRFY_DBINFO *vdp; 00036 QMETA *meta; 00037 db_pgno_t pgno; 00038 u_int32_t flags; 00039 { 00040 VRFY_PAGEINFO *pip; 00041 int isbad, ret, t_ret; 00042 00043 if ((ret = CDB___db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0) 00044 return (ret); 00045 isbad = 0; 00046 00047 /* 00048 * Queue can't be used in subdatabases, so if this isn't set 00049 * something very odd is going on. 00050 */ 00051 if (!F_ISSET(pip, VRFY_INCOMPLETE)) 00052 EPRINT((dbp->dbenv, "Queue databases must be one-per-file.")); 00053 00054 /* start */ 00055 if (meta->start != 1) { 00056 EPRINT((dbp->dbenv, 00057 "Queue start offset of %lu", meta->start)); 00058 isbad = 1; 00059 } 00060 00061 /* first_recno, cur_recno */ 00062 if (meta->cur_recno < meta->first_recno) { 00063 EPRINT((dbp->dbenv, 00064 "Wrongly ordered first/current recnos, %lu/%lu", 00065 meta->first_recno, meta->cur_recno)); 00066 isbad = 1; 00067 } 00068 00069 /* cur_recno/rec_page */ 00070 if (vdp->last_pgno > 0 && 00071 (1 + ((meta->cur_recno - meta->start) / meta->rec_page)) != 00072 vdp->last_pgno) { 00073 EPRINT((dbp->dbenv, 00074 "Incorrect last page number in queue database")); 00075 isbad = 1; 00076 } 00077 00078 /* 00079 * re_len: If this is bad, we can't safely verify queue data pages, so 00080 * return DB_VERIFY_FATAL 00081 */ 00082 if (ALIGN(meta->re_len + sizeof(QAMDATA) - 1, sizeof(u_int32_t)) * 00083 meta->rec_page + sizeof(QPAGE) > dbp->pgsize) { 00084 EPRINT((dbp->dbenv, 00085 "Queue record length %lu impossibly high for page size and records per page", 00086 meta->re_len)); 00087 ret = DB_VERIFY_FATAL; 00088 goto err; 00089 } else { 00090 vdp->re_len = meta->re_len; 00091 vdp->rec_page = meta->rec_page; 00092 } 00093 00094 err: if ((t_ret = CDB___db_vrfy_putpageinfo(vdp, pip)) != 0 && ret == 0) 00095 ret = t_ret; 00096 return (ret == 0 && isbad == 1 ? DB_VERIFY_BAD : ret); 00097 } 00098 00099 /* 00100 * CDB___qam_vrfy_data -- 00101 * Verify a queue data page. 00102 * 00103 * PUBLIC: int CDB___qam_vrfy_data __P((DB *, VRFY_DBINFO *, QPAGE *, 00104 * PUBLIC: db_pgno_t, u_int32_t)); 00105 */ 00106 int 00107 CDB___qam_vrfy_data(dbp, vdp, h, pgno, flags) 00108 DB *dbp; 00109 VRFY_DBINFO *vdp; 00110 QPAGE *h; 00111 db_pgno_t pgno; 00112 u_int32_t flags; 00113 { 00114 DB fakedb; 00115 struct __queue fakeq; 00116 QAMDATA *qp; 00117 db_recno_t i; 00118 u_int8_t qflags; 00119 00120 /* 00121 * Not much to do here, except make sure that flags are reasonable. 00122 * 00123 * QAM_GET_RECORD assumes a properly initialized q_internal 00124 * structure, however, and we don't have one, so we play 00125 * some gross games to fake it out. 00126 */ 00127 fakedb.q_internal = &fakeq; 00128 fakeq.re_len = vdp->re_len; 00129 00130 for (i = 0; i < vdp->rec_page; i++) { 00131 qp = QAM_GET_RECORD(&fakedb, h, i); 00132 if ((u_int8_t *)qp >= (u_int8_t *)h + dbp->pgsize) { 00133 EPRINT((dbp->dbenv, 00134 "Queue record %lu extends past end of page %lu", 00135 i, pgno)); 00136 return (DB_VERIFY_BAD); 00137 } 00138 00139 qflags = qp->flags; 00140 qflags &= !(QAM_VALID | QAM_SET); 00141 if (qflags != 0) { 00142 EPRINT((dbp->dbenv, 00143 "Queue record %lu on page %lu has bad flags", 00144 i, pgno)); 00145 return (DB_VERIFY_BAD); 00146 } 00147 } 00148 00149 return (0); 00150 } 00151 00152 /* 00153 * CDB___qam_vrfy_structure -- 00154 * Verify a queue database structure, such as it is. 00155 * 00156 * PUBLIC: int CDB___qam_vrfy_structure __P((DB *, VRFY_DBINFO *, u_int32_t)); 00157 */ 00158 int 00159 CDB___qam_vrfy_structure(dbp, vdp, flags) 00160 DB *dbp; 00161 VRFY_DBINFO *vdp; 00162 u_int32_t flags; 00163 { 00164 VRFY_PAGEINFO *pip; 00165 db_pgno_t i; 00166 int ret, isbad; 00167 00168 isbad = 0; 00169 00170 if ((ret = CDB___db_vrfy_getpageinfo(vdp, PGNO_BASE_MD, &pip)) != 0) 00171 return (ret); 00172 00173 if (pip->type != P_QAMMETA) { 00174 EPRINT((dbp->dbenv, 00175 "Queue database has no meta page")); 00176 isbad = 1; 00177 goto err; 00178 } 00179 00180 if ((ret = CDB___db_vrfy_pgset_inc(vdp->pgset, 0)) != 0) 00181 goto err; 00182 00183 for (i = 1; i <= vdp->last_pgno; i++) { 00184 if ((ret = CDB___db_vrfy_putpageinfo(vdp, pip)) != 0 || 00185 (ret = CDB___db_vrfy_getpageinfo(vdp, i, &pip)) != 0) 00186 return (ret); 00187 if (!F_ISSET(pip, VRFY_IS_ALLZEROES) && 00188 pip->type != P_QAMDATA) { 00189 EPRINT((dbp->dbenv, 00190 "Queue database page %lu of incorrect type %lu", 00191 i, pip->type)); 00192 isbad = 1; 00193 goto err; 00194 } else if ((ret = CDB___db_vrfy_pgset_inc(vdp->pgset, i)) != 0) 00195 goto err; 00196 } 00197 00198 err: if ((ret = CDB___db_vrfy_putpageinfo(vdp, pip)) != 0) 00199 return (ret); 00200 return (isbad == 1 ? DB_VERIFY_BAD : 0); 00201 }