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

Generated on Thu Feb 7 03:43:19 2008 for rpm by  doxygen 1.5.1