Merge changes from rpm-4.0.2.
authorjbj <devnull@localhost>
Sat, 17 Feb 2001 17:53:21 +0000 (17:53 +0000)
committerjbj <devnull@localhost>
Sat, 17 Feb 2001 17:53:21 +0000 (17:53 +0000)
Add iterators and reverse flag so that erase transactions can run backwards.

CVS patchset: 4556
CVS date: 2001/02/17 17:53:21

15 files changed:
configure.in
lib/Makefile.am
lib/db2.c
lib/db3.c
lib/depends.h
lib/rpmdb.h
lib/rpminstall.c
lib/rpmlib.h
lib/rpmlibprov.c
lib/transaction.c
po/POTFILES.in
po/rpm.pot
rpmio/rpmerr.h
rpmio/rpmlog.c
rpmio/rpmlog.h

index 84dafba..a86c7fa 100644 (file)
@@ -308,6 +308,7 @@ DBLIBSRCS=""
 libdb3=""
 libdb2=""
 libdb1=""
+
 dnl Check for Berkeley db3 API.
 AC_CHECK_FUNC(db_create, [DBLIBSRCS="$DBLIBSRCS db3.c"],
   AC_CHECK_LIB(db-3.1, db_create, [DBLIBSRCS="$DBLIBSRCS db3.c"; libdb3="-ldb-3.1"],
@@ -320,10 +321,14 @@ AC_CHECK_FUNC(db_create, [DBLIBSRCS="$DBLIBSRCS db3.c"],
 
 dnl Check for Berkeley db2 API.
 dnl AC_CHECK_FUNC(db_open, [DBLIBSRCS="$DBLIBSRCS db2.c"],
-dnl   AC_CHECK_LIB(db, db_open, [LIBS="$LIBS"; DBLIBSRCS="$DBLIBSRCS db2.c" ; libdb2="-ldb"])
+dnl   AC_CHECK_LIB(db2, db_open, [LIBS="$LIBS"; DBLIBSRCS="$DBLIBSRCS db2.c" ; libdb2="-ldb2"],
+dnl     AC_CHECK_LIB(db, db_open, [LIBS="$LIBS"; DBLIBSRCS="$DBLIBSRCS db2.c" ; libdb2="-ldb"],
+dnl     )
+dnl   )
 dnl )
+
 dnl Check for Berkeley db1 API retrofit to db2/db3 database.
-dnl AC_CHECK_FUNC(dbopen, [DBLIBSRCS="$DBLIBSRCS db1.c"],
+dnl AC_CHECK_FUNC(dbopen, [DBLIBSRCS="$DBLIBSRCS db1.c falloc.c"],
 dnl     AC_CHECK_LIB(db, dbopen, [DBLIBSRCS="$DBLIBSRCS db1.c"])
 dnl )
 
index e3ab735..36f1b68 100644 (file)
@@ -22,7 +22,7 @@ LIBS =
 
 lib_LTLIBRARIES = librpm.la
 librpm_la_SOURCES = \
-       cpio.c $(DBLIBSRCS) depends.c \
+       cpio.c $(DBLIBSRCS) dbconfig.c depends.c \
        formats.c fprint.c fs.c fsm.c hash.c header.c \
        md5.c md5sum.c misc.c package.c problems.c \
        poptBT.c poptQV.c psm.c query.c \
index bc28671..5bc8396 100644 (file)
--- a/lib/db2.c
+++ b/lib/db2.c
@@ -4,8 +4,19 @@
 
 static int _debug = 1; /* XXX if < 0 debugging, > 0 unusual error returns */
 
+#ifdef __LCLINT__
+typedef        unsigned int u_int32_t;
+typedef        unsigned short u_int16_t;
+typedef        unsigned char u_int8_t;
+typedef        int int32_t;
+#endif
+
+#define        INLINE
+
 #include "system.h"
+
 #include <db2/db.h>
+
 #include <rpmlib.h>
 #include <rpmmacro.h>
 #include <rpmurl.h>    /* XXX urlPath proto */
@@ -13,16 +24,15 @@ static int _debug = 1;      /* XXX if < 0 debugging, > 0 unusual error returns */
 #include "rpmdb.h"
 #include "debug.h"
 
+/*@access rpmdb@*/
 /*@access dbiIndex@*/
 /*@access dbiIndexSet@*/
 
-static const char * db2basename = "packages.db2";
-
 #if DB_VERSION_MAJOR == 2
 #define        __USE_DB2       1
 
 /* XXX remap DB3 types back into DB2 types */
-static inline DBTYPE db3_to_dbtype(int dbitype)
+static INLINE DBTYPE db3_to_dbtype(int dbitype)
 {
     switch(dbitype) {
     case 1:    return DB_BTREE;
@@ -100,12 +110,7 @@ static int db_env_create(DB_ENV **dbenvp, int foo)
 static int cvtdberr(dbiIndex dbi, const char * msg, int error, int printit) {
     int rc = 0;
 
-    if (error == 0)
-       rc = 0;
-    else if (error < 0)
-       rc = 1;
-    else if (error > 0)
-       rc = -1;
+    rc = error;
 
     if (printit && rc) {
        if (msg)
@@ -120,14 +125,13 @@ static int cvtdberr(dbiIndex dbi, const char * msg, int error, int printit) {
 }
 
 static int db_fini(dbiIndex dbi, const char * dbhome, const char * dbfile,
-               const char * dbsubfile)
+               /*@unused@*/ const char * dbsubfile)
 {
-    rpmdb rpmdb = dbi->dbi_rpmdb;
-    DB_ENV * dbenv = (DB_ENV *)dbi->dbi_dbenv;
+    DB_ENV * dbenv = dbi->dbi_dbenv;
+    int rc;
 
 #if defined(__USE_DB3)
-    char **dbconfig = NULL;
-    int rc;
+    rpmdb rpmdb = dbi->dbi_rpmdb;
 
     if (dbenv == NULL) {
        dbi->dbi_dbenv = NULL;
@@ -138,20 +142,24 @@ static int db_fini(dbiIndex dbi, const char * dbhome, const char * dbfile,
     rc = cvtdberr(dbi, "dbenv->close", rc, _debug);
 
     if (dbfile)
-       rpmMessage(RPMMESS_DEBUG, _("closed  db environment %s/%s(%s)\n"),
-               dbhome, dbfile, dbsubfile);
+       rpmMessage(RPMMESS_DEBUG, _("closed  db environment %s/%s\n"),
+               dbhome, dbfile);
 
     if (rpmdb->db_remove_env || dbi->dbi_tear_down) {
        int xx;
 
        xx = db_env_create(&dbenv, 0);
        xx = cvtdberr(dbi, "db_env_create", rc, _debug);
-       xx = dbenv->remove(dbenv, dbhome, dbconfig, 0);
+#if DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1
+       xx = dbenv->remove(dbenv, dbhome, 0);
+#else
+       xx = dbenv->remove(dbenv, dbhome, NULL, 0);
+#endif
        xx = cvtdberr(dbi, "dbenv->remove", rc, _debug);
 
        if (dbfile)
-           rpmMessage(RPMMESS_DEBUG, _("removed db environment %s/%s(%s)\n"),
-               dbhome, dbfile, dbsubfile);
+           rpmMessage(RPMMESS_DEBUG, _("removed db environment %s/%s\n"),
+                       dbhome, dbfile);
 
     }
        
@@ -164,12 +172,12 @@ static int db_fini(dbiIndex dbi, const char * dbhome, const char * dbfile,
     return rc;
 }
 
-static int db2_fsync_disable(int fd) {
+static int db2_fsync_disable(/*@unused@*/ int fd) {
     return 0;
 }
 
 static int db_init(dbiIndex dbi, const char *dbhome, const char *dbfile,
-               const char * dbsubfile, DB_ENV **dbenvp)
+               /*@unused@*/ const char * dbsubfile, /*@out@*/ DB_ENV **dbenvp)
 {
     rpmdb rpmdb = dbi->dbi_rpmdb;
     DB_ENV *dbenv = NULL;
@@ -187,8 +195,8 @@ static int db_init(dbiIndex dbi, const char *dbhome, const char *dbfile,
     if ( dbi->dbi_mode & O_CREAT) eflags |= DB_CREATE;
 
     if (dbfile)
-       rpmMessage(RPMMESS_DEBUG, _("opening db environment %s/%s(%s) %s\n"),
-               dbhome, dbfile, dbsubfile, prDbiOpenFlags(eflags, 1));
+       rpmMessage(RPMMESS_DEBUG, _("opening db environment %s/%s %s\n"),
+               dbhome, dbfile, prDbiOpenFlags(eflags, 1));
 
     rc = db_env_create(&dbenv, dbi->dbi_cflags);
     rc = cvtdberr(dbi, "db_env_create", rc, _debug);
@@ -220,8 +228,12 @@ static int db_init(dbiIndex dbi, const char *dbhome, const char *dbfile,
  /* dbenv->set_tx_max(???) */
  /* dbenv->set_tx_recover(???) */
     if (dbi->dbi_no_fsync) {
-       xx = dbenv->set_func_fsync(dbenv, db2_fsync_disable);
-       xx = cvtdberr(dbi, "dbenv->set_func_fsync", xx, _debug);
+#if DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1
+       xx = db_env_set_func_fsync(db3_fsync_disable);
+#else
+       xx = dbenv->set_func_fsync(dbenv, db3_fsync_disable);
+#endif
+       xx = cvtdberr(dbi, "db_env_set_func_fsync", xx, _debug);
     }
   }
 #else  /* __USE_DB3 */
@@ -234,7 +246,11 @@ static int db_init(dbiIndex dbi, const char *dbhome, const char *dbfile,
 #endif /* __USE_DB3 */
 
 #if defined(__USE_DB3)
+#if DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1
+    rc = dbenv->open(dbenv, dbhome, eflags, dbi->dbi_perms);
+#else
     rc = dbenv->open(dbenv, dbhome, NULL, eflags, dbi->dbi_perms);
+#endif
     rc = cvtdberr(dbi, "dbenv->open", rc, _debug);
     if (rc)
        goto errxit;
@@ -272,6 +288,7 @@ static int db2sync(dbiIndex dbi, unsigned int flags)
 
 #if defined(__USE_DB2) || defined(__USE_DB3)
     int _printit;
+
     rc = db->sync(db, flags);
     /* XXX DB_INCOMPLETE is returned occaisionally with multiple access. */
     _printit = (rc == DB_INCOMPLETE ? 0 : _debug);
@@ -292,12 +309,15 @@ static int db2c_del(dbiIndex dbi, DBC * dbcursor, u_int32_t flags)
     return rc;
 }
 
-static int db2c_dup(dbiIndex dbi, DBC * dbcursor, DBC ** dbcp, u_int32_t flags)
+/*@unused@*/ static int db2c_dup(dbiIndex dbi, DBC * dbcursor, DBC ** dbcp,
+               u_int32_t flags)
 {
-    int rc;
+    int rc = 0;
 
+#if defined(__USE_DB3)
     rc = dbcursor->c_dup(dbcursor, dbcp, flags);
     rc = cvtdberr(dbi, "dbcursor->c_dup", rc, _debug);
+#endif
     return rc;
 }
 
@@ -309,9 +329,7 @@ static int db2c_get(dbiIndex dbi, DBC * dbcursor,
     int rmw;
 
 #ifdef NOTYET
-    if ((dbi->dbi_eflags & DB_INIT_CDB) &&
-               !(dbi->dbi_oflags & DB_RDONLY) &&
-               !(dbi->dbi_mode & O_RDWR))
+    if ((dbi->dbi_eflags & DB_INIT_CDB) && !(dbi->dbi_oflags & DB_RDONLY))
        rmw = DB_RMW;
     else
 #endif
@@ -319,12 +337,13 @@ static int db2c_get(dbiIndex dbi, DBC * dbcursor,
 
     rc = dbcursor->c_get(dbcursor, key, data, rmw | flags);
 
+    /* XXX DB_NOTFOUND can be returned */
     _printit = (rc == DB_NOTFOUND ? 0 : _debug);
     rc = cvtdberr(dbi, "dbcursor->c_get", rc, _printit);
     return rc;
 }
 
-static int db2c_put(dbiIndex dbi, DBC * dbcursor,
+static int db2c_put(dbiIndex dbi, /*@only@*/ DBC * dbcursor,
        DBT * key, DBT * data, u_int32_t flags)
 {
     int rc;
@@ -335,7 +354,7 @@ static int db2c_put(dbiIndex dbi, DBC * dbcursor,
     return rc;
 }
 
-static inline int db2c_close(dbiIndex dbi, DBC * dbcursor)
+static INLINE int db2c_close(dbiIndex dbi, DBC * dbcursor)
 {
     int rc;
 
@@ -344,17 +363,16 @@ static inline int db2c_close(dbiIndex dbi, DBC * dbcursor)
     return rc;
 }
 
-static inline int db2c_open(dbiIndex dbi, DBC ** dbcp)
+static INLINE int db2c_open(dbiIndex dbi, /*@out@*/ DBC ** dbcp)
 {
     DB * db = dbi->dbi_db;
     DB_TXN * txnid = NULL;
-    int flags;
     int rc;
 
 #if defined(__USE_DB3)
-    if ((dbi->dbi_eflags & DB_INIT_CDB) &&
-               !(dbi->dbi_oflags & DB_RDONLY) &&
-               !(dbi->dbi_mode & O_RDWR))
+    int flags;
+
+    if ((dbi->dbi_eflags & DB_INIT_CDB) && !(dbi->dbi_oflags & DB_RDONLY))
        flags = DB_WRITECURSOR;
     else
        flags = 0;
@@ -362,45 +380,62 @@ static inline int db2c_open(dbiIndex dbi, DBC ** dbcp)
 #else  /* __USE_DB3 */
     rc = db->cursor(db, txnid, dbcp);
 #endif /* __USE_DB3 */
-    rc = cvtdberr(dbi, "db2copen", rc, _debug);
+    rc = cvtdberr(dbi, "db2c_open", rc, _debug);
 
     return rc;
 }
 
-static int db2cclose(dbiIndex dbi, DBC * dbcursor, unsigned int flags)
+static int db2cclose(dbiIndex dbi, /*@only@*/ DBC * dbcursor,
+               unsigned int flags)
 {
     int rc = 0;
 
+    /* XXX per-iterator cursors */
+    if (flags == 1)
+       return db2c_close(dbi, dbcursor);
+
+    if (!dbi->dbi_use_cursors)
+       return 0;
+
     if (dbcursor == NULL)
        dbcursor = dbi->dbi_rmw;
     if (dbcursor) {
-       rc = db2c_close(dbi, dbcursor);
        if (dbcursor == dbi->dbi_rmw)
            dbi->dbi_rmw = NULL;
+       rc = db2c_close(dbi, dbcursor);
     }
     return rc;
 }
 
-static int db2copen(dbiIndex dbi, DBC ** dbcp, unsigned int flags)
+static int db2copen(dbiIndex dbi, /*@out@*/ DBC ** dbcp, unsigned int flags)
 {
     DBC * dbcursor;
     int rc = 0;
 
-    if ((dbcursor = dbi->dbi_rmw) != NULL) {
-       if (dbcp) *dbcp = dbi->dbi_rmw;
+    /* XXX per-iterator cursors */
+    if (flags == 1)
+       return db2c_open(dbi, dbcp);
+
+    if (!dbi->dbi_use_cursors) {
+       if (dbcp) *dbcp = NULL;
        return 0;
-    } else if ((rc = db2c_open(dbi, &dbcursor)) == 0) {
-       dbi->dbi_rmw = dbcursor;
+    }
+
+    if ((dbcursor = dbi->dbi_rmw) == NULL) {
+       if ((rc = db2c_open(dbi, &dbcursor)) == 0)
+           dbi->dbi_rmw = dbcursor;
     }
 
     if (dbcp)
-       *dbcp = dbcursor;
+       *dbcp = dbi->dbi_rmw;
 
     return rc;
 }
 
-static int db2cput(dbiIndex dbi, const void * keyp, size_t keylen,
-               const void * datap, size_t datalen, unsigned int flags)
+static int db2cput(dbiIndex dbi, DBC * dbcursor,
+               const void * keyp, size_t keylen,
+               const void * datap, size_t datalen,
+               /*@unused@*/ unsigned int flags)
 {
     DB * db = dbi->dbi_db;
     DB_TXN * txnid = NULL;
@@ -414,24 +449,21 @@ static int db2cput(dbiIndex dbi, const void * keyp, size_t keylen,
     data.data = (void *)datap;
     data.size = datalen;
 
-    if (!dbi->dbi_use_cursors) {
+    if (dbcursor == NULL) {
        rc = db->put(db, txnid, &key, &data, 0);
        rc = cvtdberr(dbi, "db->put", rc, _debug);
     } else {
-       DBC * dbcursor;
 
-       if ((rc = db2copen(dbi, &dbcursor, 0)) != 0)
-           return rc;
+       rc = db2c_put(dbi, dbcursor, &key, &data, DB_AFTER);
 
-       rc = db2c_put(dbi, dbcursor, &key, &data, DB_KEYLAST);
-
-       (void) db2cclose(dbi, dbcursor, 0);
     }
 
     return rc;
 }
 
-static int db2cdel(dbiIndex dbi, const void * keyp, size_t keylen, unsigned int flags)
+static int db2cdel(dbiIndex dbi, DBC * dbcursor,
+               const void * keyp, size_t keylen,
+               /*@unused@*/ unsigned int flags)
 {
     DB * db = dbi->dbi_db;
     DB_TXN * txnid = NULL;
@@ -444,14 +476,10 @@ static int db2cdel(dbiIndex dbi, const void * keyp, size_t keylen, unsigned int
     key.data = (void *)keyp;
     key.size = keylen;
 
-    if (!dbi->dbi_use_cursors) {
+    if (dbcursor == NULL) {
        rc = db->del(db, txnid, &key, 0);
        rc = cvtdberr(dbi, "db->del", rc, _debug);
     } else {
-       DBC * dbcursor;
-
-       if ((rc = db2copen(dbi, &dbcursor, 0)) != 0)
-           return rc;
 
        rc = db2c_get(dbi, dbcursor, &key, &data, DB_SET);
 
@@ -460,15 +488,15 @@ static int db2cdel(dbiIndex dbi, const void * keyp, size_t keylen, unsigned int
            rc = db2c_del(dbi, dbcursor, 0);
        }
 
-       (void) db2c_close(dbi, dbcursor);
-
     }
 
     return rc;
 }
 
-static int db2cget(dbiIndex dbi, void ** keyp, size_t * keylen,
-               void ** datap, size_t * datalen, unsigned int flags)
+static int db2cget(dbiIndex dbi, DBC * dbcursor,
+               void ** keyp, size_t * keylen,
+               void ** datap, size_t * datalen,
+               /*@unused@*/ unsigned int flags)
 {
     DB * db = dbi->dbi_db;
     DB_TXN * txnid = NULL;
@@ -482,23 +510,18 @@ static int db2cget(dbiIndex dbi, void ** keyp, size_t * keylen,
     if (datap)         data.data = *datap;
     if (datalen)       data.size = *datalen;
 
-    if (!dbi->dbi_use_cursors) {
+    if (dbcursor == NULL) {
        int _printit;
        rc = db->get(db, txnid, &key, &data, 0);
+       /* XXX DB_NOTFOUND can be returned */
        _printit = (rc == DB_NOTFOUND ? 0 : _debug);
        rc = cvtdberr(dbi, "db->get", rc, _printit);
     } else {
-       DBC * dbcursor;
-
-       if ((rc = db2copen(dbi, &dbcursor, 0)) != 0)
-           return rc;
 
        /* XXX W2DO? db2 does DB_FIRST on uninitialized cursor? */
        rc = db2c_get(dbi, dbcursor, &key, &data,
                key.data == NULL ? DB_NEXT : DB_SET);
 
-       if (rc > 0)     /* DB_NOTFOUND */
-           (void) db2cclose(dbi, dbcursor, 0);
     }
 
     if (rc == 0) {
@@ -513,17 +536,18 @@ static int db2cget(dbiIndex dbi, void ** keyp, size_t * keylen,
 
 static int db2byteswapped(dbiIndex dbi)
 {
-    DB * db = dbi->dbi_db;
     int rc = 0;
 
 #if defined(__USE_DB3)
+    DB * db = dbi->dbi_db;
+
     rc = db->get_byteswapped(db);
 #endif /* __USE_DB3 */
 
     return rc;
 }
 
-static int db2close(dbiIndex dbi, unsigned int flags)
+static int db2close(/*@only@*/ dbiIndex dbi, unsigned int flags)
 {
     rpmdb rpmdb = dbi->dbi_rpmdb;
     const char * urlfn = NULL;
@@ -561,9 +585,8 @@ static int db2close(dbiIndex dbi, unsigned int flags)
        rc = cvtdberr(dbi, "db->close", rc, _debug);
        db = dbi->dbi_db = NULL;
 
-       if (dbfile)
-           rpmMessage(RPMMESS_DEBUG, _("closed  db index       %s/%s(%s)\n"),
-               dbhome, dbfile, dbsubfile);
+       rpmMessage(RPMMESS_DEBUG, _("closed  db index       %s/%s\n"),
+               dbhome, (dbfile ? dbfile : tagName(dbi->dbi_rpmtag)));
 
     }
 
@@ -572,7 +595,8 @@ static int db2close(dbiIndex dbi, unsigned int flags)
        dbi->dbi_dbinfo = NULL;
     }
 
-    xx = db_fini(dbi, dbhome, dbfile, dbsubfile);
+    if (dbi->dbi_use_dbenv)
+       xx = db_fini(dbi, dbhome, dbfile, dbsubfile);
 
 #else  /* __USE_DB2 || __USE_DB3 */
 
@@ -584,7 +608,7 @@ static int db2close(dbiIndex dbi, unsigned int flags)
     if (urlfn)
        free((void *)urlfn);
 
-    db2Free(dbi);
+    db3Free(dbi);
 
     return rc;
 }
@@ -595,14 +619,16 @@ static int db2open(rpmdb rpmdb, int rpmtag, dbiIndex * dbip)
     const char * dbhome;
     const char * dbfile;
     const char * dbsubfile;
+    extern struct _dbiVec db2vec;
     dbiIndex dbi = NULL;
     int rc = 0;
+    int xx;
 
 #if defined(__USE_DB2) || defined(__USE_DB3)
     DB * db = NULL;
     DB_ENV * dbenv = NULL;
-    DB_TXN * txnid = NULL;
     u_int32_t oflags;
+    int _printit;
 
     if (dbip)
        *dbip = NULL;
@@ -629,19 +655,29 @@ static int db2open(rpmdb rpmdb, int rpmtag, dbiIndex * dbip)
     }
 
     oflags = (dbi->dbi_oeflags | dbi->dbi_oflags);
+    oflags &= ~DB_TRUNCATE;    /* XXX this is dangerous */
+
 #if 0  /* XXX rpmdb: illegal flag combination specified to DB->open */
     if ( dbi->dbi_mode & O_EXCL) oflags |= DB_EXCL;
 #endif
-    if(!(dbi->dbi_mode & O_RDWR)) oflags |= DB_RDONLY;
-    if ( dbi->dbi_mode & O_CREAT) oflags |= DB_CREATE;
-    if ( dbi->dbi_mode & O_TRUNC) oflags |= DB_TRUNCATE;
 
-    rc = db_init(dbi, dbhome, dbfile, dbsubfile, &dbenv);
+    if (dbi->dbi_temporary) {
+       oflags &= ~DB_RDONLY;
+       oflags |= DB_CREATE;
+    } else {
+       if(!(dbi->dbi_mode & O_RDWR)) oflags |= DB_RDONLY;
+       if ( dbi->dbi_mode & O_CREAT) oflags |= DB_CREATE;
+       if ( dbi->dbi_mode & O_TRUNC) oflags |= DB_TRUNCATE;
+    }
+
     dbi->dbi_dbinfo = NULL;
 
-    if (dbfile)
-       rpmMessage(RPMMESS_DEBUG, _("opening db index       %s/%s(%s) %s mode=0x%x\n"),
-               dbhome, dbfile, dbsubfile, prDbiOpenFlags(oflags, 0), dbi->dbi_mode);
+    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"),
+               dbhome, (dbfile ? dbfile : tagName(dbi->dbi_rpmtag)),
+               prDbiOpenFlags(oflags, 0), dbi->dbi_mode);
 
     if (rc == 0) {
 #if defined(__USE_DB3)
@@ -697,21 +733,69 @@ static int db2open(rpmdb rpmdb, int rpmtag, dbiIndex * dbip)
            }
            dbi->dbi_dbinfo = NULL;
 
-           rc = db->open(db, dbfile, dbsubfile,
+           {   const char * dbfullpath;
+               const char * dbpath;
+               char * t;
+               int nb;
+
+               nb = strlen(dbhome);
+               if (dbfile)     nb += 1 + strlen(dbfile);
+               dbfullpath = t = alloca(nb + 1);
+
+               t = stpcpy(t, dbhome);
+               if (dbfile)
+                   t = stpcpy( stpcpy( t, "/"), dbfile);
+               dbpath = (!dbi->dbi_use_dbenv && !dbi->dbi_temporary)
+                       ? dbfullpath : dbfile;
+
+               rc = db->open(db, dbpath, dbsubfile,
                    dbi->dbi_type, oflags, dbi->dbi_perms);
-           rc = cvtdberr(dbi, "db->open", rc, _debug);
+           }
+
+           /* XXX return rc == errno without printing */
+           _printit = (rc > 0 ? 0 : _debug);
+           xx = cvtdberr(dbi, "db->open", rc, _printit);
 
-           if (dbi->dbi_get_rmw_cursor) {
+           if (rc == 0 && dbi->dbi_get_rmw_cursor) {
                DBC * dbcursor = NULL;
-               int xx;
+               DB_TXN * txnid = NULL;
                xx = db->cursor(db, txnid, &dbcursor,
                        ((oflags & DB_RDONLY) ? 0 : DB_WRITECURSOR));
                xx = cvtdberr(dbi, "db->cursor", xx, _debug);
                dbi->dbi_rmw = dbcursor;
            } else
                dbi->dbi_rmw = NULL;
+
+           if (rc == 0 && dbi->dbi_lockdbfd) {
+               int fdno = -1;
+
+               if (!(db->fd(db, &fdno) == 0 && fdno >= 0)) {
+                   rc = 1;
+               } else {
+                   struct flock l;
+                   l.l_whence = 0;
+                   l.l_start = 0;
+                   l.l_len = 0;
+                   l.l_type = (dbi->dbi_mode & O_RDWR) ? F_WRLCK : F_RDLCK;
+                   l.l_pid = 0;
+
+                   if (fcntl(fdno, F_SETLK, (void *) &l)) {
+                       rpmError(RPMERR_FLOCK,
+                               _("cannot get %s lock on %s/%s\n"),
+                               ((dbi->dbi_mode & O_RDWR)
+                                       ? _("exclusive") : _("shared")),
+                               dbhome, dbfile);
+                       rc = 1;
+                   } else if (dbfile) {
+                       rpmMessage(RPMMESS_DEBUG,
+                               _("locked  db index       %s/%s\n"),
+                               dbhome, dbfile);
+                   }
+               }
+           }
        }
-#else
+       }
+#else  /* __USE_DB3 */
       {        DB_INFO * dbinfo = xcalloc(1, sizeof(*dbinfo));
        dbinfo->db_cachesize = dbi->dbi_cachesize;
        dbinfo->db_lorder = dbi->dbi_lorder;
@@ -729,9 +813,29 @@ static int db2open(rpmdb rpmdb, int rpmtag, dbiIndex * dbip)
            }
        }
        dbi->dbi_dbinfo = dbinfo;
-       rc = db_open(dbfile, db3_to_dbtype(dbi->dbi_type), oflags,
+
+           {   const char * dbfullpath;
+               const char * dbpath;
+               char * t;
+               int nb;
+
+               nb = strlen(dbhome);
+               if (dbfile)     nb += 1 + strlen(dbfile);
+               dbfullpath = t = alloca(nb + 1);
+
+               t = stpcpy(t, dbhome);
+               if (dbfile)
+                   t = stpcpy( stpcpy( t, "/"), dbfile);
+               dbpath = (!dbi->dbi_use_dbenv && !dbi->dbi_temporary)
+                       ? dbfullpath : dbfile;
+
+               rc = db_open(dbpath, db3_to_dbtype(dbi->dbi_type), oflags,
                        dbi->dbi_perms, dbenv, dbinfo, &db);
-       rc = cvtdberr(dbi, "db_open", rc, _debug);
+           }
+
+       /* XXX return rc == errno without printing */
+       _printit = (rc > 0 ? 0 : _debug);
+       xx = cvtdberr(dbi, "db->open", rc, _printit);
       }
 #endif /* __USE_DB3 */
     }
@@ -744,20 +848,21 @@ static int db2open(rpmdb rpmdb, int rpmtag, dbiIndex * dbip)
 
     if (dbip)
        *dbip = NULL;
-    if ((dbi = db2New(rpmdb, rpmtag)) == NULL)
+    if ((dbi = db3New(rpmdb, rpmtag)) == NULL)
        return 1;
 
     dbi->dbi_db = dbopen(dbfile, dbi->dbi_mode, dbi->dbi_perms,
                db3_to_dbtype(dbi->dbi_type), dbopeninfo);
+
+    /* XXX return rc == errno without printing */
+    if (dbi->dbi_db == NULL) rc = errno;
 #endif /* __USE_DB2 || __USE_DB3 */
 
     if (rc == 0 && dbi->dbi_db != NULL && dbip != NULL) {
-       rc = 0;
+       dbi->dbi_vec = &db2vec;
        *dbip = dbi;
-    } else {
-       rc = 1;
-       db3Free(dbi);
-    }
+    } else
+       db2close(dbi, 0);
 
     if (urlfn)
        free((void *)urlfn);
@@ -765,6 +870,8 @@ static int db2open(rpmdb rpmdb, int rpmtag, dbiIndex * dbip)
     return rc;
 }
 
+/** \ingroup db2
+ */
 struct _dbiVec db2vec = {
     DB_VERSION_MAJOR, DB_VERSION_MINOR, DB_VERSION_PATCH,
     db2open, db2close, db2sync, db2copen, db2cclose, db2cdel, db2cget, db2cput,
index 2f0505d..4270053 100644 (file)
--- a/lib/db3.c
+++ b/lib/db3.c
@@ -29,360 +29,6 @@ typedef     int int32_t;
 #if DB_VERSION_MAJOR == 3
 #define        __USE_DB3       1
 
-struct _dbiIndex db3dbi;
-
-/** \ingroup db3
- *  Analogue to struct poptOption
- */
-struct dbOption {
-    const char * longName;     /* may be NULL */
-    int argInfo;
-    void * arg;                        /* depends on argInfo */
-    int val;                   /* 0 means don't return, just update flag */
-};
-
-#define        _POPT_SET_BIT   (POPT_ARG_VAL|POPT_ARGFLAG_OR)
-
-/*@-immediatetrans@*/
-/** \ingroup db3
- */
-struct dbOption rdbOptions[] = {
- /* XXX DB_CXX_NO_EXCEPTIONS */
- { "xa_create",        _POPT_SET_BIT,          &db3dbi.dbi_cflags, DB_XA_CREATE },
-
- { "create",   _POPT_SET_BIT,          &db3dbi.dbi_oeflags, DB_CREATE },
- { "nommap",   _POPT_SET_BIT,          &db3dbi.dbi_oeflags, DB_NOMMAP },
- { "thread",   _POPT_SET_BIT,          &db3dbi.dbi_oeflags, DB_THREAD },
-
- { "force",    _POPT_SET_BIT,          &db3dbi.dbi_eflags, DB_FORCE },
- { "cdb",      _POPT_SET_BIT,          &db3dbi.dbi_eflags, DB_INIT_CDB },
- { "lock",     _POPT_SET_BIT,          &db3dbi.dbi_eflags, DB_INIT_LOCK },
- { "log",      _POPT_SET_BIT,          &db3dbi.dbi_eflags, DB_INIT_LOG },
- { "mpool",    _POPT_SET_BIT,          &db3dbi.dbi_eflags, DB_INIT_MPOOL },
- { "txn",      _POPT_SET_BIT,          &db3dbi.dbi_eflags, DB_INIT_TXN },
- { "recover",  _POPT_SET_BIT,          &db3dbi.dbi_eflags, DB_RECOVER },
- { "recover_fatal", _POPT_SET_BIT,     &db3dbi.dbi_eflags, DB_RECOVER_FATAL },
- { "shared",   _POPT_SET_BIT,          &db3dbi.dbi_eflags, DB_SYSTEM_MEM },
- { "txn_nosync", _POPT_SET_BIT,                &db3dbi.dbi_eflags, DB_TXN_NOSYNC },
- { "use_environ_root", _POPT_SET_BIT,  &db3dbi.dbi_eflags, DB_USE_ENVIRON_ROOT },
- { "use_environ", _POPT_SET_BIT,       &db3dbi.dbi_eflags, DB_USE_ENVIRON },
- { "lockdown", _POPT_SET_BIT,          &db3dbi.dbi_eflags, DB_LOCKDOWN },
- { "private",  _POPT_SET_BIT,          &db3dbi.dbi_eflags, DB_PRIVATE },
-
- { "txn_sync", _POPT_SET_BIT,          &db3dbi.dbi_tflags, DB_TXN_SYNC },
- { "txn_nowait",_POPT_SET_BIT,         &db3dbi.dbi_tflags, DB_TXN_NOWAIT },
-
- { "excl",     _POPT_SET_BIT,          &db3dbi.dbi_oflags, DB_EXCL },
- { "rdonly",   _POPT_SET_BIT,          &db3dbi.dbi_oflags, DB_RDONLY },
- { "truncate", _POPT_SET_BIT,          &db3dbi.dbi_oflags, DB_TRUNCATE },
- { "fcntl_locking",_POPT_SET_BIT,      &db3dbi.dbi_oflags, DB_FCNTL_LOCKING },
-
- { "btree",    POPT_ARG_VAL,           &db3dbi.dbi_type, DB_BTREE },
- { "hash",     POPT_ARG_VAL,           &db3dbi.dbi_type, DB_HASH },
- { "recno",    POPT_ARG_VAL,           &db3dbi.dbi_type, DB_RECNO },
- { "queue",    POPT_ARG_VAL,           &db3dbi.dbi_type, DB_QUEUE },
- { "unknown",  POPT_ARG_VAL,           &db3dbi.dbi_type, DB_UNKNOWN },
-
- { "root",     POPT_ARG_STRING,        &db3dbi.dbi_root, 0 },
- { "home",     POPT_ARG_STRING,        &db3dbi.dbi_home, 0 },
- { "file",     POPT_ARG_STRING,        &db3dbi.dbi_file, 0 },
- { "subfile",  POPT_ARG_STRING,        &db3dbi.dbi_subfile, 0 },
- { "mode",     POPT_ARG_INT,           &db3dbi.dbi_mode, 0 },
- { "perms",    POPT_ARG_INT,           &db3dbi.dbi_perms, 0 },
-
- { "teardown", POPT_ARG_NONE,          &db3dbi.dbi_tear_down, 0 },
- { "usecursors",POPT_ARG_NONE,         &db3dbi.dbi_use_cursors, 0 },
- { "usedbenv", POPT_ARG_NONE,          &db3dbi.dbi_use_dbenv, 0 },
- { "rmwcursor",        POPT_ARG_NONE,          &db3dbi.dbi_get_rmw_cursor, 0 },
- { "nofsync",  POPT_ARG_NONE,          &db3dbi.dbi_no_fsync, 0 },
- { "nodbsync", POPT_ARG_NONE,          &db3dbi.dbi_no_dbsync, 0 },
- { "lockdbfd", POPT_ARG_NONE,          &db3dbi.dbi_lockdbfd, 0 },
- { "temporary",        POPT_ARG_NONE,          &db3dbi.dbi_temporary, 0 },
- { "debug",    POPT_ARG_NONE,          &db3dbi.dbi_debug, 0 },
-
- { "cachesize",        POPT_ARG_INT,           &db3dbi.dbi_cachesize, 0 },
- { "errpfx",   POPT_ARG_STRING,        &db3dbi.dbi_errpfx, 0 },
- { "region_init", POPT_ARG_VAL,                &db3dbi.dbi_region_init, 1 },
- { "tas_spins",        POPT_ARG_INT,           &db3dbi.dbi_tas_spins, 0 },
-
- { "chkpoint", _POPT_SET_BIT,          &db3dbi.dbi_verbose, DB_VERB_CHKPOINT },
- { "deadlock", _POPT_SET_BIT,          &db3dbi.dbi_verbose, DB_VERB_DEADLOCK },
- { "recovery", _POPT_SET_BIT,          &db3dbi.dbi_verbose, DB_VERB_RECOVERY },
- { "waitsfor", _POPT_SET_BIT,          &db3dbi.dbi_verbose, DB_VERB_WAITSFOR },
- { "verbose",  POPT_ARG_VAL,           &db3dbi.dbi_verbose, -1 },
-
- { "lk_oldest",        POPT_ARG_VAL,           &db3dbi.dbi_lk_detect, DB_LOCK_OLDEST },
- { "lk_random",        POPT_ARG_VAL,           &db3dbi.dbi_lk_detect, DB_LOCK_RANDOM },
- { "lk_youngest", POPT_ARG_VAL,                &db3dbi.dbi_lk_detect, DB_LOCK_YOUNGEST },
-/* XXX lk_conflicts matrix */
- { "lk_max",   POPT_ARG_INT,           &db3dbi.dbi_lk_max, 0 },
-
- { "lg_bsize", POPT_ARG_INT,           &db3dbi.dbi_lg_bsize, 0 },
- { "lg_max",   POPT_ARG_INT,           &db3dbi.dbi_lg_max, 0 },
-
-/* XXX tx_recover */
- { "tx_max",   POPT_ARG_INT,           &db3dbi.dbi_tx_max, 0 },
-
- { "lorder",   POPT_ARG_INT,           &db3dbi.dbi_lorder, 0 },
-
- { "mp_mmapsize", POPT_ARG_INT,                &db3dbi.dbi_mp_mmapsize, 0 },
- { "mp_size",  POPT_ARG_INT,           &db3dbi.dbi_mp_size, 0 },
- { "pagesize", POPT_ARG_INT,           &db3dbi.dbi_pagesize, 0 },
-
-/* XXX bt_minkey */
-/* XXX bt_compare */
-/* XXX bt_dup_compare */
-/* XXX bt_prefix */
- { "bt_dup",   _POPT_SET_BIT,          &db3dbi.dbi_bt_flags, DB_DUP },
- { "bt_dupsort",_POPT_SET_BIT,         &db3dbi.dbi_bt_flags, DB_DUPSORT },
- { "bt_recnum",        _POPT_SET_BIT,          &db3dbi.dbi_bt_flags, DB_RECNUM },
- { "bt_revsplitoff", _POPT_SET_BIT,    &db3dbi.dbi_bt_flags, DB_REVSPLITOFF },
-
- { "h_dup",    _POPT_SET_BIT,          &db3dbi.dbi_h_flags, DB_DUP },
- { "h_dupsort",        _POPT_SET_BIT,          &db3dbi.dbi_h_flags, DB_DUPSORT },
- { "h_ffactor",        POPT_ARG_INT,           &db3dbi.dbi_h_ffactor, 0 },
- { "h_nelem",  POPT_ARG_INT,           &db3dbi.dbi_h_nelem, 0 },
-
- { "re_renumber", _POPT_SET_BIT,       &db3dbi.dbi_re_flags, DB_RENUMBER },
- { "re_snapshot",_POPT_SET_BIT,                &db3dbi.dbi_re_flags, DB_SNAPSHOT },
- { "re_delim", POPT_ARG_INT,           &db3dbi.dbi_re_delim, 0 },
- { "re_len",   POPT_ARG_INT,           &db3dbi.dbi_re_len, 0 },
- { "re_pad",   POPT_ARG_INT,           &db3dbi.dbi_re_pad, 0 },
- { "re_source",        POPT_ARG_STRING,        &db3dbi.dbi_re_source, 0 },
-
- { NULL, 0, NULL, 0 }
-};
-/*@=immediatetrans@*/
-
-static int dbSaveLong(const struct dbOption * opt, long aLong) {
-    if (opt->argInfo & POPT_ARGFLAG_NOT)
-       aLong = ~aLong;
-    switch (opt->argInfo & POPT_ARGFLAG_LOGICALOPS) {
-    case 0:
-       *((long *) opt->arg) = aLong;
-       break;
-    case POPT_ARGFLAG_OR:
-       *((long *) opt->arg) |= aLong;
-       break;
-    case POPT_ARGFLAG_AND:
-       *((long *) opt->arg) &= aLong;
-       break;
-    case POPT_ARGFLAG_XOR:
-       *((long *) opt->arg) ^= aLong;
-       break;
-    default:
-       return POPT_ERROR_BADOPERATION;
-       /*@notreached@*/ break;
-    }
-    return 0;
-}
-
-static int dbSaveInt(const struct dbOption * opt, long aLong) {
-    if (opt->argInfo & POPT_ARGFLAG_NOT)
-       aLong = ~aLong;
-    switch (opt->argInfo & POPT_ARGFLAG_LOGICALOPS) {
-    case 0:
-       *((int *) opt->arg) = aLong;
-       break;
-    case POPT_ARGFLAG_OR:
-       *((int *) opt->arg) |= aLong;
-       break;
-    case POPT_ARGFLAG_AND:
-       *((int *) opt->arg) &= aLong;
-       break;
-    case POPT_ARGFLAG_XOR:
-       *((int *) opt->arg) ^= aLong;
-       break;
-    default:
-       return POPT_ERROR_BADOPERATION;
-       /*@notreached@*/ break;
-    }
-    return 0;
-}
-
-void db3Free(dbiIndex dbi) {
-    if (dbi) {
-       if (dbi->dbi_root)      free((void *)dbi->dbi_root);
-       if (dbi->dbi_home)      free((void *)dbi->dbi_home);
-       if (dbi->dbi_file)      free((void *)dbi->dbi_file);
-       if (dbi->dbi_subfile)   free((void *)dbi->dbi_subfile);
-       if (dbi->dbi_errpfx)    free((void *)dbi->dbi_errpfx);
-       if (dbi->dbi_re_source) free((void *)dbi->dbi_re_source);
-       if (dbi->dbi_dbenv)     free(dbi->dbi_dbenv);
-       if (dbi->dbi_dbinfo)    free(dbi->dbi_dbinfo);
-       free((void *)dbi);
-    }
-}
-
-static const char *db3_config_default =
-    "db3:hash:mpool:cdb:usecursors:verbose:mp_mmapsize=8Mb:mp_size=512Kb:pagesize=512:perms=0644";
-
-dbiIndex db3New(rpmdb rpmdb, int rpmtag)
-{
-    dbiIndex dbi = xcalloc(1, sizeof(*dbi));
-    char dbiTagMacro[128];
-    char * dbOpts;
-
-    sprintf(dbiTagMacro, "%%{_dbi_config_%s}", tagName(rpmtag));
-    dbOpts = rpmExpand(dbiTagMacro, NULL);
-    if (!(dbOpts && *dbOpts && *dbOpts != '%')) {
-       if (dbOpts) {
-           free(dbOpts);
-           dbOpts = NULL;
-       }
-       dbOpts = rpmExpand("%{_dbi_config}", NULL);
-       if (!(dbOpts && *dbOpts && *dbOpts != '%')) {
-           dbOpts = rpmExpand(db3_config_default, NULL);
-       }
-    }
-
-    if (dbOpts && *dbOpts && *dbOpts != '%') {
-       char *o, *oe;
-       char *p, *pe;
-       for (o = dbOpts; o && *o; o = oe) {
-           struct dbOption *opt;
-
-           while (*o && isspace(*o))
-               o++;
-           for (oe = o; oe && *oe; oe++) {
-               if (isspace(*oe))
-                   break;
-               if (oe[0] == ':' && !(oe[1] == '/' && oe[2] == '/'))
-                   break;
-           }
-           if (oe && *oe)
-               *oe++ = '\0';
-           if (*o == '\0')
-               continue;
-           for (pe = o; pe && *pe && *pe != '='; pe++)
-               ;
-           p = (pe ? *pe++ = '\0', pe : NULL);
-
-           for (opt = rdbOptions; opt->longName != NULL; opt++) {
-               if (strcmp(o, opt->longName))
-                   continue;
-               break;
-           }
-           if (opt->longName == NULL) {
-               rpmError(RPMERR_DBCONFIG,
-                       _("unrecognized db option: \"%s\" ignored\n"), o);
-               continue;
-           }
-
-           switch (opt->argInfo & POPT_ARG_MASK) {
-           long aLong;
-
-           case POPT_ARG_NONE:
-               (void) dbSaveInt(opt, 1L);
-               break;
-           case POPT_ARG_VAL:
-               (void) dbSaveInt(opt, (long)opt->val);
-               break;
-           case POPT_ARG_STRING:
-           {   const char ** t = opt->arg;
-               if (*t) free((void *)*t);
-               *t = xstrdup( (p ? p : "") );
-           }   break;
-
-           case POPT_ARG_INT:
-           case POPT_ARG_LONG:
-               aLong = strtol(p, &pe, 0);
-               if (pe) {
-                   if (!xstrncasecmp(pe, "Mb", 2))
-                       aLong *= 1024 * 1024;
-                   else if (!xstrncasecmp(pe, "Kb", 2))
-                       aLong *= 1024;
-                   else if (*pe != '\0') {
-                       rpmError(RPMERR_DBCONFIG,
-                               _("%s has invalid numeric value, skipped\n"),
-                               opt->longName);
-                       continue;
-                   }
-               }
-
-               if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_LONG) {
-                   if (aLong == LONG_MIN || aLong == LONG_MAX) {
-                       rpmError(RPMERR_DBCONFIG,
-                               _("%s has too large or too small long value, skipped\n"),
-                               opt->longName);
-                       continue;
-                   }
-                   (void) dbSaveLong(opt, aLong);
-                   break;
-               } else {
-                   if (aLong > INT_MAX || aLong < INT_MIN) {
-                       rpmError(RPMERR_DBCONFIG,
-                               _("%s has too large or too small integer value, skipped\n"),
-                               opt->longName);
-                       continue;
-                   }
-                   (void) dbSaveInt(opt, aLong);
-               }
-               break;
-           default:
-               break;
-           }
-       }
-    }
-
-    free(dbOpts);
-
-    *dbi = db3dbi;     /* structure assignment */
-    memset(&db3dbi, 0, sizeof(db3dbi));
-
-    if (!(dbi->dbi_perms & 0600))
-       dbi->dbi_perms = 0644;
-    dbi->dbi_mode = rpmdb->db_mode;
-    dbi->dbi_rpmdb = rpmdb;
-    dbi->dbi_rpmtag = rpmtag;
-    
-    switch (rpmtag) {
-    case RPMDBI_PACKAGES:
-    case RPMDBI_DEPENDS:
-       dbi->dbi_jlen = 1 * sizeof(int_32);
-       break;
-    default:
-       dbi->dbi_jlen = 2 * sizeof(int_32);
-       break;
-    }
-    return dbi;
-}
-
-static /*@exposed@*/ const char *const prDbiOpenFlags(int dbflags, int print_dbenv_flags)
-{
-    static char buf[256];
-    struct dbOption *opt;
-    char * oe;
-
-    oe = buf;
-    *oe = '\0';
-    for (opt = rdbOptions; opt->longName != NULL; opt++) {
-       if (opt->argInfo != _POPT_SET_BIT)
-           continue;
-       if (print_dbenv_flags) {
-           if (!(opt->arg == &db3dbi.dbi_oeflags ||
-                 opt->arg == &db3dbi.dbi_eflags))
-               continue;
-       } else {
-           if (!(opt->arg == &db3dbi.dbi_oeflags ||
-                 opt->arg == &db3dbi.dbi_oflags))
-               continue;
-       }
-       if ((dbflags & opt->val) != opt->val)
-           continue;
-       if (oe != buf)
-           *oe++ = ':';
-       oe = stpcpy(oe, opt->longName);
-       dbflags &= ~opt->val;
-    }
-    if (dbflags) {
-       if (oe != buf)
-           *oe++ = ':';
-           sprintf(oe, "0x%x", (unsigned)dbflags);
-    }
-    return buf;
-}
-
 #if defined(__USE_DB2) || defined(__USE_DB3)
 #if defined(__USE_DB2)
 static /*@observer@*/ const char * db_strerror(int error)
@@ -481,7 +127,7 @@ static int db_fini(dbiIndex dbi, const char * dbhome, const char * dbfile,
     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) {
@@ -716,7 +362,7 @@ static inline int db3c_open(dbiIndex dbi, /*@out@*/ DBC ** dbcp)
 #else  /* __USE_DB3 */
     rc = db->cursor(db, txnid, dbcp);
 #endif /* __USE_DB3 */
-    rc = cvtdberr(dbi, "db3copen", rc, _debug);
+    rc = cvtdberr(dbi, "db3c_open", rc, _debug);
 
     return rc;
 }
index 3143c19..8786c1c 100644 (file)
@@ -141,6 +141,8 @@ struct rpmTransactionSet_s {
                                /*!< Packages sorted by dependencies. */
     int orderCount;            /*!< No. of transaction elements. */
     int orderAlloced;          /*!< No. of allocated transaction elements. */
+/*@shared@*/ TFI_t flList;     /*!< Transaction element(s) file info. */
+    int flEntries;             /*!< No. of transaction elements. */
     int chrootDone;            /*!< Has chroot(2) been been done? */
 /*@only@*/ const char * rootDir;/*!< Path to top of install tree. */
 /*@only@*/ const char * currDir;/*!< Current working directory. */
index fa3b671..9954bc4 100644 (file)
@@ -289,6 +289,15 @@ extern "C" {
  */
 void db3Free( /*@only@*/ /*@null@*/ dbiIndex dbi);
 
+/** \ingroup db3
+ * Format db3 open flags for debugging print.
+ * @param dbflags              db open flags
+ * @param print_dbenv_flags    format db env flags instead?
+ * @return                     formatted flags (static buffer)
+ */
+/*@exposed@*/ const char *const prDbiOpenFlags(int dbflags,
+                                               int print_dbenv_flags);
+
 /** \ingroup dbi
  * Return handle for an index database.
  * @param rpmdb                rpm database
index 17f90d7..47024f0 100644 (file)
@@ -598,6 +598,7 @@ int rpmErase(const char * rootdir, const char ** argv,
     }
 
     if (!stopUninstall) {
+       transFlags |= RPMTRANS_FLAG_REVERSE;
        numFailed += rpmRunTransactions(ts, NULL, NULL, NULL, &probs,
                                        transFlags, 0);
     }
index afa44c5..9c82b24 100644 (file)
@@ -1077,6 +1077,7 @@ typedef enum rpmtransFlags_e {
     RPMTRANS_FLAG_PKGUNDO      = (1 << 12),
     RPMTRANS_FLAG_COMMIT       = (1 << 13),
     RPMTRANS_FLAG_UNDO         = (1 << 14),
+    RPMTRANS_FLAG_REVERSE      = (1 << 15),
 } rpmtransFlags;
 
 /** \ingroup rpmtrans
index e4db095..23d0400 100644 (file)
@@ -15,21 +15,22 @@ static struct rpmlibProvides {
 } rpmlibProvides[] = {
     { "rpmlib(VersionedDependencies)", "3.0.3-1",
        (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
-       "PreReq:, Provides:, and Obsoletes: dependencies support versions." },
+    N_("PreReq:, Provides:, and Obsoletes: dependencies support versions.") },
     { "rpmlib(CompressedFileNames)",   "3.0.4-1",
        (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
-       "file names stored as (dirName,BaseName,dirIndex) tuple, not as path."},
+    N_("file names stored as (dirName,baseName,dirIndex) tuple, not as path.")},
     { "rpmlib(PayloadIsBzip2)",                "3.0.5-1",
        (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
-       "package payload compressed using bzip2." },
+    N_("package payload compressed using bzip2.") },
     { "rpmlib(PayloadFilesHavePrefix)",        "4.0-1",
        (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
-       "package payload files have \"./\" prefix." },
+    N_("package payload files have \"./\" prefix.") },
     { "rpmlib(ExplicitPackageProvide)",        "4.0-1",
        (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
-       "package name-version-release not implicitly provided." },
-    { "rpmlib(HeaderLoadSortsTags)",    "4.0.1-1",      RPMSENSE_EQUAL,
-        "header tags are always sorted after being loaded." },
+    N_("package name-version-release not implicitly provided.") },
+    { "rpmlib(HeaderLoadSortsTags)",    "4.0.1-1",
+       (                RPMSENSE_EQUAL),
+    N_("header tags are always sorted after being loaded.") },
     { NULL,                            NULL,   0 }
 };
 
index d170683..e69804d 100644 (file)
@@ -61,6 +61,17 @@ struct diskspaceInfo {
 
 #define XSTRCMP(a, b) ((!(a) && !(b)) || ((a) && (b) && !strcmp((a), (b))))
 
+
+/**
+ * Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
+ * @param this         memory to free
+ * @retval             NULL always
+ */
+static /*@null@*/ void * _free(/*@only@*/ /*@null@*/ const void * this) {
+    if (this)  free((void *)this);
+    return NULL;
+}
+
 static void freeFl(rpmTransactionSet ts, TFI_t flList)
 {
     TFI_t fi;
@@ -1261,6 +1272,90 @@ static void skipFiles(const rpmTransactionSet ts, TFI_t fi)
     if (languages) freeSplitString((char **)languages);
 }
 
+/**
+ * Iterator across transaction elements, forward on install, backward on erase.
+ */
+struct tsIterator_s {
+/*@kept@*/ rpmTransactionSet ts;       /*!< transaction set. */
+    int reverse;                       /*!< reversed traversal? */
+    int ocsave;                                /*!< last returned iterator index. */
+    int oc;                            /*!< iterator index. */
+};
+
+/**
+ */
+static int tsGetOc(void * this) {
+    struct tsIterator_s * iter = this;
+    int oc = iter->ocsave;
+    return oc;
+}
+
+/**
+ */
+static struct availablePackage * tsGetAlp(void * this) {
+    struct tsIterator_s * iter = this;
+    struct availablePackage * alp = NULL;
+    int oc = iter->ocsave;
+
+    if (oc != -1) {
+       rpmTransactionSet ts = iter->ts;
+       TFI_t fi = ts->flList + oc;
+       if (fi->type == TR_ADDED)
+           alp = ts->addedPackages.list + ts->order[oc].u.addedIndex;
+    }
+    return alp;
+}
+
+/**
+ * Destroy transaction element iterator.
+ * @param this         transaction element iterator
+ * @retval             NULL always
+ */
+static /*@null@*/ void * tsFreeIterator(/*@only@*//*@null@*/ const void * this)
+{
+    return _free((void *)this);
+}
+
+/**
+ * Create transaction element iterator.
+ * @param this         transaction set
+ * @return             transaction element iterator
+ */
+static void * tsInitIterator(/*@kept@*/ const void * this)
+{
+    rpmTransactionSet ts = (void *)this;
+    struct tsIterator_s * iter = NULL;
+
+    iter = xcalloc(1, sizeof(*iter));
+    iter->ts = ts;
+    iter->oc = ((ts->transFlags & RPMTRANS_FLAG_REVERSE)
+                       ? (ts->orderCount - 1) : 0);
+    iter->ocsave = iter->oc;
+    return iter;
+}
+
+/**
+ * Return next transaction element's file info.
+ * @param this         file info iterator
+ * @return             next index, -1 on termination
+ */
+static TFI_t tsNextIterator(void * this) {
+    struct tsIterator_s * iter = this;
+    rpmTransactionSet ts = iter->ts;
+    TFI_t fi = NULL;
+    int oc = -1;
+
+    if (iter->reverse) {
+       if (iter->oc >= 0)              oc = iter->oc--;
+    } else {
+       if (iter->oc < ts->orderCount)  oc = iter->oc++;
+    }
+    iter->ocsave = oc;
+    if (oc != -1)
+       fi = ts->flList + oc;
+    return fi;
+}
+
 #define        NOTIFY(_ts, _al)        if ((_ts)->notify) (void) (_ts)->notify _al
 
 int rpmRunTransactions(        rpmTransactionSet ts,
@@ -1269,20 +1364,20 @@ int rpmRunTransactions( rpmTransactionSet ts,
                        rpmtransFlags transFlags, rpmprobFilterFlags ignoreSet)
 {
     int i, j;
-    int rc, ourrc = 0;
+    int ourrc = 0;
     struct availablePackage * alp;
     Header * hdrs;
     int totalFileCount = 0;
     hashTable ht;
-    TFI_t flList, fi;
+    TFI_t fi;
     struct diskspaceInfo * dip;
     struct sharedFileInfo * shared, * sharedList;
     int numShared;
-    int flEntries;
     int nexti;
     int lastFailed;
     int oc;
     fingerPrintCache fpc;
+    void * tsi;
 
     /* FIXME: what if the same package is included in ts twice? */
 
@@ -1425,15 +1520,15 @@ int rpmRunTransactions( rpmTransactionSet ts,
     /* ===============================================
      * Initialize file list:
      */
-    flEntries = ts->addedPackages.size + ts->numRemovedPackages;
-    flList = alloca(sizeof(*flList) * (flEntries));
+    ts->flEntries = ts->addedPackages.size + ts->numRemovedPackages;
+    ts->flList = alloca(sizeof(*ts->flList) * (ts->flEntries));
 
     /*
      * FIXME?: we'd be better off assembling one very large file list and
      * calling fpLookupList only once. I'm not sure that the speedup is
      * worth the trouble though.
      */
-    for (oc = 0, fi = flList; oc < ts->orderCount; oc++, fi++) {
+    for (oc = 0, fi = ts->flList; oc < ts->orderCount; oc++, fi++) {
        const char **preTrans;
        int preTransCount;
 
@@ -1501,7 +1596,7 @@ int rpmRunTransactions(   rpmTransactionSet ts,
     /* ===============================================
      * Add fingerprint for each file not skipped.
      */
-    for (fi = flList; (fi - flList) < flEntries; fi++) {
+    for (fi = ts->flList; (fi - ts->flList) < ts->flEntries; fi++) {
        fpLookupList(fpc, fi->dnl, fi->bnl, fi->dil, fi->fc, fi->fps);
        for (i = 0; i < fi->fc; i++) {
            if (XFA_SKIPPING(fi->actions[i]))
@@ -1510,18 +1605,18 @@ int rpmRunTransactions( rpmTransactionSet ts,
        }
     }
 
-    NOTIFY(ts, (NULL, RPMCALLBACK_TRANS_START, 6, flEntries,
+    NOTIFY(ts, (NULL, RPMCALLBACK_TRANS_START, 6, ts->flEntries,
        NULL, ts->notifyData));
 
     /* ===============================================
      * Compute file disposition for each package in transaction set.
      */
-    for (fi = flList; (fi - flList) < flEntries; fi++) {
+    for (fi = ts->flList; (fi - ts->flList) < ts->flEntries; fi++) {
        dbiIndexSet * matches;
        int knownBad;
 
-       NOTIFY(ts, (NULL, RPMCALLBACK_TRANS_PROGRESS, (fi - flList), flEntries,
-              NULL, ts->notifyData));
+       NOTIFY(ts, (NULL, RPMCALLBACK_TRANS_PROGRESS, (fi - ts->flList),
+                       ts->flEntries, NULL, ts->notifyData));
 
        if (fi->fc == 0) continue;
 
@@ -1645,7 +1740,7 @@ int rpmRunTransactions(   rpmTransactionSet ts,
        }
     }
 
-    NOTIFY(ts, (NULL, RPMCALLBACK_TRANS_STOP, 6, flEntries,
+    NOTIFY(ts, (NULL, RPMCALLBACK_TRANS_STOP, 6, ts->flEntries,
        NULL, ts->notifyData));
 
     if (ts->chrootDone) {
@@ -1658,7 +1753,7 @@ int rpmRunTransactions(   rpmTransactionSet ts,
      * Free unused memory as soon as possible.
      */
 
-    for (oc = 0, fi = flList; oc < ts->orderCount; oc++, fi++) {
+    for (oc = 0, fi = ts->flList; oc < ts->orderCount; oc++, fi++) {
        if (fi->fc == 0)
            continue;
        if (fi->fps) {
@@ -1676,13 +1771,13 @@ int rpmRunTransactions( rpmTransactionSet ts,
            (ts->probs->numProblems && (!okProbs || psTrim(okProbs, ts->probs)))) {
        *newProbs = ts->probs;
 
-       for (alp = ts->addedPackages.list, fi = flList;
+       for (alp = ts->addedPackages.list, fi = ts->flList;
                (alp - ts->addedPackages.list) < ts->addedPackages.size;
                alp++, fi++) {
            headerFree(hdrs[alp - ts->addedPackages.list]);
        }
 
-       freeFl(ts, flList);
+       freeFl(ts, ts->flList);
        return ts->orderCount;
     }
 
@@ -1690,7 +1785,7 @@ int rpmRunTransactions(   rpmTransactionSet ts,
      * Save removed files before erasing.
      */
     if (ts->transFlags & (RPMTRANS_FLAG_DIRSTASH | RPMTRANS_FLAG_REPACKAGE)) {
-       for (oc = 0, fi = flList; oc < ts->orderCount; oc++, fi++) {
+       for (oc = 0, fi = ts->flList; oc < ts->orderCount; oc++, fi++) {
            switch (ts->order[oc].type) {
            case TR_ADDED:
                break;
@@ -1707,14 +1802,31 @@ int rpmRunTransactions( rpmTransactionSet ts,
      */
 
     lastFailed = -2;   /* erased packages have -1 */
-    for (oc = 0, fi = flList; oc < ts->orderCount; oc++, fi++) {
+#ifdef DYING
+    for (oc = 0, fi = ts->flList; oc < ts->orderCount; oc++, fi++)
+#else
+    tsi = tsInitIterator(ts);
+    while ((fi = tsNextIterator(tsi)) != NULL)
+#endif
+    {
        int gotfd;
 
        gotfd = 0;
-       switch (ts->order[oc].type) {
+#ifdef DYING
+       switch (ts->order[oc].type)
+#else
+       switch (fi->type)
+#endif
+       {
        case TR_ADDED:
+#ifdef DYING
            i = ts->order[oc].u.addedIndex;
            alp = ts->addedPackages.list + i;
+#else
+           alp = tsGetAlp(tsi);
+assert(alp == fi->ap);
+           i = alp - ts->addedPackages.list;
+#endif
 
            if (alp->fd == NULL) {
                alp->fd = ts->notify(fi->h, RPMCALLBACK_INST_OPEN_FILE, 0, 0,
@@ -1775,6 +1887,7 @@ if (fi->ap == NULL) fi->ap = alp; /* XXX WTFO? */
            }
            break;
        case TR_REMOVED:
+           oc = tsGetOc(tsi);
            /* If install failed, then we shouldn't erase. */
            if (ts->order[oc].u.removed.dependsOnIndex == lastFailed)
                break;
@@ -1786,8 +1899,11 @@ if (fi->ap == NULL) fi->ap = alp;        /* XXX WTFO? */
        }
        (void) rpmdbSync(ts->rpmdb);
     }
+#ifndef        DYING
+    tsi = tsFreeIterator(tsi);
+#endif
 
-    freeFl(ts, flList);
+    freeFl(ts, ts->flList);
 
     if (ourrc)
        return -1;
index 6f32c31..48f8d50 100644 (file)
@@ -25,10 +25,11 @@ build/parseSpec.c
 build/reqprov.c
 build/spec.c
 lib/cpio.c
-lib/depends.c
 lib/db1.c
 lib/db2.c
 lib/db3.c
+lib/dbconfig.c
+lib/depends.c
 lib/falloc.c
 lib/formats.c
 lib/fprint.c
index 8af360b..3b38b25 100644 (file)
@@ -6,7 +6,7 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 2001-02-12 13:55-0500\n"
+"POT-Creation-Date: 2001-02-15 15:44-0500\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -2222,230 +2222,205 @@ msgstr ""
 msgid " failed - "
 msgstr ""
 
-#. XXX legacy epoch-less requires/conflicts compatibility
-#: lib/depends.c:565
+#: lib/db1.c:92 lib/db2.c:117 lib/db3.c:102
 #, c-format
-msgid ""
-"the \"B\" dependency needs an epoch (assuming same as \"A\")\n"
-"\tA %s\tB %s\n"
+msgid "db%d error(%d) from %s: %s\n"
 msgstr ""
 
-#: lib/depends.c:594
+#: lib/db1.c:95 lib/db2.c:120 lib/db3.c:105
 #, c-format
-msgid "  %s    A %s\tB %s\n"
+msgid "db%d error(%d): %s\n"
 msgstr ""
 
-#: lib/depends.c:962
+#: lib/db1.c:387
 #, c-format
-msgid "%s: %-45s YES (added files)\n"
+msgid "closed  db file        %s\n"
 msgstr ""
 
-#: lib/depends.c:1021
+#: lib/db1.c:390
 #, c-format
-msgid "%s: %-45s YES (added provide)\n"
+msgid "removed db file        %s\n"
 msgstr ""
 
-#: lib/depends.c:1073
+#: lib/db1.c:421
 #, c-format
-msgid "%s: %-45s %-3s (cached)\n"
+msgid "bad db file %s\n"
 msgstr ""
 
-#: lib/depends.c:1092
+#: lib/db1.c:426
 #, c-format
-msgid "%s: %-45s YES (rpmrc provides)\n"
+msgid "opening db file        %s mode 0x%x\n"
 msgstr ""
 
-#: lib/depends.c:1109
+#. XXX check errno validity
+#: lib/db1.c:449
 #, c-format
-msgid "%s: %-45s YES (rpmlib provides)\n"
+msgid "cannot get %s lock on database\n"
 msgstr ""
 
-#: lib/depends.c:1131
-#, c-format
-msgid "%s: %-45s YES (db files)\n"
+#: lib/db1.c:450 lib/db2.c:786 lib/db3.c:766
+msgid "exclusive"
 msgstr ""
 
-#: lib/depends.c:1144
-#, c-format
-msgid "%s: %-45s YES (db provides)\n"
+#: lib/db1.c:450 lib/db2.c:786 lib/db3.c:766
+msgid "shared"
 msgstr ""
 
-#: lib/depends.c:1158
+#: lib/db2.c:145 lib/db3.c:130
 #, c-format
-msgid "%s: %-45s YES (db package)\n"
+msgid "closed  db environment %s/%s\n"
 msgstr ""
 
-#: lib/depends.c:1174
+#: lib/db2.c:161 lib/db3.c:146
 #, c-format
-msgid "%s: %-45s NO\n"
+msgid "removed db environment %s/%s\n"
 msgstr ""
 
-#: lib/depends.c:1195
+#: lib/db2.c:198 lib/db3.c:183
 #, c-format
-msgid "%s: (%s, %s) added to Depends cache.\n"
+msgid "opening db environment %s/%s %s\n"
 msgstr ""
 
-#. requirements are not satisfied.
-#: lib/depends.c:1256
+#: lib/db2.c:588 lib/db3.c:569
 #, c-format
-msgid "package %s-%s-%s require not satisfied: %s\n"
+msgid "closed  db index       %s/%s\n"
 msgstr ""
 
-#. conflicts exist.
-#: lib/depends.c:1323
+#: lib/db2.c:678 lib/db3.c:659
 #, c-format
-msgid "package %s conflicts: %s\n"
+msgid "opening db index       %s/%s %s mode=0x%x\n"
 msgstr ""
 
-#: lib/depends.c:1539
+#: lib/db2.c:784 lib/db3.c:764
 #, c-format
-msgid "removing %s-%s-%s \"%s\" from tsort relations.\n"
-msgstr ""
-
-#. Record all relations.
-#: lib/depends.c:1678
-msgid "========== recording tsort relations\n"
-msgstr ""
-
-#. T4. Scan for zeroes.
-#: lib/depends.c:1725
-msgid "========== tsorting packages\n"
-msgstr ""
-
-#: lib/depends.c:1770
-msgid "========== successors only (presentation order)\n"
-msgstr ""
-
-#: lib/depends.c:1819
-msgid "LOOP:\n"
-msgstr ""
-
-#: lib/depends.c:1850
-msgid "========== continuing tsort ...\n"
+msgid "cannot get %s lock on %s/%s\n"
 msgstr ""
 
-#: lib/db1.c:92 lib/db2.c:112 lib/db3.c:456
+#: lib/db2.c:791 lib/db3.c:771
 #, c-format
-msgid "db%d error(%d) from %s: %s\n"
+msgid "locked  db index       %s/%s\n"
 msgstr ""
 
-#: lib/db1.c:95 lib/db2.c:115 lib/db3.c:459
+#: lib/dbconfig.c:258
 #, c-format
-msgid "db%d error(%d): %s\n"
+msgid "unrecognized db option: \"%s\" ignored\n"
 msgstr ""
 
-#: lib/db1.c:387
+#: lib/dbconfig.c:287
 #, c-format
-msgid "closed  db file        %s\n"
+msgid "%s has invalid numeric value, skipped\n"
 msgstr ""
 
-#: lib/db1.c:390
+#: lib/dbconfig.c:296
 #, c-format
-msgid "removed db file        %s\n"
+msgid "%s has too large or too small long value, skipped\n"
 msgstr ""
 
-#: lib/db1.c:421
+#: lib/dbconfig.c:305
 #, c-format
-msgid "bad db file %s\n"
+msgid "%s has too large or too small integer value, skipped\n"
 msgstr ""
 
-#: lib/db1.c:426
+#. XXX legacy epoch-less requires/conflicts compatibility
+#: lib/depends.c:565
 #, c-format
-msgid "opening db file        %s mode 0x%x\n"
+msgid ""
+"the \"B\" dependency needs an epoch (assuming same as \"A\")\n"
+"\tA %s\tB %s\n"
 msgstr ""
 
-#. XXX check errno validity
-#: lib/db1.c:449
+#: lib/depends.c:594
 #, c-format
-msgid "cannot get %s lock on database\n"
+msgid "  %s    A %s\tB %s\n"
 msgstr ""
 
-#: lib/db1.c:450 lib/db3.c:1120
-msgid "exclusive"
+#: lib/depends.c:962
+#, c-format
+msgid "%s: %-45s YES (added files)\n"
 msgstr ""
 
-#: lib/db1.c:450 lib/db3.c:1120
-msgid "shared"
+#: lib/depends.c:1021
+#, c-format
+msgid "%s: %-45s YES (added provide)\n"
 msgstr ""
 
-#: lib/db2.c:141
+#: lib/depends.c:1073
 #, c-format
-msgid "closed  db environment %s/%s(%s)\n"
+msgid "%s: %-45s %-3s (cached)\n"
 msgstr ""
 
-#: lib/db2.c:153
+#: lib/depends.c:1092
 #, c-format
-msgid "removed db environment %s/%s(%s)\n"
+msgid "%s: %-45s YES (rpmrc provides)\n"
 msgstr ""
 
-#: lib/db2.c:190
+#: lib/depends.c:1109
 #, c-format
-msgid "opening db environment %s/%s(%s) %s\n"
+msgid "%s: %-45s YES (rpmlib provides)\n"
 msgstr ""
 
-#: lib/db2.c:565
+#: lib/depends.c:1131
 #, c-format
-msgid "closed  db index       %s/%s(%s)\n"
+msgid "%s: %-45s YES (db files)\n"
 msgstr ""
 
-#: lib/db2.c:643
+#: lib/depends.c:1144
 #, c-format
-msgid "opening db index       %s/%s(%s) %s mode=0x%x\n"
+msgid "%s: %-45s YES (db provides)\n"
 msgstr ""
 
-#: lib/db3.c:268
+#: lib/depends.c:1158
 #, c-format
-msgid "unrecognized db option: \"%s\" ignored\n"
+msgid "%s: %-45s YES (db package)\n"
 msgstr ""
 
-#: lib/db3.c:297
+#: lib/depends.c:1174
 #, c-format
-msgid "%s has invalid numeric value, skipped\n"
+msgid "%s: %-45s NO\n"
 msgstr ""
 
-#: lib/db3.c:306
+#: lib/depends.c:1195
 #, c-format
-msgid "%s has too large or too small long value, skipped\n"
+msgid "%s: (%s, %s) added to Depends cache.\n"
 msgstr ""
 
-#: lib/db3.c:315
+#. requirements are not satisfied.
+#: lib/depends.c:1256
 #, c-format
-msgid "%s has too large or too small integer value, skipped\n"
+msgid "package %s-%s-%s require not satisfied: %s\n"
 msgstr ""
 
-#: lib/db3.c:484
+#. conflicts exist.
+#: lib/depends.c:1323
 #, c-format
-msgid "closed  db environment %s/%s\n"
+msgid "package %s conflicts: %s\n"
 msgstr ""
 
-#: lib/db3.c:500
+#: lib/depends.c:1539
 #, c-format
-msgid "removed db environment %s/%s\n"
+msgid "removing %s-%s-%s \"%s\" from tsort relations.\n"
 msgstr ""
 
-#: lib/db3.c:537
-#, c-format
-msgid "opening db environment %s/%s %s\n"
+#. Record all relations.
+#: lib/depends.c:1678
+msgid "========== recording tsort relations\n"
 msgstr ""
 
-#: lib/db3.c:923
-#, c-format
-msgid "closed  db index       %s/%s\n"
+#. T4. Scan for zeroes.
+#: lib/depends.c:1725
+msgid "========== tsorting packages\n"
 msgstr ""
 
-#: lib/db3.c:1013
-#, c-format
-msgid "opening db index       %s/%s %s mode=0x%x\n"
+#: lib/depends.c:1770
+msgid "========== successors only (presentation order)\n"
 msgstr ""
 
-#: lib/db3.c:1118
-#, c-format
-msgid "cannot get %s lock on %s/%s\n"
+#: lib/depends.c:1819
+msgid "LOOP:\n"
 msgstr ""
 
-#: lib/db3.c:1125
-#, c-format
-msgid "locked  db index       %s/%s\n"
+#: lib/depends.c:1850
+msgid "========== continuing tsort ...\n"
 msgstr ""
 
 #: lib/falloc.c:141
@@ -3371,7 +3346,7 @@ msgstr ""
 msgid "cannot open file %s: %s\n"
 msgstr ""
 
-#: lib/rpminstall.c:327 lib/rpminstall.c:632
+#: lib/rpminstall.c:327 lib/rpminstall.c:633
 #, c-format
 msgid "%s cannot be installed\n"
 msgstr ""
@@ -3423,12 +3398,12 @@ msgstr ""
 msgid "removing these packages would break dependencies:\n"
 msgstr ""
 
-#: lib/rpminstall.c:619
+#: lib/rpminstall.c:620
 #, c-format
 msgid "cannot open %s: %s\n"
 msgstr ""
 
-#: lib/rpminstall.c:625
+#: lib/rpminstall.c:626
 #, c-format
 msgid "Installing %s\n"
 msgstr ""
@@ -3661,46 +3636,46 @@ msgstr ""
 msgid "You must set \"%%_pgp_name\" in your macro file\n"
 msgstr ""
 
-#: lib/transaction.c:392
+#: lib/transaction.c:403
 msgid "========== relocations\n"
 msgstr ""
 
-#: lib/transaction.c:395
+#: lib/transaction.c:406
 #, c-format
 msgid "%5d exclude  %s\n"
 msgstr ""
 
-#: lib/transaction.c:398
+#: lib/transaction.c:409
 #, c-format
 msgid "%5d relocate %s -> %s\n"
 msgstr ""
 
-#: lib/transaction.c:472
+#: lib/transaction.c:483
 #, c-format
 msgid "excluding multilib path %s%s\n"
 msgstr ""
 
-#: lib/transaction.c:521
+#: lib/transaction.c:532
 #, c-format
 msgid "excluding %s %s\n"
 msgstr ""
 
-#: lib/transaction.c:528
+#: lib/transaction.c:539
 #, c-format
 msgid "relocating %s to %s\n"
 msgstr ""
 
-#: lib/transaction.c:600
+#: lib/transaction.c:611
 #, c-format
 msgid "relocating directory %s to %s\n"
 msgstr ""
 
-#: lib/transaction.c:605
+#: lib/transaction.c:616
 #, c-format
 msgid "excluding directory %s\n"
 msgstr ""
 
-#: lib/transaction.c:729
+#: lib/transaction.c:740
 #, c-format
 msgid "%s skipped due to missingok flag\n"
 msgstr ""
@@ -3870,22 +3845,22 @@ msgstr ""
 msgid "logging into %s as %s, pw %s\n"
 msgstr ""
 
-#: rpmio/rpmlog.c:24
+#: rpmio/rpmlog.c:32
 msgid "(no error)"
 msgstr ""
 
 #. !< RPMLOG_EMERG
-#: rpmio/rpmlog.c:83 rpmio/rpmlog.c:84 rpmio/rpmlog.c:85
+#: rpmio/rpmlog.c:91 rpmio/rpmlog.c:92 rpmio/rpmlog.c:93
 msgid "fatal error: "
 msgstr ""
 
 #. !< RPMLOG_CRIT
-#: rpmio/rpmlog.c:86
+#: rpmio/rpmlog.c:94
 msgid "error: "
 msgstr ""
 
 #. !< RPMLOG_ERR
-#: rpmio/rpmlog.c:87
+#: rpmio/rpmlog.c:95
 msgid "warning: "
 msgstr ""
 
index 431f1fa..8eda49f 100644 (file)
@@ -98,6 +98,7 @@ typedef enum rpmerrCode_e {
  * Retrofit rpmError() onto rpmlog sub-system.
  */
 #define        rpmError                        rpmlog
+#define        rpmErrorCode()                  rpmlogCode()
 #define        rpmErrorString()                rpmlogMessage()
 #define        rpmErrorSetCallback(_cb)        rpmlogSetCallback(_cb)
 typedef rpmlogCallback rpmErrorCallBackType;
index f79d02c..1d5bdb5 100644 (file)
@@ -17,6 +17,14 @@ int rpmlogGetNrecs(void)
     return nrecs;
 }
 
+int rpmlogCode(void)
+{
+    if (nrecs > 0)
+       return recs[nrecs-1].code;
+    return -1;
+}
+
+
 const char * rpmlogMessage(void)
 {
     if (nrecs > 0)
@@ -95,15 +103,31 @@ static void vrpmlog (unsigned code, const char *fmt, va_list ap)
     int pri = RPMLOG_PRI(code);
     int mask = RPMLOG_MASK(pri);
     /*@unused@*/ int fac = RPMLOG_FAC(code);
-    char msgbuf[BUFSIZ], *msg;
+    char *msgbuf, *msg;
+    int msgnb = BUFSIZ, nb;
     FILE * msgout = stderr;
     rpmlogRec rec;
 
     if ((mask & rpmlogMask) == 0)
        return;
 
-    /*@-unrecog@*/ vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap); /*@=unrecog@*/
-    msgbuf[sizeof(msgbuf) - 1] = '\0';
+    msgbuf = xmalloc(msgnb);
+    *msgbuf = '\0';
+
+    /* Allocate a sufficently large buffer for output. */
+    while (1) {
+       /*@-unrecog@*/
+       nb = vsnprintf(msgbuf, msgnb, fmt, ap);
+       /*@=unrecog@*/
+       if (nb > -1 && nb < msgnb)
+           break;
+       if (nb > -1)            /* glibc 2.1 */
+           msgnb = nb+1;
+       else                    /* glibc 2.0 */
+           msgnb *= 2;
+       msgbuf = xrealloc(msgbuf, msgnb);
+    }
+    msgbuf[msgnb - 1] = '\0';
     msg = msgbuf;
 
     /* Save copy of all messages at warning (or below == "more important"). */
@@ -119,10 +143,13 @@ static void vrpmlog (unsigned code, const char *fmt, va_list ap)
        ++nrecs;
 
        rec->code = code;
-       rec->message = xstrdup(msg);
+       rec->message = msgbuf;
+       msgbuf = NULL;
 
        if (_rpmlogCallback) {
            _rpmlogCallback();
+           if (msgbuf)
+               free(msgbuf);
            return;     /* XXX Preserve legacy rpmError behavior. */
        }
     }
@@ -152,6 +179,8 @@ static void vrpmlog (unsigned code, const char *fmt, va_list ap)
 
     fputs(msg, msgout);
     fflush(msgout);
+    if (msgbuf)
+       free(msgbuf);
     if (pri <= RPMLOG_CRIT)
        exit(EXIT_FAILURE);
 }
@@ -165,6 +194,11 @@ void rpmlog (int code, const char *fmt, ...)
     va_end(ap);
 }
 
+int rpmErrorCode(void)
+{
+    return rpmlogCode();
+}
+
 const char * rpmErrorString(void)
 {
     return rpmlogMessage();
index 36f55a0..bbf568e 100644 (file)
@@ -174,6 +174,15 @@ int rpmlogGetNrecs(void);
 /*@observer@*/ const char * rpmlogMessage(void);
 
 /**
+ * Return error code from last rpmError() message.
+ * @deprecated Perl-RPM needs, what's really needed is predictable, non-i18n
+ *     encumbered, error text that can be retrieved through rpmlogMessage()
+ *     and parsed IMHO.
+ * @return             code from last message
+ */
+int rpmlogCode(void);
+
+/**
  * Print all rpmError() messages.
  * @param f            file handle (NULL uses stderr)
  */
@@ -213,6 +222,13 @@ rpmlogCallback rpmlogSetCallback(rpmlogCallback cb);
 rpmlogCallback rpmErrorSetCallback(rpmlogCallback cb);
 
 /**
+ * Return error code from last rpmError() message.
+ * @deprecated Perl-RPM needs, use rpmlogCode() instead.
+ * @return             code from last message
+ */
+int rpmErrorCode(void);
+
+/**
  * Return text of last rpmError() message.
  * @deprecated gnorpm needs, use rpmlogMessage() instead.
  * @return             text of last message