- 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.
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
listobjs:\
@echo $(OBJS) $(C_OBJS) \
\
-distdir install:\
+distdir install check:\
\
db3_install: all install_setip \\' > Makefile
/*@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 @*/;
/** \ingroup rpmdb
* Sync all database indices.
* @param rpmdb rpm database
- * @return 0 always
+ * @return 0 on success
*/
int rpmdbSync (/*@null@*/ rpmdb rpmdb)
/*@modifies fileSystem @*/;
/** \ingroup rpmdb
* Open all database indices.
* @param rpmdb rpm database
- * @return 0 always
+ * @return 0 on success
*/
int rpmdbOpenAll (/*@null@*/ rpmdb rpmdb)
/*@modifies fileSystem @*/;
#/*! \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
# 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
#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
#define GETOPT_DEFINEMACRO 1020
#define GETOPT_EVALMACRO 1021
#define GETOPT_RCFILE 1022
+#define GETOPT_VERIFYDB 1023
enum modes {
MODE_UNKNOWN = 0,
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)
{ "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},
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}"));
}
_("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> ",
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 /"));
ec = rpmdbRebuild(rootdir);
break;
+ case MODE_VERIFYDB:
+ ec = rpmdbVerify(rootdir);
+ break;
+
case MODE_QUERYTAGS:
if (argc != 2)
argerror(_("unexpected arguments to --querytags "));
.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:
return rc;
}
-static int db1byteswapped(/*@unused@*/dbiIndex dbi)
-{
- return 0;
-}
-
static void * doGetRecord(FD_t pkgs, unsigned int offset)
{
void * uh = NULL;
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;
(void) unlink(fn);
}
- db3Free(dbi);
+ dbi = db3Free(dbi);
base = _free(base);
urlfn = _free(urlfn);
return rc;
struct _dbiVec db1vec = {
DB_VERSION_MAJOR, DB_VERSION_MINOR, DB_VERSION_PATCH,
db1open, db1close, db1sync, db1copen, db1cclose, db1cdel, db1cget, db1cput,
- db1byteswapped
+ db1ccount, db1byteswapped, db1stat
};
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;
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;
urlfn = _free(urlfn);
- db3Free(dbi);
+ dbi = db3Free(dbi);
return rc;
}
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 */
/*@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
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) {
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);
}
#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;
xx = cvtdberr(dbi, "dbenv->close", xx, _debug);
}
#else /* __USE_DB3 */
- if (dbenv) free(dbenv);
+ dbenv = _free(dbenv);
#endif /* __USE_DB3 */
return rc;
}
/*@=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;
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;
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),
#endif
}
-#if defined(__USE_DB2) || defined(__USE_DB3)
-
if (dbi->dbi_rmw)
rc = db3cclose(dbi, NULL, 0);
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;
}
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);
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);
}
}
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);
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 */
{ "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,
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);
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 =
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));
}
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;
}
/* 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);
}
}
};
/*@=fullinitblock@*/
-int rpmdbOpenAll (rpmdb rpmdb)
+int rpmdbOpenAll(rpmdb rpmdb)
{
int dbix;
+ int rc = 0;
if (rpmdb == NULL) return -2;
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@*/
}
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++) {
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@*/
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;
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;
}
int mi_rpmtag;
dbiIndexSet mi_set;
DBC * mi_dbc;
+ unsigned int mi_ndups;
int mi_setx;
/*@null@*/ Header mi_h;
int mi_sorted;
#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);
}
rpmcnt = 0;
}
- if (rec) {
- free(rec);
- rec = NULL;
- }
+ rec = _free(rec);
}
unblockSignals(rpmdb, &signalMask);
rpmcnt = 0;
}
- if (rec) {
- free(rec);
- rec = NULL;
- }
+ rec = _free(rec);
}
exit:
int nocleanup = 1;
int failed = 0;
int removedir = 0;
- int rc = 0;
+ int rc = 0, xx;
int _dbapi;
int _dbapi_rebuild;
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) {
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
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;
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? */
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 */
/** \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.
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)
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
#endif
#ifdef IAM_RPMDB
-#define GETOPT_REBUILDDB 1013
+#define GETOPT_REBUILDDB 1013
+#define GETOPT_VERIFYDB 1023
static int initdb = 0;
#endif
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
};
{ "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},
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
case MODE_REBUILDDB:
ec = rpmdbRebuild(rootdir);
break;
+ case MODE_VERIFYDB:
+ ec = rpmdbVerify(rootdir);
+ break;
#if !defined(__LCLINT__)
case MODE_QUERY:
case MODE_VERIFY:
case MODE_RESIGN:
case MODE_INITDB:
case MODE_REBUILDDB:
+ case MODE_VERIFYDB:
if (!showVersion && !help && !noUsageMsg) printUsage();
break;
#endif
case MODE_RESIGN:
case MODE_INITDB:
case MODE_REBUILDDB:
+ case MODE_VERIFYDB:
if (!showVersion && !help && !noUsageMsg) printUsage();
break;
#endif
case MODE_RESIGN:
case MODE_INITDB:
case MODE_REBUILDDB:
+ case MODE_VERIFYDB:
if (!showVersion && !help && !noUsageMsg) printUsage();
break;
#endif
case MODE_TARBUILD:
case MODE_INITDB:
case MODE_REBUILDDB:
+ case MODE_VERIFYDB:
if (!showVersion && !help && !noUsageMsg) printUsage();
break;
#endif