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