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 0
00225 #if HAVE_LIBPTHREAD
00226 #if HAVE_PTHREAD_H
00227 #include <pthread.h>
00228 #endif
00229
00234 static int db3_pthread_nptl(void)
00235
00236 {
00237 pthread_mutex_t mutex;
00238 pthread_mutexattr_t mutexattr, *mutexattrp = NULL;
00239 pthread_cond_t cond;
00240 pthread_condattr_t condattr, *condattrp = NULL;
00241 int ret = 0;
00242
00243 ret = pthread_mutexattr_init(&mutexattr);
00244 if (ret == 0) {
00245 ret = pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED);
00246 mutexattrp = &mutexattr;
00247 }
00248
00249 if (ret == 0)
00250 ret = pthread_mutex_init(&mutex, mutexattrp);
00251 if (mutexattrp != NULL)
00252 pthread_mutexattr_destroy(mutexattrp);
00253 if (ret)
00254 return ret;
00255 (void) pthread_mutex_destroy(&mutex);
00256
00257 ret = pthread_condattr_init(&condattr);
00258 if (ret == 0) {
00259 ret = pthread_condattr_setpshared(&condattr, PTHREAD_PROCESS_SHARED);
00260 condattrp = &condattr;
00261 }
00262
00263 if (ret == 0)
00264 ret = pthread_cond_init(&cond, condattrp);
00265
00266 if (condattrp != NULL)
00267 (void)pthread_condattr_destroy(condattrp);
00268 if (ret == 0)
00269 (void) pthread_cond_destroy(&cond);
00270 return ret;
00271 }
00272 #endif
00273 #endif
00274
00275 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 5)
00276
00284 static int db3is_alive( DB_ENV *dbenv, pid_t pid, db_threadid_t tid,
00285 u_int32_t flags)
00286
00287 {
00288 int is_alive = 1;
00289
00290 switch (flags) {
00291 case DB_MUTEX_PROCESS_ONLY:
00292 case 0:
00293 default:
00294 is_alive = (!(kill(pid, 0) < 0 && errno == ESRCH));
00295 break;
00296 }
00297 return is_alive;
00298 }
00299 #endif
00300
00301
00302 static int db_init(dbiIndex dbi, const char * dbhome,
00303 const char * dbfile,
00304 const char * dbsubfile,
00305 DB_ENV ** dbenvp)
00306
00307
00308
00309 {
00310 rpmdb rpmdb = dbi->dbi_rpmdb;
00311 DB_ENV *dbenv = NULL;
00312 int eflags;
00313 int rc;
00314 int xx;
00315
00316 if (dbenvp == NULL)
00317 return 1;
00318
00319
00320
00321 if (rpmdb->db_errfile == NULL)
00322 rpmdb->db_errfile = stderr;
00323
00324
00325 eflags = (dbi->dbi_oeflags | dbi->dbi_eflags);
00326
00327
00328 if (eflags & DB_JOINENV) eflags &= DB_JOINENV;
00329
00330 if (dbfile)
00331 rpmMessage(RPMMESS_DEBUG, _("opening db environment %s/%s %s\n"),
00332 dbhome, dbfile, prDbiOpenFlags(eflags, 1));
00333
00334
00335 if (dbi->dbi_host == NULL)
00336 dbi->dbi_ecflags &= ~DB_CLIENT;
00337
00338
00339 if ((dbi->dbi_eflags & DB_SYSTEM_MEM) && dbi->dbi_shmkey == 0) {
00340 #if defined(HAVE_FTOK)
00341 dbi->dbi_shmkey = ftok(dbhome, 0);
00342 #else
00343 dbi->dbi_shmkey = 0x44631380;
00344 #endif
00345 }
00346
00347 rc = db_env_create(&dbenv, dbi->dbi_ecflags);
00348 rc = cvtdberr(dbi, "db_env_create", rc, _debug);
00349 if (dbenv == NULL || rc)
00350 goto errxit;
00351
00352
00353
00354
00355
00356
00357
00358
00359 dbenv->set_errcall(dbenv, rpmdb->db_errcall);
00360 dbenv->set_errfile(dbenv, rpmdb->db_errfile);
00361 dbenv->set_errpfx(dbenv, rpmdb->db_errpfx);
00362
00363
00364
00365
00366
00367
00368
00369 if ((dbi->dbi_ecflags & DB_CLIENT) && dbi->dbi_host) {
00370 const char * home;
00371 int retry = 0;
00372
00373 if ((home = strrchr(dbhome, '/')) != NULL)
00374 dbhome = ++home;
00375
00376 while (retry++ < 5) {
00377
00378 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3) || (DB_VERSION_MAJOR == 4)
00379 xx = dbenv->set_rpc_server(dbenv, NULL, dbi->dbi_host,
00380 dbi->dbi_cl_timeout, dbi->dbi_sv_timeout, 0);
00381 xx = cvtdberr(dbi, "dbenv->set_server", xx, _debug);
00382 #else
00383 xx = dbenv->set_server(dbenv, dbi->dbi_host,
00384 dbi->dbi_cl_timeout, dbi->dbi_sv_timeout, 0);
00385 xx = cvtdberr(dbi, "dbenv->set_server", xx, _debug);
00386 #endif
00387 if (!xx)
00388 break;
00389 (void) sleep(15);
00390 }
00391 } else {
00392 #if !(DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3)
00393 xx = dbenv->set_verbose(dbenv, DB_VERB_CHKPOINT,
00394 (dbi->dbi_verbose & DB_VERB_CHKPOINT));
00395 #endif
00396 xx = dbenv->set_verbose(dbenv, DB_VERB_DEADLOCK,
00397 (dbi->dbi_verbose & DB_VERB_DEADLOCK));
00398 xx = dbenv->set_verbose(dbenv, DB_VERB_RECOVERY,
00399 (dbi->dbi_verbose & DB_VERB_RECOVERY));
00400 #if defined(DB_VERB_REGISTER)
00401 xx = dbenv->set_verbose(dbenv, DB_VERB_REGISTER,
00402 (dbi->dbi_verbose & DB_VERB_REGISTER));
00403 #endif
00404 #if defined(DB_VERB_REPLICATION)
00405 xx = dbenv->set_verbose(dbenv, DB_VERB_REPLICATION,
00406 (dbi->dbi_verbose & DB_VERB_REPLICATION));
00407 #endif
00408 xx = dbenv->set_verbose(dbenv, DB_VERB_WAITSFOR,
00409 (dbi->dbi_verbose & DB_VERB_WAITSFOR));
00410
00411 if (dbi->dbi_mmapsize) {
00412 xx = dbenv->set_mp_mmapsize(dbenv, dbi->dbi_mmapsize);
00413 xx = cvtdberr(dbi, "dbenv->set_mp_mmapsize", xx, _debug);
00414 }
00415 if (dbi->dbi_tmpdir) {
00416 const char * root;
00417 const char * tmpdir;
00418
00419 root = (dbi->dbi_root ? dbi->dbi_root : rpmdb->db_root);
00420
00421 if ((root[0] == '/' && root[1] == '\0') || rpmdb->db_chrootDone)
00422 root = NULL;
00423
00424
00425 tmpdir = rpmGenPath(root, dbi->dbi_tmpdir, NULL);
00426
00427 xx = dbenv->set_tmp_dir(dbenv, tmpdir);
00428 xx = cvtdberr(dbi, "dbenv->set_tmp_dir", xx, _debug);
00429 tmpdir = _free(tmpdir);
00430 }
00431 }
00432
00433
00434
00435 if (dbi->dbi_lk_detect) {
00436 xx = dbenv->set_lk_detect(dbenv, dbi->dbi_lk_detect);
00437 xx = cvtdberr(dbi, "dbenv->set_lk_detect", xx, _debug);
00438 }
00439 #if !(DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
00440 if (dbi->dbi_lk_max_lockers) {
00441 xx = dbenv->set_lk_max_lockers(dbenv, dbi->dbi_lk_max_lockers);
00442 xx = cvtdberr(dbi, "dbenv->set_lk_max_lockers", xx, _debug);
00443 }
00444 if (dbi->dbi_lk_max_locks) {
00445 xx = dbenv->set_lk_max_locks(dbenv, dbi->dbi_lk_max_locks);
00446 xx = cvtdberr(dbi, "dbenv->set_lk_max_locks", xx, _debug);
00447 }
00448 if (dbi->dbi_lk_max_objects) {
00449 xx = dbenv->set_lk_max_objects(dbenv, dbi->dbi_lk_max_objects);
00450 xx = cvtdberr(dbi, "dbenv->set_lk_max_objects", xx, _debug);
00451 }
00452
00453 if (dbi->dbi_lg_bsize) {
00454 xx = dbenv->set_lg_bsize(dbenv, dbi->dbi_lg_bsize);
00455 xx = cvtdberr(dbi, "dbenv->set_lg_bsize", xx, _debug);
00456 }
00457 if (dbi->dbi_lg_dir) {
00458 xx = dbenv->set_lg_dir(dbenv, dbi->dbi_lg_dir);
00459 xx = cvtdberr(dbi, "dbenv->set_lg_dir", xx, _debug);
00460 }
00461 if (dbi->dbi_lg_filemode) {
00462 xx = dbenv->set_lg_filemode(dbenv, dbi->dbi_lg_filemode);
00463 xx = cvtdberr(dbi, "dbenv->set_lg_filemode", xx, _debug);
00464 }
00465 if (dbi->dbi_lg_max) {
00466 xx = dbenv->set_lg_max(dbenv, dbi->dbi_lg_max);
00467 xx = cvtdberr(dbi, "dbenv->set_lg_max", xx, _debug);
00468 }
00469 if (dbi->dbi_lg_regionmax) {
00470 xx = dbenv->set_lg_regionmax(dbenv, dbi->dbi_lg_regionmax);
00471 xx = cvtdberr(dbi, "dbenv->set_lg_regionmax", xx, _debug);
00472 }
00473 #endif
00474
00475
00476 if (dbi->dbi_cachesize) {
00477 xx = dbenv->set_cachesize(dbenv, 0, dbi->dbi_cachesize, 0);
00478 xx = cvtdberr(dbi, "dbenv->set_cachesize", xx, _debug);
00479 }
00480
00481
00482 if (dbi->dbi_mutex_align) {
00483 xx = dbenv->mutex_set_align(dbenv, dbi->dbi_mutex_align);
00484 xx = cvtdberr(dbi, "dbenv->mutex_set_align", xx, _debug);
00485 }
00486 if (dbi->dbi_mutex_increment) {
00487 xx = dbenv->mutex_set_increment(dbenv, dbi->dbi_mutex_increment);
00488 xx = cvtdberr(dbi, "dbenv->mutex_set_increment", xx, _debug);
00489 }
00490 if (dbi->dbi_mutex_max) {
00491 xx = dbenv->mutex_set_max(dbenv, dbi->dbi_mutex_max);
00492 xx = cvtdberr(dbi, "dbenv->mutex_set_max", xx, _debug);
00493 }
00494 if (dbi->dbi_mutex_tas_spins) {
00495 xx = dbenv->mutex_set_tas_spins(dbenv, dbi->dbi_mutex_tas_spins);
00496 xx = cvtdberr(dbi, "dbenv->mutex_set_tas_spins", xx, _debug);
00497 }
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510 if (dbi->dbi_tx_max) {
00511 xx = dbenv->set_tx_max(dbenv, dbi->dbi_tx_max);
00512 xx = cvtdberr(dbi, "dbenv->set_tx_max", xx, _debug);
00513 }
00514
00515
00516
00517
00518
00519
00520
00521
00522 if (dbi->dbi_no_fsync) {
00523 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR != 0) || (DB_VERSION_MAJOR == 4)
00524 xx = db_env_set_func_fsync(db3_fsync_disable);
00525 #else
00526 xx = dbenv->set_func_fsync(dbenv, db3_fsync_disable);
00527 #endif
00528 xx = cvtdberr(dbi, "db_env_set_func_fsync", xx, _debug);
00529 }
00530
00531 if (dbi->dbi_shmkey) {
00532 xx = dbenv->set_shm_key(dbenv, dbi->dbi_shmkey);
00533 xx = cvtdberr(dbi, "dbenv->set_shm_key", xx, _debug);
00534 }
00535
00536 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 5)
00537
00538
00539 dbenv->set_msgfile(dbenv, rpmdb->db_errfile);
00540
00541
00542 if (dbi->dbi_thread_count >= 8) {
00543 xx = dbenv->set_thread_count(dbenv, dbi->dbi_thread_count);
00544 xx = cvtdberr(dbi, "dbenv->set_thread_count", xx, _debug);
00545 }
00546 #endif
00547
00548 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR != 0) || (DB_VERSION_MAJOR == 4)
00549 rc = dbenv->open(dbenv, dbhome, eflags, dbi->dbi_perms);
00550 #else
00551 rc = dbenv->open(dbenv, dbhome, NULL, eflags, dbi->dbi_perms);
00552 #endif
00553 xx = _debug;
00554 #if defined(DB_VERSION_MISMATCH)
00555 if (rc == DB_VERSION_MISMATCH) xx = 0;
00556 #endif
00557 if (rc == EINVAL) xx = 0;
00558 rc = cvtdberr(dbi, "dbenv->open", rc, xx);
00559 if (rc)
00560 goto errxit;
00561
00562 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 5)
00563 if (!rpmdb->db_verifying && dbi->dbi_thread_count >= 8) {
00564
00565 xx = dbenv->set_isalive(dbenv, db3is_alive);
00566 xx = cvtdberr(dbi, "dbenv->set_isalive", xx, _debug);
00567
00568 xx = dbenv->failchk(dbenv, 0);
00569 xx = cvtdberr(dbi, "dbenv->failchk", xx, _debug);
00570 if (xx == DB_RUNRECOVERY) {
00571 rc = xx;
00572 goto errxit;
00573 }
00574 }
00575 #endif
00576
00577
00578 *dbenvp = dbenv;
00579
00580
00581 return 0;
00582
00583 errxit:
00584 if (dbenv) {
00585 xx = dbenv->close(dbenv, 0);
00586 xx = cvtdberr(dbi, "dbenv->close", xx, _debug);
00587 }
00588 return rc;
00589 }
00590
00591
00592 static int db3sync(dbiIndex dbi, unsigned int flags)
00593
00594
00595 {
00596 DB * db = dbi->dbi_db;
00597 int rc = 0;
00598 int _printit;
00599
00600 if (db != NULL)
00601 rc = db->sync(db, flags);
00602 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
00603 _printit = _debug;
00604 #else
00605
00606 _printit = (rc == DB_INCOMPLETE ? 0 : _debug);
00607 #endif
00608 rc = cvtdberr(dbi, "db->sync", rc, _printit);
00609 return rc;
00610 }
00611
00612 static int db3cdup(dbiIndex dbi, DBC * dbcursor, DBC ** dbcp,
00613 unsigned int flags)
00614
00615
00616 {
00617 int rc;
00618
00619
00620 if (dbcp) *dbcp = NULL;
00621
00622 rc = dbcursor->c_dup(dbcursor, dbcp, flags);
00623 rc = cvtdberr(dbi, "dbcursor->c_dup", rc, _debug);
00624
00625 return rc;
00626
00627 }
00628
00629
00630 static int db3cclose(dbiIndex dbi, DBC * dbcursor,
00631 unsigned int flags)
00632
00633
00634 {
00635 int rc = -2;
00636
00637
00638 if (dbcursor != NULL) {
00639 rc = dbcursor->c_close(dbcursor);
00640 rc = cvtdberr(dbi, "dbcursor->c_close", rc, _debug);
00641 }
00642 return rc;
00643 }
00644
00645
00646 static int db3copen(dbiIndex dbi, DB_TXN * txnid,
00647 DBC ** dbcp, unsigned int dbiflags)
00648
00649
00650 {
00651 DB * db = dbi->dbi_db;
00652 DBC * dbcursor = NULL;
00653 int flags;
00654 int rc;
00655
00656
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 unsigned int flags)
00678
00679
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 rc = dbcursor->c_put(dbcursor, key, data, DB_KEYLAST);
00690 rc = cvtdberr(dbi, "dbcursor->c_put", rc, _debug);
00691 }
00692
00693 return rc;
00694 }
00695
00696
00697 static int db3cdel(dbiIndex dbi, DBC * dbcursor, DBT * key, DBT * data,
00698 unsigned int flags)
00699
00700
00701 {
00702 DB * db = dbi->dbi_db;
00703 int rc;
00704
00705 assert(db != NULL);
00706 if (dbcursor == NULL) {
00707 rc = db->del(db, dbi->dbi_txnid, key, flags);
00708 rc = cvtdberr(dbi, "db->del", rc, _debug);
00709 } else {
00710 int _printit;
00711
00712
00713 rc = dbcursor->c_get(dbcursor, key, data, DB_SET);
00714
00715 _printit = (rc == DB_NOTFOUND ? 0 : _debug);
00716 rc = cvtdberr(dbi, "dbcursor->c_get", rc, _printit);
00717
00718 if (rc == 0) {
00719 rc = dbcursor->c_del(dbcursor, flags);
00720 rc = cvtdberr(dbi, "dbcursor->c_del", rc, _debug);
00721 }
00722 }
00723
00724 return rc;
00725 }
00726
00727
00728
00729 static int db3cget(dbiIndex dbi, DBC * dbcursor, DBT * key, DBT * data,
00730 unsigned int flags)
00731
00732
00733 {
00734 DB * db = dbi->dbi_db;
00735 int _printit;
00736 int rc;
00737
00738 assert(db != NULL);
00739 if (dbcursor == NULL) {
00740
00741 rc = db->get(db, dbi->dbi_txnid, key, data, 0);
00742
00743 _printit = (rc == DB_NOTFOUND ? 0 : _debug);
00744 rc = cvtdberr(dbi, "db->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 }
00752
00753 return rc;
00754 }
00755
00756
00757
00758 static int db3cpget(dbiIndex dbi, DBC * dbcursor, DBT * key, DBT * pkey,
00759 DBT * data, unsigned int flags)
00760
00761
00762 {
00763 DB * db = dbi->dbi_db;
00764 int _printit;
00765 int rc;
00766
00767 assert(db != NULL);
00768 assert(dbcursor != NULL);
00769
00770
00771 rc = dbcursor->c_pget(dbcursor, key, pkey, data, flags);
00772
00773 _printit = (rc == DB_NOTFOUND ? 0 : _debug);
00774 rc = cvtdberr(dbi, "dbcursor->c_pget", rc, _printit);
00775
00776 return rc;
00777 }
00778
00779
00780 static int db3ccount(dbiIndex dbi, DBC * dbcursor,
00781 unsigned int * countp,
00782 unsigned int flags)
00783
00784
00785 {
00786 db_recno_t count = 0;
00787 int rc = 0;
00788
00789 flags = 0;
00790 rc = dbcursor->c_count(dbcursor, &count, flags);
00791 rc = cvtdberr(dbi, "dbcursor->c_count", rc, _debug);
00792 if (rc) return rc;
00793
00794 if (countp) *countp = count;
00795
00796
00797 return rc;
00798 }
00799
00800 static int db3byteswapped(dbiIndex dbi)
00801 {
00802 DB * db = dbi->dbi_db;
00803 int rc = 0;
00804
00805 if (db != NULL) {
00806 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3 && DB_VERSION_PATCH == 11) \
00807 || (DB_VERSION_MAJOR == 4)
00808 int isswapped = 0;
00809 rc = db->get_byteswapped(db, &isswapped);
00810 if (rc == 0)
00811 rc = isswapped;
00812 #else
00813 rc = db->get_byteswapped(db);
00814 #endif
00815 }
00816
00817 return rc;
00818 }
00819
00820 static int db3stat(dbiIndex dbi, unsigned int flags)
00821
00822
00823 {
00824 DB * db = dbi->dbi_db;
00825 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3)
00826 DB_TXN * txnid = NULL;
00827 #endif
00828 int rc = 0;
00829
00830 assert(db != NULL);
00831 #if defined(DB_FAST_STAT)
00832 if (flags)
00833 flags = DB_FAST_STAT;
00834 else
00835 #endif
00836 flags = 0;
00837 dbi->dbi_stats = _free(dbi->dbi_stats);
00838
00839 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3) || (DB_VERSION_MAJOR == 4)
00840 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3)
00841 rc = db->stat(db, txnid, &dbi->dbi_stats, flags);
00842 #else
00843 rc = db->stat(db, &dbi->dbi_stats, flags);
00844 #endif
00845 #else
00846 rc = db->stat(db, &dbi->dbi_stats, NULL, flags);
00847 #endif
00848 rc = cvtdberr(dbi, "db->stat", rc, _debug);
00849 return rc;
00850 }
00851
00852
00853 static int db3associate(dbiIndex dbi, dbiIndex dbisecondary,
00854 int (*callback)(DB *, const DBT *, const DBT *, DBT *),
00855 unsigned int flags)
00856
00857
00858 {
00859 DB * db = dbi->dbi_db;
00860 DB * secondary = dbisecondary->dbi_db;
00861 int rc;
00862
00863
00864 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
00865 DB_TXN * txnid = NULL;
00866
00867 assert(db != NULL);
00868 rc = db->associate(db, txnid, secondary, callback, flags);
00869 #else
00870 assert(db != NULL);
00871 rc = db->associate(db, secondary, callback, flags);
00872 #endif
00873
00874 rc = cvtdberr(dbi, "db->associate", rc, _debug);
00875 return rc;
00876 }
00877
00878
00879
00880 static int db3join(dbiIndex dbi, DBC ** curslist, DBC ** dbcp,
00881 unsigned int flags)
00882
00883
00884 {
00885 DB * db = dbi->dbi_db;
00886 int rc;
00887
00888 assert(db != NULL);
00889
00890 rc = db->join(db, curslist, dbcp, flags);
00891
00892 rc = cvtdberr(dbi, "db->join", rc, _debug);
00893 return rc;
00894 }
00895
00896
00897
00898 static int db3close( dbiIndex dbi, unsigned int flags)
00899
00900
00901
00902 {
00903 rpmdb rpmdb = dbi->dbi_rpmdb;
00904 const char * urlfn = NULL;
00905 const char * root;
00906 const char * home;
00907 const char * dbhome;
00908 const char * dbfile;
00909 const char * dbsubfile;
00910 DB * db = dbi->dbi_db;
00911 int _printit;
00912 int rc = 0, xx;
00913
00914 flags = 0;
00915
00916
00917
00918
00919 root = (dbi->dbi_root ? dbi->dbi_root : rpmdb->db_root);
00920
00921 if ((root[0] == '/' && root[1] == '\0') || rpmdb->db_chrootDone)
00922 root = NULL;
00923
00924 home = (dbi->dbi_home ? dbi->dbi_home : rpmdb->db_home);
00925
00926
00927
00928
00929
00930
00931 urlfn = rpmGenPath(root, home, NULL);
00932
00933 (void) urlPath(urlfn, &dbhome);
00934 if (dbi->dbi_temporary) {
00935 dbfile = NULL;
00936 dbsubfile = NULL;
00937 } else {
00938 #ifdef HACK
00939 dbfile = (dbi->dbi_file ? dbi->dbi_file : db3basename);
00940 dbsubfile = (dbi->dbi_subfile ? dbi->dbi_subfile : tagName(dbi->dbi_rpmtag));
00941 #else
00942 dbfile = (dbi->dbi_file ? dbi->dbi_file : tagName(dbi->dbi_rpmtag));
00943 dbsubfile = NULL;
00944 #endif
00945 }
00946
00947 if (db) {
00948 rc = db->close(db, 0);
00949
00950 _printit = (rc == ENOENT ? 0 : _debug);
00951 rc = cvtdberr(dbi, "db->close", rc, _printit);
00952 db = dbi->dbi_db = NULL;
00953
00954 rpmMessage(RPMMESS_DEBUG, _("closed db index %s/%s\n"),
00955 dbhome, (dbfile ? dbfile : tagName(dbi->dbi_rpmtag)));
00956
00957 }
00958
00959 if (rpmdb->db_dbenv != NULL && dbi->dbi_use_dbenv) {
00960 if (rpmdb->db_opens == 1) {
00961
00962 xx = db_fini(dbi, (dbhome ? dbhome : ""), dbfile, dbsubfile);
00963
00964 rpmdb->db_dbenv = NULL;
00965 }
00966 rpmdb->db_opens--;
00967 }
00968
00969 if (dbi->dbi_verify_on_close && !dbi->dbi_temporary) {
00970 DB_ENV * dbenv = NULL;
00971 int eflags;
00972
00973
00974 rc = db_env_create(&dbenv, 0);
00975
00976 rc = cvtdberr(dbi, "db_env_create", rc, _debug);
00977 if (rc || dbenv == NULL) goto exit;
00978
00979
00980 dbenv->set_errcall(dbenv, rpmdb->db_errcall);
00981 dbenv->set_errfile(dbenv, rpmdb->db_errfile);
00982 dbenv->set_errpfx(dbenv, rpmdb->db_errpfx);
00983
00984
00985 #if !(DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3)
00986 xx = dbenv->set_verbose(dbenv, DB_VERB_CHKPOINT,
00987 (dbi->dbi_verbose & DB_VERB_CHKPOINT));
00988 #endif
00989 xx = dbenv->set_verbose(dbenv, DB_VERB_DEADLOCK,
00990 (dbi->dbi_verbose & DB_VERB_DEADLOCK));
00991 xx = dbenv->set_verbose(dbenv, DB_VERB_RECOVERY,
00992 (dbi->dbi_verbose & DB_VERB_RECOVERY));
00993 xx = dbenv->set_verbose(dbenv, DB_VERB_WAITSFOR,
00994 (dbi->dbi_verbose & DB_VERB_WAITSFOR));
00995
00996 if (dbi->dbi_tmpdir) {
00997
00998 const char * tmpdir = rpmGenPath(root, dbi->dbi_tmpdir, NULL);
00999
01000 rc = dbenv->set_tmp_dir(dbenv, tmpdir);
01001 rc = cvtdberr(dbi, "dbenv->set_tmp_dir", rc, _debug);
01002 tmpdir = _free(tmpdir);
01003 if (rc) goto exit;
01004 }
01005
01006 eflags = DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE | DB_USE_ENVIRON;
01007 rc = dbenv->open(dbenv, dbhome, eflags, 0);
01008 rc = cvtdberr(dbi, "dbenv->open", rc, _debug);
01009 if (rc) goto exit;
01010
01011
01012 rc = db_create(&db, dbenv, 0);
01013
01014 rc = cvtdberr(dbi, "db_create", rc, _debug);
01015
01016 if (db != NULL) {
01017
01018 const char * dbf = rpmGetPath(dbhome, "/", dbfile, NULL);
01019
01020
01021 rc = db->verify(db, dbf, NULL, NULL, flags);
01022 rc = cvtdberr(dbi, "db->verify", rc, _debug);
01023
01024 rpmMessage(RPMMESS_DEBUG, _("verified db index %s/%s\n"),
01025 (dbhome ? dbhome : ""),
01026 (dbfile ? dbfile : tagName(dbi->dbi_rpmtag)));
01027
01028
01029
01030
01031
01032 db = NULL;
01033 dbf = _free(dbf);
01034 }
01035 xx = dbenv->close(dbenv, 0);
01036 xx = cvtdberr(dbi, "dbenv->close", xx, _debug);
01037 if (rc == 0 && xx) rc = xx;
01038 }
01039
01040 exit:
01041 dbi->dbi_db = NULL;
01042
01043 urlfn = _free(urlfn);
01044
01045 dbi = db3Free(dbi);
01046
01047 return rc;
01048 }
01049
01050
01051 static int db3open(rpmdb rpmdb, rpmTag rpmtag, dbiIndex * dbip)
01052
01053
01054
01055 {
01056
01057 extern struct _dbiVec db3vec;
01058
01059 const char * urlfn = NULL;
01060 const char * root;
01061 const char * home;
01062 const char * dbhome;
01063 const char * dbfile;
01064 const char * dbsubfile;
01065 dbiIndex dbi = NULL;
01066 int rc = 0;
01067 int xx;
01068
01069 DB * db = NULL;
01070 DB_ENV * dbenv = NULL;
01071 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
01072 DB_TXN * txnid = NULL;
01073 #endif
01074 DBTYPE dbi_type = DB_UNKNOWN;
01075 u_int32_t oflags;
01076 int _printit;
01077
01078
01079 if (dbip)
01080 *dbip = NULL;
01081
01082
01083
01084
01085
01086
01087 if ((dbi = db3New(rpmdb, rpmtag)) == NULL)
01088
01089 return 1;
01090
01091
01092 dbi->dbi_api = DB_VERSION_MAJOR;
01093
01094
01095
01096
01097 root = (dbi->dbi_root ? dbi->dbi_root : rpmdb->db_root);
01098
01099 if ((root[0] == '/' && root[1] == '\0') || rpmdb->db_chrootDone)
01100 root = NULL;
01101
01102 home = (dbi->dbi_home ? dbi->dbi_home : rpmdb->db_home);
01103
01104
01105
01106
01107
01108
01109 urlfn = rpmGenPath(root, home, NULL);
01110
01111 (void) urlPath(urlfn, &dbhome);
01112 if (dbi->dbi_temporary) {
01113 dbfile = NULL;
01114 dbsubfile = NULL;
01115 } else {
01116 #ifdef HACK
01117 dbfile = (dbi->dbi_file ? dbi->dbi_file : db3basename);
01118 dbsubfile = (dbi->dbi_subfile ? dbi->dbi_subfile : tagName(dbi->dbi_rpmtag));
01119 #else
01120 dbfile = (dbi->dbi_file ? dbi->dbi_file : tagName(dbi->dbi_rpmtag));
01121 dbsubfile = NULL;
01122 #endif
01123 }
01124
01125 oflags = (dbi->dbi_oeflags | dbi->dbi_oflags);
01126 oflags &= ~DB_TRUNCATE;
01127
01128 #if 0
01129 if ( dbi->dbi_mode & O_EXCL) oflags |= DB_EXCL;
01130 #endif
01131
01132
01133
01134
01135 if (dbi->dbi_temporary) {
01136 oflags |= DB_CREATE;
01137 dbi->dbi_oeflags |= DB_CREATE;
01138 oflags &= ~DB_RDONLY;
01139 dbi->dbi_oflags &= ~DB_RDONLY;
01140 } else {
01141 if (!(dbi->dbi_mode & (O_RDWR|O_WRONLY))) oflags |= DB_RDONLY;
01142 if (dbi->dbi_mode & O_CREAT) {
01143 oflags |= DB_CREATE;
01144 dbi->dbi_oeflags |= DB_CREATE;
01145 }
01146 #ifdef DANGEROUS
01147 if ( dbi->dbi_mode & O_TRUNC) oflags |= DB_TRUNCATE;
01148 #endif
01149 }
01150
01151
01152
01153
01154 (void) rpmioMkpath(dbhome, 0755, getuid(), getgid());
01155
01156
01157
01158
01159 if (dbi->dbi_use_dbenv) {
01160
01161 #if 0
01162 #if HAVE_LIBPTHREAD
01163 if (rpmdb->db_dbenv == NULL) {
01164
01165 xx = db3_pthread_nptl();
01166 if (xx) {
01167 dbi->dbi_eflags |= DB_PRIVATE;
01168 rpmMessage(RPMMESS_DEBUG, _("unshared posix mutexes found(%d), adding DB_PRIVATE, using fcntl lock\n"), xx);
01169 }
01170 }
01171 #endif
01172 #endif
01173
01174 if (access(dbhome, W_OK) == -1) {
01175
01176
01177 oflags &= ~DB_CREATE;
01178
01179
01180 if (dbi->dbi_eflags & DB_PRIVATE) {
01181 dbi->dbi_eflags &= ~DB_JOINENV;
01182 } else {
01183 dbi->dbi_eflags |= DB_JOINENV;
01184 dbi->dbi_oeflags &= ~DB_CREATE;
01185 dbi->dbi_oeflags &= ~DB_THREAD;
01186
01187 dbi->dbi_use_dbenv = 0;
01188 }
01189
01190
01191 if (dbi->dbi_temporary) {
01192 oflags |= DB_CREATE;
01193 dbi->dbi_oeflags |= DB_CREATE;
01194 oflags &= ~DB_RDONLY;
01195 dbi->dbi_oflags &= ~DB_RDONLY;
01196 } else {
01197 oflags |= DB_RDONLY;
01198
01199 dbi->dbi_oflags |= DB_RDONLY;
01200 }
01201
01202 } else {
01203
01204 const char * dbf = rpmGetPath(dbhome, "/__db.001", NULL);
01205
01206
01207 if (access(dbf, F_OK) == -1) {
01208
01209 dbi->dbi_oeflags |= DB_CREATE;
01210 dbi->dbi_eflags &= ~DB_JOINENV;
01211 } else {
01212
01213 if (dbi->dbi_eflags & DB_PRIVATE) {
01214 dbi->dbi_eflags &= ~DB_JOINENV;
01215 } else {
01216 dbi->dbi_eflags |= DB_JOINENV;
01217 dbi->dbi_oeflags &= ~DB_CREATE;
01218 dbi->dbi_oeflags &= ~DB_THREAD;
01219 }
01220 }
01221 dbf = _free(dbf);
01222 }
01223 }
01224
01225
01226
01227
01228 if ((oflags & DB_CREATE) && (oflags & DB_RDONLY)) {
01229
01230 const char * dbfn = (dbfile ? dbfile : tagName(dbi->dbi_rpmtag));
01231
01232 const char * dbf = rpmGetPath(dbhome, "/", dbfn, NULL);
01233
01234
01235 if (access(dbf, F_OK) == -1) {
01236
01237 oflags &= ~DB_RDONLY;
01238 } else {
01239
01240 oflags &= ~DB_CREATE;
01241 }
01242
01243
01244 if (!(oflags & DB_RDONLY) && access(dbf, W_OK) == 0) {
01245 dbi->dbi_oflags &= ~DB_RDONLY;
01246 } else {
01247 dbi->dbi_oflags |= DB_RDONLY;
01248 }
01249 dbf = _free(dbf);
01250 }
01251
01252