Main Page | Modules | Data Structures | File List | Data Fields | Globals | Related Pages

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

Generated on Wed Dec 28 07:45:58 2016 for rpm by  doxygen 1.4.4