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