- Main Page
- Related Pages
- Modules
- Data Structures
- Files

# rpmdb/db3.c

Go to the documentation of this file.

    00001 /*@-type@*/ /* FIX: annotate db3 methods */
    00006 /*@unchecked@*/
    00007 static int _debug = 1;  /* XXX if < 0 debugging, > 0 unusual error returns */
    00008
    00009 #include "system.h"
    00010
    00011 #if defined(HAVE_FTOK) && defined(HAVE_SYS_IPC_H)
    00012 #include <sys/ipc.h>
    00013 #endif
    00014
    00015 #include <rpmio.h>
    00016 #include <rpmlog.h>
    00017 #include <rpmmacro.h>
    00018 #include <rpmurl.h>     /* XXX urlPath proto */
    00019
    00020 #define _RPMTAG_INTERNAL
    00021 #include <rpmtag.h>
    00022 #define _RPMDB_INTERNAL
    00023 #include <rpmdb.h>
    00024
    00025 #include "debug.h"
    00026
    00027 #if !defined(DB_CLIENT) /* XXX db-4.2.42 retrofit */
    00028 #define DB_CLIENT       DB_RPCCLIENT
    00029 #endif
    00030
    00031 /*@access rpmdb @*/
    00032 /*@access dbiIndex @*/
    00033 /*@access dbiIndexSet @*/
    00034
    00038 /*@-fielduse@*/
    00039 struct dbiHStats_s {
    00040     unsigned int hash_magic;
    00041     unsigned int hash_version;
    00042     unsigned int hash_nkeys;
    00043     unsigned int hash_ndata;
    00044     unsigned int hash_pagesize;
    00045     unsigned int hash_nelem;
    00046     unsigned int hash_ffactor;
    00047     unsigned int hash_buckets;
    00048     unsigned int hash_free;
    00049     unsigned int hash_bfree;
    00050     unsigned int hash_bigpages;
    00051     unsigned int hash_big_bfree;
    00052     unsigned int hash_overflows;
    00053     unsigned int hash_ovfl_free;
    00054     unsigned int hash_dup;
    00055     unsigned int hash_dup_free;
    00056 };
    00057
    00061 struct dbiBStats_s {
    00062     unsigned int bt_magic;
    00063     unsigned int bt_version;
    00064     unsigned int bt_nkeys;
    00065     unsigned int bt_ndata;
    00066     unsigned int bt_pagesize;
    00067     unsigned int bt_minkey;
    00068     unsigned int bt_re_len;
    00069     unsigned int bt_re_pad;
    00070     unsigned int bt_levels;
    00071     unsigned int bt_int_pg;
    00072     unsigned int bt_leaf_pg;
    00073     unsigned int bt_dup_pg;
    00074     unsigned int bt_over_pg;
    00075     unsigned int bt_free;
    00076     unsigned int bt_int_pgfree;
    00077     unsigned int bt_leaf_pgfree;
    00078     unsigned int bt_dup_pgfree;
    00079     unsigned int bt_over_pgfree;
    00080 };
    00081 /*@=fielduse@*/
    00082
    00083 #ifdef  NOTNOW
    00084 static const char * bfstring(unsigned int x, const char * xbf)
    00085 {
    00086     const char * s = xbf;
    00087     static char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
    00088     static char buf[BUFSIZ];
    00089     char * t, * te;
    00090     unsigned radix;
    00091     unsigned c, i, k;
    00092
    00093     radix = (s != NULL ? *s++ : 16);
    00094
    00095     if (radix <= 1 || radix >= 32)
    00096         radix = 16;
    00097
    00098     t = buf;
    00099     switch (radix) {
    00100     case 8:     *t++ = '0';     break;
    00101     case 16:    *t++ = '0';     *t++ = 'x';     break;
    00102     }
    00103
    00104     i = 0;
    00105     k = x;
    00106     do { i++; k /= radix; } while (k);
    00107
    00108     te = t + i;
    00109
    00110     k = x;
    00111     do { --i; t[i] = digits[k % radix]; k /= radix; } while (k);
    00112
    00113     t = te;
    00114     i = '<';
    00115     if (s != NULL)
    00116     while ((c = *s++) != '\0') {
    00117         if (c > ' ') continue;
    00118
    00119         k = (1 << (c - 1));
    00120         if (!(x & k)) continue;
    00121
    00122         if (t == te) *t++ = '=';
    00123
    00124         *t++ = i;
    00125         i = ',';
    00126         while (*s > ' ')
    00127             *t++ = *s++;
    00128     }
    00129     if (t > te) *t++ = '>';
    00130     *t = '\0';
    00131     return buf;
    00132 }
    00133
    00134 /* XXX checked with db-4.5.20 */
    00135 static const char * dbtFlags =
    00136         "\20\1APPMALLOC\2ISSET\3MALLOC\4PARTIAL\5REALLOC\6USERMEM\7DUPOK";
    00137
    00138 static const char * dbenvOpenFlags =
    00139         "\20\1CREATE\2DURABLE_UNKNOWN\3FORCE\4MULTIVERSION\5NOMMAP\6RDONLY\7RECOVER\10THREAD\11TRUNCATE\12TXN_NOSYNC\13TXN_NOT_DURABLEi\14TXN_WRITE_NOSYNC\15USE_ENVIRON\16USE_ENVIRON_ROOT\17CDB\20LOCK\21LOG\22MPOOL\23REP\24TXN\25LOCKDOWN\26PRIVATE\27RECOVER_FATAL\30REGISTER\31SYSTEM_MEM";
    00140
    00141 static const char * dbOpenFlags =
    00142         "\20\1CREATE\2DURABLE_UNKNOWN\3FORCE\4MULTIVERSION\5NOMMAP\6RDONLY\7RECOVER\10THREAD\11TRUNCATE\12TXN_NOSYNC\13TXN_NOT_DURABLEi\14TXN_WRITE_NOSYNC\15USE_ENVIRON\16USE_ENVIRON_ROOT\17EXCL\20FCNTL_LOCKING\21NO_AUTO_COMMIT\22RDWRMASTER\23WRITEOPEN";
    00143
    00144 static const char * dbenvSetFlags =
    00145         "\20\1CREATE\2DURABLE_UNKNOWN\3FORCE\4MULTIVERSION\5NOMMAP\6RDONLY\7RECOVER\10THREAD\11TRUNCATE\12TXN_NOSYNC\13TXN_NOT_DURABLEi\14TXN_WRITE_NOSYNC\15USE_ENVIRON\16USE_ENVIRON_ROOT\17CDB_ALLDB\20DIRECT_DB\21DIRECT_LOG\22DSYNC_DB\23DSYNC_LOG\24LOG_AUTOREMOVE\25LOG_INMEMORY\26NOLOCKING\27NOPANIC\30OVERWRITE\31PANIC_ENV\36REGION_INIT\37TIME_NOTGRANTED\40YIELDCPU";
    00146
    00147 static const char * dbSetFlags =
    00148         "\20\1CREATE\2DURABLE_UNKNOWN\3FORCE\4MULTIVERSION\5NOMMAP\6RDONLY\7RECOVER\10THREAD\11TRUNCATE\12TXN_NOSYNC\13TXN_NOT_DURABLEi\14TXN_WRITE_NOSYNC\15USE_ENVIRON\16USE_ENVIRON_ROOT\17CHKSUM\20DUP\21DUPSORT\22ENCRYPT\23INORDER\24RECNUM\25RENUMBER\26REVSPLITOFF\27SNAPSHOT";
    00149
    00150 static const char * dbiModeFlags =
    00151         "\20\1WRONLY\2RDWR\7CREAT\10EXCL\11NOCTTY\12TRUNC\13APPEND\14NONBLOCK\15SYNC\16ASYNC\17DIRECT\20LARGEFILE\21DIRECTORY\22NOFOLLOW";
    00152 #endif  /* NOTNOW */
    00153
    00154
    00155 /*@-globuse -mustmod @*/        /* FIX: rpmError not annotated yet. */
    00156 static int cvtdberr(/*@unused@*/ dbiIndex dbi, const char * msg, int error, int printit)
    00157         /*@globals fileSystem @*/
    00158         /*@modifies fileSystem @*/
    00159 {
    00160     int rc = error;
    00161
    00162     if (printit && rc) {
    00163         /*@-moduncon@*/ /* FIX: annotate db3 methods */
    00164         if (msg)
    00165             rpmlog(RPMLOG_ERR, _("db%d error(%d) from %s: %s\n"),
    00166                 DB_VERSION_MAJOR, rc, msg, db_strerror(error));
    00167         else
    00168             rpmlog(RPMLOG_ERR, _("db%d error(%d): %s\n"),
    00169                 DB_VERSION_MAJOR, rc, db_strerror(error));
    00170         /*@=moduncon@*/
    00171     }
    00172
    00173     return rc;
    00174 }
    00175 /*@=globuse =mustmod @*/
    00176
    00183 /*@observer@*/
    00184 static const char * mapTagName(rpmdb rpmdb, dbiIndex dbi)
    00185         /*@*/
    00186 {
    00187     tagStore_t dbiTags = rpmdb->db_tags;
    00188     int dbix = 0;
    00189
    00190     if (dbiTags != NULL)
    00191     while (dbix < rpmdb->db_ndbi) {
    00192         if (dbi->dbi_rpmtag == dbiTags->tag)
    00193             return dbiTags->str;
    00194         dbiTags++;
    00195         dbix++;
    00196     }
    00197     /* XXX should never reach here */
    00198     return tagName(dbi->dbi_rpmtag);
    00199 }
    00200
    00201 static int db_fini(dbiIndex dbi, const char * dbhome,
    00202                 /*@null@*/ const char * dbfile,
    00203                 /*@unused@*/ /*@null@*/ const char * dbsubfile)
    00204         /*@globals fileSystem @*/
    00205         /*@modifies fileSystem @*/
    00206 {
    00207     rpmdb rpmdb = dbi->dbi_rpmdb;
    00208     DB_ENV * dbenv = rpmdb->db_dbenv;
    00209     int rc;
    00210
    00211     if (dbenv == NULL)
    00212         return 0;
    00213
    00214     rc = dbenv->close(dbenv, 0);
    00215     rc = cvtdberr(dbi, "dbenv->close", rc, _debug);
    00216
    00217     if (dbfile)
    00218         rpmlog(RPMLOG_DEBUG, D_("closed   db environment %s/%s\n"),
    00219                         dbhome, dbfile);
    00220
    00221     if (rpmdb->db_remove_env) {
    00222         int xx;
    00223
    00224         /*@-moduncon@*/ /* FIX: annotate db3 methods */
    00225         xx = db_env_create(&dbenv, 0);
    00226         /*@=moduncon@*/
    00227         if (!xx && dbenv != NULL) {
    00228             xx = cvtdberr(dbi, "db_env_create", xx, _debug);
    00229 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR != 0) || (DB_VERSION_MAJOR == 4)
    00230             xx = dbenv->remove(dbenv, dbhome, DB_FORCE);
    00231 #else
    00232             xx = dbenv->remove(dbenv, dbhome, NULL, 0);
    00233 #endif
    00234             xx = cvtdberr(dbi, "dbenv->remove", xx, _debug);
    00235
    00236             if (dbfile)
    00237                 rpmlog(RPMLOG_DEBUG, D_("removed  db environment %s/%s\n"),
    00238                         dbhome, dbfile);
    00239         }
    00240
    00241     }
    00242     return rc;
    00243 }
    00244
    00245 static int db3_fsync_disable(/*@unused@*/ int fd)
    00246         /*@*/
    00247 {
    00248     return 0;
    00249 }
    00250
    00251 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 5)
    00252
    00260 static int db3is_alive(/*@unused@*/ DB_ENV *dbenv, pid_t pid, /*@unused@*/ db_threadid_t tid,
    00261                 uint32_t flags)
    00262         /*@*/
    00263 {
    00264     int is_alive = 1;   /* assume all processes are alive */
    00265
    00266     switch (flags) {
    00267     case DB_MUTEX_PROCESS_ONLY:
    00268     case 0:
    00269     default:
    00270         is_alive = (!(kill(pid, 0) < 0 && errno == ESRCH));
    00271         break;
    00272     }
    00273     return is_alive;
    00274 }
    00275 #endif
    00276
    00277 /*@-moduncon@*/ /* FIX: annotate db3 methods */
    00278 static int db_init(dbiIndex dbi, const char * dbhome,
    00279                 /*@null@*/ const char * dbfile,
    00280                 /*@unused@*/ /*@null@*/ const char * dbsubfile,
    00281                 /*@out@*/ DB_ENV ** dbenvp)
    00282         /*@globals rpmGlobalMacroContext, h_errno,
    00283                 fileSystem @*/
    00284         /*@modifies dbi, *dbenvp, fileSystem @*/
    00285 {
    00286     static int oneshot = 0;
    00287     rpmdb rpmdb = dbi->dbi_rpmdb;
    00288     DB_ENV *dbenv = NULL;
    00289     int eflags;
    00290     int rc;
    00291     int xx;
    00292
    00293     if (!oneshot) {
    00294 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR != 0) || (DB_VERSION_MAJOR == 4)
    00295         xx = db_env_set_func_open((int (*)(const char *, int, ...))Open);
    00296         xx = cvtdberr(dbi, "db_env_set_func_open", xx, _debug);
    00297 #endif
    00298         oneshot++;
    00299     }
    00300
    00301     if (dbenvp == NULL)
    00302         return 1;
    00303
    00304     /* XXX HACK */
    00305     /*@-assignexpose@*/
    00306     if (rpmdb->db_errfile == NULL)
    00307         rpmdb->db_errfile = stderr;
    00308     /*@=assignexpose@*/
    00309
    00310     eflags = (dbi->dbi_oeflags | dbi->dbi_eflags);
    00311     /* Try to join, rather than create, the environment. */
    00312     /* XXX DB_JOINENV is defined to 0 in db-4.5.20 */
    00313     if (eflags & DB_JOINENV) eflags &= DB_JOINENV;
    00314
    00315     if (dbfile)
    00316         rpmlog(RPMLOG_DEBUG, D_("opening  db environment %s/%s %s\n"),
    00317                 dbhome, dbfile, prDbiOpenFlags(eflags, 1));
    00318
    00319     /* XXX Can't do RPC w/o host. */
    00320     if (dbi->dbi_host == NULL)
    00321         dbi->dbi_ecflags &= ~DB_CLIENT;
    00322
    00323     /* XXX Set a default shm_key. */
    00324     if ((dbi->dbi_eflags & DB_SYSTEM_MEM) && dbi->dbi_shmkey == 0) {
    00325 #if defined(HAVE_FTOK)
    00326         dbi->dbi_shmkey = ftok(dbhome, 0);
    00327 #else
    00328         dbi->dbi_shmkey = 0x44631380;
    00329 #endif
    00330     }
    00331
    00332     rc = db_env_create(&dbenv, dbi->dbi_ecflags);
    00333     rc = cvtdberr(dbi, "db_env_create", rc, _debug);
    00334     if (dbenv == NULL || rc)
    00335         goto errxit;
    00336
    00337     /*@-noeffectuncon@*/ /* FIX: annotate db3 methods */
    00338
    00339  /* 4.1: dbenv->set_app_dispatch(???) */
    00340  /* 4.1: dbenv->set_alloc(???) */
    00341  /* 4.1: dbenv->set_data_dir(???) */
    00342  /* 4.1: dbenv->set_encrypt(???) */
    00343
    00344 /*@-castfcnptr@*/
    00345     dbenv->set_errcall(dbenv, (void *)rpmdb->db_errcall);
    00346 /*@=castfcnptr@*/
    00347     dbenv->set_errfile(dbenv, rpmdb->db_errfile);
    00348     dbenv->set_errpfx(dbenv, rpmdb->db_errpfx);
    00349     /*@=noeffectuncon@*/
    00350
    00351  /* 4.1: dbenv->set_feedback(???) */
    00352  /* 4.1: dbenv->set_flags(???) */
    00353
    00354  /* dbenv->set_paniccall(???) */
    00355
    00356     if ((dbi->dbi_ecflags & DB_CLIENT) && dbi->dbi_host) {
    00357         const char * home;
    00358         int retry = 0;
    00359
    00360         if ((home = strrchr(dbhome, '/')) != NULL)
    00361             dbhome = ++home;
    00362
    00363         while (retry++ < 5) {
    00364 /* XXX 3.3.4 change. */
    00365 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3) || (DB_VERSION_MAJOR == 4)
    00366             xx = dbenv->set_rpc_server(dbenv, NULL, dbi->dbi_host,
    00367                 dbi->dbi_cl_timeout, dbi->dbi_sv_timeout, 0);
    00368             xx = cvtdberr(dbi, "dbenv->set_server", xx, _debug);
    00369 #else
    00370             xx = dbenv->set_server(dbenv, dbi->dbi_host,
    00371                 dbi->dbi_cl_timeout, dbi->dbi_sv_timeout, 0);
    00372             xx = cvtdberr(dbi, "dbenv->set_server", xx, _debug);
    00373 #endif
    00374             if (!xx)
    00375                 break;
    00376             (void) sleep(15);
    00377         }
    00378     } else {
    00379 #if !(DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3)
    00380         xx = dbenv->set_verbose(dbenv, DB_VERB_CHKPOINT,
    00381                 (dbi->dbi_verbose & DB_VERB_CHKPOINT));
    00382 #endif
    00383         xx = dbenv->set_verbose(dbenv, DB_VERB_DEADLOCK,
    00384                 (dbi->dbi_verbose & DB_VERB_DEADLOCK));
    00385         xx = dbenv->set_verbose(dbenv, DB_VERB_RECOVERY,
    00386                 (dbi->dbi_verbose & DB_VERB_RECOVERY));
    00387 #if defined(DB_VERB_REGISTER)
    00388         xx = dbenv->set_verbose(dbenv, DB_VERB_REGISTER,
    00389                 (dbi->dbi_verbose & DB_VERB_REGISTER));
    00390 #endif
    00391 #if defined(DB_VERB_REPLICATION)
    00392         xx = dbenv->set_verbose(dbenv, DB_VERB_REPLICATION,
    00393                 (dbi->dbi_verbose & DB_VERB_REPLICATION));
    00394 #endif
    00395         xx = dbenv->set_verbose(dbenv, DB_VERB_WAITSFOR,
    00396                 (dbi->dbi_verbose & DB_VERB_WAITSFOR));
    00397 #if defined(DB_VERB_FILEOPS)
    00398         xx = dbenv->set_verbose(dbenv, DB_VERB_FILEOPS,
    00399                 (dbi->dbi_verbose & DB_VERB_FILEOPS));
    00400 #endif
    00401 #if defined(DB_VERB_FILEOPS_ALL)
    00402         xx = dbenv->set_verbose(dbenv, DB_VERB_FILEOPS_ALL,
    00403                 (dbi->dbi_verbose & DB_VERB_FILEOPS_ALL));
    00404 #endif
    00405
    00406         if (dbi->dbi_mmapsize) {
    00407             xx = dbenv->set_mp_mmapsize(dbenv, dbi->dbi_mmapsize);
    00408             xx = cvtdberr(dbi, "dbenv->set_mp_mmapsize", xx, _debug);
    00409         }
    00410         if (dbi->dbi_tmpdir) {
    00411             const char * root;
    00412             const char * tmpdir;
    00413
    00414             root = (dbi->dbi_root ? dbi->dbi_root : rpmdb->db_root);
    00415             if ((root[0] == '/' && root[1] == '\0') || rpmdb->db_chrootDone)
    00416                 root = NULL;
    00417 /*@-mods@*/
    00418             tmpdir = rpmGenPath(root, dbi->dbi_tmpdir, NULL);
    00419 /*@=mods@*/
    00420             xx = dbenv->set_tmp_dir(dbenv, tmpdir);
    00421             xx = cvtdberr(dbi, "dbenv->set_tmp_dir", xx, _debug);
    00422             tmpdir = _free(tmpdir);
    00423         }
    00424     }
    00425
    00426 /* ==== Locking: */
    00427  /* dbenv->set_lk_conflicts(???) */
    00428     if (dbi->dbi_lk_detect) {
    00429         xx = dbenv->set_lk_detect(dbenv, dbi->dbi_lk_detect);
    00430         xx = cvtdberr(dbi, "dbenv->set_lk_detect", xx, _debug);
    00431     }
    00432 #if !(DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
    00433     if (dbi->dbi_lk_max_lockers) {
    00434         xx = dbenv->set_lk_max_lockers(dbenv, dbi->dbi_lk_max_lockers);
    00435         xx = cvtdberr(dbi, "dbenv->set_lk_max_lockers", xx, _debug);
    00436     }
    00437     if (dbi->dbi_lk_max_locks) {
    00438         xx = dbenv->set_lk_max_locks(dbenv, dbi->dbi_lk_max_locks);
    00439         xx = cvtdberr(dbi, "dbenv->set_lk_max_locks", xx, _debug);
    00440     }
    00441     if (dbi->dbi_lk_max_objects) {
    00442         xx = dbenv->set_lk_max_objects(dbenv, dbi->dbi_lk_max_objects);
    00443         xx = cvtdberr(dbi, "dbenv->set_lk_max_objects", xx, _debug);
    00444     }
    00445 /* ==== Logging: */
    00446     if (dbi->dbi_lg_bsize) {
    00447         xx = dbenv->set_lg_bsize(dbenv, dbi->dbi_lg_bsize);
    00448         xx = cvtdberr(dbi, "dbenv->set_lg_bsize", xx, _debug);
    00449     }
    00450     if (dbi->dbi_lg_dir) {
    00451         xx = dbenv->set_lg_dir(dbenv, dbi->dbi_lg_dir);
    00452         xx = cvtdberr(dbi, "dbenv->set_lg_dir", xx, _debug);
    00453     }
    00454     if (dbi->dbi_lg_filemode) {
    00455         xx = dbenv->set_lg_filemode(dbenv, dbi->dbi_lg_filemode);
    00456         xx = cvtdberr(dbi, "dbenv->set_lg_filemode", xx, _debug);
    00457     }
    00458     if (dbi->dbi_lg_max) {
    00459         xx = dbenv->set_lg_max(dbenv, dbi->dbi_lg_max);
    00460         xx = cvtdberr(dbi, "dbenv->set_lg_max", xx, _debug);
    00461     }
    00462     if (dbi->dbi_lg_regionmax) {
    00463         xx = dbenv->set_lg_regionmax(dbenv, dbi->dbi_lg_regionmax);
    00464         xx = cvtdberr(dbi, "dbenv->set_lg_regionmax", xx, _debug);
    00465     }
    00466 #endif
    00467
    00468 /* ==== Memory pool: */
    00469     if (dbi->dbi_cachesize) {
    00470         xx = dbenv->set_cachesize(dbenv, 0, dbi->dbi_cachesize, 0);
    00471         xx = cvtdberr(dbi, "dbenv->set_cachesize", xx, _debug);
    00472     }
    00473
    00474 /* ==== Mutexes: */
    00475     if (dbi->dbi_mutex_align) {
    00476         xx = dbenv->mutex_set_align(dbenv, dbi->dbi_mutex_align);
    00477         xx = cvtdberr(dbi, "dbenv->mutex_set_align", xx, _debug);
    00478     }
    00479     if (dbi->dbi_mutex_increment) {
    00480         xx = dbenv->mutex_set_increment(dbenv, dbi->dbi_mutex_increment);
    00481         xx = cvtdberr(dbi, "dbenv->mutex_set_increment", xx, _debug);
    00482     }
    00483     if (dbi->dbi_mutex_max) {
    00484         xx = dbenv->mutex_set_max(dbenv, dbi->dbi_mutex_max);
    00485         xx = cvtdberr(dbi, "dbenv->mutex_set_max", xx, _debug);
    00486     }
    00487     if (dbi->dbi_mutex_tas_spins) {
    00488         xx = dbenv->mutex_set_tas_spins(dbenv, dbi->dbi_mutex_tas_spins);
    00489         xx = cvtdberr(dbi, "dbenv->mutex_set_tas_spins", xx, _debug);
    00490     }
    00491
    00492 /* ==== Replication: */
    00493 /* dbenv->rep_set_config */
    00494 /* dbenv->rep_set_limit */
    00495 /* dbenv->rep_set_nsites */
    00496 /* dbenv->rep_set_priority */
    00497 /* dbenv->rep_set_timeout */
    00498 /* dbenv->rep_set_transport */
    00499
    00500 /* ==== Sequences: */
    00501
    00502 /* ==== Transactions: */
    00503     if (dbi->dbi_tx_max) {
    00504         xx = dbenv->set_tx_max(dbenv, dbi->dbi_tx_max);
    00505         xx = cvtdberr(dbi, "dbenv->set_tx_max", xx, _debug);
    00506     }
    00507 /* XXX dbenv->txn_checkpoint */
    00508 /* XXX dbenv->txn_recover */
    00509 /* XXX dbenv->txn_stat */
    00510  /* 4.1 dbenv->set_timeout(???) */
    00511  /* 4.1: dbenv->set_tx_timestamp(???) */
    00512
    00513
    00514 /* ==== Other: */
    00515     if (dbi->dbi_no_fsync) {
    00516 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR != 0) || (DB_VERSION_MAJOR == 4)
    00517         xx = db_env_set_func_fsync(db3_fsync_disable);
    00518 #else
    00519         xx = dbenv->set_func_fsync(dbenv, db3_fsync_disable);
    00520 #endif
    00521         xx = cvtdberr(dbi, "db_env_set_func_fsync", xx, _debug);
    00522     }
    00523
    00524     if (dbi->dbi_shmkey) {
    00525         xx = dbenv->set_shm_key(dbenv, dbi->dbi_shmkey);
    00526         xx = cvtdberr(dbi, "dbenv->set_shm_key", xx, _debug);
    00527     }
    00528
    00529 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 5)
    00530     /* XXX capture dbenv->falchk output on stderr. */
    00531 /*@-noeffectuncon@*/
    00532     dbenv->set_msgfile(dbenv, rpmdb->db_errfile);
    00533 /*@=noeffectuncon@*/
    00534     /* XXX must be at least 8, and __db* files need nuking to instantiate. */
    00535     if (dbi->dbi_thread_count >= 8) {
    00536         xx = dbenv->set_thread_count(dbenv, dbi->dbi_thread_count);
    00537         xx = cvtdberr(dbi, "dbenv->set_thread_count", xx, _debug);
    00538     }
    00539 #endif
    00540
    00541 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR != 0) || (DB_VERSION_MAJOR == 4)
    00542     rc = (dbenv->open)(dbenv, dbhome, eflags, dbi->dbi_perms);
    00543 #else
    00544     rc = (dbenv->open)(dbenv, dbhome, NULL, eflags, dbi->dbi_perms);
    00545 #endif
    00546     xx = _debug;
    00547 #if defined(DB_VERSION_MISMATCH)
    00548     if (rc == DB_VERSION_MISMATCH) xx = 0;
    00549 #endif
    00550     if (rc == EINVAL) xx = 0;
    00551     rc = cvtdberr(dbi, "dbenv->open", rc, xx);
    00552     if (rc)
    00553         goto errxit;
    00554
    00555 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 5)
    00556     if (!rpmdb->db_verifying && dbi->dbi_thread_count >= 8) {
    00557         /* XXX Set pid/tid is_alive probe. */
    00558         xx = dbenv->set_isalive(dbenv, db3is_alive);
    00559         xx = cvtdberr(dbi, "dbenv->set_isalive", xx, _debug);
    00560         /* XXX Clean out stale shared read locks. */
    00561         xx = dbenv->failchk(dbenv, 0);
    00562         xx = cvtdberr(dbi, "dbenv->failchk", xx, _debug);
    00563         if (xx == DB_RUNRECOVERY) {
    00564             rc = xx;
    00565             goto errxit;
    00566         }
    00567     }
    00568 #endif
    00569
    00570     *dbenvp = dbenv;
    00571
    00572     return 0;
    00573
    00574 errxit:
    00575     if (dbenv) {
    00576         xx = dbenv->close(dbenv, 0);
    00577         xx = cvtdberr(dbi, "dbenv->close", xx, _debug);
    00578     }
    00579     return rc;
    00580 }
    00581 /*@=moduncon@*/
    00582
    00583 static int db3sync(dbiIndex dbi, unsigned int flags)
    00584         /*@globals fileSystem @*/
    00585         /*@modifies fileSystem @*/
    00586 {
    00587     DB * db = dbi->dbi_db;
    00588     int rc = 0;
    00589     int _printit;
    00590
    00591     if (db != NULL)
    00592         rc = db->sync(db, flags);
    00593 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
    00594     _printit = _debug;
    00595 #else
    00596     /* XXX DB_INCOMPLETE is returned occaisionally with multiple access. */
    00597     _printit = (rc == DB_INCOMPLETE ? 0 : _debug);
    00598 #endif
    00599     rc = cvtdberr(dbi, "db->sync", rc, _printit);
    00600     return rc;
    00601 }
    00602
    00603 static int db3cdup(dbiIndex dbi, DBC * dbcursor, DBC ** dbcp,
    00604                 unsigned int flags)
    00605         /*@globals fileSystem @*/
    00606         /*@modifies *dbcp, fileSystem @*/
    00607 {
    00608     int rc;
    00609
    00610     if (dbcp) *dbcp = NULL;
    00611 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 6)
    00612     rc = dbcursor->dup(dbcursor, dbcp, flags);
    00613     rc = cvtdberr(dbi, "dbcursor->dup", rc, _debug);
    00614 #else
    00615     rc = dbcursor->c_dup(dbcursor, dbcp, flags);
    00616     rc = cvtdberr(dbi, "dbcursor->c_dup", rc, _debug);
    00617 #endif
    00618     /*@-nullstate @*/ /* FIX: *dbcp can be NULL */
    00619     return rc;
    00620     /*@=nullstate @*/
    00621 }
    00622
    00623 /*@-mustmod@*/
    00624 static int db3cclose(dbiIndex dbi, /*@only@*/ /*@null@*/ DBC * dbcursor,
    00625                 /*@unused@*/ unsigned int flags)
    00626         /*@globals fileSystem @*/
    00627         /*@modifies dbi, fileSystem @*/
    00628 {
    00629     int rc = -2;
    00630
    00631     /* XXX db3copen error pathways come through here. */
    00632     if (dbcursor != NULL) {
    00633 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 6)
    00634         rc = dbcursor->close(dbcursor);
    00635         rc = cvtdberr(dbi, "dbcursor->close", rc, _debug);
    00636 #else
    00637         rc = dbcursor->c_close(dbcursor);
    00638         rc = cvtdberr(dbi, "dbcursor->c_close", rc, _debug);
    00639 #endif
    00640     }
    00641     return rc;
    00642 }
    00643 /*@=mustmod@*/
    00644
    00645 static int db3copen(dbiIndex dbi, DB_TXN * txnid,
    00646                 /*@null@*/ /*@out@*/ DBC ** dbcp, unsigned int dbiflags)
    00647         /*@globals fileSystem @*/
    00648         /*@modifies dbi, *dbcp, fileSystem @*/
    00649 {
    00650     DB * db = dbi->dbi_db;
    00651     DBC * dbcursor = NULL;
    00652     int flags;
    00653     int rc;
    00654
    00655    /* XXX DB_WRITECURSOR cannot be used with sunrpc dbenv. */
    00656     assert(db != NULL);
    00657     if ((dbiflags & DB_WRITECURSOR) &&
    00658         (dbi->dbi_eflags & DB_INIT_CDB) && !(dbi->dbi_oflags & DB_RDONLY))
    00659     {
    00660         flags = DB_WRITECURSOR;
    00661     } else
    00662         flags = 0;
    00663
    00664     rc = db->cursor(db, txnid, &dbcursor, flags);
    00665     rc = cvtdberr(dbi, "db->cursor", rc, _debug);
    00666
    00667     if (dbcp)
    00668         *dbcp = dbcursor;
    00669     else
    00670         (void) db3cclose(dbi, dbcursor, 0);
    00671
    00672     return rc;
    00673 }
    00674
    00675 static int db3cput(dbiIndex dbi, DBC * dbcursor, DBT * key, DBT * data,
    00676                 /*@unused@*/ unsigned int flags)
    00677         /*@globals fileSystem @*/
    00678         /*@modifies fileSystem @*/
    00679 {
    00680     DB * db = dbi->dbi_db;
    00681     int rc;
    00682
    00683     assert(db != NULL);
    00684     if (dbcursor == NULL) {
    00685         rc = db->put(db, dbi->dbi_txnid, key, data, 0);
    00686         rc = cvtdberr(dbi, "db->put", rc, _debug);
    00687     } else {
    00688 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 6)
    00689         rc = dbcursor->put(dbcursor, key, data, DB_KEYLAST);
    00690         rc = cvtdberr(dbi, "dbcursor->put", rc, _debug);
    00691 #else
    00692         rc = dbcursor->c_put(dbcursor, key, data, DB_KEYLAST);
    00693         rc = cvtdberr(dbi, "dbcursor->c_put", rc, _debug);
    00694 #endif
    00695     }
    00696
    00697     return rc;
    00698 }
    00699
    00700 /*@-mustmod@*/
    00701 static int db3cdel(dbiIndex dbi, DBC * dbcursor, DBT * key, DBT * data,
    00702                 unsigned int flags)
    00703         /*@globals fileSystem @*/
    00704         /*@modifies *dbcursor, fileSystem @*/
    00705 {
    00706     DB * db = dbi->dbi_db;
    00707     int rc;
    00708
    00709     assert(db != NULL);
    00710     if (dbcursor == NULL) {
    00711         rc = db->del(db, dbi->dbi_txnid, key, flags);
    00712         rc = cvtdberr(dbi, "db->del", rc, _debug);
    00713     } else {
    00714         int _printit;
    00715
    00716         /* XXX TODO: insure that cursor is positioned with duplicates */
    00717 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 6)
    00718         rc = dbcursor->get(dbcursor, key, data, DB_SET);
    00719         /* XXX DB_NOTFOUND can be returned */
    00720         _printit = (rc == DB_NOTFOUND ? 0 : _debug);
    00721         rc = cvtdberr(dbi, "dbcursor->get", rc, _printit);
    00722 #else
    00723         rc = dbcursor->c_get(dbcursor, key, data, DB_SET);
    00724         /* XXX DB_NOTFOUND can be returned */
    00725         _printit = (rc == DB_NOTFOUND ? 0 : _debug);
    00726         rc = cvtdberr(dbi, "dbcursor->c_get", rc, _printit);
    00727 #endif
    00728
    00729         if (rc == 0) {
    00730 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 6)
    00731             rc = dbcursor->del(dbcursor, flags);
    00732             rc = cvtdberr(dbi, "dbcursor->del", rc, _debug);
    00733 #else
    00734             rc = dbcursor->c_del(dbcursor, flags);
    00735             rc = cvtdberr(dbi, "dbcursor->c_del", rc, _debug);
    00736 #endif
    00737         }
    00738     }
    00739
    00740     return rc;
    00741 }
    00742 /*@=mustmod@*/
    00743
    00744 /*@-mustmod@*/
    00745 static int db3cget(dbiIndex dbi, DBC * dbcursor, DBT * key, DBT * data,
    00746                 unsigned int flags)
    00747         /*@globals fileSystem @*/
    00748         /*@modifies *dbcursor, *key, *data, fileSystem @*/
    00749 {
    00750     DB * db = dbi->dbi_db;
    00751     int _printit;
    00752     int rc;
    00753
    00754     assert(db != NULL);
    00755     if (dbcursor == NULL) {
    00756         /* XXX duplicates require cursors. */
    00757         rc = db->get(db, dbi->dbi_txnid, key, data, 0);
    00758         /* XXX DB_NOTFOUND can be returned */
    00759         _printit = (rc == DB_NOTFOUND ? 0 : _debug);
    00760         rc = cvtdberr(dbi, "db->get", rc, _printit);
    00761     } else {
    00762 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 6)
    00763         /* XXX db3 does DB_FIRST on uninitialized cursor */
    00764         rc = dbcursor->get(dbcursor, key, data, flags);
    00765         /* XXX DB_NOTFOUND can be returned */
    00766         _printit = (rc == DB_NOTFOUND ? 0 : _debug);
    00767         rc = cvtdberr(dbi, "dbcursor->get", rc, _printit);
    00768 #else
    00769         /* XXX db3 does DB_FIRST on uninitialized cursor */
    00770         rc = dbcursor->c_get(dbcursor, key, data, flags);
    00771         /* XXX DB_NOTFOUND can be returned */
    00772         _printit = (rc == DB_NOTFOUND ? 0 : _debug);
    00773         rc = cvtdberr(dbi, "dbcursor->c_get", rc, _printit);
    00774 #endif
    00775     }
    00776
    00777     return rc;
    00778 }
    00779 /*@=mustmod@*/
    00780
    00781 /*@-mustmod@*/
    00782 static int db3cpget(dbiIndex dbi, DBC * dbcursor, DBT * key, DBT * pkey,
    00783                 DBT * data, unsigned int flags)
    00784         /*@globals fileSystem @*/
    00785         /*@modifies *dbcursor, *key, *data, fileSystem @*/
    00786 {
    00787     DB * db = dbi->dbi_db;
    00788     int _printit;
    00789     int rc;
    00790
    00791     assert(db != NULL);
    00792     assert(dbcursor != NULL);
    00793
    00794 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 6)
    00795     /* XXX db3 does DB_FIRST on uninitialized cursor */
    00796     rc = dbcursor->pget(dbcursor, key, pkey, data, flags);
    00797     /* XXX DB_NOTFOUND can be returned */
    00798     _printit = (rc == DB_NOTFOUND ? 0 : _debug);
    00799     rc = cvtdberr(dbi, "dbcursor->pget", rc, _printit);
    00800 #else
    00801     /* XXX db3 does DB_FIRST on uninitialized cursor */
    00802     rc = dbcursor->c_pget(dbcursor, key, pkey, data, flags);
    00803     /* XXX DB_NOTFOUND can be returned */
    00804     _printit = (rc == DB_NOTFOUND ? 0 : _debug);
    00805     rc = cvtdberr(dbi, "dbcursor->c_pget", rc, _printit);
    00806 #endif
    00807
    00808     return rc;
    00809 }
    00810 /*@=mustmod@*/
    00811
    00812 static int db3ccount(dbiIndex dbi, DBC * dbcursor,
    00813                 /*@null@*/ /*@out@*/ unsigned int * countp,
    00814                 /*@unused@*/ unsigned int flags)
    00815         /*@globals fileSystem @*/
    00816         /*@modifies *countp, fileSystem @*/
    00817 {
    00818     db_recno_t count = 0;
    00819     int rc = 0;
    00820
    00821     flags = 0;
    00822 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 6)
    00823     rc = dbcursor->count(dbcursor, &count, flags);
    00824     rc = cvtdberr(dbi, "dbcursor->count", rc, _debug);
    00825 #else
    00826     rc = dbcursor->c_count(dbcursor, &count, flags);
    00827     rc = cvtdberr(dbi, "dbcursor->c_count", rc, _debug);
    00828 #endif
    00829     if (rc) return rc;
    00830     if (countp) *countp = count;
    00831
    00832     return rc;
    00833 }
    00834
    00835 static int db3byteswapped(dbiIndex dbi) /*@*/
    00836 {
    00837     DB * db = dbi->dbi_db;
    00838     int rc = 0;
    00839
    00840     if (db != NULL) {
    00841 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3 && DB_VERSION_PATCH == 11) \
    00842  || (DB_VERSION_MAJOR == 4)
    00843         int isswapped = 0;
    00844         rc = db->get_byteswapped(db, &isswapped);
    00845         if (rc == 0)
    00846             rc = isswapped;
    00847 #else
    00848         rc = db->get_byteswapped(db);
    00849 #endif
    00850     }
    00851
    00852     return rc;
    00853 }
    00854
    00855 static int db3stat(dbiIndex dbi, unsigned int flags)
    00856         /*@globals fileSystem @*/
    00857         /*@modifies dbi, fileSystem @*/
    00858 {
    00859     DB * db = dbi->dbi_db;
    00860 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3)
    00861     DB_TXN * txnid = NULL;
    00862 #endif
    00863     int rc = 0;
    00864
    00865     assert(db != NULL);
    00866 #if defined(DB_FAST_STAT)
    00867     if (flags)
    00868         flags = DB_FAST_STAT;
    00869     else
    00870 #endif
    00871         flags = 0;
    00872     dbi->dbi_stats = _free(dbi->dbi_stats);
    00873 /* XXX 3.3.4 change. */
    00874 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3) || (DB_VERSION_MAJOR == 4)
    00875 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3)
    00876     rc = db->stat(db, txnid, &dbi->dbi_stats, flags);
    00877 #else
    00878     rc = db->stat(db, &dbi->dbi_stats, flags);
    00879 #endif
    00880 #else
    00881     rc = db->stat(db, &dbi->dbi_stats, NULL, flags);
    00882 #endif
    00883     rc = cvtdberr(dbi, "db->stat", rc, _debug);
    00884     return rc;
    00885 }
    00886
    00887 /*@-mustmod@*/
    00888 static int db3associate(dbiIndex dbi, dbiIndex dbisecondary,
    00889                 int (*callback)(DB *, const DBT *, const DBT *, DBT *),
    00890                 unsigned int flags)
    00891         /*@globals fileSystem @*/
    00892         /*@modifies dbi, fileSystem @*/
    00893 {
    00894     DB * db = dbi->dbi_db;
    00895     DB * secondary = dbisecondary->dbi_db;
    00896     int rc;
    00897
    00898 /*@-moduncon@*/ /* FIX: annotate db3 methods */
    00899 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
    00900     DB_TXN * txnid = NULL;
    00901
    00902 assert(db != NULL);
    00903     rc = db->associate(db, txnid, secondary, callback, flags);
    00904 #else
    00905 assert(db != NULL);
    00906     rc = db->associate(db, secondary, callback, flags);
    00907 #endif
    00908 /*@=moduncon@*/
    00909     rc = cvtdberr(dbi, "db->associate", rc, _debug);
    00910     return rc;
    00911 }
    00912 /*@=mustmod@*/
    00913
    00914 /*@-mustmod@*/
    00915 static int db3join(dbiIndex dbi, DBC ** curslist, DBC ** dbcp,
    00916                 unsigned int flags)
    00917         /*@globals fileSystem @*/
    00918         /*@modifies dbi, fileSystem @*/
    00919 {
    00920     DB * db = dbi->dbi_db;
    00921     int rc;
    00922
    00923 assert(db != NULL);
    00924 /*@-moduncon@*/ /* FIX: annotate db3 methods */
    00925     rc = db->join(db, curslist, dbcp, flags);
    00926 /*@=moduncon@*/
    00927     rc = cvtdberr(dbi, "db->join", rc, _debug);
    00928     return rc;
    00929 }
    00930 /*@=mustmod@*/
    00931
    00932 /*@-moduncon@*/ /* FIX: annotate db3 methods */
    00933 static int db3close(/*@only@*/ dbiIndex dbi, /*@unused@*/ unsigned int flags)
    00934         /*@globals rpmGlobalMacroContext, h_errno,
    00935                 fileSystem @*/
    00936         /*@modifies dbi, fileSystem @*/
    00937 {
    00938     rpmdb rpmdb = dbi->dbi_rpmdb;
    00939     const char * urlfn = NULL;
    00940     const char * root;
    00941     const char * home;
    00942     const char * dbhome;
    00943     const char * dbfile;
    00944     const char * dbsubfile;
    00945     DB * db = dbi->dbi_db;
    00946     const char * dbiBN = mapTagName(rpmdb, dbi);
    00947     int _printit;
    00948     int rc = 0, xx;
    00949
    00950     flags = 0;  /* XXX unused */
    00951
    00952     /*
    00953      * Get the prefix/root component and directory path.
    00954      */
    00955     root = (dbi->dbi_root ? dbi->dbi_root : rpmdb->db_root);
    00956     if ((root[0] == '/' && root[1] == '\0') || rpmdb->db_chrootDone)
    00957         root = NULL;
    00958     home = (dbi->dbi_home ? dbi->dbi_home : rpmdb->db_home);
    00959
    00960     /*
    00961      * Either the root or directory components may be a URL. Concatenate,
    00962      * convert the URL to a path, and add the name of the file.
    00963      */
    00964     /*@-mods@*/
    00965     urlfn = rpmGenPath(root, home, NULL);
    00966     /*@=mods@*/
    00967     (void) urlPath(urlfn, &dbhome);
    00968     if (dbi->dbi_temporary) {
    00969         dbfile = NULL;
    00970         dbsubfile = NULL;
    00971     } else {
    00972 #ifdef  HACK    /* XXX necessary to support dbsubfile */
    00973         dbfile = (dbi->dbi_file ? dbi->dbi_file : db3basename);
    00974         dbsubfile = (dbi->dbi_subfile ? dbi->dbi_subfile : dbiBN);
    00975 #else
    00976         dbfile = (dbi->dbi_file ? dbi->dbi_file : dbiBN);
    00977         dbsubfile = NULL;
    00978 #endif
    00979     }
    00980
    00981     if (db) {
    00982         rc = db->close(db, 0);
    00983         /* XXX ignore not found error messages. */
    00984         _printit = (rc == ENOENT ? 0 : _debug);
    00985         rc = cvtdberr(dbi, "db->close", rc, _printit);
    00986         db = dbi->dbi_db = NULL;
    00987
    00988         rpmlog(RPMLOG_DEBUG, D_("closed   db index       %s/%s\n"),
    00989                 dbhome, (dbfile ? dbfile : dbiBN));
    00990
    00991     }
    00992
    00993     if (rpmdb->db_dbenv != NULL && dbi->dbi_use_dbenv) {
    00994         if (rpmdb->db_opens == 1) {
    00995             /*@-nullstate@*/
    00996             xx = db_fini(dbi, (dbhome ? dbhome : ""), dbfile, dbsubfile);
    00997             /*@=nullstate@*/
    00998             rpmdb->db_dbenv = NULL;
    00999         }
    01000         rpmdb->db_opens--;
    01001     }
    01002
    01003     if (dbi->dbi_verify_on_close && !dbi->dbi_temporary) {
    01004         DB_ENV * dbenv = NULL;
    01005         int eflags;
    01006
    01007         /*@-moduncon@*/ /* FIX: annotate db3 methods */
    01008         rc = db_env_create(&dbenv, 0);
    01009         /*@=moduncon@*/
    01010         rc = cvtdberr(dbi, "db_env_create", rc, _debug);
    01011         if (rc || dbenv == NULL) goto exit;
    01012
    01013         /*@-noeffectuncon@*/ /* FIX: annotate db3 methods */
    01014 /*@-castfcnptr@*/
    01015         dbenv->set_errcall(dbenv, (void *)rpmdb->db_errcall);
    01016 /*@=castfcnptr@*/
    01017         dbenv->set_errfile(dbenv, rpmdb->db_errfile);
    01018         dbenv->set_errpfx(dbenv, rpmdb->db_errpfx);
    01019  /*     dbenv->set_paniccall(???) */
    01020         /*@=noeffectuncon@*/
    01021 #if !(DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3)
    01022         xx = dbenv->set_verbose(dbenv, DB_VERB_CHKPOINT,
    01023                 (dbi->dbi_verbose & DB_VERB_CHKPOINT));
    01024 #endif
    01025         xx = dbenv->set_verbose(dbenv, DB_VERB_DEADLOCK,
    01026                 (dbi->dbi_verbose & DB_VERB_DEADLOCK));
    01027         xx = dbenv->set_verbose(dbenv, DB_VERB_RECOVERY,
    01028                 (dbi->dbi_verbose & DB_VERB_RECOVERY));
    01029         xx = dbenv->set_verbose(dbenv, DB_VERB_WAITSFOR,
    01030                 (dbi->dbi_verbose & DB_VERB_WAITSFOR));
    01031
    01032         if (dbi->dbi_tmpdir) {
    01033             /*@-mods@*/
    01034             const char * tmpdir = rpmGenPath(root, dbi->dbi_tmpdir, NULL);
    01035             /*@=mods@*/
    01036             rc = dbenv->set_tmp_dir(dbenv, tmpdir);
    01037             rc = cvtdberr(dbi, "dbenv->set_tmp_dir", rc, _debug);
    01038             tmpdir = _free(tmpdir);
    01039             if (rc) goto exit;
    01040         }
    01041
    01042         eflags = DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE | DB_USE_ENVIRON;
    01043         rc = (dbenv->open)(dbenv, dbhome, eflags, 0);
    01044         rc = cvtdberr(dbi, "dbenv->open", rc, _debug);
    01045         if (rc) goto exit;
    01046
    01047         /*@-moduncon -nullstate@*/ /* FIX: annotate db3 methods */
    01048         rc = db_create(&db, dbenv, 0);
    01049         /*@=moduncon =nullstate@*/
    01050         rc = cvtdberr(dbi, "db_create", rc, _debug);
    01051
    01052         if (db != NULL) {
    01053                 /*@-mods@*/
    01054                 const char * dbf = rpmGetPath(dbhome, "/", dbfile, NULL);
    01055                 /*@=mods@*/
    01056
    01057                 rc = db->verify(db, dbf, NULL, NULL, flags);
    01058                 rc = cvtdberr(dbi, "db->verify", rc, _debug);
    01059
    01060                 rpmlog(RPMLOG_DEBUG, D_("verified db index       %s/%s\n"),
    01061                         (dbhome ? dbhome : ""),
    01062                         (dbfile ? dbfile : dbiBN));
    01063
    01064                 /*
    01065                  * The DB handle may not be accessed again after
    01066                  * DB->verify is called, regardless of its return.
    01067                  */
    01068                 db = NULL;
    01069                 dbf = _free(dbf);
    01070         }
    01071         xx = dbenv->close(dbenv, 0);
    01072         xx = cvtdberr(dbi, "dbenv->close", xx, _debug);
    01073         if (rc == 0 && xx) rc = xx;
    01074     }
    01075
    01076 exit:
    01077     dbi->dbi_db = NULL;
    01078
    01079     urlfn = _free(urlfn);
    01080
    01081     dbi = db3Free(dbi);
    01082
    01083     return rc;
    01084 }
    01085 /*@=moduncon@*/
    01086
    01087 static int db3open(rpmdb rpmdb, rpmTag rpmtag, dbiIndex * dbip)
    01088         /*@globals rpmGlobalMacroContext, h_errno,
    01089                 fileSystem, internalState @*/
    01090         /*@modifies *dbip, fileSystem, internalState @*/
    01091 {
    01092     /*@-nestedextern -shadow@*/
    01093     extern struct _dbiVec db3vec;
    01094     /*@=nestedextern =shadow@*/
    01095     const char * urlfn = NULL;
    01096     const char * root;
    01097     const char * home;
    01098     const char * dbhome;
    01099     const char * dbfile;
    01100     const char * dbsubfile;
    01101     const char * dbiBN;
    01102     dbiIndex dbi = NULL;
    01103     int rc = 0;
    01104     int xx;
    01105
    01106     DB * db = NULL;
    01107     DB_ENV * dbenv = NULL;
    01108 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
    01109     DB_TXN * txnid = NULL;
    01110 #endif
    01111     DBTYPE dbi_type = DB_UNKNOWN;
    01112     uint32_t oflags;
    01113     int _printit;
    01114
    01115     if (dbip)
    01116         *dbip = NULL;
    01117
    01118     /*
    01119      * Parse db configuration parameters.
    01120      */
    01121     /*@-mods@*/
    01122     if ((dbi = db3New(rpmdb, rpmtag)) == NULL)
    01123         /*@-nullstate@*/
    01124         return 1;
    01125         /*@=nullstate@*/
    01126     /*@=mods@*/
    01127     dbi->dbi_api = DB_VERSION_MAJOR;
    01128     dbiBN = mapTagName(rpmdb, dbi);
    01129
    01130     /*
    01131      * Get the prefix/root component and directory path.
    01132      */
    01133     root = (dbi->dbi_root ? dbi->dbi_root : rpmdb->db_root);
    01134     if ((root[0] == '/' && root[1] == '\0') || rpmdb->db_chrootDone)
    01135         root = NULL;
    01136     home = (dbi->dbi_home ? dbi->dbi_home : rpmdb->db_home);
    01137
    01138     /*
    01139      * Either the root or directory components may be a URL. Concatenate,
    01140      * convert the URL to a path, and add the name of the file.
    01141      */
    01142     /*@-mods@*/
    01143     urlfn = rpmGenPath(root, home, NULL);
    01144     /*@=mods@*/
    01145     (void) urlPath(urlfn, &dbhome);
    01146     if (dbi->dbi_temporary) {
    01147         dbfile = NULL;
    01148         dbsubfile = NULL;
    01149     } else {
    01150 #ifdef  HACK    /* XXX necessary to support dbsubfile */
    01151         dbfile = (dbi->dbi_file ? dbi->dbi_file : db3basename);
    01152         dbsubfile = (dbi->dbi_subfile ? dbi->dbi_subfile : dbiBN);
    01153 #else
    01154         dbfile = (dbi->dbi_file ? dbi->dbi_file : dbiBN);
    01155         dbsubfile = NULL;
    01156 #endif
    01157     }
    01158
    01159     oflags = (dbi->dbi_oeflags | dbi->dbi_oflags);
    01160     oflags &= ~DB_TRUNCATE;     /* XXX this is dangerous */
    01161
    01162 #if 0   /* XXX rpmdb: illegal flag combination specified to DB->open */
    01163     if ( dbi->dbi_mode & O_EXCL) oflags |= DB_EXCL;
    01164 #endif
    01165
    01166     /*
    01167      * Map open mode flags onto configured database/environment flags.
    01168      */
    01169     if (dbi->dbi_temporary) {
    01170         oflags |= DB_CREATE;
    01171         dbi->dbi_oeflags |= DB_CREATE;
    01172         oflags &= ~DB_RDONLY;
    01173         dbi->dbi_oflags &= ~DB_RDONLY;
    01174     } else {
    01175         if (!(dbi->dbi_mode & (O_RDWR|O_WRONLY))) oflags |= DB_RDONLY;
    01176         if (dbi->dbi_mode & O_CREAT) {
    01177             oflags |= DB_CREATE;
    01178             dbi->dbi_oeflags |= DB_CREATE;
    01179         }
    01180 #ifdef  DANGEROUS
    01181         if ( dbi->dbi_mode & O_TRUNC) oflags |= DB_TRUNCATE;
    01182 #endif
    01183     }
    01184
    01185     /*
    01186      * Create the /var/lib/rpm directory if it doesn't exist (root only).
    01187      */
    01188     (void) rpmioMkpath(dbhome, 0755, getuid(), getgid());
    01189
    01190     /*
    01191      * Avoid incompatible DB_CREATE/DB_RDONLY flags on DBENV->open.
    01192      */
    01193     if (dbi->dbi_use_dbenv) {
    01194
    01195         if (access(dbhome, W_OK) == -1) {
    01196
    01197             /* dbhome is unwritable, don't attempt DB_CREATE on DB->open ... */
    01198             oflags &= ~DB_CREATE;
    01199
    01200             /* ... but DBENV->open might still need DB_CREATE ... */
    01201             if (dbi->dbi_eflags & DB_PRIVATE) {
    01202                 dbi->dbi_eflags &= ~DB_JOINENV;
    01203             } else {
    01204                 dbi->dbi_eflags |= DB_JOINENV;
    01205                 dbi->dbi_oeflags &= ~DB_CREATE;
    01206                 dbi->dbi_oeflags &= ~DB_THREAD;
    01207                 /* ... but, unless DB_PRIVATE is used, skip DBENV. */
    01208                 dbi->dbi_use_dbenv = 0;
    01209             }
    01210
    01211             /* ... DB_RDONLY maps dbhome perms across files ...  */
    01212             if (dbi->dbi_temporary) {
    01213                 oflags |= DB_CREATE;
    01214                 dbi->dbi_oeflags |= DB_CREATE;
    01215                 oflags &= ~DB_RDONLY;
    01216                 dbi->dbi_oflags &= ~DB_RDONLY;
    01217             } else {
    01218                 oflags |= DB_RDONLY;
    01219                 /* ... and DB_WRITECURSOR won't be needed ...  */
    01220                 dbi->dbi_oflags |= DB_RDONLY;
    01221             }
    01222
    01223         } else {        /* dbhome is writable, check for persistent dbenv. */
    01224             /*@-mods@*/
    01225             const char * dbf = rpmGetPath(dbhome, "/__db.001", NULL);
    01226             /*@=mods@*/
    01227
    01228 #if defined(RPM_VENDOR_OPENPKG) /* bdb-allow-zero-sized-files */
    01229             /* Make sure RPM passes DB_CREATE to Berkeley-DB also
    01230                if file exists, but is (still) zero-sized. */
    01231             struct stat sb;
    01232             long size = -1;
    01233             if (stat(dbf, &sb) == 0)
    01234                 size = (long)sb.st_size;
    01235             if (access(dbf, F_OK) == -1 || size == 0) {
    01236 #else
    01237             if (access(dbf, F_OK) == -1) {
    01238 #endif
    01239                 /* ... non-existent (or unwritable) DBENV, will create ... */
    01240                 dbi->dbi_oeflags |= DB_CREATE;
    01241                 dbi->dbi_eflags &= ~DB_JOINENV;
    01242             } else {
    01243                 /* ... pre-existent (or bogus) DBENV, will join ... */
    01244                 if (dbi->dbi_eflags & DB_PRIVATE) {
    01245                     dbi->dbi_eflags &= ~DB_JOINENV;
    01246                 } else {
    01247                     dbi->dbi_eflags |= DB_JOINENV;
    01248                     dbi->dbi_oeflags &= ~DB_CREATE;
    01249                     dbi->dbi_oeflags &= ~DB_THREAD;
    01250                 }
    01251             }
    01252             dbf = _free(dbf);
    01253         }
    01254     }
    01255
    01256     /*
    01257      * Avoid incompatible DB_CREATE/DB_RDONLY flags on DB->open.
    01258      */
    01259     if ((oflags & DB_CREATE) && (oflags & DB_RDONLY)) {
    01260         /* dbhome is writable, and DB->open flags may conflict. */
    01261         const char * dbfn = (dbfile ? dbfile : dbiBN);
    01262         /*@-mods@*/
    01263         const char * dbf = rpmGetPath(dbhome, "/", dbfn, NULL);
    01264         /*@=mods@*/
    01265
    01266         if (access(dbf, F_OK) == -1) {
    01267             /* File does not exist, DB->open might create ... */
    01268             oflags &= ~DB_RDONLY;
    01269         } else {
    01270             /* File exists, DB->open need not create ... */
    01271             oflags &= ~DB_CREATE;
    01272         }
    01273
    01274         /* Only writers need DB_WRITECURSOR ... */
    01275         if (!(oflags & DB_RDONLY) && access(dbf, W_OK) == 0) {
    01276             dbi->dbi_oflags &= ~DB_RDONLY;
    01277         } else {
    01278             dbi->dbi_oflags |= DB_RDONLY;
    01279         }
    01280         dbf = _free(dbf);
    01281     }
    01282
    01283     /*
    01284      * Set db type if creating.
    01285      */
    01286     if (oflags & DB_CREATE)
    01287         dbi_type = dbi->dbi_type;
    01288
    01289     /*
    01290      * Turn off verify-on-close if opening read-only.
    01291      */
    01292     if (oflags & DB_RDONLY)
    01293         dbi->dbi_verify_on_close = 0;
    01294
    01295     if (dbi->dbi_use_dbenv) {
    01296         /*@-mods@*/
    01297         if (rpmdb->db_dbenv == NULL) {
    01298             rc = db_init(dbi, dbhome, dbfile, dbsubfile, &dbenv);
    01299             switch (rc) {
    01300             default:
    01301                 break;
    01302
    01303             case DB_RUNRECOVERY:
    01304                 rpmlog(RPMLOG_ERR, _("Runnning db->verify ...\n"));
    01305                 rpmdb = rpmdbLink(rpmdb, "DB_RUNRECOVERY");
    01306                 rpmdb->db_remove_env = 1;
    01307                 rpmdb->db_verifying = 1;
    01308                 xx = rpmdbVerifyAllDBI(rpmdb);
    01309                 xx = cvtdberr(dbi, "db->verify", xx, _debug);
    01310                 rpmdb->db_remove_env = 0;
    01311                 rpmdb->db_verifying = 0;
    01312
    01313                 dbi->dbi_oeflags |= DB_CREATE;
    01314                 dbi->dbi_eflags &= ~DB_JOINENV;
    01315                 rc = db_init(dbi, dbhome, dbfile, dbsubfile, &dbenv);
    01316                 /* XXX db_init EINVAL was masked. */
    01317                 rc = cvtdberr(dbi, "dbenv->open", rc, _debug);
    01318                 if (rc)
    01319                     break;
    01320
    01321 assert(dbenv);
    01322                 rpmdb->db_dbenv = dbenv;
    01323                 rpmdb->db_opens = 1;
    01324                 break;
    01325
    01326 #if defined(DB_VERSION_MISMATCH) /* Nuke __db* files and retry open once. */
    01327             case DB_VERSION_MISMATCH:
    01328 #endif
    01329             case EINVAL:
    01330                 if (getuid() != 0)
    01331                     break;
    01332                 {   char * filename = alloca(BUFSIZ);
    01333                     struct stat st;
    01334                     int i;
    01335
    01336                     for (i = 0; i < 16; i++) {
    01337                         sprintf(filename, "%s/__db.%03d", dbhome, i);
    01338                         (void)rpmCleanPath(filename);
    01339                         if (Stat(filename, &st)
    01340                           && (errno == ENOENT || errno == EINVAL))
    01341                             continue;
    01342                         xx = Unlink(filename);
    01343                     }
    01344                 }
    01345                 dbi->dbi_oeflags |= DB_CREATE;
    01346                 dbi->dbi_eflags &= ~DB_JOINENV;
    01347                 rc = db_init(dbi, dbhome, dbfile, dbsubfile, &dbenv);
    01348                 /* XXX db_init EINVAL was masked. */
    01349                 rc = cvtdberr(dbi, "dbenv->open", rc, _debug);
    01350                 if (rc)
    01351                     break;
    01352                 /*@fallthrough@*/
    01353             case 0:
    01354 assert(dbenv);
    01355                 rpmdb->db_dbenv = dbenv;
    01356                 rpmdb->db_opens = 1;
    01357                 break;
    01358             }
    01359         } else {
    01360 assert(rpmdb && rpmdb->db_dbenv);
    01361             dbenv = rpmdb->db_dbenv;
    01362 #define PLD_CHROOT
    01363 #ifdef  PLD_CHROOT
    01364             if (rpmdb->db_chrootDone)
    01365                 xx = dbenv->set_data_dir(dbenv, dbhome);
    01366 #endif
    01367             rpmdb->db_opens++;
    01368         }
    01369         /*@=mods@*/
    01370     }
    01371
    01372     rpmlog(RPMLOG_DEBUG, D_("opening  db index       %s/%s %s mode=0x%x\n"),
    01373                 dbhome, (dbfile ? dbfile : dbiBN),
    01374                 prDbiOpenFlags(oflags, 0), dbi->dbi_mode);
    01375
    01376     if (rc == 0) {
    01377         static int _lockdbfd = 0;
    01378
    01379         /*@-moduncon@*/ /* FIX: annotate db3 methods */
    01380         rc = db_create(&db, dbenv, dbi->dbi_cflags);
    01381         /*@=moduncon@*/
    01382         rc = cvtdberr(dbi, "db_create", rc, _debug);
    01383         if (rc == 0 && db != NULL) {
    01384
    01385 /* XXX 3.3.4 change. */
    01386 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3) || (DB_VERSION_MAJOR == 4)
    01387             if (rc == 0 &&
    01388                         rpmdb->db_malloc && rpmdb->db_realloc && rpmdb->db_free)
    01389             {
    01390                 rc = db->set_alloc(db,
    01391                         rpmdb->db_malloc, rpmdb->db_realloc, rpmdb->db_free);
    01392                 rc = cvtdberr(dbi, "db->set_alloc", rc, _debug);
    01393             }
    01394 #else
    01395             if (rc == 0 && rpmdb->db_malloc) {
    01396                 rc = db->set_malloc(db, rpmdb->db_malloc);
    01397                 rc = cvtdberr(dbi, "db->set_malloc", rc, _debug);
    01398             }
    01399 #endif
    01400
    01401 /* 4.1: db->set_cache_priority(???) */
    01402             if (rc == 0 && !dbi->dbi_use_dbenv && dbi->dbi_cachesize) {
    01403                 rc = db->set_cachesize(db, 0, dbi->dbi_cachesize, 0);
    01404                 rc = cvtdberr(dbi, "db->set_cachesize", rc, _debug);
    01405             }
    01406 /* 4.1: db->set_encrypt(???) */
    01407 /* 4.1: db->set_errcall(dbenv, rpmdb->db_errcall); */
    01408 /* 4.1: db->set_errfile(dbenv, rpmdb->db_errfile); */
    01409 /* 4.1: db->set_errpfx(dbenv, rpmdb->db_errpfx); */
    01410  /* 4.1: db->set_feedback(???) */
    01411
    01412             if (rc == 0 && dbi->dbi_lorder) {
    01413                 rc = db->set_lorder(db, dbi->dbi_lorder);
    01414                 rc = cvtdberr(dbi, "db->set_lorder", rc, _debug);
    01415             }
    01416             if (rc == 0 && dbi->dbi_pagesize) {
    01417                 rc = db->set_pagesize(db, dbi->dbi_pagesize);
    01418                 rc = cvtdberr(dbi, "db->set_pagesize", rc, _debug);
    01419             }
    01420  /* 4.1: db->set_paniccall(???) */
    01421             if (rc == 0 && oflags & DB_CREATE) {
    01422                 switch(dbi->dbi_type) {
    01423                 default:
    01424                 case DB_HASH:
    01425                     if (dbi->dbi_h_ffactor) {
    01426                         rc = db->set_h_ffactor(db, dbi->dbi_h_ffactor);
    01427                         rc = cvtdberr(dbi, "db->set_h_ffactor", rc, _debug);
    01428                         if (rc) break;
    01429                     }
    01430                     if (dbi->dbi_h_nelem) {
    01431                         rc = db->set_h_nelem(db, dbi->dbi_h_nelem);
    01432                         rc = cvtdberr(dbi, "db->set_h_nelem", rc, _debug);
    01433                         if (rc) break;
    01434                     }
    01435                     if (dbi->dbi_h_flags) {
    01436                         rc = db->set_flags(db, dbi->dbi_h_flags);
    01437                         rc = cvtdberr(dbi, "db->set_h_flags", rc, _debug);
    01438                         if (rc) break;
    01439                     }
    01440 /* XXX db-3.2.9 has added a DB arg to the call. */
    01441 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 2) || (DB_VERSION_MAJOR == 4)
    01442                     if (dbi->dbi_h_hash_fcn) {
    01443                         rc = db->set_h_hash(db, dbi->dbi_h_hash_fcn);
    01444                         rc = cvtdberr(dbi, "db->set_h_hash", rc, _debug);
    01445                         if (rc) break;
    01446                     }
    01447                     if (dbi->dbi_h_dup_compare_fcn) {
    01448                         rc = db->set_dup_compare(db, dbi->dbi_h_dup_compare_fcn);
    01449                         rc = cvtdberr(dbi, "db->set_dup_compare", rc, _debug);
    01450                         if (rc) break;
    01451                     }
    01452 #endif
    01453                     break;
    01454                 case DB_BTREE:
    01455 /* 4.1: db->set_append_recno(???) */
    01456                     if (dbi->dbi_bt_flags) {
    01457                         rc = db->set_flags(db, dbi->dbi_bt_flags);
    01458                         rc = cvtdberr(dbi, "db->set_bt_flags", rc, _debug);
    01459                         if (rc) break;
    01460                     }
    01461                     if (dbi->dbi_bt_minkey) {
    01462                         rc = db->set_bt_minkey(db, dbi->dbi_bt_minkey);
    01463                         rc = cvtdberr(dbi, "db->set_bt_minkey", rc, _debug);
    01464                         if (rc) break;
    01465                     }
    01466 /* XXX db-3.2.9 has added a DB arg to the call. */
    01467 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 2) || (DB_VERSION_MAJOR == 4)
    01468                     if (dbi->dbi_bt_compare_fcn) {
    01469                         rc = db->set_bt_compare(db, dbi->dbi_bt_compare_fcn);
    01470                         rc = cvtdberr(dbi, "db->set_bt_compare", rc, _debug);
    01471                         if (rc) break;
    01472                     }
    01473                     if (dbi->dbi_bt_dup_compare_fcn) {
    01474                         rc = db->set_dup_compare(db, dbi->dbi_bt_dup_compare_fcn);
    01475                         rc = cvtdberr(dbi, "db->set_dup_compare", rc, _debug);
    01476                         if (rc) break;
    01477                     }
    01478                     if (dbi->dbi_bt_prefix_fcn) {
    01479                         rc = db->set_bt_prefix(db, dbi->dbi_bt_prefix_fcn);
    01480                         rc = cvtdberr(dbi, "db->set_bt_prefix", rc, _debug);
    01481                         if (rc) break;
    01482                     }
    01483 #endif
    01484                     break;
    01485                 case DB_RECNO:
    01486                     if (dbi->dbi_re_delim) {
    01487 /* 4.1: db->set_append_recno(???) */
    01488                         rc = db->set_re_delim(db, dbi->dbi_re_delim);
    01489                         rc = cvtdberr(dbi, "db->set_re_selim", rc, _debug);
    01490                         if (rc) break;
    01491                     }
    01492                     if (dbi->dbi_re_len) {
    01493                         rc = db->set_re_len(db, dbi->dbi_re_len);
    01494                         rc = cvtdberr(dbi, "db->set_re_len", rc, _debug);
    01495                         if (rc) break;
    01496                     }
    01497                     if (dbi->dbi_re_pad) {
    01498                         rc = db->set_re_pad(db, dbi->dbi_re_pad);
    01499                         rc = cvtdberr(dbi, "db->set_re_pad", rc, _debug);
    01500                         if (rc) break;
    01501                     }
    01502                     if (dbi->dbi_re_source) {
    01503                         rc = db->set_re_source(db, dbi->dbi_re_source);
    01504                         rc = cvtdberr(dbi, "db->set_re_source", rc, _debug);
    01505                         if (rc) break;
    01506                     }
    01507                     break;
    01508                 case DB_QUEUE:
    01509                     if (dbi->dbi_q_extentsize) {
    01510                         rc = db->set_q_extentsize(db, dbi->dbi_q_extentsize);
    01511                         rc = cvtdberr(dbi, "db->set_q_extentsize", rc, _debug);
    01512                         if (rc) break;
    01513                     }
    01514                     break;
    01515                 }
    01516             }
    01517
    01518             if (rc == 0) {
    01519                 const char * dbfullpath;
    01520                 const char * dbpath;
    01521                 char * t;
    01522                 int nb;
    01523
    01524                 nb = strlen(dbhome);
    01525                 if (dbfile)     nb += 1 + strlen(dbfile);
    01526                 dbfullpath = t = alloca(nb + 1);
    01527
    01528                 t = stpcpy(t, dbhome);
    01529                 if (dbfile)
    01530                     t = stpcpy( stpcpy( t, "/"), dbfile);
    01531 #ifdef  HACK    /* XXX necessary to support dbsubfile */
    01532                 dbpath = (!dbi->dbi_use_dbenv && !dbi->dbi_temporary)
    01533                         ? dbfullpath : dbfile;
    01534 #else
    01535 #ifdef  PLD_CHROOT
    01536                 /* XXX Make dbpath relative. */
    01537                 dbpath = (!dbi->dbi_use_dbenv)
    01538                         ? dbfullpath : dbfile;
    01539 #else
    01540                 dbpath = (!dbi->dbi_temporary)
    01541                         ? dbfullpath : dbfile;
    01542 #endif  /* PLD_CHROOT */
    01543 #endif  /* HACK */
    01544
    01545 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
    01546                 rc = (db->open)(db, txnid, dbpath, dbsubfile,
    01547                     dbi_type, oflags, dbi->dbi_perms);
    01548 #else
    01549                 rc = (db->open)(db, dbpath, dbsubfile,
    01550                     dbi_type, oflags, dbi->dbi_perms);
    01551 #endif
    01552
    01553                 if (rc == 0 && dbi_type == DB_UNKNOWN) {
    01554 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3 && DB_VERSION_PATCH == 11) \
    01555  || (DB_VERSION_MAJOR == 4)
    01556                     xx = db->get_type(db, &dbi_type);
    01557                     if (xx == 0)
    01558                         dbi->dbi_type = dbi_type;
    01559 #else
    01560                     dbi->dbi_type = db->get_type(db);
    01561 #endif
    01562                 }
    01563             }
    01564
    01565             /* XXX return rc == errno without printing */
    01566             _printit = (rc > 0 ? 0 : _debug);
    01567             xx = cvtdberr(dbi, "db->open", rc, _printit);
    01568
    01569             dbi->dbi_txnid = NULL;
    01570
    01571             /*
    01572              * Lock a file using fcntl(2). Traditionally this is Packages,
    01573              * the file used to store metadata of installed header(s),
    01574              * as Packages is always opened, and should be opened first,
    01575              * for any rpmdb access.
    01576              *
    01577              * If no DBENV is used, then access is protected with a
    01578              * shared/exclusive locking scheme, as always.
    01579              *
    01580              * With a DBENV, the fcntl(2) lock is necessary only to keep
    01581              * the riff-raff from playing where they don't belong, as
    01582              * the DBENV should provide it's own locking scheme. So try to
    01583              * acquire a lock, but permit failures, as some other
    01584              * DBENV player may already have acquired the lock.
    01585              *
    01586              * With NPTL posix mutexes, revert to fcntl lock on non-functioning
    01587              * glibc/kernel combinations.
    01588              */
    01589             if (rc == 0 && dbi->dbi_lockdbfd &&
    01590                 !((dbi->dbi_ecflags & DB_CLIENT) && dbi->dbi_host) &&
    01591                 (!dbi->dbi_use_dbenv || _lockdbfd++ == 0))
    01592             {
    01593                 int fdno = -1;
    01594
    01595                 if (!(db->fd(db, &fdno) == 0 && fdno >= 0)) {
    01596                     rc = 1;
    01597                 } else {
    01598                     struct flock l;
    01599                     memset(&l, 0, sizeof(l));
    01600                     l.l_whence = 0;
    01601                     l.l_start = 0;
    01602                     l.l_len = 0;
    01603                     l.l_type = (dbi->dbi_mode & (O_RDWR|O_WRONLY))
    01604                                 ? F_WRLCK : F_RDLCK;
    01605                     l.l_pid = 0;
    01606
    01607                     rc = fcntl(fdno, F_SETLK, (void *) &l);
    01608                     if (rc) {
    01609                         /* Warning iff using non-private CDB locking. */
    01610                         rc = ((dbi->dbi_use_dbenv &&
    01611                                 (dbi->dbi_eflags & DB_INIT_CDB) &&
    01612                                 !(dbi->dbi_eflags & DB_PRIVATE))
    01613                             ? 0 : 1);
    01614                         rpmlog( (rc ? RPMLOG_ERR : RPMLOG_WARNING),
    01615                                 _("cannot get %s lock on %s/%s\n"),
    01616                                 ((dbi->dbi_mode & (O_RDWR|O_WRONLY))
    01617                                         ? _("exclusive") : _("shared")),
    01618                                 dbhome, (dbfile ? dbfile : ""));
    01619                     } else if (dbfile) {
    01620                         rpmlog(RPMLOG_DEBUG,
    01621                                 D_("locked   db index       %s/%s\n"),
    01622                                 dbhome, dbfile);
    01623                     }
    01624                 }
    01625             }
    01626         }
    01627     }
    01628
    01629     dbi->dbi_db = db;
    01630
    01631     if (rc == 0 && dbi->dbi_db != NULL && dbip != NULL) {
    01632         dbi->dbi_vec = &db3vec;
    01633         *dbip = dbi;
    01634     } else {
    01635         dbi->dbi_verify_on_close = 0;
    01636         (void) db3close(dbi, 0);
    01637     }
    01638
    01639     urlfn = _free(urlfn);
    01640
    01641     /*@-nullstate -compmempass@*/
    01642     return rc;
    01643     /*@=nullstate =compmempass@*/
    01644 }
    01645
    01648 /*@-exportheadervar@*/
    01649 /*@observer@*/ /*@unchecked@*/
    01650 struct _dbiVec db3vec = {
    01651     DB_VERSION_MAJOR, DB_VERSION_MINOR, DB_VERSION_PATCH,
    01652     db3open, db3close, db3sync, db3associate, db3join,
    01653     db3copen, db3cclose, db3cdup, db3cdel, db3cget, db3cpget, db3cput, db3ccount,
    01654     db3byteswapped, db3stat
    01655 };
    01656 /*@=exportheadervar@*/
    01657 /*@=type@*/