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

rpmdb/db3.c

Go to the documentation of this file.
00001 /*@-type@*/ /* FIX: annotate db3 methods */
00006 /*@unchecked@*/
00007 static int _debug = 1;  /* XXX if < 0 debugging, > 0 unusual error returns */
00008 
00009 #include "system.h"
00010 
00011 #if defined(HAVE_FTOK) && defined(HAVE_SYS_IPC_H)
00012 #include <sys/ipc.h>
00013 #endif
00014 
00015 #include <rpmlib.h>
00016 #include <rpmmacro.h>
00017 #include <rpmurl.h>     /* XXX urlPath proto */
00018 
00019 #include <rpmdb.h>
00020 
00021 #include "debug.h"
00022 
00023 /*@access rpmdb @*/
00024 /*@access dbiIndex @*/
00025 /*@access dbiIndexSet @*/
00026 
00030 /*@-fielduse@*/
00031 struct dbiHStats_s {
00032     unsigned int hash_magic;    
00033     unsigned int hash_version;  
00034     unsigned int hash_nkeys;    
00035     unsigned int hash_ndata;    
00036     unsigned int hash_pagesize; 
00037     unsigned int hash_nelem;    
00038     unsigned int hash_ffactor;  
00039     unsigned int hash_buckets;  
00040     unsigned int hash_free;     
00041     unsigned int hash_bfree;    
00042     unsigned int hash_bigpages; 
00043     unsigned int hash_big_bfree;
00044     unsigned int hash_overflows;
00045     unsigned int hash_ovfl_free;
00046     unsigned int hash_dup;      
00047     unsigned int hash_dup_free; 
00048 };
00049 
00053 struct dbiBStats_s {
00054     unsigned int bt_magic;      
00055     unsigned int bt_version;    
00056     unsigned int bt_nkeys;      
00057     unsigned int bt_ndata;      
00058     unsigned int bt_pagesize;   
00059     unsigned int bt_minkey;     
00060     unsigned int bt_re_len;     
00061     unsigned int bt_re_pad;     
00062     unsigned int bt_levels;     
00063     unsigned int bt_int_pg;     
00064     unsigned int bt_leaf_pg;    
00065     unsigned int bt_dup_pg;     
00066     unsigned int bt_over_pg;    
00067     unsigned int bt_free;       
00068     unsigned int bt_int_pgfree; 
00069     unsigned int bt_leaf_pgfree;
00070     unsigned int bt_dup_pgfree; 
00071     unsigned int bt_over_pgfree;
00072 };
00073 /*@=fielduse@*/
00074 
00075 #ifdef  NOTNOW
00076 static const char * bfstring(unsigned int x, const char * xbf)
00077 {
00078     const char * s = xbf;
00079     static char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
00080     static char buf[256];
00081     char * t, * te;
00082     unsigned radix;
00083     unsigned c, i, k;
00084 
00085     radix = (s != NULL ? *s++ : 16);
00086 
00087     if (radix <= 1 || radix >= 32)
00088         radix = 16;
00089 
00090     t = buf;
00091     switch (radix) {
00092     case 8:     *t++ = '0';     break;
00093     case 16:    *t++ = '0';     *t++ = 'x';     break;
00094     }
00095 
00096     i = 0;
00097     k = x;
00098     do { i++; k /= radix; } while (k);
00099 
00100     te = t + i;
00101 
00102     k = x;
00103     do { --i; t[i] = digits[k % radix]; k /= radix; } while (k);
00104 
00105     t = te;
00106     i = '<';
00107     if (s != NULL)
00108     while ((c = *s++) != '\0') {
00109         if (c > ' ') continue;
00110 
00111         k = (1 << (c - 1));
00112         if (!(x & k)) continue;
00113 
00114         if (t == te) *t++ = '=';
00115 
00116         *t++ = i;
00117         i = ',';
00118         while (*s > ' ')
00119             *t++ = *s++;
00120     }
00121     if (t > te) *t++ = '>';
00122     *t = '\0';
00123     return buf;
00124 }
00125 
00126 static const char * dbtFlags =
00127         "\20\1APPMALLOC\2ISSET\3MALLOC\4PARTIAL\5REALLOC\6USERMEM\7DUPOK";
00128 
00129 static const char * dbenvOpenFlags =
00130         "\20\1CREATE\2NO_EXCEPTIONS\3FORCE\4NOMMAP\5RDONLY\6RECOVER\7THREAD\10TXN_NOSYNC\11USE_ENVIRON\12USE_ENVIRON_ROOT\13CDB\14LOCK\15LOG\16MPOOL\17TXN\20JOINENV\21LOCKDOWN\22PRIVATE\23RECOVER_FATAL\24SYSTEM_MEM";
00131 
00132 static const char * dbOpenFlags =
00133         "\20\1CREATE\2NO_EXCEPTIONS\3FORCE\4NOMMAP\5RDONLY\6RECOVER\7THREAD\10TXN_NOSYNC\11USE_ENVIRON\12USE_ENVIRON_ROOT\13EXCL\14FCNTL_LOCKING\15RDWRMASTER\16TRUNCATE\17EXTENT\20APPLY_LOGREG";
00134 
00135 static const char * dbenvSetFlags =
00136         "\20\1CREATE\2NO_EXCEPTIONS\3FORCE\4NOMMAP\5RDONLY\6RECOVER\7THREAD\10TXN_NOSYNC\11USE_ENVIRON\12USE_ENVIRON_ROOT\13CDB_ALLDB\14NOLOCKING\15NOPANIC\16PANIC_ENV\17REGION_INIT\20YIELDCPU";
00137 
00138 static const char * dbSetFlags =
00139         "\20\1DUP\2DUPSORT\3RECNUM\4RENUMBER\5REVSPLITOFF\6SNAPSHOT";
00140 
00141 static const char * dbiModeFlags =
00142         "\20\1WRONLY\2RDWR\7CREAT\10EXCL\11NOCTTY\12TRUNC\13APPEND\14NONBLOCK\15SYNC\16ASYNC\17DIRECT\20LARGEFILE\21DIRECTORY\22NOFOLLOW";
00143 #endif  /* NOTNOW */
00144 
00145 
00146 /*@-globuse -mustmod @*/        /* FIX: rpmError not annotated yet. */
00147 static int cvtdberr(dbiIndex dbi, const char * msg, int error, int printit)
00148         /*@globals fileSystem @*/
00149         /*@modifies fileSystem @*/
00150 {
00151     int rc = error;
00152 
00153     if (printit && rc) {
00154         /*@-moduncon@*/ /* FIX: annotate db3 methods */
00155         if (msg)
00156             rpmError(RPMERR_DBERR, _("db%d error(%d) from %s: %s\n"),
00157                 dbi->dbi_api, rc, msg, db_strerror(error));
00158         else
00159             rpmError(RPMERR_DBERR, _("db%d error(%d): %s\n"),
00160                 dbi->dbi_api, rc, db_strerror(error));
00161         /*@=moduncon@*/
00162     }
00163 
00164     return rc;
00165 }
00166 /*@=globuse =mustmod @*/
00167 
00168 static int db_fini(dbiIndex dbi, const char * dbhome,
00169                 /*@null@*/ const char * dbfile,
00170                 /*@unused@*/ /*@null@*/ const char * dbsubfile)
00171         /*@globals fileSystem @*/
00172         /*@modifies fileSystem @*/
00173 {
00174     rpmdb rpmdb = dbi->dbi_rpmdb;
00175     DB_ENV * dbenv = rpmdb->db_dbenv;
00176     int rc;
00177 
00178     if (dbenv == NULL)
00179         return 0;
00180 
00181     rc = dbenv->close(dbenv, 0);
00182     rc = cvtdberr(dbi, "dbenv->close", rc, _debug);
00183 
00184     if (dbfile)
00185         rpmMessage(RPMMESS_DEBUG, _("closed   db environment %s/%s\n"),
00186                         dbhome, dbfile);
00187 
00188     if (rpmdb->db_remove_env) {
00189         int xx;
00190 
00191         /*@-moduncon@*/ /* FIX: annotate db3 methods */
00192         xx = db_env_create(&dbenv, 0);
00193         /*@=moduncon@*/
00194         xx = cvtdberr(dbi, "db_env_create", rc, _debug);
00195 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR != 0) || (DB_VERSION_MAJOR == 4)
00196         xx = dbenv->remove(dbenv, dbhome, 0);
00197 #else
00198         xx = dbenv->remove(dbenv, dbhome, NULL, 0);
00199 #endif
00200         xx = cvtdberr(dbi, "dbenv->remove", rc, _debug);
00201 
00202         if (dbfile)
00203             rpmMessage(RPMMESS_DEBUG, _("removed  db environment %s/%s\n"),
00204                         dbhome, dbfile);
00205 
00206     }
00207     return rc;
00208 }
00209 
00210 static int db3_fsync_disable(/*@unused@*/ int fd)
00211         /*@*/
00212 {
00213     return 0;
00214 }
00215 
00216 /*@-moduncon@*/ /* FIX: annotate db3 methods */
00217 static int db_init(dbiIndex dbi, const char * dbhome,
00218                 /*@null@*/ const char * dbfile,
00219                 /*@unused@*/ /*@null@*/ const char * dbsubfile,
00220                 /*@out@*/ DB_ENV ** dbenvp)
00221         /*@globals rpmGlobalMacroContext,
00222                 fileSystem @*/
00223         /*@modifies dbi, *dbenvp, fileSystem @*/
00224 {
00225     rpmdb rpmdb = dbi->dbi_rpmdb;
00226     DB_ENV *dbenv = NULL;
00227     int eflags;
00228     int rc;
00229 
00230     if (dbenvp == NULL)
00231         return 1;
00232 
00233     /* XXX HACK */
00234     /*@-assignexpose@*/
00235     if (rpmdb->db_errfile == NULL)
00236         rpmdb->db_errfile = stderr;
00237     /*@=assignexpose@*/
00238 
00239     eflags = (dbi->dbi_oeflags | dbi->dbi_eflags);
00240     if (eflags & DB_JOINENV) eflags &= DB_JOINENV;
00241 
00242     if (dbfile)
00243         rpmMessage(RPMMESS_DEBUG, _("opening  db environment %s/%s %s\n"),
00244                 dbhome, dbfile, prDbiOpenFlags(eflags, 1));
00245 
00246     /* XXX Can't do RPC w/o host. */
00247     if (dbi->dbi_host == NULL)
00248         dbi->dbi_ecflags &= ~DB_CLIENT;
00249 
00250     /* XXX Set a default shm_key. */
00251     if ((dbi->dbi_eflags & DB_SYSTEM_MEM) && dbi->dbi_shmkey == 0) {
00252 #if defined(HAVE_FTOK)
00253         dbi->dbi_shmkey = ftok(dbhome, 0);
00254 #else
00255         dbi->dbi_shmkey = 0x44631380;
00256 #endif
00257     }
00258 
00259     rc = db_env_create(&dbenv, dbi->dbi_ecflags);
00260     rc = cvtdberr(dbi, "db_env_create", rc, _debug);
00261     if (rc)
00262         goto errxit;
00263 
00264     if (dbenv == NULL)
00265         return 1;
00266 
00267   { int xx;
00268     /*@-noeffectuncon@*/ /* FIX: annotate db3 methods */
00269     dbenv->set_errcall(dbenv, rpmdb->db_errcall);
00270     dbenv->set_errfile(dbenv, rpmdb->db_errfile);
00271     dbenv->set_errpfx(dbenv, rpmdb->db_errpfx);
00272     /*@=noeffectuncon@*/
00273  /* dbenv->set_paniccall(???) */
00274     xx = dbenv->set_verbose(dbenv, DB_VERB_CHKPOINT,
00275                 (dbi->dbi_verbose & DB_VERB_CHKPOINT));
00276     xx = dbenv->set_verbose(dbenv, DB_VERB_DEADLOCK,
00277                 (dbi->dbi_verbose & DB_VERB_DEADLOCK));
00278     xx = dbenv->set_verbose(dbenv, DB_VERB_RECOVERY,
00279                 (dbi->dbi_verbose & DB_VERB_RECOVERY));
00280     xx = dbenv->set_verbose(dbenv, DB_VERB_WAITSFOR,
00281                 (dbi->dbi_verbose & DB_VERB_WAITSFOR));
00282  /* dbenv->set_lg_max(???) */
00283  /* dbenv->set_lk_conflicts(???) */
00284  /* dbenv->set_lk_detect(???) */
00285  /* dbenv->set_lk_max(???) */
00286     xx = dbenv->set_mp_mmapsize(dbenv, dbi->dbi_mp_mmapsize);
00287     xx = cvtdberr(dbi, "dbenv->set_mp_mmapsize", xx, _debug);
00288     xx = dbenv->set_cachesize(dbenv, 0, dbi->dbi_mp_size, 0);
00289     xx = cvtdberr(dbi, "dbenv->set_cachesize", xx, _debug);
00290  /* dbenv->set_tx_max(???) */
00291  /* dbenv->set_tx_recover(???) */
00292     if (dbi->dbi_no_fsync) {
00293 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR != 0) || (DB_VERSION_MAJOR == 4)
00294         xx = db_env_set_func_fsync(db3_fsync_disable);
00295 #else
00296         xx = dbenv->set_func_fsync(dbenv, db3_fsync_disable);
00297 #endif
00298         xx = cvtdberr(dbi, "db_env_set_func_fsync", xx, _debug);
00299     }
00300 
00301 /* XXX 3.3.4 change. */
00302 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3) || (DB_VERSION_MAJOR == 4)
00303     if ((dbi->dbi_ecflags & DB_CLIENT) && dbi->dbi_host) {
00304         xx = dbenv->set_rpc_server(dbenv, NULL, dbi->dbi_host,
00305                 dbi->dbi_cl_timeout, dbi->dbi_sv_timeout, 0);
00306         xx = cvtdberr(dbi, "dbenv->set_server", xx, _debug);
00307     }
00308 #else
00309     if ((dbi->dbi_ecflags & DB_CLIENT) && dbi->dbi_host) {
00310         xx = dbenv->set_server(dbenv, dbi->dbi_host,
00311                 dbi->dbi_cl_timeout, dbi->dbi_sv_timeout, 0);
00312         xx = cvtdberr(dbi, "dbenv->set_server", xx, _debug);
00313     }
00314 #endif
00315     if (dbi->dbi_shmkey) {
00316         xx = dbenv->set_shm_key(dbenv, dbi->dbi_shmkey);
00317         xx = cvtdberr(dbi, "dbenv->set_shm_key", xx, _debug);
00318     }
00319     if (dbi->dbi_tmpdir) {
00320         const char * root;
00321         const char * tmpdir;
00322 
00323         root = (dbi->dbi_root ? dbi->dbi_root : rpmdb->db_root);
00324         if ((root[0] == '/' && root[1] == '\0') || rpmdb->db_chrootDone)
00325             root = NULL;
00326         /*@-mods@*/
00327         tmpdir = rpmGenPath(root, dbi->dbi_tmpdir, NULL);
00328         /*@=mods@*/
00329         xx = dbenv->set_tmp_dir(dbenv, tmpdir);
00330         xx = cvtdberr(dbi, "dbenv->set_tmp_dir", rc, _debug);
00331         tmpdir = _free(tmpdir);
00332     }
00333   }
00334 
00335 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR != 0) || (DB_VERSION_MAJOR == 4)
00336     rc = dbenv->open(dbenv, dbhome, eflags, dbi->dbi_perms);
00337 #else
00338     rc = dbenv->open(dbenv, dbhome, NULL, eflags, dbi->dbi_perms);
00339 #endif
00340     rc = cvtdberr(dbi, "dbenv->open", rc, _debug);
00341     if (rc)
00342         goto errxit;
00343 
00344     *dbenvp = dbenv;
00345 
00346     return 0;
00347 
00348 errxit:
00349     if (dbenv) {
00350         int xx;
00351         xx = dbenv->close(dbenv, 0);
00352         xx = cvtdberr(dbi, "dbenv->close", xx, _debug);
00353     }
00354     return rc;
00355 }
00356 /*@=moduncon@*/
00357 
00358 static int db3sync(dbiIndex dbi, unsigned int flags)
00359         /*@globals fileSystem @*/
00360         /*@modifies fileSystem @*/
00361 {
00362     DB * db = dbi->dbi_db;
00363     int rc = 0;
00364     int _printit;
00365 
00366     if (db != NULL)
00367         rc = db->sync(db, flags);
00368     /* XXX DB_INCOMPLETE is returned occaisionally with multiple access. */
00369     _printit = (rc == DB_INCOMPLETE ? 0 : _debug);
00370     rc = cvtdberr(dbi, "db->sync", rc, _printit);
00371     return rc;
00372 }
00373 
00374 static int db3cdup(dbiIndex dbi, DBC * dbcursor, DBC ** dbcp,
00375                 unsigned int flags)
00376         /*@globals fileSystem @*/
00377         /*@modifies *dbcp, fileSystem @*/
00378 {
00379     int rc;
00380 
00381     if (dbcp) *dbcp = NULL;
00382     rc = dbcursor->c_dup(dbcursor, dbcp, flags);
00383     rc = cvtdberr(dbi, "dbcursor->c_dup", rc, _debug);
00384     /*@-nullstate @*/ /* FIX: *dbcp can be NULL */
00385     return rc;
00386     /*@=nullstate @*/
00387 }
00388 
00389 static int db3cclose(dbiIndex dbi, /*@only@*/ /*@null@*/ DBC * dbcursor,
00390                 unsigned int flags)
00391         /*@globals fileSystem @*/
00392         /*@modifies dbi, fileSystem @*/
00393 {
00394     int rc = -2;
00395 
00396     /* XXX db3copen error pathways come through here. */
00397     if (dbcursor != NULL) {
00398         rc = dbcursor->c_close(dbcursor);
00399         rc = cvtdberr(dbi, "dbcursor->c_close", rc, _debug);
00400     }
00401     return rc;
00402 }
00403 
00404 static int db3copen(dbiIndex dbi, DB_TXN * txnid,
00405                 /*@null@*/ /*@out@*/ DBC ** dbcp, unsigned int dbiflags)
00406         /*@globals fileSystem @*/
00407         /*@modifies dbi, *dbcp, fileSystem @*/
00408 {
00409     DB * db = dbi->dbi_db;
00410     DBC * dbcursor = NULL;
00411     int flags;
00412     int rc;
00413 
00414     assert(db != NULL);
00415     if ((dbiflags & DB_WRITECURSOR) &&
00416         (dbi->dbi_eflags & DB_INIT_CDB) && !(dbi->dbi_oflags & DB_RDONLY))
00417     {
00418         flags = DB_WRITECURSOR;
00419     } else
00420         flags = 0;
00421 
00422     rc = db->cursor(db, txnid, &dbcursor, flags);
00423     rc = cvtdberr(dbi, "db->cursor", rc, _debug);
00424 
00425     if (dbcp)
00426         /*@-onlytrans@*/ *dbcp = dbcursor; /*@=onlytrans@*/
00427     else
00428         (void) db3cclose(dbi, dbcursor, 0);
00429 
00430     return rc;
00431 }
00432 
00433 static int db3cput(dbiIndex dbi, DBC * dbcursor, DBT * key, DBT * data,
00434                 unsigned int flags)
00435         /*@globals fileSystem @*/
00436         /*@modifies fileSystem @*/
00437 {
00438     DB * db = dbi->dbi_db;
00439     int rc;
00440 
00441     assert(db != NULL);
00442     if (dbcursor == NULL) {
00443         rc = db->put(db, dbi->dbi_txnid, key, data, 0);
00444         rc = cvtdberr(dbi, "db->put", rc, _debug);
00445     } else {
00446         rc = dbcursor->c_put(dbcursor, key, data, DB_KEYLAST);
00447         rc = cvtdberr(dbi, "dbcursor->c_put", rc, _debug);
00448     }
00449 
00450     return rc;
00451 }
00452 
00453 static int db3cdel(dbiIndex dbi, DBC * dbcursor, DBT * key, DBT * data,
00454                 unsigned int flags)
00455         /*@globals fileSystem @*/
00456         /*@modifies *dbcursor, fileSystem @*/
00457 {
00458     DB * db = dbi->dbi_db;
00459     int rc;
00460 
00461     assert(db != NULL);
00462     if (dbcursor == NULL) {
00463         rc = db->del(db, dbi->dbi_txnid, key, flags);
00464         rc = cvtdberr(dbi, "db->del", rc, _debug);
00465     } else {
00466         int _printit;
00467 
00468         /* XXX TODO: insure that cursor is positioned with duplicates */
00469         rc = dbcursor->c_get(dbcursor, key, data, DB_SET);
00470         /* XXX DB_NOTFOUND can be returned */
00471         _printit = (rc == DB_NOTFOUND ? 0 : _debug);
00472         rc = cvtdberr(dbi, "dbcursor->c_get", rc, _printit);
00473 
00474         if (rc == 0) {
00475             rc = dbcursor->c_del(dbcursor, flags);
00476             rc = cvtdberr(dbi, "dbcursor->c_del", rc, _debug);
00477         }
00478     }
00479 
00480     return rc;
00481 }
00482 
00483 static int db3cget(dbiIndex dbi, DBC * dbcursor, DBT * key, DBT * data,
00484                 unsigned int flags)
00485         /*@globals fileSystem @*/
00486         /*@modifies *dbcursor, *key, *data, fileSystem @*/
00487 {
00488     DB * db = dbi->dbi_db;
00489     int _printit;
00490     int rc;
00491 
00492     assert(db != NULL);
00493     if (dbcursor == NULL) {
00494         /* XXX duplicates require cursors. */
00495         rc = db->get(db, dbi->dbi_txnid, key, data, 0);
00496         /* XXX DB_NOTFOUND can be returned */
00497         _printit = (rc == DB_NOTFOUND ? 0 : _debug);
00498         rc = cvtdberr(dbi, "db->get", rc, _printit);
00499     } else {
00500         /* XXX db3 does DB_FIRST on uninitialized cursor */
00501         rc = dbcursor->c_get(dbcursor, key, data, flags);
00502         /* XXX DB_NOTFOUND can be returned */
00503         _printit = (rc == DB_NOTFOUND ? 0 : _debug);
00504         rc = cvtdberr(dbi, "dbcursor->c_get", rc, _printit);
00505     }
00506 
00507     return rc;
00508 }
00509 
00510 static int db3cpget(dbiIndex dbi, DBC * dbcursor, DBT * key, DBT * pkey,
00511                 DBT * data, unsigned int flags)
00512         /*@globals fileSystem @*/
00513         /*@modifies *dbcursor, *key, *data, fileSystem @*/
00514 {
00515     DB * db = dbi->dbi_db;
00516     int _printit;
00517     int rc;
00518 
00519     assert(db != NULL);
00520     assert(dbcursor != NULL);
00521 
00522     /* XXX db3 does DB_FIRST on uninitialized cursor */
00523     rc = dbcursor->c_pget(dbcursor, key, pkey, data, flags);
00524     /* XXX DB_NOTFOUND can be returned */
00525     _printit = (rc == DB_NOTFOUND ? 0 : _debug);
00526     rc = cvtdberr(dbi, "dbcursor->c_pget", rc, _printit);
00527 
00528     return rc;
00529 }
00530 
00531 static int db3ccount(dbiIndex dbi, DBC * dbcursor,
00532                 /*@null@*/ /*@out@*/ unsigned int * countp,
00533                 /*@unused@*/ unsigned int flags)
00534         /*@globals fileSystem @*/
00535         /*@modifies *countp, fileSystem @*/
00536 {
00537     db_recno_t count = 0;
00538     int rc = 0;
00539 
00540     flags = 0;
00541     rc = dbcursor->c_count(dbcursor, &count, flags);
00542     rc = cvtdberr(dbi, "dbcursor->c_count", rc, _debug);
00543     if (rc) return rc;
00544     if (countp) *countp = count;
00545 
00546     return rc;
00547 }
00548 
00549 static int db3byteswapped(dbiIndex dbi) /*@*/
00550 {
00551     DB * db = dbi->dbi_db;
00552     int rc = 0;
00553 
00554     if (db != NULL) {
00555 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3 && DB_VERSION_PATCH == 11) \
00556  || (DB_VERSION_MAJOR == 4)
00557         int isswapped = 0;
00558         rc = db->get_byteswapped(db, &isswapped);
00559         if (rc == 0)
00560             rc = isswapped;
00561 #else
00562         rc = db->get_byteswapped(db);
00563 #endif
00564     }
00565 
00566     return rc;
00567 }
00568 
00569 static int db3stat(dbiIndex dbi, unsigned int flags)
00570         /*@globals fileSystem @*/
00571         /*@modifies dbi, fileSystem @*/
00572 {
00573     DB * db = dbi->dbi_db;
00574     int rc = 0;
00575 
00576     assert(db != NULL);
00577 #if defined(DB_FAST_STAT)
00578     if (flags)
00579         flags = DB_FAST_STAT;
00580     else
00581 #endif
00582         flags = 0;
00583     dbi->dbi_stats = _free(dbi->dbi_stats);
00584 /* XXX 3.3.4 change. */
00585 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3) || (DB_VERSION_MAJOR == 4)
00586     rc = db->stat(db, &dbi->dbi_stats, flags);
00587 #else
00588     rc = db->stat(db, &dbi->dbi_stats, NULL, flags);
00589 #endif
00590     rc = cvtdberr(dbi, "db->stat", rc, _debug);
00591     return rc;
00592 }
00593 
00594 static int db3associate(dbiIndex dbi, dbiIndex dbisecondary,
00595                 int (*callback)(DB *, const DBT *, const DBT *, DBT *),
00596                 unsigned int flags)
00597         /*@globals fileSystem @*/
00598         /*@modifies dbi, fileSystem @*/
00599 {
00600     DB * db = dbi->dbi_db;
00601     DB * secondary = dbisecondary->dbi_db;
00602     int rc;
00603 
00604 /*@-moduncon@*/ /* FIX: annotate db3 methods */
00605     rc = db->associate(db, secondary, callback, flags);
00606 /*@=moduncon@*/
00607     rc = cvtdberr(dbi, "db->associate", rc, _debug);
00608     return rc;
00609 }
00610 
00611 static int db3join(dbiIndex dbi, DBC ** curslist, DBC ** dbcp,
00612                 unsigned int flags)
00613         /*@globals fileSystem @*/
00614         /*@modifies dbi, fileSystem @*/
00615 {
00616     DB * db = dbi->dbi_db;
00617     int rc;
00618 
00619 /*@-moduncon@*/ /* FIX: annotate db3 methods */
00620     rc = db->join(db, curslist, dbcp, flags);
00621 /*@=moduncon@*/
00622     rc = cvtdberr(dbi, "db->join", rc, _debug);
00623     return rc;
00624 }
00625 
00626 /*@-moduncon@*/ /* FIX: annotate db3 methods */
00627 static int db3close(/*@only@*/ dbiIndex dbi, /*@unused@*/ unsigned int flags)
00628         /*@globals rpmGlobalMacroContext,
00629                 fileSystem @*/
00630         /*@modifies dbi, fileSystem @*/
00631 {
00632     rpmdb rpmdb = dbi->dbi_rpmdb;
00633     const char * urlfn = NULL;
00634     const char * root;
00635     const char * home;
00636     const char * dbhome;
00637     const char * dbfile;
00638     const char * dbsubfile;
00639     DB * db = dbi->dbi_db;
00640     int rc = 0, xx;
00641 
00642     flags = 0;  /* XXX unused */
00643 
00644     /*
00645      * Get the prefix/root component and directory path.
00646      */
00647     root = (dbi->dbi_root ? dbi->dbi_root : rpmdb->db_root);
00648     if ((root[0] == '/' && root[1] == '\0') || rpmdb->db_chrootDone)
00649         root = NULL;
00650     home = (dbi->dbi_home ? dbi->dbi_home : rpmdb->db_home);
00651 
00652     /*
00653      * Either the root or directory components may be a URL. Concatenate,
00654      * convert the URL to a path, and add the name of the file.
00655      */
00656     /*@-mods@*/
00657     urlfn = rpmGenPath(root, home, NULL);
00658     /*@=mods@*/
00659     (void) urlPath(urlfn, &dbhome);
00660     if (dbi->dbi_temporary) {
00661         dbfile = NULL;
00662         dbsubfile = NULL;
00663     } else {
00664 #ifdef  HACK    /* XXX necessary to support dbsubfile */
00665         dbfile = (dbi->dbi_file ? dbi->dbi_file : db3basename);
00666         dbsubfile = (dbi->dbi_subfile ? dbi->dbi_subfile : tagName(dbi->dbi_rpmtag));
00667 #else
00668         dbfile = (dbi->dbi_file ? dbi->dbi_file : tagName(dbi->dbi_rpmtag));
00669         dbsubfile = NULL;
00670 #endif
00671     }
00672 
00673     if (db) {
00674         rc = db->close(db, 0);
00675         rc = cvtdberr(dbi, "db->close", rc, _debug);
00676         db = dbi->dbi_db = NULL;
00677 
00678         rpmMessage(RPMMESS_DEBUG, _("closed   db index       %s/%s\n"),
00679                 dbhome, (dbfile ? dbfile : tagName(dbi->dbi_rpmtag)));
00680 
00681     }
00682 
00683     if (rpmdb->db_dbenv != NULL && dbi->dbi_use_dbenv) {
00684         if (rpmdb->db_opens == 1) {
00685             /*@-nullstate@*/
00686             xx = db_fini(dbi, (dbhome ? dbhome : ""), dbfile, dbsubfile);
00687             /*@=nullstate@*/
00688             rpmdb->db_dbenv = NULL;
00689         }
00690         rpmdb->db_opens--;
00691     }
00692 
00693     if (dbi->dbi_verify_on_close && !dbi->dbi_temporary) {
00694         DB_ENV * dbenv = NULL;
00695 
00696         /*@-moduncon@*/ /* FIX: annotate db3 methods */
00697         rc = db_env_create(&dbenv, 0);
00698         /*@=moduncon@*/
00699         rc = cvtdberr(dbi, "db_env_create", rc, _debug);
00700         if (rc || dbenv == NULL) goto exit;
00701 
00702         /*@-noeffectuncon@*/ /* FIX: annotate db3 methods */
00703         dbenv->set_errcall(dbenv, rpmdb->db_errcall);
00704         dbenv->set_errfile(dbenv, rpmdb->db_errfile);
00705         dbenv->set_errpfx(dbenv, rpmdb->db_errpfx);
00706  /*     dbenv->set_paniccall(???) */
00707         /*@=noeffectuncon@*/
00708         xx = dbenv->set_verbose(dbenv, DB_VERB_CHKPOINT,
00709                 (dbi->dbi_verbose & DB_VERB_CHKPOINT));
00710         xx = dbenv->set_verbose(dbenv, DB_VERB_DEADLOCK,
00711                 (dbi->dbi_verbose & DB_VERB_DEADLOCK));
00712         xx = dbenv->set_verbose(dbenv, DB_VERB_RECOVERY,
00713                 (dbi->dbi_verbose & DB_VERB_RECOVERY));
00714         xx = dbenv->set_verbose(dbenv, DB_VERB_WAITSFOR,
00715                 (dbi->dbi_verbose & DB_VERB_WAITSFOR));
00716 
00717         if (dbi->dbi_tmpdir) {
00718             /*@-mods@*/
00719             const char * tmpdir = rpmGenPath(root, dbi->dbi_tmpdir, NULL);
00720             /*@=mods@*/
00721             rc = dbenv->set_tmp_dir(dbenv, tmpdir);
00722             rc = cvtdberr(dbi, "dbenv->set_tmp_dir", rc, _debug);
00723             tmpdir = _free(tmpdir);
00724             if (rc) goto exit;
00725         }
00726             
00727         rc = dbenv->open(dbenv, dbhome,
00728             DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE | DB_USE_ENVIRON, 0);
00729         rc = cvtdberr(dbi, "dbenv->open", rc, _debug);
00730         if (rc) goto exit;
00731 
00732         /*@-moduncon@*/ /* FIX: annotate db3 methods */
00733         rc = db_create(&db, dbenv, 0);
00734         /*@=moduncon@*/
00735         rc = cvtdberr(dbi, "db_create", rc, _debug);
00736 
00737         if (db != NULL) {
00738                 /*@-mods@*/
00739                 const char * dbf = rpmGetPath(dbhome, "/", dbfile, NULL);
00740                 /*@=mods@*/
00741 
00742                 rc = db->verify(db, dbf, NULL, NULL, flags);
00743                 rc = cvtdberr(dbi, "db->verify", rc, _debug);
00744 
00745                 rpmMessage(RPMMESS_DEBUG, _("verified db index       %s/%s\n"),
00746                         (dbhome ? dbhome : ""),
00747                         (dbfile ? dbfile : tagName(dbi->dbi_rpmtag)));
00748 
00749                 xx = db->close(db, 0);
00750                 xx = cvtdberr(dbi, "db->close", xx, _debug);
00751                 db = NULL;
00752                 if (rc == 0 && xx) rc = xx;
00753 
00754                 dbf = _free(dbf);
00755         }
00756         xx = dbenv->close(dbenv, 0);
00757         xx = cvtdberr(dbi, "dbenv->close", xx, _debug);
00758         if (rc == 0 && xx) rc = xx;
00759     }
00760 
00761 exit:
00762     dbi->dbi_db = NULL;
00763 
00764     urlfn = _free(urlfn);
00765 
00766     dbi = db3Free(dbi);
00767 
00768     return rc;
00769 }
00770 /*@=moduncon@*/
00771 
00772 static int db3open(rpmdb rpmdb, rpmTag rpmtag, dbiIndex * dbip)
00773         /*@globals rpmGlobalMacroContext,
00774                 fileSystem @*/
00775         /*@modifies *dbip, fileSystem @*/
00776 {
00777     /*@-nestedextern@*/
00778     extern struct _dbiVec db3vec;
00779     /*@=nestedextern@*/
00780     const char * urlfn = NULL;
00781     const char * root;
00782     const char * home;
00783     const char * dbhome;
00784     const char * dbfile;
00785     const char * dbsubfile;
00786     dbiIndex dbi = NULL;
00787     int rc = 0;
00788     int xx;
00789 
00790     DB * db = NULL;
00791     DB_ENV * dbenv = NULL;
00792     u_int32_t oflags;
00793     int _printit;
00794 
00795     if (dbip)
00796         *dbip = NULL;
00797 
00798     /*
00799      * Parse db configuration parameters.
00800      */
00801     /*@-mods@*/
00802     if ((dbi = db3New(rpmdb, rpmtag)) == NULL)
00803         /*@-nullstate@*/
00804         return 1;
00805         /*@=nullstate@*/
00806     /*@=mods@*/
00807     dbi->dbi_api = DB_VERSION_MAJOR;
00808 
00809     /*
00810      * Get the prefix/root component and directory path.
00811      */
00812     root = (dbi->dbi_root ? dbi->dbi_root : rpmdb->db_root);
00813     if ((root[0] == '/' && root[1] == '\0') || rpmdb->db_chrootDone)
00814         root = NULL;
00815     home = (dbi->dbi_home ? dbi->dbi_home : rpmdb->db_home);
00816 
00817     /*
00818      * Either the root or directory components may be a URL. Concatenate,
00819      * convert the URL to a path, and add the name of the file.
00820      */
00821     /*@-mods@*/
00822     urlfn = rpmGenPath(root, home, NULL);
00823     /*@=mods@*/
00824     (void) urlPath(urlfn, &dbhome);
00825     if (dbi->dbi_temporary) {
00826         dbfile = NULL;
00827         dbsubfile = NULL;
00828     } else {
00829 #ifdef  HACK    /* XXX necessary to support dbsubfile */
00830         dbfile = (dbi->dbi_file ? dbi->dbi_file : db3basename);
00831         dbsubfile = (dbi->dbi_subfile ? dbi->dbi_subfile : tagName(dbi->dbi_rpmtag));
00832 #else
00833         dbfile = (dbi->dbi_file ? dbi->dbi_file : tagName(dbi->dbi_rpmtag));
00834         dbsubfile = NULL;
00835 #endif
00836     }
00837 
00838     oflags = (dbi->dbi_oeflags | dbi->dbi_oflags);
00839     oflags &= ~DB_TRUNCATE;     /* XXX this is dangerous */
00840 
00841 #if 0   /* XXX rpmdb: illegal flag combination specified to DB->open */
00842     if ( dbi->dbi_mode & O_EXCL) oflags |= DB_EXCL;
00843 #endif
00844 
00845     /*
00846      * Map open mode flags onto configured database/environment flags.
00847      */
00848     if (dbi->dbi_temporary) {
00849         oflags |= DB_CREATE;
00850         dbi->dbi_oeflags |= DB_CREATE;
00851         oflags &= ~DB_RDONLY;
00852         dbi->dbi_oflags &= ~DB_RDONLY;
00853     } else {
00854         if (!(dbi->dbi_mode & (O_RDWR|O_WRONLY))) oflags |= DB_RDONLY;
00855         if (dbi->dbi_mode & O_CREAT) {
00856             oflags |= DB_CREATE;
00857             dbi->dbi_oeflags |= DB_CREATE;
00858         }
00859 #ifdef  DANGEROUS
00860         if ( dbi->dbi_mode & O_TRUNC) oflags |= DB_TRUNCATE;
00861 #endif
00862     }
00863 
00864     /*
00865      * Create the /var/lib/rpm directory if it doesn't exist (root only).
00866      */
00867     (void) rpmioMkpath(dbhome, 0755, getuid(), getgid());
00868 
00869     /*
00870      * Avoid incompatible DB_CREATE/DB_RDONLY flags on DBENV->open.
00871      */
00872     if (dbi->dbi_use_dbenv) {
00873         if (access(dbhome, W_OK) == -1) {
00874 
00875             /* dbhome is unwritable, don't attempt DB_CREATE on DB->open ... */
00876             oflags &= ~DB_CREATE;
00877 
00878             /* ... but DBENV->open might still need DB_CREATE ... */
00879             if (dbi->dbi_eflags & DB_PRIVATE) {
00880                 dbi->dbi_eflags &= ~DB_JOINENV;
00881             } else {
00882                 dbi->dbi_eflags |= DB_JOINENV;
00883                 dbi->dbi_oeflags &= ~DB_CREATE;
00884                 dbi->dbi_oeflags &= ~DB_THREAD;
00885                 /* ... but, unless DB_PRIVATE is used, skip DBENV. */
00886                 dbi->dbi_use_dbenv = 0;
00887             }
00888 
00889             /* ... DB_RDONLY maps dbhome perms across files ...  */
00890             if (dbi->dbi_temporary) {
00891                 oflags |= DB_CREATE;
00892                 dbi->dbi_oeflags |= DB_CREATE;
00893                 oflags &= ~DB_RDONLY;
00894                 dbi->dbi_oflags &= ~DB_RDONLY;
00895             } else {
00896                 oflags |= DB_RDONLY;
00897                 /* ... and DB_WRITECURSOR won't be needed ...  */
00898                 dbi->dbi_oflags |= DB_RDONLY;
00899             }
00900 
00901         } else {        /* dbhome is writable, check for persistent dbenv. */
00902             /*@-mods@*/
00903             const char * dbf = rpmGetPath(dbhome, "/__db.001", NULL);
00904             /*@=mods@*/
00905 
00906             if (access(dbf, F_OK) == -1) {
00907                 /* ... non-existent (or unwritable) DBENV, will create ... */
00908                 dbi->dbi_oeflags |= DB_CREATE;
00909                 dbi->dbi_eflags &= ~DB_JOINENV;
00910             } else {
00911                 /* ... pre-existent (or bogus) DBENV, will join ... */
00912                 if (dbi->dbi_eflags & DB_PRIVATE) {
00913                     dbi->dbi_eflags &= ~DB_JOINENV;
00914                 } else {
00915                     dbi->dbi_eflags |= DB_JOINENV;
00916                     dbi->dbi_oeflags &= ~DB_CREATE;
00917                     dbi->dbi_oeflags &= ~DB_THREAD;
00918                 }
00919             }
00920             dbf = _free(dbf);
00921         }
00922     }
00923 
00924     /*
00925      * Avoid incompatible DB_CREATE/DB_RDONLY flags on DB->open.
00926      */
00927     if ((oflags & DB_CREATE) && (oflags & DB_RDONLY)) {
00928         /* dbhome is writable, and DB->open flags may conflict. */
00929         const char * dbfn = (dbfile ? dbfile : tagName(dbi->dbi_rpmtag));
00930         /*@-mods@*/
00931         const char * dbf = rpmGetPath(dbhome, "/", dbfn, NULL);
00932         /*@=mods@*/
00933 
00934         if (access(dbf, F_OK) == -1) {
00935             /* File does not exist, DB->open might create ... */
00936             oflags &= ~DB_RDONLY;
00937         } else {
00938             /* File exists, DB->open need not create ... */
00939             oflags &= ~DB_CREATE;
00940         }
00941 
00942         /* Only writers need DB_WRITECURSOR ... */
00943         if (!(oflags & DB_RDONLY) && access(dbf, W_OK) == 0) {
00944             dbi->dbi_oflags &= ~DB_RDONLY;
00945         } else {
00946             dbi->dbi_oflags |= DB_RDONLY;
00947         }
00948         dbf = _free(dbf);
00949     }
00950 
00951     /*
00952      * Turn off verify-on-close if opening read-only.
00953      */
00954     if (oflags & DB_RDONLY)
00955         dbi->dbi_verify_on_close = 0;
00956 
00957     if (dbi->dbi_use_dbenv) {
00958         /*@-mods@*/
00959         if (rpmdb->db_dbenv == NULL) {
00960             rc = db_init(dbi, dbhome, dbfile, dbsubfile, &dbenv);
00961             if (rc == 0) {
00962                 rpmdb->db_dbenv = dbenv;
00963                 rpmdb->db_opens = 1;
00964             }
00965         } else {
00966             dbenv = rpmdb->db_dbenv;
00967             rpmdb->db_opens++;
00968         }
00969         /*@=mods@*/
00970     }
00971 
00972     rpmMessage(RPMMESS_DEBUG, _("opening  db index       %s/%s %s mode=0x%x\n"),
00973                 dbhome, (dbfile ? dbfile : tagName(dbi->dbi_rpmtag)),
00974                 prDbiOpenFlags(oflags, 0), dbi->dbi_mode);
00975 
00976     if (rc == 0) {
00977         static int _lockdbfd = 0;
00978 
00979         /*@-moduncon@*/ /* FIX: annotate db3 methods */
00980         rc = db_create(&db, dbenv, dbi->dbi_cflags);
00981         /*@=moduncon@*/
00982         rc = cvtdberr(dbi, "db_create", rc, _debug);
00983         if (rc == 0 && db != NULL) {
00984             if (rc == 0 && dbi->dbi_lorder) {
00985                 rc = db->set_lorder(db, dbi->dbi_lorder);
00986                 rc = cvtdberr(dbi, "db->set_lorder", rc, _debug);
00987             }
00988             if (rc == 0 && dbi->dbi_cachesize) {
00989                 rc = db->set_cachesize(db, 0, dbi->dbi_cachesize, 0);
00990                 rc = cvtdberr(dbi, "db->set_cachesize", rc, _debug);
00991             }
00992             if (rc == 0 && dbi->dbi_pagesize) {
00993                 rc = db->set_pagesize(db, dbi->dbi_pagesize);
00994                 rc = cvtdberr(dbi, "db->set_pagesize", rc, _debug);
00995             }
00996 /* XXX 3.3.4 change. */
00997 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3) || (DB_VERSION_MAJOR == 4)
00998             if (rc == 0 &&
00999                         rpmdb->db_malloc && rpmdb->db_realloc && rpmdb->db_free)
01000             {
01001                 rc = db->set_alloc(db,
01002                         rpmdb->db_malloc, rpmdb->db_realloc, rpmdb->db_free);
01003                 rc = cvtdberr(dbi, "db->set_alloc", rc, _debug);
01004             }
01005 #else
01006             if (rc == 0 && rpmdb->db_malloc) {
01007                 rc = db->set_malloc(db, rpmdb->db_malloc);
01008                 rc = cvtdberr(dbi, "db->set_malloc", rc, _debug);
01009             }
01010 #endif
01011             if (rc == 0 && oflags & DB_CREATE) {
01012                 switch(dbi->dbi_type) {
01013                 default:
01014                 case DB_HASH:
01015                     if (dbi->dbi_h_ffactor) {
01016                         rc = db->set_h_ffactor(db, dbi->dbi_h_ffactor);
01017                         rc = cvtdberr(dbi, "db->set_h_ffactor", rc, _debug);
01018                         if (rc) break;
01019                     }
01020                     if (dbi->dbi_h_nelem) {
01021                         rc = db->set_h_nelem(db, dbi->dbi_h_nelem);
01022                         rc = cvtdberr(dbi, "db->set_h_nelem", rc, _debug);
01023                         if (rc) break;
01024                     }
01025                     if (dbi->dbi_h_flags) {
01026                         rc = db->set_flags(db, dbi->dbi_h_flags);
01027                         rc = cvtdberr(dbi, "db->set_h_flags", rc, _debug);
01028                         if (rc) break;
01029                     }
01030 /* XXX db-3.2.9 has added a DB arg to the call. */
01031 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 2) || (DB_VERSION_MAJOR == 4)
01032                     if (dbi->dbi_h_hash_fcn) {
01033                         rc = db->set_h_hash(db, dbi->dbi_h_hash_fcn);
01034                         rc = cvtdberr(dbi, "db->set_h_hash", rc, _debug);
01035                         if (rc) break;
01036                     }
01037                     if (dbi->dbi_h_dup_compare_fcn) {
01038                         rc = db->set_dup_compare(db, dbi->dbi_h_dup_compare_fcn);
01039                         rc = cvtdberr(dbi, "db->set_dup_compare", rc, _debug);
01040                         if (rc) break;
01041                     }
01042 #endif
01043                     break;
01044                 case DB_BTREE:
01045                     if (dbi->dbi_bt_flags) {
01046                         rc = db->set_flags(db, dbi->dbi_bt_flags);
01047                         rc = cvtdberr(dbi, "db->set_bt_flags", rc, _debug);
01048                         if (rc) break;
01049                     }
01050                     if (dbi->dbi_bt_minkey) {
01051                         rc = db->set_bt_minkey(db, dbi->dbi_bt_minkey);
01052                         rc = cvtdberr(dbi, "db->set_bt_minkey", rc, _debug);
01053                         if (rc) break;
01054                     }
01055 /* XXX db-3.2.9 has added a DB arg to the call. */
01056 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 2) || (DB_VERSION_MAJOR == 4)
01057                     if (dbi->dbi_bt_compare_fcn) {
01058                         rc = db->set_bt_compare(db, dbi->dbi_bt_compare_fcn);
01059                         rc = cvtdberr(dbi, "db->set_bt_compare", rc, _debug);
01060                         if (rc) break;
01061                     }
01062                     if (dbi->dbi_bt_dup_compare_fcn) {
01063                         rc = db->set_dup_compare(db, dbi->dbi_bt_dup_compare_fcn);
01064                         rc = cvtdberr(dbi, "db->set_dup_compare", rc, _debug);
01065                         if (rc) break;
01066                     }
01067                     if (dbi->dbi_bt_prefix_fcn) {
01068                         rc = db->set_bt_prefix(db, dbi->dbi_bt_prefix_fcn);
01069                         rc = cvtdberr(dbi, "db->set_bt_prefix", rc, _debug);
01070                         if (rc) break;
01071                     }
01072 #endif
01073                     break;
01074                 case DB_RECNO:
01075                     if (dbi->dbi_re_delim) {
01076                         rc = db->set_re_delim(db, dbi->dbi_re_delim);
01077                         rc = cvtdberr(dbi, "db->set_re_selim", rc, _debug);
01078                         if (rc) break;
01079                     }
01080                     if (dbi->dbi_re_len) {
01081                         rc = db->set_re_len(db, dbi->dbi_re_len);
01082                         rc = cvtdberr(dbi, "db->set_re_len", rc, _debug);
01083                         if (rc) break;
01084                     }
01085                     if (dbi->dbi_re_pad) {
01086                         rc = db->set_re_pad(db, dbi->dbi_re_pad);
01087                         rc = cvtdberr(dbi, "db->set_re_pad", rc, _debug);
01088                         if (rc) break;
01089                     }
01090                     if (dbi->dbi_re_source) {
01091                         rc = db->set_re_source(db, dbi->dbi_re_source);
01092                         rc = cvtdberr(dbi, "db->set_re_source", rc, _debug);
01093                         if (rc) break;
01094                     }
01095                     break;
01096                 case DB_QUEUE:
01097                     if (dbi->dbi_q_extentsize) {
01098                         rc = db->set_q_extentsize(db, dbi->dbi_q_extentsize);
01099                         rc = cvtdberr(dbi, "db->set_q_extentsize", rc, _debug);
01100                         if (rc) break;
01101                     }
01102                     break;
01103                 }
01104             }
01105 
01106             if (rc == 0) {
01107                 const char * dbfullpath;
01108                 const char * dbpath;
01109                 char * t;
01110                 int nb;
01111 
01112                 nb = strlen(dbhome);
01113                 if (dbfile)     nb += 1 + strlen(dbfile);
01114                 dbfullpath = t = alloca(nb + 1);
01115 
01116                 t = stpcpy(t, dbhome);
01117                 if (dbfile)
01118                     t = stpcpy( stpcpy( t, "/"), dbfile);
01119 #ifdef  HACK    /* XXX necessary to support dbsubfile */
01120                 dbpath = (!dbi->dbi_use_dbenv && !dbi->dbi_temporary)
01121                         ? dbfullpath : dbfile;
01122 #else
01123                 dbpath = (!dbi->dbi_temporary)
01124                         ? dbfullpath : dbfile;
01125 #endif
01126 
01127                 rc = db->open(db, dbpath, dbsubfile,
01128                     dbi->dbi_type, oflags, dbi->dbi_perms);
01129 
01130                 if (rc == 0 && dbi->dbi_type == DB_UNKNOWN) {
01131 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3 && DB_VERSION_PATCH == 11) \
01132  || (DB_VERSION_MAJOR == 4)
01133                     DBTYPE dbi_type = DB_UNKNOWN;
01134                     xx = db->get_type(db, &dbi_type);
01135                     if (xx == 0)
01136                         dbi->dbi_type = dbi_type;
01137 #else
01138                     dbi->dbi_type = db->get_type(db);
01139 #endif
01140                 }
01141             }
01142 
01143             /* XXX return rc == errno without printing */
01144             _printit = (rc > 0 ? 0 : _debug);
01145             xx = cvtdberr(dbi, "db->open", rc, _printit);
01146 
01147             dbi->dbi_txnid = NULL;
01148 
01149             /*
01150              * Lock a file using fcntl(2). Traditionally this is Packages,
01151              * the file used * to store metadata of installed header(s),
01152              * as Packages is always opened, and should be opened first,
01153              * for any rpmdb access.
01154              *
01155              * If no DBENV is used, then access is protected with a
01156              * shared/exclusive locking scheme, as always.
01157              *
01158              * With a DBENV, the fcntl(2) lock is necessary only to keep
01159              * the riff-raff from playing where they don't belong, as
01160              * the DBENV should provide it's own locking scheme. So try to
01161              * acquire a lock, but permit failures, as some other
01162              * DBENV player may already have acquired the lock.
01163              */
01164             if (rc == 0 && dbi->dbi_lockdbfd &&
01165                 (!dbi->dbi_use_dbenv || _lockdbfd++ == 0))
01166             {
01167                 int fdno = -1;
01168 
01169                 if (!(db->fd(db, &fdno) == 0 && fdno >= 0)) {
01170                     rc = 1;
01171                 } else {
01172                     struct flock l;
01173                     memset(&l, 0, sizeof(l));
01174                     l.l_whence = 0;
01175                     l.l_start = 0;
01176                     l.l_len = 0;
01177                     l.l_type = (dbi->dbi_mode & (O_RDWR|O_WRONLY))
01178                                 ? F_WRLCK : F_RDLCK;
01179                     l.l_pid = 0;
01180 
01181                     rc = fcntl(fdno, F_SETLK, (void *) &l);
01182                     if (rc) {
01183                         /* Warning only if using CDB locking. */
01184                         rc = ((dbi->dbi_use_dbenv &&
01185                                 (dbi->dbi_eflags & DB_INIT_CDB))
01186                             ? 0 : 1);
01187                         rpmError( (rc ? RPMERR_FLOCK : RPMWARN_FLOCK),
01188                                 _("cannot get %s lock on %s/%s\n"),
01189                                 ((dbi->dbi_mode & (O_RDWR|O_WRONLY))
01190                                         ? _("exclusive") : _("shared")),
01191                                 dbhome, (dbfile ? dbfile : ""));
01192                     } else if (dbfile) {
01193                         rpmMessage(RPMMESS_DEBUG,
01194                                 _("locked   db index       %s/%s\n"),
01195                                 dbhome, dbfile);
01196                     }
01197                 }
01198             }
01199         }
01200     }
01201 
01202     dbi->dbi_db = db;
01203 
01204     if (rc == 0 && dbi->dbi_db != NULL && dbip != NULL) {
01205         dbi->dbi_vec = &db3vec;
01206         *dbip = dbi;
01207     } else {
01208         dbi->dbi_verify_on_close = 0;
01209         (void) db3close(dbi, 0);
01210     }
01211 
01212     urlfn = _free(urlfn);
01213 
01214     /*@-nullstate -compmempass@*/
01215     return rc;
01216     /*@=nullstate =compmempass@*/
01217 }
01218 
01221 /*@-exportheadervar@*/
01222 /*@observer@*/ /*@unchecked@*/
01223 struct _dbiVec db3vec = {
01224     DB_VERSION_MAJOR, DB_VERSION_MINOR, DB_VERSION_PATCH,
01225     db3open, db3close, db3sync, db3associate, db3join,
01226     db3copen, db3cclose, db3cdup, db3cdel, db3cget, db3cpget, db3cput, db3ccount,
01227     db3byteswapped, db3stat
01228 };
01229 /*@=exportheadervar@*/
01230 /*@=type@*/

Generated on Tue Sep 17 15:59:55 2002 for rpm by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002