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