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