diff options
-rw-r--r-- | INSTALL | 52 | ||||
-rw-r--r-- | Makefile.am | 14 | ||||
-rw-r--r-- | ci/Dockerfile | 1 | ||||
-rw-r--r-- | configure.ac | 43 | ||||
-rwxr-xr-x | db3/configure | 34 | ||||
-rw-r--r-- | doc/librpm/Doxyheader.h | 2 | ||||
-rw-r--r-- | lib/Makefile.am | 23 | ||||
-rw-r--r-- | lib/backend/db3.c | 1389 | ||||
-rw-r--r-- | lib/backend/dbi.c | 3 | ||||
-rw-r--r-- | lib/backend/dbi.h | 5 | ||||
-rw-r--r-- | lib/verify.c | 4 | ||||
-rw-r--r-- | macros.in | 46 | ||||
-rw-r--r-- | po/POTFILES.in | 1 | ||||
-rw-r--r-- | rpm.pc.in | 2 |
14 files changed, 11 insertions, 1608 deletions
@@ -32,59 +32,15 @@ Debian: https://lists.debian.org/debian-legal/2002/10/msg00113.html The OpenSSL crypto library is available from https://www.openssl.org/ -RPM needs a database engine for normal operation. The main options are -"ndb" (--enable-ndb) and "sqlite" (--enable-sqlite), and the now -deprecated "bdb" (--enable-bdb). Additionally standalone support for -read-only BDB databases is available as "bdb_ro" (--enable-bdb-ro) -to aid with migration from BDB. +RPM needs a database engine for normal operation. The main options are +"ndb" (--enable-ndb) and "sqlite" (--enable-sqlite). +Additionally standalone support for read-only BDB databases is available as +"bdb_ro" (--enable-bdb-ro) to aid with migration from BDB. The ndb and bdb_ro backends have no external dependencies. SQLite >= 3.22.0 is required for the sqlite database backend. SQLite is available from https://www.sqlite.org/ -The Berkeley DB >= 4.3.x (4.5.x or newer recommended) is required for the -deprecated "bdb" database backend. BDB can be downloaded from -http://www.oracle.com/technology/software/products/berkeley-db/index.html - -RPM supports two different ways to include it, both methods have their -distinct advantages and disadvantages: - -1) Building and using an internal copy of BDB - - This is the "safe" way: upgrades to system BDB can not affect your - rpmdb integrity and you have full control over how BDB is configured. - On the other hand, any updates (security or bugfix) to BDB will require - rebuilding RPM. - - To use this method, download a recent version of BDB from the URL above, - expand the tarball into rpm source directory root and create "db" symlink - to it, eg: - $ wget http://download.oracle.com/berkeley-db/db-4.5.20.tar.gz - $ tar xzf db-4.5.20.tar.gz - $ ln -s db-4.5.20 db - $ ./configure [other options...] - -2) Linking to external (system) BDB - - If you can control when and how system BDB is upgraded, this option - saves space, removes the need to rebuild RPM in case of security etc - updates to BDB and also makes build rpm itself much faster. On the other - hand, major BDB upgrades can be disruptive, especially if - the on-disk format changes somehow. - - This method is the default if no "db" link exists in the top directory. - If the system BDB is installed outside compiler + linker default - paths, you can use CPPFLAGS and LDFLAGS to tell configure where to look, - for example: - - $ ./configure CPPFLAGS=-I/usr/include/db45 - -Minimal instructions for building BDB are - cd build_unix - ../dist/configure --with-posixmutexes - make - make install - For embedded Lua scripting support (recommended and enabled by default), you'll need Lua >= 5.2 library + development environment installed. Note that only the library is needed at runtime, RPM never calls external diff --git a/Makefile.am b/Makefile.am index aca2f8996..4ad38c36d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -23,13 +23,10 @@ AM_CFLAGS = @RPMCFLAGS@ CLEANFILES = EXTRA_DIST = ChangeLog CREDITS INSTALL \ - autogen.sh db3/configure installplatform platform.in build-aux + autogen.sh installplatform platform.in build-aux BUILT_SOURCES = SUBDIRS = po misc -if WITH_INTERNAL_DB -SUBDIRS += db3 -endif if WITH_LUA SUBDIRS += luaext endif @@ -292,13 +289,6 @@ endif EXTRA_DIST += doc/librpm.doxy.in doc/librpm/Doxyheader.h EXTRA_DIST += doc/librpm/html -if WITH_INTERNAL_DB -db.h: $(top_builddir)/db3/db.h - $(LN_S) $(top_builddir)/db3/db.h $@ -BUILT_SOURCES += db.h -endif -DISTCLEANFILES = db.h - .PHONY: ci ci: podman build -t rpm -f ci/Dockerfile . @@ -316,7 +306,7 @@ clean-local: distclean-local: rm -rf doc/librpm.doxy doc/librpm/html rm -rf Doxytags - rm -f stamp-h.in db3/*.orig db3/db3lobjs + rm -f stamp-h.in $(top_srcdir)/preinstall.am: Makefile.am rm -f $(top_srcdir)/preinstall.am diff --git a/ci/Dockerfile b/ci/Dockerfile index d9c72415f..d778de35e 100644 --- a/ci/Dockerfile +++ b/ci/Dockerfile @@ -28,7 +28,6 @@ RUN dnf -y install \ file-devel \ popt-devel \ libarchive-devel \ - libdb-devel \ sqlite-devel \ libselinux-devel \ ima-evm-utils-devel \ diff --git a/configure.ac b/configure.ac index 5c6af28d5..d2c791aaa 100644 --- a/configure.ac +++ b/configure.ac @@ -468,49 +468,6 @@ AM_CONDITIONAL(LIBDW,[test "$WITH_LIBDW" = yes]) AM_CONDITIONAL(HAVE_LIBDW_STRTAB,[test "$HAVE_LIBDW_STRTAB" = yes]) #================= -# Check for BDB support -AC_ARG_ENABLE([bdb], - [AS_HELP_STRING([--enable-bdb=@<:@yes/no/auto@:>@ (DEPRECATED)], - [build with Berkeley DB rpm database format support (default=yes)])], - [enable_bdb="$enableval"], - [enable_bdb=yes]) - -have_bdb="no" -AS_IF([test "x$enable_bdb" != "xno"], [ - if [ test -x db/dist/configure ]; then - have_bdb="internal" - else - AC_CHECK_HEADERS([db.h],[ - AC_PREPROC_IFELSE([ - AC_LANG_SOURCE([ - #include <db.h> - #if ((DB_VERSION_MAJOR < 4) || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR < 5)) - #error Berkeley DB too old - #endif - ]) - ],[ have_bdb="yes" ]) - ]) - fi - AC_MSG_CHECKING(for Berkeley DB >= 4.5) - AC_MSG_RESULT($have_bdb) - AS_IF([test "x$enable_bdb" = "xyes"], [ - if test "x$have_bdb" = "xno"; then - AC_MSG_ERROR([--enable-bdb specified, but not available]) - fi - AC_DEFINE([WITH_BDB], [1], [Define if BDB is available]) - WITH_DB_LIB=-ldb - AC_SUBST([WITH_DB_LIB]) - ]) -]) - -AM_CONDITIONAL([BDB], [test "x$have_bdb" != "xno"]) -AM_CONDITIONAL([WITH_INTERNAL_DB],[test "x$have_bdb" = "xinternal"]) -if test "x$have_bdb" = "xinternal"; then - AC_CONFIG_SUBDIRS(db3) -fi - - -#================= # Process --enable-ndb AC_ARG_ENABLE([ndb], [AS_HELP_STRING([--enable-ndb],[enable the new rpm database format])], [case "$enable_ndb" in diff --git a/db3/configure b/db3/configure deleted file mode 100755 index 160b8e801..000000000 --- a/db3/configure +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/sh -#set -x -base_name=`basename $0` -base_path=`echo $0 | sed s,$base_name,,` - -db_dist="${base_path}../db/dist" - -rm -f config.cache - -# XXX edit CFLAGS= ... out of invocation args ??? -ARGS="`echo $* | sed -e 's% [^ ]*CFLAGS=[^ ]*%%' -e 's% -[^-][^ ]*%%g' -e 's% --param=[^ ]*%%g' -e 's%--cache-file=.*$%%'`" - -CC="$CC" CFLAGS="$CFLAGS" $db_dist/configure $ARGS \ - --enable-shared --enable-static \ - --with-uniquename=_rpmdb --srcdir=$db_dist - -mv Makefile Makefile.orig -cat Makefile.orig | sed -e '/^install[:-]/c\ -.PHONY: listobjs\ -listobjs:\ -\ @echo $(OBJS) $(C_OBJS) \ -\ -distdir install check installcheck:\ -\ -db4_install: all install_setip' \ --e '/^uninstall[:-]/c\ -uninstall:' \ --e 's/^check depend/\ -check: all\ -depend/' \ - > Makefile - -# Generate manifest for rpmdb. -make -s listobjs > db3lobjs diff --git a/doc/librpm/Doxyheader.h b/doc/librpm/Doxyheader.h index ef8a03e77..879b8b1b6 100644 --- a/doc/librpm/Doxyheader.h +++ b/doc/librpm/Doxyheader.h @@ -116,7 +116,7 @@ * @{ */ /** \defgroup rpmdb Database API. - \brief Opening & accessing the RPM indices using Berkeley DB (the so called rpmdb) + \brief Opening & accessing the RPM database */ /** \defgroup rpmio RPM IO API. \brief The RPM IO API (Fd_t is RPM equivalent to libc's FILE). diff --git a/lib/Makefile.am b/lib/Makefile.am index 79ce5f014..4bc5801d2 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -50,15 +50,6 @@ librpm_la_LIBADD = \ @WITH_ACL_LIB@ \ @LIBINTL@ -if BDB -librpm_la_SOURCES += backend/db3.c -if WITH_INTERNAL_DB -librpm_la_LIBADD += $(libdb_la) -else -librpm_la_LIBADD += @WITH_DB_LIB@ -endif -endif - if BDB_RO librpm_la_SOURCES += backend/bdb_ro.c endif @@ -86,18 +77,4 @@ tagtbl.C: Makefile.am $(srcdir)/rpmtag.h gentagtbl.sh mv -f $@.new $@ BUILT_SOURCES = tagtbl.C -if WITH_INTERNAL_DB -# XXX watchout, $(top_builddir)/db3/libdb.la created by this Makefile may surprise -libdb_la = $(top_builddir)/db3/libdb.la - -# XXX grrr, force noinst libdb.la for db3. -# there are more reliable ways to get the BDB version info, just a dirty -# hack for now... -BDBVER = $(shell grep ^LIBVERSION $(top_builddir)/db3/Makefile|cut -f2) -$(libdb_la): $(top_builddir)/db3/libdb-$(BDBVER).la - sed -e"/^libdir=/s/^.*$$/libdir=''/" \ - < $(top_builddir)/db3/libdb-$(BDBVER).la > $(libdb_la) -CLEANFILES += $(libdb_la) -endif - CLEANFILES += $(BUILT_SOURCES) diff --git a/lib/backend/db3.c b/lib/backend/db3.c deleted file mode 100644 index 1d617913c..000000000 --- a/lib/backend/db3.c +++ /dev/null @@ -1,1389 +0,0 @@ -/** \ingroup rpmdb - * \file lib/db3.c - */ - -static int _debug = 1; /* XXX if < 0 debugging, > 0 unusual error returns */ - -#include "system.h" - -#include <errno.h> -#include <sys/wait.h> -#include <popt.h> -#include <db.h> -#include <signal.h> -#include <fcntl.h> - -#include <rpm/rpmtypes.h> -#include <rpm/rpmmacro.h> -#include <rpm/rpmfileutil.h> -#include <rpm/rpmlog.h> - -#include "lib/rpmdb_internal.h" - -#include "debug.h" - -static const char * _errpfx = "rpmdb"; - -struct dbiCursor_s { - dbiIndex dbi; - const void *key; - unsigned int keylen; - int flags; - DBC *cursor; -}; - -static struct dbiConfig_s staticdbicfg; -static struct dbConfig_s staticcfg; - -/** \ingroup dbi - */ -static const struct poptOption rdbOptions[] = { - /* Environment options */ - - { "cdb", 0,POPT_BIT_SET, &staticcfg.db_eflags, DB_INIT_CDB, - NULL, NULL }, - { "lock", 0,POPT_BIT_SET, &staticcfg.db_eflags, DB_INIT_LOCK, - NULL, NULL }, - { "log", 0,POPT_BIT_SET, &staticcfg.db_eflags, DB_INIT_LOG, - NULL, NULL }, - { "txn", 0,POPT_BIT_SET, &staticcfg.db_eflags, DB_INIT_TXN, - NULL, NULL }, - { "recover", 0,POPT_BIT_SET, &staticcfg.db_eflags, DB_RECOVER, - NULL, NULL }, - { "recover_fatal", 0,POPT_BIT_SET, &staticcfg.db_eflags, DB_RECOVER_FATAL, - NULL, NULL }, - { "lockdown", 0,POPT_BIT_SET, &staticcfg.db_eflags, DB_LOCKDOWN, - NULL, NULL }, - { "private", 0,POPT_BIT_SET, &staticcfg.db_eflags, DB_PRIVATE, - NULL, NULL }, - - { "deadlock", 0,POPT_BIT_SET, &staticcfg.db_verbose, DB_VERB_DEADLOCK, - NULL, NULL }, - { "recovery", 0,POPT_BIT_SET, &staticcfg.db_verbose, DB_VERB_RECOVERY, - NULL, NULL }, - { "waitsfor", 0,POPT_BIT_SET, &staticcfg.db_verbose, DB_VERB_WAITSFOR, - NULL, NULL }, - { "verbose", 0,POPT_ARG_VAL, &staticcfg.db_verbose, -1, - NULL, NULL }, - - { "cachesize", 0,POPT_ARG_INT, &staticcfg.db_cachesize, 0, - NULL, NULL }, - { "mmapsize", 0,POPT_ARG_INT, &staticcfg.db_mmapsize, 0, - NULL, NULL }, - { "mp_mmapsize", 0,POPT_ARG_INT, &staticcfg.db_mmapsize, 0, - NULL, NULL }, - { "mp_size", 0,POPT_ARG_INT, &staticcfg.db_cachesize, 0, - NULL, NULL }, - - { "nofsync", 0,POPT_ARG_NONE, &staticcfg.db_no_fsync, 0, - NULL, NULL }, - - /* Per-dbi options */ - { "nommap", 0,POPT_BIT_SET, &staticdbicfg.dbi_oflags, DB_NOMMAP, - NULL, NULL }, - - { "nodbsync", 0,POPT_ARG_NONE, &staticdbicfg.dbi_no_dbsync, 0, - NULL, NULL }, - { "lockdbfd", 0,POPT_ARG_NONE, &staticdbicfg.dbi_lockdbfd, 0, - NULL, NULL }, - - POPT_TABLEEND -}; - - -static int dbapi_err(rpmdb rdb, const char * msg, int error, int printit) -{ - if (printit && error) { - if (msg) - rpmlog(RPMLOG_ERR, _("%s error(%d) from %s: %s\n"), - rdb->db_descr, error, msg, db_strerror(error)); - else - rpmlog(RPMLOG_ERR, _("%s error(%d): %s\n"), - rdb->db_descr, error, db_strerror(error)); - } - return error; -} - -static int cvtdberr(dbiIndex dbi, const char * msg, int error, int printit) -{ - return dbapi_err(dbi->dbi_rpmdb, msg, error, printit); -} - -static void errlog(const DB_ENV * env, const char *errpfx, const char *msg) -{ - rpmlog(RPMLOG_ERR, "%s: %s\n", errpfx, msg); -} - -static void warnlog(const DB_ENV *env, const char *msg) -{ - rpmlog(RPMLOG_WARNING, "%s: %s\n", _errpfx, msg); -} - -static uint32_t db_envflags(DB * db) -{ - DB_ENV * env = db->get_env(db); - uint32_t eflags = 0; - (void) env->get_open_flags(env, &eflags); - return eflags; -} - -/* - * Try to acquire db environment open/close serialization lock. - * Return the open, locked fd on success, -1 on failure. - */ -static int serialize_env(const char *dbhome) -{ - char *lock_path = rstrscat(NULL, dbhome, "/.dbenv.lock", NULL); - mode_t oldmask = umask(022); - int fd = open(lock_path, (O_RDWR|O_CREAT), 0644); - umask(oldmask); - - if (fd >= 0) { - int rc; - struct flock info; - memset(&info, 0, sizeof(info)); - info.l_type = F_WRLCK; - info.l_whence = SEEK_SET; - do { - rc = fcntl(fd, F_SETLKW, &info); - } while (rc == -1 && errno == EINTR); - - if (rc == -1) { - close(fd); - fd = -1; - } - } - - free(lock_path); - return fd; -} - -static int db_fini(rpmdb rdb, const char * dbhome) -{ - DB_ENV * dbenv = rdb->db_dbenv; - int rc; - int lockfd = -1; - uint32_t eflags = 0; - - if (dbenv == NULL) - return 0; - - if (rdb->db_opens > 1) { - rdb->db_opens--; - return 0; - } - - (void) dbenv->get_open_flags(dbenv, &eflags); - if (!(eflags & DB_PRIVATE)) - lockfd = serialize_env(dbhome); - - rc = dbenv->close(dbenv, 0); - rc = dbapi_err(rdb, "dbenv->close", rc, _debug); - - rpmlog(RPMLOG_DEBUG, "closed db environment %s\n", dbhome); - - if (!(eflags & DB_PRIVATE) && rdb->db_remove_env) { - int xx; - - xx = db_env_create(&dbenv, 0); - xx = dbapi_err(rdb, "db_env_create", xx, _debug); - xx = dbenv->remove(dbenv, dbhome, 0); - /* filter out EBUSY as it just means somebody else gets to clean it */ - xx = dbapi_err(rdb, "dbenv->remove", xx, (xx == EBUSY ? 0 : _debug)); - - rpmlog(RPMLOG_DEBUG, "removed db environment %s\n", dbhome); - - } - - if (lockfd >= 0) - close(lockfd); - - return rc; -} - -static int fsync_disable(int fd) -{ - return 0; -} - -/* - * dbenv->failchk() callback method for determining is the given pid/tid - * is alive. We only care about pid's though. - */ -static int isalive(DB_ENV *dbenv, pid_t pid, db_threadid_t tid, uint32_t flags) -{ - int alive = 0; - - if (pid == getpid()) { - alive = 1; - } else if (kill(pid, 0) == 0) { - alive = 1; - /* only existing processes can fail with EPERM */ - } else if (errno == EPERM) { - alive = 1; - } - - return alive; -} - - -static void dbConfigure(rpmDbiTagVal rpmtag, struct dbConfig_s *cfg, struct dbiConfig_s *dbicfg) -{ - char *dbOpts; - - dbOpts = rpmExpand("%{_dbi_config_", rpmTagGetName(rpmtag), "}", NULL); - - if (!(dbOpts && *dbOpts && *dbOpts != '%')) { - dbOpts = _free(dbOpts); - dbOpts = rpmExpand("%{_dbi_config}", NULL); - if (!(dbOpts && *dbOpts && *dbOpts != '%')) { - dbOpts = _free(dbOpts); - } - } - - /* Parse the options for the database element(s). */ - if (dbOpts && *dbOpts && *dbOpts != '%') { - char *o, *oe; - char *p, *pe; - - memset(&staticdbicfg, 0, sizeof(staticdbicfg)); -/*=========*/ - for (o = dbOpts; o && *o; o = oe) { - const struct poptOption *opt; - const char * tok; - unsigned int argInfo; - - /* Skip leading white space. */ - while (*o && risspace(*o)) - o++; - - /* Find and terminate next key=value pair. Save next start point. */ - for (oe = o; oe && *oe; oe++) { - if (risspace(*oe)) - break; - if (oe[0] == ':' && !(oe[1] == '/' && oe[2] == '/')) - break; - } - if (oe && *oe) - *oe++ = '\0'; - if (*o == '\0') - continue; - - /* Separate key from value, save value start (if any). */ - for (pe = o; pe && *pe && *pe != '='; pe++) - {}; - p = (pe ? *pe++ = '\0', pe : NULL); - - /* Skip over negation at start of token. */ - for (tok = o; *tok == '!'; tok++) - {}; - - /* Find key in option table. */ - for (opt = rdbOptions; opt->longName != NULL; opt++) { - if (!rstreq(tok, opt->longName)) - continue; - break; - } - if (opt->longName == NULL) { - rpmlog(RPMLOG_ERR, - _("unrecognized db option: \"%s\" ignored.\n"), o); - continue; - } - - /* Toggle the flags for negated tokens, if necessary. */ - argInfo = opt->argInfo; - if (argInfo == POPT_BIT_SET && *o == '!' && ((tok - o) % 2)) - argInfo = POPT_BIT_CLR; - - /* Save value in template as appropriate. */ - switch (argInfo & POPT_ARG_MASK) { - - case POPT_ARG_NONE: - (void) poptSaveInt((int *)opt->arg, argInfo, 1L); - break; - case POPT_ARG_VAL: - (void) poptSaveInt((int *)opt->arg, argInfo, (long)opt->val); - break; - case POPT_ARG_STRING: - { char ** t = opt->arg; - if (t) { -/* FIX: opt->arg annotation in popt.h */ - *t = _free(*t); - *t = xstrdup( (p ? p : "") ); - } - } break; - - case POPT_ARG_INT: - case POPT_ARG_LONG: - { long aLong = strtol(p, &pe, 0); - if (pe) { - if (!rstrncasecmp(pe, "Mb", 2)) - aLong *= 1024 * 1024; - else if (!rstrncasecmp(pe, "Kb", 2)) - aLong *= 1024; - else if (*pe != '\0') { - rpmlog(RPMLOG_ERR, - _("%s has invalid numeric value, skipped\n"), - opt->longName); - continue; - } - } - - if ((argInfo & POPT_ARG_MASK) == POPT_ARG_LONG) { - if (aLong == LONG_MIN || aLong == LONG_MAX) { - rpmlog(RPMLOG_ERR, - _("%s has too large or too small long value, skipped\n"), - opt->longName); - continue; - } - (void) poptSaveLong((long *)opt->arg, argInfo, aLong); - break; - } else { - if (aLong > INT_MAX || aLong < INT_MIN) { - rpmlog(RPMLOG_ERR, - _("%s has too large or too small integer value, skipped\n"), - opt->longName); - continue; - } - (void) poptSaveInt((int *)opt->arg, argInfo, aLong); - } - } break; - default: - break; - } - } -/*=========*/ - } - - dbOpts = _free(dbOpts); - if (cfg) { - *cfg = staticcfg; /* structure assignment */ - /* Throw in some defaults if configuration didn't set any */ - if (!cfg->db_mmapsize) - cfg->db_mmapsize = 16 * 1024 * 1024; - if (!cfg->db_cachesize) - cfg->db_cachesize = 8 * 1024 * 1024; - } - if (dbicfg) { - *dbicfg = staticdbicfg; - } -} - -static char * prDbiOpenFlags(int dbflags, int print_dbenv_flags) -{ - ARGV_t flags = NULL; - const struct poptOption *opt; - char *buf; - - for (opt = rdbOptions; opt->longName != NULL; opt++) { - if (opt->argInfo != POPT_BIT_SET) - continue; - if (print_dbenv_flags) { - if (!(opt->arg == &staticcfg.db_eflags)) - continue; - } else { - if (!(opt->arg == &staticdbicfg.dbi_oflags)) - continue; - } - if ((dbflags & opt->val) != opt->val) - continue; - argvAdd(&flags, opt->longName); - dbflags &= ~opt->val; - } - if (dbflags) { - char *df = NULL; - rasprintf(&df, "0x%x", (unsigned)dbflags); - argvAdd(&flags, df); - free(df); - } - buf = argvJoin(flags, ":"); - argvFree(flags); - - return buf ? buf : xstrdup("(none)"); -} - -static int db_init(rpmdb rdb, const char * dbhome) -{ - DB_ENV *dbenv = NULL; - int rc, xx; - int retry_open = 2; - int lockfd = -1; - int rdonly = ((rdb->db_mode & O_ACCMODE) == O_RDONLY); - struct dbConfig_s * cfg = &rdb->cfg; - /* This is our setup, thou shall not have other setups before us */ - uint32_t eflags = (DB_CREATE|DB_INIT_MPOOL|DB_INIT_CDB); - - if (rdb->db_dbenv != NULL) { - rdb->db_opens++; - return 0; - } - - /* - * Both verify and rebuild are rather special, if for different reasons: - * On rebuild we dont want to be affected by eg paniced environment, and - * CDB only slows things down there. Verify is a quirky beast unlike - * anything else in BDB, and does not like shared env or CDB. - */ - if (rdb->db_flags & (RPMDB_FLAG_VERIFYONLY|RPMDB_FLAG_REBUILD)) { - eflags |= DB_PRIVATE; - eflags &= ~DB_INIT_CDB; - } - - rc = db_env_create(&dbenv, 0); - rc = dbapi_err(rdb, "db_env_create", rc, _debug); - if (dbenv == NULL || rc) - goto errxit; - - dbenv->set_alloc(dbenv, rmalloc, rrealloc, NULL); - dbenv->set_errcall(dbenv, NULL); - dbenv->set_errpfx(dbenv, _errpfx); - dbenv->set_msgcall(dbenv, warnlog); - - /* - * These enable automatic stale lock removal. - * thread_count 8 is some kind of "magic minimum" value... - */ - dbenv->set_thread_count(dbenv, 8); - dbenv->set_isalive(dbenv, isalive); - - dbenv->set_verbose(dbenv, DB_VERB_DEADLOCK, - (cfg->db_verbose & DB_VERB_DEADLOCK)); - dbenv->set_verbose(dbenv, DB_VERB_RECOVERY, - (cfg->db_verbose & DB_VERB_RECOVERY)); - dbenv->set_verbose(dbenv, DB_VERB_WAITSFOR, - (cfg->db_verbose & DB_VERB_WAITSFOR)); - - if (cfg->db_mmapsize) { - xx = dbenv->set_mp_mmapsize(dbenv, cfg->db_mmapsize); - xx = dbapi_err(rdb, "dbenv->set_mp_mmapsize", xx, _debug); - } - - if (cfg->db_cachesize) { - xx = dbenv->set_cachesize(dbenv, 0, cfg->db_cachesize, 0); - xx = dbapi_err(rdb, "dbenv->set_cachesize", xx, _debug); - } - - /* - * Serialize shared environment open (and clock) via fcntl() lock. - * Otherwise we can end up calling dbenv->failchk() while another - * process is joining the environment, leading to transient - * DB_RUNRECOVER errors. Also prevents races wrt removing the - * environment (eg chrooted operation). Silently fall back to - * private environment on failure to allow non-privileged queries - * to "work", broken as it might be. - */ - if (!(eflags & DB_PRIVATE)) { - lockfd = serialize_env(dbhome); - if (lockfd < 0 && rdonly) { - eflags |= DB_PRIVATE; - retry_open--; - rpmlog(RPMLOG_DEBUG, "serialize failed, using private dbenv\n"); - } - } - - /* - * Actually open the environment. Fall back to private environment - * if we dont have permission to join/create shared environment or - * system doesn't support it.. - */ - while (retry_open) { - char *fstr = prDbiOpenFlags(eflags, 1); - rpmlog(RPMLOG_DEBUG, "opening db environment %s %s\n", dbhome, fstr); - free(fstr); - - rc = (dbenv->open)(dbenv, dbhome, eflags, rdb->db_perms); - if (rc == EINVAL && errno == rc) { - eflags |= DB_PRIVATE; - retry_open--; - } else if (rdonly && (rc == EACCES || rc == EROFS || rc == DB_VERSION_MISMATCH)) { - eflags |= DB_PRIVATE; - retry_open--; - } else { - retry_open = 0; - } - } - rc = dbapi_err(rdb, "dbenv->open", rc, _debug); - if (rc) - goto errxit; - - dbenv->set_errcall(dbenv, errlog); - - /* stale lock removal */ - rc = dbenv->failchk(dbenv, 0); - rc = dbapi_err(rdb, "dbenv->failchk", rc, _debug); - if (rc) - goto errxit; - - rdb->db_dbenv = dbenv; - rdb->db_opens = 1; - - if (lockfd >= 0) - close(lockfd); - return 0; - -errxit: - if (dbenv) { - int xx; - xx = dbenv->close(dbenv, 0); - xx = dbapi_err(rdb, "dbenv->close", xx, _debug); - } - if (lockfd >= 0) - close(lockfd); - return rc; -} - -static void db3_dbSetFSync(rpmdb rdb, int enable) -{ -#ifdef HAVE_FDATASYNC - db_env_set_func_fsync(enable ? fdatasync : fsync_disable); -#else - db_env_set_func_fsync(enable ? fsync : fsync_disable); -#endif -} - -static int db3_Ctrl(rpmdb rdb, dbCtrlOp ctrl) -{ - return 0; -} - -static int dbiSync(dbiIndex dbi, unsigned int flags) -{ - DB * db = dbi->dbi_db; - int rc = 0; - - if (db != NULL && !dbi->cfg.dbi_no_dbsync) { - rc = db->sync(db, flags); - rc = cvtdberr(dbi, "db->sync", rc, _debug); - } - return rc; -} - -static dbiCursor db3_dbiCursorInit(dbiIndex dbi, unsigned int flags) -{ - dbiCursor dbc = NULL; - - if (dbi && dbi->dbi_db) { - DB * db = dbi->dbi_db; - DBC * cursor; - int cflags; - int rc = 0; - uint32_t eflags = db_envflags(db); - - /* DB_WRITECURSOR requires CDB and writable db */ - if ((flags & DBC_WRITE) && - (eflags & DB_INIT_CDB) && !(dbi->dbi_flags & DBI_RDONLY)) - { - cflags = DB_WRITECURSOR; - } else - cflags = 0; - - /* - * Check for stale locks which could block writes "forever". - * XXX: Should we also do this on reads? Reads are less likely - * to get blocked so it seems excessive... - * XXX: On DB_RUNRECOVER, we should abort everything. Now - * we'll just fail to open a cursor again and again and again. - */ - if (cflags & DB_WRITECURSOR) { - DB_ENV *dbenv = db->get_env(db); - rc = dbenv->failchk(dbenv, 0); - rc = cvtdberr(dbi, "dbenv->failchk", rc, _debug); - } - - if (rc == 0) { - rc = db->cursor(db, NULL, &cursor, cflags); - rc = cvtdberr(dbi, "db->cursor", rc, _debug); - } - - if (rc == 0) { - dbc = xcalloc(1, sizeof(*dbc)); - dbc->cursor = cursor; - dbc->dbi = dbi; - dbc->flags = flags; - } - } - - return dbc; -} - -static dbiCursor db3_dbiCursorFree(dbiIndex dbi, dbiCursor dbc) -{ - if (dbc) { - /* Automatically sync on write-cursor close */ - if (dbc->flags & DBC_WRITE) - dbiSync(dbc->dbi, 0); - DBC * cursor = dbc->cursor; - int rc = cursor->c_close(cursor); - cvtdberr(dbc->dbi, "dbcursor->c_close", rc, _debug); - free(dbc); - } - return NULL; -} - -static int dbiCursorPut(dbiCursor dbc, DBT * key, DBT * data, unsigned int flags) -{ - int rc = EINVAL; - int sane = (key->data != NULL && key->size > 0 && - data->data != NULL && data->size > 0); - - if (dbc && sane) { - DBC * cursor = dbc->cursor; - rpmdb rdb = dbc->dbi->dbi_rpmdb; - rpmswEnter(&rdb->db_putops, (ssize_t) 0); - - rc = cursor->c_put(cursor, key, data, DB_KEYLAST); - rc = cvtdberr(dbc->dbi, "dbcursor->c_put", rc, _debug); - - rpmswExit(&rdb->db_putops, (ssize_t) data->size); - } - return rc; -} - -static int dbiCursorGet(dbiCursor dbc, DBT * key, DBT * data, unsigned int flags) -{ - int rc = EINVAL; - int sane = ((flags == DB_NEXT) || (key->data != NULL && key->size > 0)); - - if (dbc && sane) { - DBC * cursor = dbc->cursor; - rpmdb rdb = dbc->dbi->dbi_rpmdb; - int _printit; - rpmswEnter(&rdb->db_getops, 0); - - /* XXX db4 does DB_FIRST on uninitialized cursor */ - rc = cursor->c_get(cursor, key, data, flags); - /* XXX DB_NOTFOUND can be returned */ - _printit = (rc == DB_NOTFOUND ? 0 : _debug); - rc = cvtdberr(dbc->dbi, "dbcursor->c_get", rc, _printit); - - /* Remember the last key fetched */ - if (rc == 0) { - dbc->key = key->data; - dbc->keylen = key->size; - } else { - dbc->key = NULL; - dbc->keylen = 0; - } - - rpmswExit(&rdb->db_getops, data->size); - } - return rc; -} - -static int dbiCursorDel(dbiCursor dbc, DBT * key, DBT * data, unsigned int flags) -{ - int rc = EINVAL; - int sane = (key->data != NULL && key->size > 0); - - if (dbc && sane) { - DBC * cursor = dbc->cursor; - int _printit; - rpmdb rdb = dbc->dbi->dbi_rpmdb; - rpmswEnter(&rdb->db_delops, 0); - - /* XXX TODO: insure that cursor is positioned with duplicates */ - rc = cursor->c_get(cursor, key, data, DB_SET); - /* XXX DB_NOTFOUND can be returned */ - _printit = (rc == DB_NOTFOUND ? 0 : _debug); - rc = cvtdberr(dbc->dbi, "dbcursor->c_get", rc, _printit); - - if (rc == 0) { - rc = cursor->c_del(cursor, flags); - rc = cvtdberr(dbc->dbi, "dbcursor->c_del", rc, _debug); - } - rpmswExit(&rdb->db_delops, data->size); - } - return rc; -} - -static int dbiByteSwapped(dbiIndex dbi) -{ - DB * db = dbi->dbi_db; - int rc = 0; - - if (dbi->dbi_byteswapped != -1) - return dbi->dbi_byteswapped; - - if (db != NULL) { - int isswapped = 0; - rc = db->get_byteswapped(db, &isswapped); - if (rc == 0) - dbi->dbi_byteswapped = rc = isswapped; - } - return rc; -} - -static int db3_dbiVerify(dbiIndex dbi, unsigned int flags) -{ - int rc = 0; - - if (dbi && dbi->dbi_db) { - DB * db = dbi->dbi_db; - - rc = db->verify(db, dbi->dbi_file, NULL, NULL, flags); - rc = cvtdberr(dbi, "db->verify", rc, _debug); - - rpmlog(RPMLOG_DEBUG, "verified db index %s\n", dbi->dbi_file); - - /* db->verify() destroys the handle, make sure nobody accesses it */ - dbi->dbi_db = NULL; - } - return rc; -} - -static int db3_dbiClose(dbiIndex dbi, unsigned int flags) -{ - rpmdb rdb = dbi->dbi_rpmdb; - const char * dbhome = rpmdbHome(rdb); - DB * db = dbi->dbi_db; - int _printit; - int rc = 0; - - if (db) { - rc = db->close(db, flags); - /* XXX ignore not found error messages. */ - _printit = (rc == ENOENT ? 0 : _debug); - rc = cvtdberr(dbi, "db->close", rc, _printit); - db = dbi->dbi_db = NULL; - - rpmlog(RPMLOG_DEBUG, "closed db index %s/%s\n", - dbhome, dbi->dbi_file); - } - - db_fini(rdb, dbhome ? dbhome : ""); - - dbi->dbi_db = NULL; - - dbi = dbiFree(dbi); - - return rc; -} - -/* - * Lock a file using fcntl(2). Traditionally this is Packages, - * the file used to store metadata of installed header(s), - * as Packages is always opened, and should be opened first, - * for any rpmdb access. - * - * If no DBENV is used, then access is protected with a - * shared/exclusive locking scheme, as always. - * - * With a DBENV, the fcntl(2) lock is necessary only to keep - * the riff-raff from playing where they don't belong, as - * the DBENV should provide it's own locking scheme. So try to - * acquire a lock, but permit failures, as some other - * DBENV player may already have acquired the lock. - * - * With NPTL posix mutexes, revert to fcntl lock on non-functioning - * glibc/kernel combinations. - */ -static int dbiFlock(dbiIndex dbi, int mode) -{ - int fdno = -1; - int rc = 0; - DB * db = dbi->dbi_db; - - if (!(db->fd(db, &fdno) == 0 && fdno >= 0)) { - rc = 1; - } else { - const char *dbhome = rpmdbHome(dbi->dbi_rpmdb); - struct flock l; - memset(&l, 0, sizeof(l)); - l.l_whence = 0; - l.l_start = 0; - l.l_len = 0; - l.l_type = (mode & O_ACCMODE) == O_RDONLY - ? F_RDLCK : F_WRLCK; - l.l_pid = 0; - - rc = fcntl(fdno, F_SETLK, (void *) &l); - if (rc) { - uint32_t eflags = db_envflags(db); - /* Warning iff using non-private CDB locking. */ - rc = (((eflags & DB_INIT_CDB) && !(eflags & DB_PRIVATE)) ? 0 : 1); - rpmlog( (rc ? RPMLOG_ERR : RPMLOG_WARNING), - _("cannot get %s lock on %s/%s\n"), - ((mode & O_ACCMODE) == O_RDONLY) - ? _("shared") : _("exclusive"), - dbhome, dbi->dbi_file); - } else { - rpmlog(RPMLOG_DEBUG, - "locked db index %s/%s\n", - dbhome, dbi->dbi_file); - } - } - return rc; -} - -static int db3_dbiOpen(rpmdb rdb, rpmDbiTagVal rpmtag, dbiIndex * dbip, int flags) -{ - const char *dbhome = rpmdbHome(rdb); - dbiIndex dbi = NULL; - int rc = 0; - int retry_open; - int verifyonly = (flags & RPMDB_FLAG_VERIFYONLY); - - DB * db = NULL; - DBTYPE dbtype = DB_UNKNOWN; - uint32_t oflags; - static int _lockdbfd = 0; - - if (dbip) - *dbip = NULL; - - if ((dbi = dbiNew(rdb, rpmtag)) == NULL) - return 1; - - /* - * Parse db configuration parameters. - */ - dbConfigure(rpmtag, rdb->db_dbenv == NULL ? &rdb->cfg : NULL, &dbi->cfg); - - /* - * Map open mode flags onto configured database/environment flags. - */ - oflags = dbi->cfg.dbi_oflags; - if ((rdb->db_mode & O_ACCMODE) == O_RDONLY) - oflags |= DB_RDONLY; - - rc = db_init(rdb, dbhome); - - retry_open = (rc == 0) ? 2 : 0; - - while (retry_open) { - rc = db_create(&db, rdb->db_dbenv, 0); - rc = cvtdberr(dbi, "db_create", rc, _debug); - - /* For verify we only want the handle, not an open db */ - if (verifyonly) - break; - - if (rc == 0 && db != NULL) { - int _printit; - char *dbfs = prDbiOpenFlags(oflags, 0); - rpmlog(RPMLOG_DEBUG, "opening db index %s/%s %s mode=0x%x\n", - dbhome, dbi->dbi_file, dbfs, rdb->db_mode); - free(dbfs); - - rc = (db->open)(db, NULL, dbi->dbi_file, NULL, - dbtype, oflags, rdb->db_perms); - - /* Attempt to create if missing, if not read-only */ - if (rc == ENOENT && !(oflags & DB_RDONLY)) { - oflags |= DB_CREATE; - dbtype = (rpmtag == RPMDBI_PACKAGES) ? DB_HASH : DB_BTREE; - retry_open--; - } else { - retry_open = 0; - } - - /* XXX return rc == errno without printing */ - _printit = (rc > 0 ? 0 : _debug); - rc = cvtdberr(dbi, "db->open", rc, _printit); - - /* Validate the index type is something we can support */ - if ((rc == 0) && (dbtype == DB_UNKNOWN)) { - db->get_type(db, &dbtype); - if (dbtype != DB_HASH && dbtype != DB_BTREE) { - rpmlog(RPMLOG_ERR, _("invalid index type %x on %s/%s\n"), - dbtype, dbhome, dbi->dbi_file); - rc = 1; - } - } - - if (rc != 0) { - db->close(db, 0); - db = NULL; - } - } - } - - dbi->dbi_db = db; - - dbi->dbi_flags = 0; - if (oflags & DB_CREATE) - dbi->dbi_flags |= DBI_CREATED; - if (oflags & DB_RDONLY) - dbi->dbi_flags |= DBI_RDONLY; - - if (!verifyonly && rc == 0 && dbi->cfg.dbi_lockdbfd && _lockdbfd++ == 0) { - rc = dbiFlock(dbi, rdb->db_mode); - } - - if (rc == 0 && dbi->dbi_db != NULL && dbip != NULL) { - *dbip = dbi; - } else { - (void) dbiClose(dbi, 0); - } - - return rc; -} - -/** - * Convert retrieved data to index set. - * @param dbi index database handle - * @param data retrieved data - * @param[out] setp (malloc'ed) index set - * @return 0 on success - */ -static int dbt2set(dbiIndex dbi, DBT * data, dbiIndexSet * setp) -{ - int _dbbyteswapped = dbiByteSwapped(dbi); - const char * sdbir; - dbiIndexSet set; - unsigned int i; - - if (dbi == NULL || data == NULL || setp == NULL) - return -1; - - if ((sdbir = data->data) == NULL) { - *setp = NULL; - return 0; - } - - set = dbiIndexSetNew(data->size / (2 * sizeof(int32_t))); - set->count = data->size / (2 * sizeof(int32_t)); - - for (i = 0; i < set->count; i++) { - union _dbswap hdrNum, tagNum; - - memcpy(&hdrNum.ui, sdbir, sizeof(hdrNum.ui)); - sdbir += sizeof(hdrNum.ui); - memcpy(&tagNum.ui, sdbir, sizeof(tagNum.ui)); - sdbir += sizeof(tagNum.ui); - if (_dbbyteswapped) { - _DBSWAP(hdrNum); - _DBSWAP(tagNum); - } - set->recs[i].hdrNum = hdrNum.ui; - set->recs[i].tagNum = tagNum.ui; - } - *setp = set; - return 0; -} - -/** - * Convert index set to database representation. - * @param dbi index database handle - * @param data retrieved data - * @param set index set - * @return 0 on success - */ -static int set2dbt(dbiIndex dbi, DBT * data, dbiIndexSet set) -{ - int _dbbyteswapped = dbiByteSwapped(dbi); - char * tdbir; - unsigned int i; - - if (dbi == NULL || data == NULL || set == NULL) - return -1; - - data->size = set->count * (2 * sizeof(int32_t)); - if (data->size == 0) { - data->data = NULL; - return 0; - } - tdbir = data->data = xmalloc(data->size); - - for (i = 0; i < set->count; i++) { - union _dbswap hdrNum, tagNum; - - memset(&hdrNum, 0, sizeof(hdrNum)); - memset(&tagNum, 0, sizeof(tagNum)); - hdrNum.ui = set->recs[i].hdrNum; - tagNum.ui = set->recs[i].tagNum; - if (_dbbyteswapped) { - _DBSWAP(hdrNum); - _DBSWAP(tagNum); - } - memcpy(tdbir, &hdrNum.ui, sizeof(hdrNum.ui)); - tdbir += sizeof(hdrNum.ui); - memcpy(tdbir, &tagNum.ui, sizeof(tagNum.ui)); - tdbir += sizeof(tagNum.ui); - } - return 0; -} - -static rpmRC db3_idxdbGet(dbiIndex dbi, dbiCursor dbc, const char *keyp, size_t keylen, - dbiIndexSet *set, int searchType) -{ - rpmRC rc = RPMRC_FAIL; /* assume failure */ - if (dbi != NULL && dbc != NULL) { - int cflags = DB_NEXT; - int dbrc; - DBT data, key; - memset(&data, 0, sizeof(data)); - memset(&key, 0, sizeof(key)); - - if (keyp) { - if (keylen == 0) { /* XXX "/" fixup */ - keyp = ""; - keylen = 1; - } - key.data = (void *) keyp; /* discards const */ - key.size = keylen; - cflags = searchType == DBC_PREFIX_SEARCH ? DB_SET_RANGE : DB_SET; - } - - for (;;) { - dbiIndexSet newset = NULL; - dbrc = dbiCursorGet(dbc, &key, &data, cflags); - if (dbrc != 0) - break; - if (searchType == DBC_PREFIX_SEARCH && - (key.size < keylen || memcmp(key.data, keyp, keylen) != 0)) - break; - if (set) { - dbt2set(dbi, &data, &newset); - if (*set == NULL) { - *set = newset; - } else { - dbiIndexSetAppendSet(*set, newset, 0); - dbiIndexSetFree(newset); - } - } - if (searchType != DBC_PREFIX_SEARCH) - break; - key.data = NULL; - key.size = 0; - cflags = DB_NEXT; - } - - /* fixup result status for prefix search */ - if (searchType == DBC_PREFIX_SEARCH && set) { - if (dbrc == DB_NOTFOUND && *set != NULL && (*set)->count > 0) - dbrc = 0; - else if (dbrc == 0 && (*set == NULL || (*set)->count == 0)) - dbrc = DB_NOTFOUND; - } - - if (dbrc == 0) { - rc = RPMRC_OK; - } else if (dbrc == DB_NOTFOUND) { - rc = RPMRC_NOTFOUND; - } else { - rpmlog(RPMLOG_ERR, - _("error(%d) getting \"%s\" records from %s index: %s\n"), - dbrc, keyp ? keyp : "???", dbiName(dbi), db_strerror(dbrc)); - } - } - return rc; -} - -/* Update secondary index. NULL set deletes the key */ -static rpmRC updateIndex(dbiCursor dbc, const char *keyp, unsigned int keylen, - dbiIndexSet set) -{ - rpmRC rc = RPMRC_FAIL; - - if (dbc && keyp) { - dbiIndex dbi = dbc->dbi; - int dbrc; - DBT data, key; - memset(&key, 0, sizeof(data)); - memset(&data, 0, sizeof(data)); - - key.data = (void *) keyp; /* discards const */ - key.size = keylen; - - if (set) - set2dbt(dbi, &data, set); - - if (dbiIndexSetCount(set) > 0) { - dbrc = dbiCursorPut(dbc, &key, &data, DB_KEYLAST); - if (dbrc) { - rpmlog(RPMLOG_ERR, - _("error(%d) storing record \"%s\" into %s\n"), - dbrc, (char*)key.data, dbiName(dbi)); - } - free(data.data); - } else { - dbrc = dbiCursorDel(dbc, &key, &data, 0); - if (dbrc) { - rpmlog(RPMLOG_ERR, - _("error(%d) removing record \"%s\" from %s\n"), - dbrc, (char*)key.data, dbiName(dbi)); - } - } - - if (dbrc == 0) - rc = RPMRC_OK; - } - - return rc; -} - -static rpmRC db3_idxdbPutOne(dbiIndex dbi, dbiCursor dbc, const char *keyp, size_t keylen, - dbiIndexItem rec) -{ - dbiIndexSet set = NULL; - rpmRC rc; - - if (keyp && keylen == 0) { /* XXX "/" fixup */ - keyp = ""; - keylen++; - } - rc = idxdbGet(dbi, dbc, keyp, keylen, &set, DBC_NORMAL_SEARCH); - - /* Not found means a new key and is not an error. */ - if (rc && rc != RPMRC_NOTFOUND) - return rc; - - if (set == NULL) - set = dbiIndexSetNew(1); - dbiIndexSetAppend(set, rec, 1, 0); - - rc = updateIndex(dbc, keyp, keylen, set); - - dbiIndexSetFree(set); - return rc; -} - -static rpmRC db3_idxdbPut(dbiIndex dbi, rpmTagVal rpmtag, unsigned int hdrNum, Header h) -{ - return tag2index(dbi, rpmtag, hdrNum, h, db3_idxdbPutOne); -} - -static rpmRC db3_idxdbDelOne(dbiIndex dbi, dbiCursor dbc, const char *keyp, size_t keylen, - dbiIndexItem rec) -{ - dbiIndexSet set = NULL; - rpmRC rc; - - if (keyp && keylen == 0) { /* XXX "/" fixup */ - keyp = ""; - keylen++; - } - rc = idxdbGet(dbi, dbc, keyp, keylen, &set, DBC_NORMAL_SEARCH); - if (rc) - return rc; - - if (dbiIndexSetPrune(set, rec, 1, 1)) { - /* Nothing was pruned. XXX: Can this actually happen? */ - rc = RPMRC_OK; - } else { - /* If there's data left, update data. Otherwise delete the key. */ - if (dbiIndexSetCount(set) > 0) { - rc = updateIndex(dbc, keyp, keylen, set); - } else { - rc = updateIndex(dbc, keyp, keylen, NULL); - } - }; - dbiIndexSetFree(set); - - return rc; -} - -static rpmRC db3_idxdbDel(dbiIndex dbi, rpmTagVal rpmtag, unsigned int hdrNum, Header h) -{ - return tag2index(dbi, rpmtag, hdrNum, h, db3_idxdbDelOne); -} - -static const void * db3_idxdbKey(dbiIndex dbi, dbiCursor dbc, unsigned int *keylen) -{ - const void *key = NULL; - if (dbc) { - key = dbc->key; - if (key && keylen) - *keylen = dbc->keylen; - } - return key; -} - - -/* Update primary Packages index. NULL hdr means remove */ -static rpmRC updatePackages(dbiCursor dbc, unsigned int hdrNum, DBT *hdr) -{ - union _dbswap mi_offset; - int rc = 0; - DBT key; - - if (dbc == NULL || hdrNum == 0) - return RPMRC_FAIL; - - memset(&key, 0, sizeof(key)); - - mi_offset.ui = hdrNum; - if (dbiByteSwapped(dbc->dbi) == 1) - _DBSWAP(mi_offset); - key.data = (void *) &mi_offset; - key.size = sizeof(mi_offset.ui); - - if (hdr) { - rc = dbiCursorPut(dbc, &key, hdr, DB_KEYLAST); - if (rc) { - rpmlog(RPMLOG_ERR, - _("error(%d) adding header #%d record\n"), rc, hdrNum); - } - } else { - DBT data; - - memset(&data, 0, sizeof(data)); - rc = dbiCursorGet(dbc, &key, &data, DB_SET); - if (rc) { - rpmlog(RPMLOG_ERR, - _("error(%d) removing header #%d record\n"), rc, hdrNum); - } else - rc = dbiCursorDel(dbc, &key, &data, 0); - } - - return rc == 0 ? RPMRC_OK : RPMRC_FAIL; -} - -/* Get current header instance number or try to allocate a new one */ -static unsigned int pkgInstance(dbiIndex dbi, int alloc) -{ - unsigned int hdrNum = 0; - - if (dbi != NULL && dbi->dbi_type == DBI_PRIMARY) { - dbiCursor dbc; - DBT key, data; - unsigned int firstkey = 0; - union _dbswap mi_offset; - int ret; - - memset(&key, 0, sizeof(key)); - memset(&data, 0, sizeof(data)); - - dbc = dbiCursorInit(dbi, alloc ? DBC_WRITE : 0); - - /* Key 0 holds the current largest instance, fetch it */ - key.data = &firstkey; - key.size = sizeof(firstkey); - ret = dbiCursorGet(dbc, &key, &data, DB_SET); - - if (ret == 0 && data.data) { - memcpy(&mi_offset, data.data, sizeof(mi_offset.ui)); - if (dbiByteSwapped(dbi) == 1) - _DBSWAP(mi_offset); - hdrNum = mi_offset.ui; - } - - if (alloc) { - /* Rather complicated "increment by one", bswapping as needed */ - ++hdrNum; - mi_offset.ui = hdrNum; - if (dbiByteSwapped(dbi) == 1) - _DBSWAP(mi_offset); - if (ret == 0 && data.data) { - memcpy(data.data, &mi_offset, sizeof(mi_offset.ui)); - } else { - data.data = &mi_offset; - data.size = sizeof(mi_offset.ui); - } - - /* Unless we manage to insert the new instance number, we failed */ - ret = dbiCursorPut(dbc, &key, &data, DB_KEYLAST); - if (ret) { - hdrNum = 0; - rpmlog(RPMLOG_ERR, - _("error(%d) allocating new package instance\n"), ret); - } - } - dbiCursorFree(dbi, dbc); - } - - return hdrNum; -} - -static rpmRC db3_pkgdbPut(dbiIndex dbi, dbiCursor dbc, unsigned int *hdrNum, - unsigned char *hdrBlob, unsigned int hdrLen) -{ - rpmRC rc = RPMRC_FAIL; - unsigned int hnum = *hdrNum; - DBT hdr; - memset(&hdr, 0, sizeof(hdr)); - hdr.data = hdrBlob; - hdr.size = hdrLen; - - if (hnum == 0) - hnum = pkgInstance(dbi, 1); - - if (hnum) - rc = updatePackages(dbc, hnum, &hdr); - - if (rc == RPMRC_OK) - *hdrNum = hnum; - - return rc; -} - -static rpmRC db3_pkgdbDel(dbiIndex dbi, dbiCursor dbc, unsigned int hdrNum) -{ - return updatePackages(dbc, hdrNum, NULL); -} - -static rpmRC db3_pkgdbGet(dbiIndex dbi, dbiCursor dbc, unsigned int hdrNum, - unsigned char **hdrBlob, unsigned int *hdrLen) -{ - DBT key, data; - union _dbswap mi_offset; - int rc; - - if (dbc == NULL) - return RPMRC_FAIL; - - memset(&key, 0, sizeof(key)); - memset(&data, 0, sizeof(data)); - - if (hdrNum) { - mi_offset.ui = hdrNum; - if (dbiByteSwapped(dbc->dbi) == 1) - _DBSWAP(mi_offset); - key.data = (void *) &mi_offset; - key.size = sizeof(mi_offset.ui); - } - -#if !defined(_USE_COPY_LOAD) - data.flags |= DB_DBT_MALLOC; -#endif - rc = dbiCursorGet(dbc, &key, &data, hdrNum ? DB_SET : DB_NEXT); - if (rc == 0) { - if (hdrBlob) - *hdrBlob = data.data; - if (hdrLen) - *hdrLen = data.size; - return RPMRC_OK; - } else if (rc == DB_NOTFOUND) - return RPMRC_NOTFOUND; - else - return RPMRC_FAIL; -} - -static unsigned int db3_pkgdbKey(dbiIndex dbi, dbiCursor dbc) -{ - union _dbswap mi_offset; - - if (dbc == NULL || dbc->key == NULL) - return 0; - memcpy(&mi_offset, dbc->key, sizeof(mi_offset.ui)); - if (dbiByteSwapped(dbc->dbi) == 1) - _DBSWAP(mi_offset); - return mi_offset.ui; -} - -struct rpmdbOps_s db3_dbops = { - .name = "bdb", - .path = "Packages", - - .open = db3_dbiOpen, - .close = db3_dbiClose, - .verify = db3_dbiVerify, - - .setFSync = db3_dbSetFSync, - .ctrl = db3_Ctrl, - - .cursorInit = db3_dbiCursorInit, - .cursorFree = db3_dbiCursorFree, - - .pkgdbGet = db3_pkgdbGet, - .pkgdbPut = db3_pkgdbPut, - .pkgdbDel = db3_pkgdbDel, - .pkgdbKey = db3_pkgdbKey, - - .idxdbGet = db3_idxdbGet, - .idxdbPut = db3_idxdbPut, - .idxdbDel = db3_idxdbDel, - .idxdbKey = db3_idxdbKey -}; - diff --git a/lib/backend/dbi.c b/lib/backend/dbi.c index 809d013bf..bcfe4de82 100644 --- a/lib/backend/dbi.c +++ b/lib/backend/dbi.c @@ -20,9 +20,6 @@ const struct rpmdbOps_s *backends[] = { #ifdef ENABLE_NDB &ndb_dbops, #endif -#if defined(WITH_BDB) - &db3_dbops, -#endif #if defined(WITH_BDB_RO) &bdbro_dbops, #endif diff --git a/lib/backend/dbi.h b/lib/backend/dbi.h index fba2f04eb..7f32d5050 100644 --- a/lib/backend/dbi.h +++ b/lib/backend/dbi.h @@ -270,11 +270,6 @@ struct rpmdbOps_s { const void * (*idxdbKey)(dbiIndex dbi, dbiCursor dbc, unsigned int *keylen); }; -#if defined(WITH_BDB) -RPM_GNUC_INTERNAL -extern struct rpmdbOps_s db3_dbops; -#endif - #if defined(WITH_BDB_RO) RPM_GNUC_INTERNAL extern struct rpmdbOps_s bdbro_dbops; diff --git a/lib/verify.c b/lib/verify.c index e3c829329..5b97fbf27 100644 --- a/lib/verify.c +++ b/lib/verify.c @@ -485,8 +485,8 @@ int rpmcliVerify(rpmts ts, QVA_t qva, char * const * argv) FD_t scriptFd = fdDup(STDOUT_FILENO); /* - * Open the DB + indices explicitly before possible chroot, - * otherwises BDB is going to be unhappy... + * Open the DB + indices explicitly before possible chroot for + * consistency with how transactions operate. */ rpmtsOpenDB(ts, O_RDONLY); rpmdbOpenAll(rpmtsGetRdb(ts)); @@ -590,57 +590,13 @@ package or when debugging this package.\ # ---- Database configuration macros. # # Select backend database. The following values are supported: -# bdb Berkeley DB +# bdb_ro Berkeley DB (read-only) # ndb new data base format # sqlite Sqlite database # dummy dummy backend (no actual functionality) # %_db_backend sqlite -# -# Macros used to configure Berkley db parameters. -# -# rpmdb macro configuration values are a colon (or white space) separated -# list of tokens, with an optional '!' negation to explicitly disable bit -# values, or a "=value" if a parameter. A per-tag value is used (e.g. -# %_dbi_config_Packages) if defined, otherwise a per-rpmdb default -# (e.g. %_dbi_config). -# -# Here's a short list of the tokens, with a guess of whether the option is -# useful: -# (nothing) currently used in rpm, known to work. -# "+++" under development, will be supported in rpm eventually. -# "???" I have no clue, you're mostly on your own. -# -# If you do find yourself inclined to fiddle, here's what I see (shrug): -# 1) Only the value of mp_size has any serious impact on overall performance, -# and you will need ~256Kb to handle a typical machine install. -# 2) Only the Packages hash, because of the size of the values (i.e. headers), -# will ever need tuning. Diddle the pagesize if you're interested, although -# I believe that you will find pagesize=512 "best". -# 3) Adding nofsync increases speed, but risks total data loss. Fiddle shared -# and/or mp_size instead. -# -# token works? Berkeley db flag or value -#================================================== -#---------------------- DBENV tunable values: -# mmapsize=16Mb DBENV->set_mp_mmapsize -# cachesize=1Mb DBENV->set_cachesize, DB->set_cachesize -#---------------------- DB->open bits: -# nommap ??? DB_NOMMAP -#----------------------- rpmdb specific configuration: -# lockdbfd (always on for Packages) Use fcntl(2) locking ? -# nofsync Disable fsync(2) call performed after db3 writes? -# - -# Misc BDB tuning options -%__dbi_other mp_mmapsize=128Mb mp_size=1Mb - -%_dbi_config %{?__dbi_other} - -# "Packages" should have shared/exclusive fcntl(2) lock using "lockdbfd". -%_dbi_config_Packages %{?_dbi_config} lockdbfd - #============================================================================== # ---- GPG/PGP/PGP5 signature macros. # Macro(s) to hold the arguments passed to GPG/PGP for package diff --git a/po/POTFILES.in b/po/POTFILES.in index 2a48950ab..7c42231b1 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -26,7 +26,6 @@ build/policies.c build/reqprov.c build/rpmfc.c build/spec.c -lib/backend/db3.c lib/backend/dbi.c lib/backend/dummydb.c lib/backend/ndb/glue.c @@ -13,4 +13,4 @@ Requires.private: @ZSTD_REQUIRES@ # Conflicts: Cflags: -I${includedir} Libs: -L${libdir} -lrpm -lrpmio -Libs.private: -lpopt -lrt -lpthread @WITH_LZMA_LIB@ @WITH_DB_LIB@ @WITH_BZ2_LIB@ @WITH_ZLIB_LIB@ @LUA_LIBS@ +Libs.private: -lpopt -lrt -lpthread @WITH_LZMA_LIB@ @WITH_BZ2_LIB@ @WITH_ZLIB_LIB@ @LUA_LIBS@ |