From e6c22123bc088afd6f0f564b8f5224af3cf2d2e6 Mon Sep 17 00:00:00 2001 From: jbj Date: Fri, 25 May 2001 19:51:53 +0000 Subject: [PATCH] - perform db->verify when closing db files. CVS patchset: 4813 CVS date: 2001/05/25 19:51:53 --- CHANGES | 1 + db3/configure | 6 +-- lib/rpmlib.h | 14 +++-- macros.in | 13 ++--- rpm.c | 22 ++++++-- rpmdb/Makefile.am | 2 +- rpmdb/db1.c | 26 ++++++--- rpmdb/db2.c | 16 +++++- rpmdb/db3.c | 157 +++++++++++++++++++++++++++++++++++++++++++++++------- rpmdb/dbconfig.c | 6 ++- rpmdb/rpmdb.c | 120 ++++++++++++++++++++++++++++++----------- rpmdb/rpmdb.h | 52 ++++++++++++++++-- rpmpopt.in | 1 + rpmqv.c | 21 +++++++- 14 files changed, 374 insertions(+), 83 deletions(-) diff --git a/CHANGES b/CHANGES index 968a305..e299ab8 100644 --- a/CHANGES +++ b/CHANGES @@ -63,6 +63,7 @@ - fix: skip %ghost files when building packages (#38218). - headerFree() returns NULL, _free is C++ safe. - remove all header region assertion failures, return NULL instead. + - perform db->verify when closing db files. 4.0 -> 4.0.[12] - add doxygen and lclint annotations most everywhere. diff --git a/db3/configure b/db3/configure index ff79eee..e4782e4 100755 --- a/db3/configure +++ b/db3/configure @@ -8,8 +8,8 @@ rm -f config.cache ln -sf ../dist $db_dist/../db/dist ln -sf ../dist $db_dist -CFALGS="-O2" $db_dist/configure \ - $(echo $* | sed -e "s% --cache-file=.*$% --enable-shared --enable-static --enable-debug --enable-rpc --with-uniquename=rpmdb --srcdir=$db_dist%") +CC="$CC" CFLAGS="$CFLAGS" $db_dist/configure \ + `echo $* | sed -e "s% --cache-file=.*$% --enable-shared --enable-static --enable-debug --enable-rpc --with-uniquename=rpmdb --srcdir=$db_dist%"` # XXX hack to get db-3.3.4 to configure properly rm -f $db_dist/../db/dist $db_dist/dist @@ -20,7 +20,7 @@ cat Makefile.orig | sed -e 's/ -g$/ -g -O2/' -e '/^install:/c\ listobjs:\ @echo $(OBJS) $(C_OBJS) \ \ -distdir install:\ +distdir install check:\ \ db3_install: all install_setip \\' > Makefile diff --git a/lib/rpmlib.h b/lib/rpmlib.h index 368c984..c08580d 100644 --- a/lib/rpmlib.h +++ b/lib/rpmlib.h @@ -603,9 +603,17 @@ int rpmdbInit(/*@null@*/ const char * root, int perms) /*@modifies fileSystem @*/; /** \ingroup rpmdb + * Verify database components. + * @param root path to top of install tree + * @return 0 on success + */ +int rpmdbVerify(/*@null@*/ const char * root) + /*@modifies fileSystem @*/; + +/** \ingroup rpmdb * Close all database indices and free rpmdb. * @param rpmdb rpm database - * @return 0 always + * @return 0 on success */ int rpmdbClose (/*@only@*/ /*@null@*/ rpmdb rpmdb) /*@modifies fileSystem @*/; @@ -613,7 +621,7 @@ int rpmdbClose (/*@only@*/ /*@null@*/ rpmdb rpmdb) /** \ingroup rpmdb * Sync all database indices. * @param rpmdb rpm database - * @return 0 always + * @return 0 on success */ int rpmdbSync (/*@null@*/ rpmdb rpmdb) /*@modifies fileSystem @*/; @@ -621,7 +629,7 @@ int rpmdbSync (/*@null@*/ rpmdb rpmdb) /** \ingroup rpmdb * Open all database indices. * @param rpmdb rpm database - * @return 0 always + * @return 0 on success */ int rpmdbOpenAll (/*@null@*/ rpmdb rpmdb) /*@modifies fileSystem @*/; diff --git a/macros.in b/macros.in index a4912a7..1aef98a 100644 --- a/macros.in +++ b/macros.in @@ -1,7 +1,7 @@ #/*! \page config_macros Default configuration: /usr/lib/rpm/macros # \verbatim # -# $Id: macros.in,v 1.77 2001/05/14 20:12:10 jbj Exp $ +# $Id: macros.in,v 1.78 2001/05/25 19:51:53 jbj Exp $ # # This is a global RPM configuration file. All changes made here will # be lost when the rpm package is upgraded. Any per-system configuration @@ -341,23 +341,24 @@ # ht_dup +++ (hash only) DB_DUP # ht_dupsort +++ (hash only) DB_DUPSORT #----------------------- rpmdb specific configuration: -# usedbenv +++ (on if not "traditional") Use db3 environment? # usecursors (always on) Use db3 cursors in get/put/del ? +# usedbenv +++ (on if not "traditional") Use db3 environment? +# verify (always on, db3 only) Verify db after close? # lockdbfd (always on for Packages) Use fcntl(2) locking ? -# nofsync Disable fsync(2) call performed after every db3 write? +# nofsync Disable fsync(2) call performed after db3 writes? # temporary Unlink file when closing. # # XXX Use a CDB database model for concurrent access (under development, # cursor teardown with signals needs work, much more besides.) #%__dbi_other usedbenv create joinenv cdb mpool \ -# mp_mmapsize=8Mb mp_size=512Kb usecursors +# mp_mmapsize=8Mb mp_size=512Kb verify usecursors # XXX Use transactions and logs for rpmdb durability (no clue yet): #%__dbi_other usedbenv create joinenv mpool txn log \ -# mp_mmapsize=8Mb mp_size=512Kb usecursors +# mp_mmapsize=8Mb mp_size=512Kb verify usecursors # XXX The "traditional" rpmdb shared/exclusive fcntl(2) lock on Packages model: -%__dbi_other usecursors +%__dbi_other verify usecursors # Note: adding nofsync here speeds up --rebuilddb a lot. %__dbi_rebuild nofsync !log !txn !cdb diff --git a/rpm.c b/rpm.c index 0e3cd66..35b4b81 100755 --- a/rpm.c +++ b/rpm.c @@ -10,7 +10,7 @@ #define GETOPT_ADDSIGN 1005 #define GETOPT_RESIGN 1006 #define GETOPT_DBPATH 1010 -#define GETOPT_REBUILDDB 1013 +#define GETOPT_REBUILDDB 1013 #define GETOPT_INSTALL 1014 #define GETOPT_RELOCATE 1016 #define GETOPT_SHOWRC 1018 @@ -18,6 +18,7 @@ #define GETOPT_DEFINEMACRO 1020 #define GETOPT_EVALMACRO 1021 #define GETOPT_RCFILE 1022 +#define GETOPT_VERIFYDB 1023 enum modes { MODE_UNKNOWN = 0, @@ -33,13 +34,14 @@ enum modes { MODE_QUERYTAGS = (1 << 9), MODE_INITDB = (1 << 10), MODE_TARBUILD = (1 << 11), - MODE_REBUILDDB = (1 << 12) + MODE_REBUILDDB = (1 << 12), + MODE_VERIFYDB = (1 << 13) }; #define MODES_QV (MODE_QUERY | MODE_VERIFY) #define MODES_BT (MODE_BUILD | MODE_TARBUILD | MODE_REBUILD | MODE_RECOMPILE) #define MODES_IE (MODE_INSTALL | MODE_UNINSTALL) -#define MODES_DB (MODE_INITDB | MODE_REBUILDDB) +#define MODES_DB (MODE_INITDB | MODE_REBUILDDB | MODE_VERIFYDB) #define MODES_K (MODE_CHECKSIG | MODES_RESIGN) #define MODES_FOR_DBPATH (MODES_BT | MODES_IE | MODES_QV | MODES_DB) @@ -184,6 +186,7 @@ static struct poptOption optionsTable[] = { { "rcfile", '\0', 0, 0, GETOPT_RCFILE, NULL, NULL}, #endif { "rebuilddb", '\0', 0, 0, GETOPT_REBUILDDB, NULL, NULL}, + { "verifydb", '\0', 0, 0, GETOPT_VERIFYDB, NULL, NULL}, { "relocate", '\0', POPT_ARG_STRING, 0, GETOPT_RELOCATE, NULL, NULL}, { "repackage", '\0', POPT_ARG_VAL, &rePackage, 1, NULL, NULL}, { "replacefiles", '\0', 0, &replaceFiles, 0, NULL, NULL}, @@ -290,6 +293,7 @@ static void printUsage(void) { puts(_(" rpm {--checksig -K} [--nopgp] [--nogpg] [--nomd5] [--rcfile ]")); puts(_(" package1 ... packageN")); puts(_(" rpm {--rebuilddb} [--rcfile ] [--dbpath ]")); + puts(_(" rpm {--verifydb} [--rcfile ] [--dbpath ]")); puts(_(" rpm {--querytags}")); } @@ -557,6 +561,8 @@ static void printHelp(void) { _("make sure a valid database exists")); printHelpLine( " --rebuilddb ", _("rebuild database from existing database")); + printHelpLine( " --verifydb ", + _("verify database files")); printHelpLine(_(" --dbpath "), _("use as the directory for the database")); printHelpLine( " --root ", @@ -810,6 +816,12 @@ int main(int argc, const char ** argv) bigMode = MODE_REBUILDDB; break; + case GETOPT_VERIFYDB: + if (bigMode != MODE_UNKNOWN && bigMode != MODE_VERIFYDB) + argerror(_("only one major mode may be specified")); + bigMode = MODE_VERIFYDB; + break; + case GETOPT_RELOCATE: if (*optArg != '/') argerror(_("relocations must begin with a /")); @@ -1095,6 +1107,10 @@ int main(int argc, const char ** argv) ec = rpmdbRebuild(rootdir); break; + case MODE_VERIFYDB: + ec = rpmdbVerify(rootdir); + break; + case MODE_QUERYTAGS: if (argc != 2) argerror(_("unexpected arguments to --querytags ")); diff --git a/rpmdb/Makefile.am b/rpmdb/Makefile.am index c3a8df3..43422a8 100644 --- a/rpmdb/Makefile.am +++ b/rpmdb/Makefile.am @@ -44,7 +44,7 @@ falloc.lo: falloc.c $(top_srcdir)/system.h $(top_srcdir)/rpmio/rpmio.h falloc.h .PHONY: createlinks createlinks: for lo in $(DB3LOBJS); do \ - [ -e $$lo ] || $(LN_S) $(top_builddir)/$(WITH_DB_SUBDIR)/$$lo $$lo ; \ + [ -f $$lo ] || $(LN_S) $(top_builddir)/$(WITH_DB_SUBDIR)/$$lo $$lo ; \ done clean-local: diff --git a/rpmdb/db1.c b/rpmdb/db1.c index cb88f37..1af5f2f 100644 --- a/rpmdb/db1.c +++ b/rpmdb/db1.c @@ -125,11 +125,6 @@ static int db1sync(dbiIndex dbi, unsigned int flags) { return rc; } -static int db1byteswapped(/*@unused@*/dbiIndex dbi) -{ - return 0; -} - static void * doGetRecord(FD_t pkgs, unsigned int offset) { void * uh = NULL; @@ -393,6 +388,23 @@ static int db1cput(dbiIndex dbi, /*@unused@*/ DBC * dbcursor, return rc; } +static int db1ccount(dbiIndex dbi, DBC * dbcursor, + /*@out@*/ unsigned int * countp, + /*@unused@*/ unsigned int flags) +{ + return EINVAL; +} + +static int db1byteswapped(/*@unused@*/dbiIndex dbi) +{ + return 0; +} + +static int db1stat(dbiIndex dbi, unsigned int flags) +{ + return EINVAL; +} + static int db1close(/*@only@*/ dbiIndex dbi, /*@unused@*/ unsigned int flags) { rpmdb rpmdb = dbi->dbi_rpmdb; @@ -422,7 +434,7 @@ static int db1close(/*@only@*/ dbiIndex dbi, /*@unused@*/ unsigned int flags) (void) unlink(fn); } - db3Free(dbi); + dbi = db3Free(dbi); base = _free(base); urlfn = _free(urlfn); return rc; @@ -515,5 +527,5 @@ exit: struct _dbiVec db1vec = { DB_VERSION_MAJOR, DB_VERSION_MINOR, DB_VERSION_PATCH, db1open, db1close, db1sync, db1copen, db1cclose, db1cdel, db1cget, db1cput, - db1byteswapped + db1ccount, db1byteswapped, db1stat }; diff --git a/rpmdb/db2.c b/rpmdb/db2.c index 7a59e87..af6d74f 100644 --- a/rpmdb/db2.c +++ b/rpmdb/db2.c @@ -534,6 +534,13 @@ static int db2cget(dbiIndex dbi, DBC * dbcursor, return rc; } +static int db2ccount(dbiIndex dbi, DBC * dbcursor, + /*@out@*/ unsigned int * countp, + /*@unused@*/ unsigned int flags) +{ + return EINVAL; +} + static int db2byteswapped(dbiIndex dbi) { int rc = 0; @@ -547,6 +554,11 @@ static int db2byteswapped(dbiIndex dbi) return rc; } +static int db2stat(dbiIndex dbi, unsigned int flags) +{ + return EINVAL; +} + static int db2close(/*@only@*/ dbiIndex dbi, unsigned int flags) { rpmdb rpmdb = dbi->dbi_rpmdb; @@ -607,7 +619,7 @@ static int db2close(/*@only@*/ dbiIndex dbi, unsigned int flags) urlfn = _free(urlfn); - db3Free(dbi); + dbi = db3Free(dbi); return rc; } @@ -875,7 +887,7 @@ static int db2open(/*@keep@*/ rpmdb rpmdb, int rpmtag, dbiIndex * dbip) struct _dbiVec db2vec = { DB_VERSION_MAJOR, DB_VERSION_MINOR, DB_VERSION_PATCH, db2open, db2close, db2sync, db2copen, db2cclose, db2cdel, db2cget, db2cput, - db2byteswapped + db2ccount, db2byteswapped, db2stat }; #endif /* DB_VERSION_MAJOR == 2 */ diff --git a/rpmdb/db3.c b/rpmdb/db3.c index 7daf6dc..34fe074 100644 --- a/rpmdb/db3.c +++ b/rpmdb/db3.c @@ -30,6 +30,52 @@ typedef int int32_t; /*@access dbiIndex@*/ /*@access dbiIndexSet@*/ +/** \ingroup dbi + * Hash database statistics. + */ +struct dbiHStats_s { + unsigned int hash_magic; /*!< hash database magic number. */ + unsigned int hash_version; /*!< version of the hash database. */ + unsigned int hash_nkeys; /*!< no. of unique keys in the database. */ + unsigned int hash_ndata; /*!< no. of key/data pairs in the database. */ + unsigned int hash_pagesize; /*!< db page (and bucket) size, in bytes. */ + unsigned int hash_nelem; /*!< estimated size of the hash table. */ + unsigned int hash_ffactor; /*!< no. of items per bucket. */ + unsigned int hash_buckets; /*!< no. of hash buckets. */ + unsigned int hash_free; /*!< no. of pages on the free list. */ + unsigned int hash_bfree; /*!< no. of bytes free on bucket pages. */ + unsigned int hash_bigpages; /*!< no. of big key/data pages. */ + unsigned int hash_big_bfree;/*!< no. of bytes free on big item pages. */ + unsigned int hash_overflows;/*!< no. of overflow pages. */ + unsigned int hash_ovfl_free;/*!< no. of bytes free on overflow pages. */ + unsigned int hash_dup; /*!< no. of duplicate pages. */ + unsigned int hash_dup_free; /*!< no. bytes free on duplicate pages. */ +}; + +/** \ingroup dbi + * B-tree database statistics. + */ +struct dbiBStats_s { + unsigned int bt_magic; /*!< btree database magic. */ + unsigned int bt_version; /*!< version of the btree database. */ + unsigned int bt_nkeys; /*!< no. of unique keys in the database. */ + unsigned int bt_ndata; /*!< no. of key/data pairs in the database. */ + unsigned int bt_pagesize; /*!< database page size, in bytes. */ + unsigned int bt_minkey; /*!< minimum keys per page. */ + unsigned int bt_re_len; /*!< length of fixed-length records. */ + unsigned int bt_re_pad; /*!< padding byte for fixed-length records. */ + unsigned int bt_levels; /*!< no. of levels in the database. */ + unsigned int bt_int_pg; /*!< no. of database internal pages. */ + unsigned int bt_leaf_pg; /*!< no. of database leaf pages. */ + unsigned int bt_dup_pg; /*!< no. of database duplicate pages. */ + unsigned int bt_over_pg; /*!< no. of database overflow pages. */ + unsigned int bt_free; /*!< no. of pages on the free list. */ + unsigned int bt_int_pgfree; /*!< no. of bytes free in internal pages. */ + unsigned int bt_leaf_pgfree;/*!< no. of bytes free in leaf pages. */ + unsigned int bt_dup_pgfree; /*!< no. of bytes free in duplicate pages. */ + unsigned int bt_over_pgfree;/*!< no. of bytes free in overflow pages. */ +}; + #if DB_VERSION_MAJOR == 3 #define __USE_DB3 1 @@ -132,7 +178,7 @@ static int db_fini(dbiIndex dbi, const char * dbhome, rc = cvtdberr(dbi, "dbenv->close", rc, _debug); if (dbfile) - rpmMessage(RPMMESS_DEBUG, _("closed db environment %s/%s\n"), + rpmMessage(RPMMESS_DEBUG, _("closed db environment %s/%s\n"), dbhome, dbfile); if (rpmdb->db_remove_env || dbi->dbi_tear_down) { @@ -148,7 +194,7 @@ static int db_fini(dbiIndex dbi, const char * dbhome, xx = cvtdberr(dbi, "dbenv->remove", rc, _debug); if (dbfile) - rpmMessage(RPMMESS_DEBUG, _("removed db environment %s/%s\n"), + rpmMessage(RPMMESS_DEBUG, _("removed db environment %s/%s\n"), dbhome, dbfile); } @@ -156,7 +202,7 @@ static int db_fini(dbiIndex dbi, const char * dbhome, #else /* __USE_DB3 */ rc = db_appexit(dbenv); rc = cvtdberr(dbi, "db_appexit", rc, _debug); - free(dbenv); + dbenv = _free(dbenv); #endif /* __USE_DB3 */ dbi->dbi_dbenv = NULL; return rc; @@ -301,7 +347,7 @@ errxit: xx = cvtdberr(dbi, "dbenv->close", xx, _debug); } #else /* __USE_DB3 */ - if (dbenv) free(dbenv); + dbenv = _free(dbenv); #endif /* __USE_DB3 */ return rc; } @@ -575,6 +621,22 @@ static int db3cget(dbiIndex dbi, DBC * dbcursor, /*@=compmempass =nullstate@*/ } +static int db3ccount(dbiIndex dbi, DBC * dbcursor, + /*@out@*/ unsigned int * countp, + /*@unused@*/ unsigned int flags) +{ + db_recno_t count = 0; + int rc = 0; + + flags = 0; + rc = dbcursor->c_count(dbcursor, &count, flags); + rc = cvtdberr(dbi, "dbcursor->c_count", rc, _debug); + if (rc) return rc; + if (countp) *countp = count; + + return rc; +} + static int db3byteswapped(dbiIndex dbi) { DB * db = dbi->dbi_db; @@ -588,6 +650,25 @@ static int db3byteswapped(dbiIndex dbi) return rc; } +static int db3stat(dbiIndex dbi, unsigned int flags) +{ + DB * db = dbi->dbi_db; + int rc = 0; + + if (db == NULL) return -2; +#if defined(DB_FAST_STAT) + if (flags) + flags = DB_FAST_STAT; + else +#endif + flags = 0; + dbi->dbi_stats = _free(dbi->dbi_stats); + rc = db->stat(db, &dbi->dbi_stats, flags); + rc = cvtdberr(dbi, "db->stat", rc, _debug); + return rc; +} + +/** @todo Add/use per-rpmdb verify_on_close. */ static int db3close(/*@only@*/ dbiIndex dbi, /*@unused@*/ unsigned int flags) { rpmdb rpmdb = dbi->dbi_rpmdb; @@ -598,6 +679,8 @@ static int db3close(/*@only@*/ dbiIndex dbi, /*@unused@*/ unsigned int flags) DB * db = dbi->dbi_db; int rc = 0, xx; + flags = 0; /* XXX unused */ + urlfn = rpmGenPath( (dbi->dbi_root ? dbi->dbi_root : rpmdb->db_root), (dbi->dbi_home ? dbi->dbi_home : rpmdb->db_home), @@ -616,8 +699,6 @@ static int db3close(/*@only@*/ dbiIndex dbi, /*@unused@*/ unsigned int flags) #endif } -#if defined(__USE_DB2) || defined(__USE_DB3) - if (dbi->dbi_rmw) rc = db3cclose(dbi, NULL, 0); @@ -626,31 +707,65 @@ static int db3close(/*@only@*/ dbiIndex dbi, /*@unused@*/ unsigned int flags) rc = cvtdberr(dbi, "db->close", rc, _debug); db = dbi->dbi_db = NULL; - rpmMessage(RPMMESS_DEBUG, _("closed db index %s/%s\n"), + rpmMessage(RPMMESS_DEBUG, _("closed db index %s/%s\n"), dbhome, (dbfile ? dbfile : tagName(dbi->dbi_rpmtag))); } - if (dbi->dbi_dbinfo) { - free(dbi->dbi_dbinfo); - dbi->dbi_dbinfo = NULL; - } + dbi->dbi_dbinfo = _free(dbi->dbi_dbinfo); - if (dbi->dbi_use_dbenv) + if (dbi->dbi_use_dbenv) { /*@-nullstate@*/ xx = db_fini(dbi, (dbhome ? dbhome : ""), dbfile, dbsubfile); /*@=nullstate@*/ + } -#else /* __USE_DB2 || __USE_DB3 */ + if (dbi->dbi_verify_on_close && !dbi->dbi_temporary) { + DB_ENV * dbenv = NULL; - rc = db->close(db); + rc = db_env_create(&dbenv, 0); + rc = cvtdberr(dbi, "db_env_create", rc, _debug); + if (rc) goto exit; -#endif /* __USE_DB2 || __USE_DB3 */ + if (dbenv) /* XXX can't happen. */ + rc = dbenv->open(dbenv, dbhome, + DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE | DB_USE_ENVIRON, 0); + rc = cvtdberr(dbi, "dbenv->open", rc, _debug); + if (rc) goto exit; + + if (dbenv) { + rc = db_create(&db, dbenv, 0); + rc = cvtdberr(dbi, "db_create", rc, _debug); + + if (db != NULL) { + const char * dbf = rpmGetPath(dbhome, "/", dbfile, NULL); + + rc = db->verify(db, dbf, NULL, NULL, flags); + rc = cvtdberr(dbi, "db->verify", rc, _debug); + + rpmMessage(RPMMESS_DEBUG, _("verified db index %s/%s\n"), + (dbhome ? dbhome : ""), + (dbfile ? dbfile : tagName(dbi->dbi_rpmtag))); + + xx = db->close(db, 0); + xx = cvtdberr(dbi, "db->close", xx, _debug); + db = NULL; + if (rc == 0 && xx) rc = xx; + + dbf = _free(dbf); + } + xx = dbenv->close(dbenv, 0); + xx = cvtdberr(dbi, "dbenv->close", xx, _debug); + if (rc == 0 && xx) rc = xx; + } + } + +exit: dbi->dbi_db = NULL; urlfn = _free(urlfn); - db3Free(dbi); + dbi = db3Free(dbi); return rc; } @@ -805,7 +920,7 @@ static int db3open(/*@keep@*/ rpmdb rpmdb, int rpmtag, dbiIndex * dbip) if (dbi->dbi_use_dbenv) rc = db_init(dbi, dbhome, dbfile, dbsubfile, &dbenv); - rpmMessage(RPMMESS_DEBUG, _("opening db index %s/%s %s mode=0x%x\n"), + rpmMessage(RPMMESS_DEBUG, _("opening db index %s/%s %s mode=0x%x\n"), dbhome, (dbfile ? dbfile : tagName(dbi->dbi_rpmtag)), prDbiOpenFlags(oflags, 0), dbi->dbi_mode); @@ -992,7 +1107,7 @@ static int db3open(/*@keep@*/ rpmdb rpmdb, int rpmtag, dbiIndex * dbip) rc = (!dbi->dbi_use_dbenv ? 1 : 0); } else if (dbfile) { rpmMessage(RPMMESS_DEBUG, - _("locked db index %s/%s\n"), + _("locked db index %s/%s\n"), dbhome, dbfile); } } @@ -1045,8 +1160,10 @@ static int db3open(/*@keep@*/ rpmdb rpmdb, int rpmtag, dbiIndex * dbip) if (rc == 0 && dbi->dbi_db != NULL && dbip != NULL) { dbi->dbi_vec = &db3vec; *dbip = dbi; - } else + } else { + dbi->dbi_verify_on_close = 0; (void) db3close(dbi, 0); + } urlfn = _free(urlfn); @@ -1060,7 +1177,7 @@ static int db3open(/*@keep@*/ rpmdb rpmdb, int rpmtag, dbiIndex * dbip) struct _dbiVec db3vec = { DB_VERSION_MAJOR, DB_VERSION_MINOR, DB_VERSION_PATCH, db3open, db3close, db3sync, db3copen, db3cclose, db3cdel, db3cget, db3cput, - db3byteswapped + db3ccount, db3byteswapped, db3stat }; #endif /* DB_VERSION_MAJOR == 3 */ diff --git a/rpmdb/dbconfig.c b/rpmdb/dbconfig.c index 061956c..35bd2c6 100644 --- a/rpmdb/dbconfig.c +++ b/rpmdb/dbconfig.c @@ -137,6 +137,8 @@ struct dbOption rdbOptions[] = { { "sv_timeout", 0,POPT_ARG_LONG, &db3dbi.dbi_sv_timeout, 0, NULL, NULL }, + { "verify", 0,POPT_ARG_NONE, &db3dbi.dbi_verify_on_close, 0, + NULL, NULL }, { "teardown", 0,POPT_ARG_NONE, &db3dbi.dbi_tear_down, 0, NULL, NULL }, { "usecursors",0,POPT_ARG_NONE, &db3dbi.dbi_use_cursors, 0, @@ -295,7 +297,7 @@ static int dbSaveInt(const struct dbOption * opt, int argInfo, long aLong) { return 0; } -void db3Free(dbiIndex dbi) { +dbiIndex db3Free(dbiIndex dbi) { if (dbi) { dbi->dbi_root = _free(dbi->dbi_root); dbi->dbi_home = _free(dbi->dbi_home); @@ -306,8 +308,10 @@ void db3Free(dbiIndex dbi) { dbi->dbi_re_source = _free(dbi->dbi_re_source); dbi->dbi_dbenv = _free(dbi->dbi_dbenv); dbi->dbi_dbinfo = _free(dbi->dbi_dbinfo); + dbi->dbi_stats = _free(dbi->dbi_stats); dbi = _free(dbi); } + return dbi; } static const char *db3_config_default = diff --git a/rpmdb/rpmdb.c b/rpmdb/rpmdb.c index cfaa5d9..a2a4f75 100644 --- a/rpmdb/rpmdb.c +++ b/rpmdb/rpmdb.c @@ -271,6 +271,32 @@ if (_debug < 0 || dbi->dbi_debug) { return rc; } +INLINE int dbiCount(dbiIndex dbi, DBC * dbcursor, + unsigned int * countp, unsigned int flags) +{ + int rc = (*dbi->dbi_vec->ccount) (dbi, dbcursor, countp, flags); + +if (rc == 0 && countp && *countp > 1) +fprintf(stderr, " Count %s: %u rc %d\n", tagName(dbi->dbi_rpmtag), *countp, rc); + + return rc; +} + +INLINE int dbiVerify(dbiIndex dbi, unsigned int flags) +{ + int dbi_debug = dbi->dbi_debug; + int dbi_rpmtag = dbi->dbi_rpmtag; + int rc; + + dbi->dbi_verify_on_close = 1; + rc = (*dbi->dbi_vec->close) (dbi, flags); + +if (_debug < 0 || dbi_debug) +fprintf(stderr, " Verify %s rc %d\n", tagName(dbi_rpmtag), rc); + + return rc; +} + INLINE int dbiClose(dbiIndex dbi, unsigned int flags) { if (_debug < 0 || dbi->dbi_debug) fprintf(stderr, " Close %s\n", tagName(dbi->dbi_rpmtag)); @@ -363,12 +389,10 @@ dbiIndex dbiOpen(rpmdb rpmdb, int rpmtag, /*@unused@*/ unsigned int flags) } exit: - if (rc == 0 && dbi) { + if (rc == 0 && dbi) rpmdb->_dbi[dbix] = dbi; - } else if (dbi) { - db3Free(dbi); - dbi = NULL; - } + else + dbi = db3Free(dbi); return dbi; } @@ -664,8 +688,8 @@ unsigned int dbiIndexRecordFileNumber(dbiIndexSet set, int recno) { /* XXX transaction.c */ void dbiFreeIndexSet(dbiIndexSet set) { if (set) { - if (set->recs) free(set->recs); - free(set); + set->recs = _free(set->recs); + set = _free(set); } } @@ -712,9 +736,10 @@ static void unblockSignals(rpmdb rpmdb, sigset_t * oldMask) }; /*@=fullinitblock@*/ -int rpmdbOpenAll (rpmdb rpmdb) +int rpmdbOpenAll(rpmdb rpmdb) { int dbix; + int rc = 0; if (rpmdb == NULL) return -2; @@ -724,20 +749,24 @@ int rpmdbOpenAll (rpmdb rpmdb) continue; (void) dbiOpen(rpmdb, dbiTags[dbix], rpmdb->db_flags); } - return 0; + return rc; } /* XXX query.c, rpminstall.c, verify.c */ -int rpmdbClose (rpmdb rpmdb) +int rpmdbClose(rpmdb rpmdb) { int dbix; + int rc = 0; if (rpmdb == NULL) return 0; + if (rpmdb->_dbi) for (dbix = rpmdb->db_ndbi; --dbix >= 0; ) { + int xx; if (rpmdb->_dbi[dbix] == NULL) continue; - /*@-unqualifiedtrans@*/ - (void) dbiClose(rpmdb->_dbi[dbix], 0); + /*@-unqualifiedtrans@*/ /* FIX: double indirection. */ + xx = dbiClose(rpmdb->_dbi[dbix], 0); + if (xx && rc == 0) rc = xx; rpmdb->_dbi[dbix] = NULL; /*@=unqualifiedtrans@*/ } @@ -746,12 +775,13 @@ int rpmdbClose (rpmdb rpmdb) rpmdb->db_home = _free(rpmdb->db_home); rpmdb->_dbi = _free(rpmdb->_dbi); rpmdb = _free(rpmdb); - return 0; + return rc; } int rpmdbSync(rpmdb rpmdb) { int dbix; + int rc = 0; if (rpmdb == NULL) return 0; for (dbix = 0; dbix < rpmdb->db_ndbi; dbix++) { @@ -759,8 +789,9 @@ int rpmdbSync(rpmdb rpmdb) if (rpmdb->_dbi[dbix] == NULL) continue; xx = dbiSync(rpmdb->_dbi[dbix], 0); + if (xx && rc == 0) rc = xx; } - return 0; + return rc; } static /*@only@*/ /*@null@*/ @@ -934,8 +965,42 @@ int rpmdbInit (const char * prefix, int perms) rc = openDatabase(prefix, NULL, _dbapi, &rpmdb, (O_CREAT | O_RDWR), perms, RPMDB_FLAG_JUSTCHECK); if (rpmdb) { - (void) rpmdbOpenAll(rpmdb); - (void) rpmdbClose(rpmdb); + int xx; + xx = rpmdbOpenAll(rpmdb); + if (xx && rc == 0) rc = xx; + xx = rpmdbClose(rpmdb); + if (xx && rc == 0) rc = xx; + rpmdb = NULL; + } + return rc; +} + +int rpmdbVerify(const char * prefix) +{ + rpmdb rpmdb = NULL; + int _dbapi = rpmExpandNumeric("%{_dbapi}"); + int rc = 0; + + rc = openDatabase(prefix, NULL, _dbapi, &rpmdb, O_RDONLY, 0644, 0); + if (rc) return rc; + + if (rpmdb) { + int dbix; + int xx; + rc = rpmdbOpenAll(rpmdb); + + for (dbix = rpmdb->db_ndbi; --dbix >= 0; ) { + if (rpmdb->_dbi[dbix] == NULL) + continue; + /*@-unqualifiedtrans@*/ /* FIX: double indirection. */ + xx = dbiVerify(rpmdb->_dbi[dbix], 0); + if (xx && rc == 0) rc = xx; + rpmdb->_dbi[dbix] = NULL; + /*@=unqualifiedtrans@*/ + } + + xx = rpmdbClose(rpmdb); + if (xx && rc == 0) rc = xx; rpmdb = NULL; } return rc; @@ -1271,7 +1336,7 @@ static int dbiUpdateRecord(dbiIndex dbi, DBC * dbcursor, int offset, Header h) rc = dbiPut(dbi, dbcursor, &offset, sizeof(offset), uh, uhlen, 0); xx = dbiSync(dbi, 0); unblockSignals(dbi->dbi_rpmdb, &signalMask); - free(uh); + uh = _free(uh); } return rc; } @@ -1283,6 +1348,7 @@ struct _rpmdbMatchIterator { int mi_rpmtag; dbiIndexSet mi_set; DBC * mi_dbc; + unsigned int mi_ndups; int mi_setx; /*@null@*/ Header mi_h; int mi_sorted; @@ -1511,7 +1577,7 @@ exit: #ifdef NOTNOW if (mi->mi_h) { const char *n, *v, *r; - headerNVR(mi->mi_h, &n, &v, &r); + (void) headerNVR(mi->mi_h, &n, &v, &r); rpmMessage(RPMMESS_DEBUG, "%s-%s-%s at 0x%x, h %p\n", n, v, r, mi->mi_offset, mi->mi_h); } @@ -1882,10 +1948,7 @@ int rpmdbRemove(rpmdb rpmdb, int rid, unsigned int hdrNum) rpmcnt = 0; } - if (rec) { - free(rec); - rec = NULL; - } + rec = _free(rec); } unblockSignals(rpmdb, &signalMask); @@ -2183,10 +2246,7 @@ int rpmdbAdd(rpmdb rpmdb, int iid, Header h) rpmcnt = 0; } - if (rec) { - free(rec); - rec = NULL; - } + rec = _free(rec); } exit: @@ -2499,7 +2559,7 @@ int rpmdbRebuild(const char * rootdir) int nocleanup = 1; int failed = 0; int removedir = 0; - int rc = 0; + int rc = 0, xx; int _dbapi; int _dbapi_rebuild; @@ -2645,14 +2705,14 @@ int rpmdbRebuild(const char * rootdir) olddb->db_remove_env = 1; newdb->db_remove_env = 1; } - (void) rpmdbClose(olddb); - (void) rpmdbClose(newdb); + xx = rpmdbClose(olddb); + xx = rpmdbClose(newdb); if (failed) { rpmMessage(RPMMESS_NORMAL, _("failed to rebuild database: original database " "remains in place\n")); - (void) rpmdbRemoveDatabase(rootdir, newdbpath, _dbapi_rebuild); + xx = rpmdbRemoveDatabase(rootdir, newdbpath, _dbapi_rebuild); rc = 1; goto exit; } else if (!nocleanup) { diff --git a/rpmdb/rpmdb.h b/rpmdb/rpmdb.h index b3de114..8764f3f 100644 --- a/rpmdb/rpmdb.h +++ b/rpmdb/rpmdb.h @@ -68,7 +68,7 @@ struct _dbiVec { int (*open) (rpmdb rpmdb, int rpmtag, /*@out@*/ dbiIndex * dbip); /** \ingroup dbi - * Close index database. + * Close index database, and destroy database handle. * @param dbi index database handle * @param flags (unused) * @return 0 on success @@ -143,16 +143,36 @@ struct _dbiVec { unsigned int flags); /** \ingroup dbi + * Retrieve count of (possible) duplicate items using dbcursor->c_count. + * @param dbi index database handle + * @param dbcursor database cursor + * @param countp address of count + * @param flags (unused) + * @return 0 on success + */ + int (*ccount) (dbiIndex dbi, DBC * dbcursor, + /*@out@*/ unsigned int * countp, + unsigned int flags); + +/** \ingroup dbi * Is database byte swapped? * @param dbi index database handle * @return 0 no */ int (*byteswapped) (dbiIndex dbi); +/** \ingroup dbi + * Save statistics in database handle. + * @param dbi index database handle + * @param flags retrieve statistics that don't require traversal? + * @return 0 on success + */ + int (*stat) (dbiIndex dbi, unsigned int flags); + }; /** \ingroup dbi - * Describes an index database (implemented on Berkeley db[123] API). + * Describes an index database (implemented on Berkeley db3 functionality). */ struct _dbiIndex { /*@null@*/ const char * dbi_root; @@ -173,6 +193,7 @@ struct _dbiIndex { long dbi_shmkey; /*!< shared memory base key */ int dbi_api; /*!< Berkeley API type */ + int dbi_verify_on_close; int dbi_tear_down; /*!< tear down dbenv on close */ int dbi_use_cursors;/*!< access with cursors? (always) */ int dbi_use_dbenv; /*!< use db environment? */ @@ -243,9 +264,10 @@ struct _dbiIndex { unsigned int dbi_lastoffset; /*!< db1 with falloc.c needs this */ /*@only@*//*@null@*/ void * dbi_db; /*!< dbi handle */ -/*@only@*//*@null@*/ void * dbi_dbenv; -/*@only@*//*@null@*/ void * dbi_dbinfo; +/*@only@*//*@null@*/ void * dbi_dbenv; /*!< */ +/*@only@*//*@null@*/ void * dbi_dbinfo; /*!< */ /*@only@*//*@null@*/ void * dbi_rmw; /*!< db cursor (with DB_WRITECURSOR) */ +/*@only@*//*@null@*/ void * dbi_stats; /*!< */ /*@observer@*/ const struct _dbiVec * dbi_vec; /*!< private methods */ @@ -298,8 +320,9 @@ extern "C" { /** \ingroup db3 * Destroy index database handle instance. * @param dbi index database handle + * @return NULL always */ -void db3Free( /*@only@*/ /*@null@*/ dbiIndex dbi); +/*@null@*/ dbiIndex db3Free( /*@only@*/ /*@null@*/ dbiIndex dbi); /** \ingroup db3 * Format db3 open flags for debugging print. @@ -382,6 +405,25 @@ int dbiPut(dbiIndex dbi, DBC * dbcursor, const void * keyp, size_t keylen, const void * datap, size_t datalen, unsigned int flags); /** \ingroup dbi + * Retrieve count of (possible) duplicate items. + * @param dbi index database handle + * @param dbcursor database cursor + * @param countp address of count + * @param flags (unused) + * @return 0 on success + */ +int dbiCount(dbiIndex dbi, DBC * dbcursor, /*@out@*/ unsigned int * countp, + unsigned int flags); + +/** \ingroup dbi + * Verify (and close) index database. + * @param dbi index database handle + * @param flags (unused) + * @return 0 on success + */ +int dbiVerify(/*@only@*/ dbiIndex dbi, unsigned int flags); + +/** \ingroup dbi * Close index database. * @param dbi index database handle * @param flags (unused) diff --git a/rpmpopt.in b/rpmpopt.in index 4bd30a9..c8f1cbb 100644 --- a/rpmpopt.in +++ b/rpmpopt.in @@ -138,6 +138,7 @@ rpm exec --short-circuit rpmb --short-circuit rpm exec --initdb rpmd --initdb rpm exec --rebuilddb rpmd --rebuilddb +rpm exec --verifydb rpmd --verifydb #rpm exec -e rpme -e #rpm exec --erase rpme --erase diff --git a/rpmqv.c b/rpmqv.c index ba54d66..d77569b 100755 --- a/rpmqv.c +++ b/rpmqv.c @@ -20,7 +20,8 @@ #endif #ifdef IAM_RPMDB -#define GETOPT_REBUILDDB 1013 +#define GETOPT_REBUILDDB 1013 +#define GETOPT_VERIFYDB 1023 static int initdb = 0; #endif @@ -76,7 +77,8 @@ enum modes { MODE_INITDB = (1 << 10), MODE_REBUILDDB = (1 << 12), -#define MODES_DB (MODE_INITDB | MODE_REBUILDDB) + MODE_VERIFYDB = (1 << 13), +#define MODES_DB (MODE_INITDB | MODE_REBUILDDB | MODE_VERIFYDB) MODE_UNKNOWN = 0 }; @@ -182,6 +184,9 @@ static struct poptOption rpmDatabasePoptTable[] = { { "rebuilddb", '\0', 0, 0, GETOPT_REBUILDDB, N_("rebuild database inverted lists from installed package headers"), NULL}, + { "verifydb", '\0', 0, 0, GETOPT_VERIFYDB, + N_("verify database files"), + NULL}, { "nodirtokens", '\0', POPT_ARG_VAL, &_noDirTokens, 1, N_("generate headers compatible with (legacy) rpm[23] packaging"), NULL}, @@ -938,6 +943,11 @@ int main(int argc, const char ** argv) argerror(_("only one major mode may be specified")); bigMode = MODE_REBUILDDB; break; + case GETOPT_VERIFYDB: + if (bigMode != MODE_UNKNOWN && bigMode != MODE_VERIFYDB) + argerror(_("only one major mode may be specified")); + bigMode = MODE_VERIFYDB; + break; #endif #ifdef IAM_RPMK @@ -1285,6 +1295,9 @@ int main(int argc, const char ** argv) case MODE_REBUILDDB: ec = rpmdbRebuild(rootdir); break; + case MODE_VERIFYDB: + ec = rpmdbVerify(rootdir); + break; #if !defined(__LCLINT__) case MODE_QUERY: case MODE_VERIFY: @@ -1404,6 +1417,7 @@ int main(int argc, const char ** argv) case MODE_RESIGN: case MODE_INITDB: case MODE_REBUILDDB: + case MODE_VERIFYDB: if (!showVersion && !help && !noUsageMsg) printUsage(); break; #endif @@ -1472,6 +1486,7 @@ int main(int argc, const char ** argv) case MODE_RESIGN: case MODE_INITDB: case MODE_REBUILDDB: + case MODE_VERIFYDB: if (!showVersion && !help && !noUsageMsg) printUsage(); break; #endif @@ -1534,6 +1549,7 @@ int main(int argc, const char ** argv) case MODE_RESIGN: case MODE_INITDB: case MODE_REBUILDDB: + case MODE_VERIFYDB: if (!showVersion && !help && !noUsageMsg) printUsage(); break; #endif @@ -1570,6 +1586,7 @@ int main(int argc, const char ** argv) case MODE_TARBUILD: case MODE_INITDB: case MODE_REBUILDDB: + case MODE_VERIFYDB: if (!showVersion && !help && !noUsageMsg) printUsage(); break; #endif -- 2.7.4