rpm 5.2.1

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

- File List
- Globals

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