• 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 <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@*/

Generated on Mon Nov 29 2010 05:18:46 for rpm by  doxygen 1.7.2