• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

rpmdb/db3.c

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

Generated on Fri Dec 3 2010 20:53:53 for rpm by  doxygen 1.7.2