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