summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjbj <devnull@localhost>2001-05-25 19:51:53 +0000
committerjbj <devnull@localhost>2001-05-25 19:51:53 +0000
commite6c22123bc088afd6f0f564b8f5224af3cf2d2e6 (patch)
tree9f1315b0301b2c8ae873d13098786e366df43d01
parent4d76eb6dee47bbb119846428af238727d7cd5b61 (diff)
downloadlibrpm-tizen-e6c22123bc088afd6f0f564b8f5224af3cf2d2e6.tar.gz
librpm-tizen-e6c22123bc088afd6f0f564b8f5224af3cf2d2e6.tar.bz2
librpm-tizen-e6c22123bc088afd6f0f564b8f5224af3cf2d2e6.zip
- perform db->verify when closing db files.
CVS patchset: 4813 CVS date: 2001/05/25 19:51:53
-rw-r--r--CHANGES1
-rwxr-xr-xdb3/configure6
-rw-r--r--lib/rpmlib.h14
-rw-r--r--macros.in13
-rwxr-xr-xrpm.c22
-rw-r--r--rpmdb/Makefile.am2
-rw-r--r--rpmdb/db1.c26
-rw-r--r--rpmdb/db2.c16
-rw-r--r--rpmdb/db3.c157
-rw-r--r--rpmdb/dbconfig.c6
-rw-r--r--rpmdb/rpmdb.c120
-rw-r--r--rpmdb/rpmdb.h52
-rw-r--r--rpmpopt.in1
-rwxr-xr-xrpmqv.c21
14 files changed, 374 insertions, 83 deletions
diff --git a/CHANGES b/CHANGES
index 968a3055f..e299ab86a 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 ff79eeed6..e4782e41d 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 368c98407..c08580d02 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 a4912a706..1aef98a2c 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 0e3cd66ef..35b4b818a 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 <file>]"));
puts(_(" package1 ... packageN"));
puts(_(" rpm {--rebuilddb} [--rcfile <file>] [--dbpath <dir>]"));
+ puts(_(" rpm {--verifydb} [--rcfile <file>] [--dbpath <dir>]"));
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 <dir> "),
_("use <dir> as the directory for the database"));
printHelpLine( " --root <dir> ",
@@ -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 c3a8df331..43422a8f9 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 cb88f3723..1af5f2f9d 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 7a59e87e6..af6d74f4f 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 7daf6dcd3..34fe0747a 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 061956c8c..35bd2c669 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 cfaa5d9a5..a2a4f758c 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 b3de11475..8764f3f31 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 4bd30a967..c8f1cbb8b 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 ba54d66e0..d77569b39 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