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 #include <rpmdb.h>
00020
00021 #include "debug.h"
00022
00023
00024
00025
00026
00030
00031 struct dbiHStats_s {
00032 unsigned int hash_magic;
00033 unsigned int hash_version;
00034 unsigned int hash_nkeys;
00035 unsigned int hash_ndata;
00036 unsigned int hash_pagesize;
00037 unsigned int hash_nelem;
00038 unsigned int hash_ffactor;
00039 unsigned int hash_buckets;
00040 unsigned int hash_free;
00041 unsigned int hash_bfree;
00042 unsigned int hash_bigpages;
00043 unsigned int hash_big_bfree;
00044 unsigned int hash_overflows;
00045 unsigned int hash_ovfl_free;
00046 unsigned int hash_dup;
00047 unsigned int hash_dup_free;
00048 };
00049
00053 struct dbiBStats_s {
00054 unsigned int bt_magic;
00055 unsigned int bt_version;
00056 unsigned int bt_nkeys;
00057 unsigned int bt_ndata;
00058 unsigned int bt_pagesize;
00059 unsigned int bt_minkey;
00060 unsigned int bt_re_len;
00061 unsigned int bt_re_pad;
00062 unsigned int bt_levels;
00063 unsigned int bt_int_pg;
00064 unsigned int bt_leaf_pg;
00065 unsigned int bt_dup_pg;
00066 unsigned int bt_over_pg;
00067 unsigned int bt_free;
00068 unsigned int bt_int_pgfree;
00069 unsigned int bt_leaf_pgfree;
00070 unsigned int bt_dup_pgfree;
00071 unsigned int bt_over_pgfree;
00072 };
00073
00074
00075 #ifdef NOTNOW
00076 static const char * bfstring(unsigned int x, const char * xbf)
00077 {
00078 const char * s = xbf;
00079 static char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
00080 static char buf[256];
00081 char * t, * te;
00082 unsigned radix;
00083 unsigned c, i, k;
00084
00085 radix = (s != NULL ? *s++ : 16);
00086
00087 if (radix <= 1 || radix >= 32)
00088 radix = 16;
00089
00090 t = buf;
00091 switch (radix) {
00092 case 8: *t++ = '0'; break;
00093 case 16: *t++ = '0'; *t++ = 'x'; break;
00094 }
00095
00096 i = 0;
00097 k = x;
00098 do { i++; k /= radix; } while (k);
00099
00100 te = t + i;
00101
00102 k = x;
00103 do { --i; t[i] = digits[k % radix]; k /= radix; } while (k);
00104
00105 t = te;
00106 i = '<';
00107 if (s != NULL)
00108 while ((c = *s++) != '\0') {
00109 if (c > ' ') continue;
00110
00111 k = (1 << (c - 1));
00112 if (!(x & k)) continue;
00113
00114 if (t == te) *t++ = '=';
00115
00116 *t++ = i;
00117 i = ',';
00118 while (*s > ' ')
00119 *t++ = *s++;
00120 }
00121 if (t > te) *t++ = '>';
00122 *t = '\0';
00123 return buf;
00124 }
00125
00126 static const char * dbtFlags =
00127 "\20\1APPMALLOC\2ISSET\3MALLOC\4PARTIAL\5REALLOC\6USERMEM\7DUPOK";
00128
00129 static const char * dbenvOpenFlags =
00130 "\20\1CREATE\2NO_EXCEPTIONS\3FORCE\4NOMMAP\5RDONLY\6RECOVER\7THREAD\10TXN_NOSYNC\11USE_ENVIRON\12USE_ENVIRON_ROOT\13CDB\14LOCK\15LOG\16MPOOL\17TXN\20JOINENV\21LOCKDOWN\22PRIVATE\23RECOVER_FATAL\24SYSTEM_MEM";
00131
00132 static const char * dbOpenFlags =
00133 "\20\1CREATE\2NO_EXCEPTIONS\3FORCE\4NOMMAP\5RDONLY\6RECOVER\7THREAD\10TXN_NOSYNC\11USE_ENVIRON\12USE_ENVIRON_ROOT\13EXCL\14FCNTL_LOCKING\15RDWRMASTER\16TRUNCATE\17EXTENT\20APPLY_LOGREG";
00134
00135 static const char * dbenvSetFlags =
00136 "\20\1CREATE\2NO_EXCEPTIONS\3FORCE\4NOMMAP\5RDONLY\6RECOVER\7THREAD\10TXN_NOSYNC\11USE_ENVIRON\12USE_ENVIRON_ROOT\13CDB_ALLDB\14NOLOCKING\15NOPANIC\16PANIC_ENV\17REGION_INIT\20YIELDCPU";
00137
00138 static const char * dbSetFlags =
00139 "\20\1DUP\2DUPSORT\3RECNUM\4RENUMBER\5REVSPLITOFF\6SNAPSHOT";
00140
00141 static const char * dbiModeFlags =
00142 "\20\1WRONLY\2RDWR\7CREAT\10EXCL\11NOCTTY\12TRUNC\13APPEND\14NONBLOCK\15SYNC\16ASYNC\17DIRECT\20LARGEFILE\21DIRECTORY\22NOFOLLOW";
00143 #endif
00144
00145
00146
00147 static int cvtdberr(dbiIndex dbi, const char * msg, int error, int printit)
00148
00149
00150 {
00151 int rc = error;
00152
00153 if (printit && rc) {
00154
00155 if (msg)
00156 rpmError(RPMERR_DBERR, _("db%d error(%d) from %s: %s\n"),
00157 dbi->dbi_api, rc, msg, db_strerror(error));
00158 else
00159 rpmError(RPMERR_DBERR, _("db%d error(%d): %s\n"),
00160 dbi->dbi_api, rc, db_strerror(error));
00161
00162 }
00163
00164 return rc;
00165 }
00166
00167
00168 static int db_fini(dbiIndex dbi, const char * dbhome,
00169 const char * dbfile,
00170 const char * dbsubfile)
00171
00172
00173 {
00174 rpmdb rpmdb = dbi->dbi_rpmdb;
00175 DB_ENV * dbenv = rpmdb->db_dbenv;
00176 int rc;
00177
00178 if (dbenv == NULL)
00179 return 0;
00180
00181 rc = dbenv->close(dbenv, 0);
00182 rc = cvtdberr(dbi, "dbenv->close", rc, _debug);
00183
00184 if (dbfile)
00185 rpmMessage(RPMMESS_DEBUG, _("closed db environment %s/%s\n"),
00186 dbhome, dbfile);
00187
00188 if (rpmdb->db_remove_env) {
00189 int xx;
00190
00191
00192 xx = db_env_create(&dbenv, 0);
00193
00194 xx = cvtdberr(dbi, "db_env_create", rc, _debug);
00195 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR != 0) || (DB_VERSION_MAJOR == 4)
00196 xx = dbenv->remove(dbenv, dbhome, 0);
00197 #else
00198 xx = dbenv->remove(dbenv, dbhome, NULL, 0);
00199 #endif
00200 xx = cvtdberr(dbi, "dbenv->remove", rc, _debug);
00201
00202 if (dbfile)
00203 rpmMessage(RPMMESS_DEBUG, _("removed db environment %s/%s\n"),
00204 dbhome, dbfile);
00205
00206 }
00207 return rc;
00208 }
00209
00210 static int db3_fsync_disable( int fd)
00211
00212 {
00213 return 0;
00214 }
00215
00216
00217 static int db_init(dbiIndex dbi, const char * dbhome,
00218 const char * dbfile,
00219 const char * dbsubfile,
00220 DB_ENV ** dbenvp)
00221
00222
00223
00224 {
00225 rpmdb rpmdb = dbi->dbi_rpmdb;
00226 DB_ENV *dbenv = NULL;
00227 int eflags;
00228 int rc;
00229
00230 if (dbenvp == NULL)
00231 return 1;
00232
00233
00234
00235 if (rpmdb->db_errfile == NULL)
00236 rpmdb->db_errfile = stderr;
00237
00238
00239 eflags = (dbi->dbi_oeflags | dbi->dbi_eflags);
00240 if (eflags & DB_JOINENV) eflags &= DB_JOINENV;
00241
00242 if (dbfile)
00243 rpmMessage(RPMMESS_DEBUG, _("opening db environment %s/%s %s\n"),
00244 dbhome, dbfile, prDbiOpenFlags(eflags, 1));
00245
00246
00247 if (dbi->dbi_host == NULL)
00248 dbi->dbi_ecflags &= ~DB_CLIENT;
00249
00250
00251 if ((dbi->dbi_eflags & DB_SYSTEM_MEM) && dbi->dbi_shmkey == 0) {
00252 #if defined(HAVE_FTOK)
00253 dbi->dbi_shmkey = ftok(dbhome, 0);
00254 #else
00255 dbi->dbi_shmkey = 0x44631380;
00256 #endif
00257 }
00258
00259 rc = db_env_create(&dbenv, dbi->dbi_ecflags);
00260 rc = cvtdberr(dbi, "db_env_create", rc, _debug);
00261 if (rc)
00262 goto errxit;
00263
00264 if (dbenv == NULL)
00265 return 1;
00266
00267 { int xx;
00268
00269 dbenv->set_errcall(dbenv, rpmdb->db_errcall);
00270 dbenv->set_errfile(dbenv, rpmdb->db_errfile);
00271 dbenv->set_errpfx(dbenv, rpmdb->db_errpfx);
00272
00273
00274 xx = dbenv->set_verbose(dbenv, DB_VERB_CHKPOINT,
00275 (dbi->dbi_verbose & DB_VERB_CHKPOINT));
00276 xx = dbenv->set_verbose(dbenv, DB_VERB_DEADLOCK,
00277 (dbi->dbi_verbose & DB_VERB_DEADLOCK));
00278 xx = dbenv->set_verbose(dbenv, DB_VERB_RECOVERY,
00279 (dbi->dbi_verbose & DB_VERB_RECOVERY));
00280 xx = dbenv->set_verbose(dbenv, DB_VERB_WAITSFOR,
00281 (dbi->dbi_verbose & DB_VERB_WAITSFOR));
00282
00283
00284
00285
00286 xx = dbenv->set_mp_mmapsize(dbenv, dbi->dbi_mp_mmapsize);
00287 xx = cvtdberr(dbi, "dbenv->set_mp_mmapsize", xx, _debug);
00288 xx = dbenv->set_cachesize(dbenv, 0, dbi->dbi_mp_size, 0);
00289 xx = cvtdberr(dbi, "dbenv->set_cachesize", xx, _debug);
00290
00291
00292 if (dbi->dbi_no_fsync) {
00293 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR != 0) || (DB_VERSION_MAJOR == 4)
00294 xx = db_env_set_func_fsync(db3_fsync_disable);
00295 #else
00296 xx = dbenv->set_func_fsync(dbenv, db3_fsync_disable);
00297 #endif
00298 xx = cvtdberr(dbi, "db_env_set_func_fsync", xx, _debug);
00299 }
00300
00301
00302 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3) || (DB_VERSION_MAJOR == 4)
00303 if ((dbi->dbi_ecflags & DB_CLIENT) && dbi->dbi_host) {
00304 xx = dbenv->set_rpc_server(dbenv, NULL, dbi->dbi_host,
00305 dbi->dbi_cl_timeout, dbi->dbi_sv_timeout, 0);
00306 xx = cvtdberr(dbi, "dbenv->set_server", xx, _debug);
00307 }
00308 #else
00309 if ((dbi->dbi_ecflags & DB_CLIENT) && dbi->dbi_host) {
00310 xx = dbenv->set_server(dbenv, dbi->dbi_host,
00311 dbi->dbi_cl_timeout, dbi->dbi_sv_timeout, 0);
00312 xx = cvtdberr(dbi, "dbenv->set_server", xx, _debug);
00313 }
00314 #endif
00315 if (dbi->dbi_shmkey) {
00316 xx = dbenv->set_shm_key(dbenv, dbi->dbi_shmkey);
00317 xx = cvtdberr(dbi, "dbenv->set_shm_key", xx, _debug);
00318 }
00319 if (dbi->dbi_tmpdir) {
00320 const char * root;
00321 const char * tmpdir;
00322
00323 root = (dbi->dbi_root ? dbi->dbi_root : rpmdb->db_root);
00324 if ((root[0] == '/' && root[1] == '\0') || rpmdb->db_chrootDone)
00325 root = NULL;
00326
00327 tmpdir = rpmGenPath(root, dbi->dbi_tmpdir, NULL);
00328
00329 xx = dbenv->set_tmp_dir(dbenv, tmpdir);
00330 xx = cvtdberr(dbi, "dbenv->set_tmp_dir", rc, _debug);
00331 tmpdir = _free(tmpdir);
00332 }
00333 }
00334
00335 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR != 0) || (DB_VERSION_MAJOR == 4)
00336 rc = dbenv->open(dbenv, dbhome, eflags, dbi->dbi_perms);
00337 #else
00338 rc = dbenv->open(dbenv, dbhome, NULL, eflags, dbi->dbi_perms);
00339 #endif
00340 rc = cvtdberr(dbi, "dbenv->open", rc, _debug);
00341 if (rc)
00342 goto errxit;
00343
00344 *dbenvp = dbenv;
00345
00346 return 0;
00347
00348 errxit:
00349 if (dbenv) {
00350 int xx;
00351 xx = dbenv->close(dbenv, 0);
00352 xx = cvtdberr(dbi, "dbenv->close", xx, _debug);
00353 }
00354 return rc;
00355 }
00356
00357
00358 static int db3sync(dbiIndex dbi, unsigned int flags)
00359
00360
00361 {
00362 DB * db = dbi->dbi_db;
00363 int rc = 0;
00364 int _printit;
00365
00366 if (db != NULL)
00367 rc = db->sync(db, flags);
00368
00369 _printit = (rc == DB_INCOMPLETE ? 0 : _debug);
00370 rc = cvtdberr(dbi, "db->sync", rc, _printit);
00371 return rc;
00372 }
00373
00374 static int db3cdup(dbiIndex dbi, DBC * dbcursor, DBC ** dbcp,
00375 unsigned int flags)
00376
00377
00378 {
00379 int rc;
00380
00381 if (dbcp) *dbcp = NULL;
00382 rc = dbcursor->c_dup(dbcursor, dbcp, flags);
00383 rc = cvtdberr(dbi, "dbcursor->c_dup", rc, _debug);
00384
00385 return rc;
00386
00387 }
00388
00389 static int db3cclose(dbiIndex dbi, DBC * dbcursor,
00390 unsigned int flags)
00391
00392
00393 {
00394 int rc = -2;
00395
00396
00397 if (dbcursor != NULL) {
00398 rc = dbcursor->c_close(dbcursor);
00399 rc = cvtdberr(dbi, "dbcursor->c_close", rc, _debug);
00400 }
00401 return rc;
00402 }
00403
00404 static int db3copen(dbiIndex dbi, DB_TXN * txnid,
00405 DBC ** dbcp, unsigned int dbiflags)
00406
00407
00408 {
00409 DB * db = dbi->dbi_db;
00410 DBC * dbcursor = NULL;
00411 int flags;
00412 int rc;
00413
00414 assert(db != NULL);
00415 if ((dbiflags & DB_WRITECURSOR) &&
00416 (dbi->dbi_eflags & DB_INIT_CDB) && !(dbi->dbi_oflags & DB_RDONLY))
00417 {
00418 flags = DB_WRITECURSOR;
00419 } else
00420 flags = 0;
00421
00422 rc = db->cursor(db, txnid, &dbcursor, flags);
00423 rc = cvtdberr(dbi, "db->cursor", rc, _debug);
00424
00425 if (dbcp)
00426 *dbcp = dbcursor;
00427 else
00428 (void) db3cclose(dbi, dbcursor, 0);
00429
00430 return rc;
00431 }
00432
00433 static int db3cput(dbiIndex dbi, DBC * dbcursor, DBT * key, DBT * data,
00434 unsigned int flags)
00435
00436
00437 {
00438 DB * db = dbi->dbi_db;
00439 int rc;
00440
00441 assert(db != NULL);
00442 if (dbcursor == NULL) {
00443 rc = db->put(db, dbi->dbi_txnid, key, data, 0);
00444 rc = cvtdberr(dbi, "db->put", rc, _debug);
00445 } else {
00446 rc = dbcursor->c_put(dbcursor, key, data, DB_KEYLAST);
00447 rc = cvtdberr(dbi, "dbcursor->c_put", rc, _debug);
00448 }
00449
00450 return rc;
00451 }
00452
00453 static int db3cdel(dbiIndex dbi, DBC * dbcursor, DBT * key, DBT * data,
00454 unsigned int flags)
00455
00456
00457 {
00458 DB * db = dbi->dbi_db;
00459 int rc;
00460
00461 assert(db != NULL);
00462 if (dbcursor == NULL) {
00463 rc = db->del(db, dbi->dbi_txnid, key, flags);
00464 rc = cvtdberr(dbi, "db->del", rc, _debug);
00465 } else {
00466 int _printit;
00467
00468
00469 rc = dbcursor->c_get(dbcursor, key, data, DB_SET);
00470
00471 _printit = (rc == DB_NOTFOUND ? 0 : _debug);
00472 rc = cvtdberr(dbi, "dbcursor->c_get", rc, _printit);
00473
00474 if (rc == 0) {
00475 rc = dbcursor->c_del(dbcursor, flags);
00476 rc = cvtdberr(dbi, "dbcursor->c_del", rc, _debug);
00477 }
00478 }
00479
00480 return rc;
00481 }
00482
00483 static int db3cget(dbiIndex dbi, DBC * dbcursor, DBT * key, DBT * data,
00484 unsigned int flags)
00485
00486
00487 {
00488 DB * db = dbi->dbi_db;
00489 int _printit;
00490 int rc;
00491
00492 assert(db != NULL);
00493 if (dbcursor == NULL) {
00494
00495 rc = db->get(db, dbi->dbi_txnid, key, data, 0);
00496
00497 _printit = (rc == DB_NOTFOUND ? 0 : _debug);
00498 rc = cvtdberr(dbi, "db->get", rc, _printit);
00499 } else {
00500
00501 rc = dbcursor->c_get(dbcursor, key, data, flags);
00502
00503 _printit = (rc == DB_NOTFOUND ? 0 : _debug);
00504 rc = cvtdberr(dbi, "dbcursor->c_get", rc, _printit);
00505 }
00506
00507 return rc;
00508 }
00509
00510 static int db3cpget(dbiIndex dbi, DBC * dbcursor, DBT * key, DBT * pkey,
00511 DBT * data, unsigned int flags)
00512
00513
00514 {
00515 DB * db = dbi->dbi_db;
00516 int _printit;
00517 int rc;
00518
00519 assert(db != NULL);
00520 assert(dbcursor != NULL);
00521
00522
00523 rc = dbcursor->c_pget(dbcursor, key, pkey, data, flags);
00524
00525 _printit = (rc == DB_NOTFOUND ? 0 : _debug);
00526 rc = cvtdberr(dbi, "dbcursor->c_pget", rc, _printit);
00527
00528 return rc;
00529 }
00530
00531 static int db3ccount(dbiIndex dbi, DBC * dbcursor,
00532 unsigned int * countp,
00533 unsigned int flags)
00534
00535
00536 {
00537 db_recno_t count = 0;
00538 int rc = 0;
00539
00540 flags = 0;
00541 rc = dbcursor->c_count(dbcursor, &count, flags);
00542 rc = cvtdberr(dbi, "dbcursor->c_count", rc, _debug);
00543 if (rc) return rc;
00544 if (countp) *countp = count;
00545
00546 return rc;
00547 }
00548
00549 static int db3byteswapped(dbiIndex dbi)
00550 {
00551 DB * db = dbi->dbi_db;
00552 int rc = 0;
00553
00554 if (db != NULL) {
00555 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3 && DB_VERSION_PATCH == 11) \
00556 || (DB_VERSION_MAJOR == 4)
00557 int isswapped = 0;
00558 rc = db->get_byteswapped(db, &isswapped);
00559 if (rc == 0)
00560 rc = isswapped;
00561 #else
00562 rc = db->get_byteswapped(db);
00563 #endif
00564 }
00565
00566 return rc;
00567 }
00568
00569 static int db3stat(dbiIndex dbi, unsigned int flags)
00570
00571
00572 {
00573 DB * db = dbi->dbi_db;
00574 int rc = 0;
00575
00576 assert(db != NULL);
00577 #if defined(DB_FAST_STAT)
00578 if (flags)
00579 flags = DB_FAST_STAT;
00580 else
00581 #endif
00582 flags = 0;
00583 dbi->dbi_stats = _free(dbi->dbi_stats);
00584
00585 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3) || (DB_VERSION_MAJOR == 4)
00586 rc = db->stat(db, &dbi->dbi_stats, flags);
00587 #else
00588 rc = db->stat(db, &dbi->dbi_stats, NULL, flags);
00589 #endif
00590 rc = cvtdberr(dbi, "db->stat", rc, _debug);
00591 return rc;
00592 }
00593
00594 static int db3associate(dbiIndex dbi, dbiIndex dbisecondary,
00595 int (*callback)(DB *, const DBT *, const DBT *, DBT *),
00596 unsigned int flags)
00597
00598
00599 {
00600 DB * db = dbi->dbi_db;
00601 DB * secondary = dbisecondary->dbi_db;
00602 int rc;
00603
00604
00605 rc = db->associate(db, secondary, callback, flags);
00606
00607 rc = cvtdberr(dbi, "db->associate", rc, _debug);
00608 return rc;
00609 }
00610
00611 static int db3join(dbiIndex dbi, DBC ** curslist, DBC ** dbcp,
00612 unsigned int flags)
00613
00614
00615 {
00616 DB * db = dbi->dbi_db;
00617 int rc;
00618
00619
00620 rc = db->join(db, curslist, dbcp, flags);
00621
00622 rc = cvtdberr(dbi, "db->join", rc, _debug);
00623 return rc;
00624 }
00625
00626
00627 static int db3close( dbiIndex dbi, unsigned int flags)
00628
00629
00630
00631 {
00632 rpmdb rpmdb = dbi->dbi_rpmdb;
00633 const char * urlfn = NULL;
00634 const char * root;
00635 const char * home;
00636 const char * dbhome;
00637 const char * dbfile;
00638 const char * dbsubfile;
00639 DB * db = dbi->dbi_db;
00640 int rc = 0, xx;
00641
00642 flags = 0;
00643
00644
00645
00646
00647 root = (dbi->dbi_root ? dbi->dbi_root : rpmdb->db_root);
00648 if ((root[0] == '/' && root[1] == '\0') || rpmdb->db_chrootDone)
00649 root = NULL;
00650 home = (dbi->dbi_home ? dbi->dbi_home : rpmdb->db_home);
00651
00652
00653
00654
00655
00656
00657 urlfn = rpmGenPath(root, home, NULL);
00658
00659 (void) urlPath(urlfn, &dbhome);
00660 if (dbi->dbi_temporary) {
00661 dbfile = NULL;
00662 dbsubfile = NULL;
00663 } else {
00664 #ifdef HACK
00665 dbfile = (dbi->dbi_file ? dbi->dbi_file : db3basename);
00666 dbsubfile = (dbi->dbi_subfile ? dbi->dbi_subfile : tagName(dbi->dbi_rpmtag));
00667 #else
00668 dbfile = (dbi->dbi_file ? dbi->dbi_file : tagName(dbi->dbi_rpmtag));
00669 dbsubfile = NULL;
00670 #endif
00671 }
00672
00673 if (db) {
00674 rc = db->close(db, 0);
00675 rc = cvtdberr(dbi, "db->close", rc, _debug);
00676 db = dbi->dbi_db = NULL;
00677
00678 rpmMessage(RPMMESS_DEBUG, _("closed db index %s/%s\n"),
00679 dbhome, (dbfile ? dbfile : tagName(dbi->dbi_rpmtag)));
00680
00681 }
00682
00683 if (rpmdb->db_dbenv != NULL && dbi->dbi_use_dbenv) {
00684 if (rpmdb->db_opens == 1) {
00685
00686 xx = db_fini(dbi, (dbhome ? dbhome : ""), dbfile, dbsubfile);
00687
00688 rpmdb->db_dbenv = NULL;
00689 }
00690 rpmdb->db_opens--;
00691 }
00692
00693 if (dbi->dbi_verify_on_close && !dbi->dbi_temporary) {
00694 DB_ENV * dbenv = NULL;
00695
00696
00697 rc = db_env_create(&dbenv, 0);
00698
00699 rc = cvtdberr(dbi, "db_env_create", rc, _debug);
00700 if (rc || dbenv == NULL) goto exit;
00701
00702
00703 dbenv->set_errcall(dbenv, rpmdb->db_errcall);
00704 dbenv->set_errfile(dbenv, rpmdb->db_errfile);
00705 dbenv->set_errpfx(dbenv, rpmdb->db_errpfx);
00706
00707
00708 xx = dbenv->set_verbose(dbenv, DB_VERB_CHKPOINT,
00709 (dbi->dbi_verbose & DB_VERB_CHKPOINT));
00710 xx = dbenv->set_verbose(dbenv, DB_VERB_DEADLOCK,
00711 (dbi->dbi_verbose & DB_VERB_DEADLOCK));
00712 xx = dbenv->set_verbose(dbenv, DB_VERB_RECOVERY,
00713 (dbi->dbi_verbose & DB_VERB_RECOVERY));
00714 xx = dbenv->set_verbose(dbenv, DB_VERB_WAITSFOR,
00715 (dbi->dbi_verbose & DB_VERB_WAITSFOR));
00716
00717 if (dbi->dbi_tmpdir) {
00718
00719 const char * tmpdir = rpmGenPath(root, dbi->dbi_tmpdir, NULL);
00720
00721 rc = dbenv->set_tmp_dir(dbenv, tmpdir);
00722 rc = cvtdberr(dbi, "dbenv->set_tmp_dir", rc, _debug);
00723 tmpdir = _free(tmpdir);
00724 if (rc) goto exit;
00725 }
00726
00727 rc = dbenv->open(dbenv, dbhome,
00728 DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE | DB_USE_ENVIRON, 0);
00729 rc = cvtdberr(dbi, "dbenv->open", rc, _debug);
00730 if (rc) goto exit;
00731
00732
00733 rc = db_create(&db, dbenv, 0);
00734
00735 rc = cvtdberr(dbi, "db_create", rc, _debug);
00736
00737 if (db != NULL) {
00738
00739 const char * dbf = rpmGetPath(dbhome, "/", dbfile, NULL);
00740
00741
00742 rc = db->verify(db, dbf, NULL, NULL, flags);
00743 rc = cvtdberr(dbi, "db->verify", rc, _debug);
00744
00745 rpmMessage(RPMMESS_DEBUG, _("verified db index %s/%s\n"),
00746 (dbhome ? dbhome : ""),
00747 (dbfile ? dbfile : tagName(dbi->dbi_rpmtag)));
00748
00749 xx = db->close(db, 0);
00750 xx = cvtdberr(dbi, "db->close", xx, _debug);
00751 db = NULL;
00752 if (rc == 0 && xx) rc = xx;
00753
00754 dbf = _free(dbf);
00755 }
00756 xx = dbenv->close(dbenv, 0);
00757 xx = cvtdberr(dbi, "dbenv->close", xx, _debug);
00758 if (rc == 0 && xx) rc = xx;
00759 }
00760
00761 exit:
00762 dbi->dbi_db = NULL;
00763
00764 urlfn = _free(urlfn);
00765
00766 dbi = db3Free(dbi);
00767
00768 return rc;
00769 }
00770
00771
00772 static int db3open(rpmdb rpmdb, rpmTag rpmtag, dbiIndex * dbip)
00773
00774
00775
00776 {
00777
00778 extern struct _dbiVec db3vec;
00779
00780 const char * urlfn = NULL;
00781 const char * root;
00782 const char * home;
00783 const char * dbhome;
00784 const char * dbfile;
00785 const char * dbsubfile;
00786 dbiIndex dbi = NULL;
00787 int rc = 0;
00788 int xx;
00789
00790 DB * db = NULL;
00791 DB_ENV * dbenv = NULL;
00792 u_int32_t oflags;
00793 int _printit;
00794
00795 if (dbip)
00796 *dbip = NULL;
00797
00798
00799
00800
00801
00802 if ((dbi = db3New(rpmdb, rpmtag)) == NULL)
00803
00804 return 1;
00805
00806
00807 dbi->dbi_api = DB_VERSION_MAJOR;
00808
00809
00810
00811
00812 root = (dbi->dbi_root ? dbi->dbi_root : rpmdb->db_root);
00813 if ((root[0] == '/' && root[1] == '\0') || rpmdb->db_chrootDone)
00814 root = NULL;
00815 home = (dbi->dbi_home ? dbi->dbi_home : rpmdb->db_home);
00816
00817
00818
00819
00820
00821
00822 urlfn = rpmGenPath(root, home, NULL);
00823
00824 (void) urlPath(urlfn, &dbhome);
00825 if (dbi->dbi_temporary) {
00826 dbfile = NULL;
00827 dbsubfile = NULL;
00828 } else {
00829 #ifdef HACK
00830 dbfile = (dbi->dbi_file ? dbi->dbi_file : db3basename);
00831 dbsubfile = (dbi->dbi_subfile ? dbi->dbi_subfile : tagName(dbi->dbi_rpmtag));
00832 #else
00833 dbfile = (dbi->dbi_file ? dbi->dbi_file : tagName(dbi->dbi_rpmtag));
00834 dbsubfile = NULL;
00835 #endif
00836 }
00837
00838 oflags = (dbi->dbi_oeflags | dbi->dbi_oflags);
00839 oflags &= ~DB_TRUNCATE;
00840
00841 #if 0
00842 if ( dbi->dbi_mode & O_EXCL) oflags |= DB_EXCL;
00843 #endif
00844
00845
00846
00847
00848 if (dbi->dbi_temporary) {
00849 oflags |= DB_CREATE;
00850 dbi->dbi_oeflags |= DB_CREATE;
00851 oflags &= ~DB_RDONLY;
00852 dbi->dbi_oflags &= ~DB_RDONLY;
00853 } else {
00854 if (!(dbi->dbi_mode & (O_RDWR|O_WRONLY))) oflags |= DB_RDONLY;
00855 if (dbi->dbi_mode & O_CREAT) {
00856 oflags |= DB_CREATE;
00857 dbi->dbi_oeflags |= DB_CREATE;
00858 }
00859 #ifdef DANGEROUS
00860 if ( dbi->dbi_mode & O_TRUNC) oflags |= DB_TRUNCATE;
00861 #endif
00862 }
00863
00864
00865
00866
00867 (void) rpmioMkpath(dbhome, 0755, getuid(), getgid());
00868
00869
00870
00871
00872 if (dbi->dbi_use_dbenv) {
00873 if (access(dbhome, W_OK) == -1) {
00874
00875
00876 oflags &= ~DB_CREATE;
00877
00878
00879 if (dbi->dbi_eflags & DB_PRIVATE) {
00880 dbi->dbi_eflags &= ~DB_JOINENV;
00881 } else {
00882 dbi->dbi_eflags |= DB_JOINENV;
00883 dbi->dbi_oeflags &= ~DB_CREATE;
00884 dbi->dbi_oeflags &= ~DB_THREAD;
00885
00886 dbi->dbi_use_dbenv = 0;
00887 }
00888
00889
00890 if (dbi->dbi_temporary) {
00891 oflags |= DB_CREATE;
00892 dbi->dbi_oeflags |= DB_CREATE;
00893 oflags &= ~DB_RDONLY;
00894 dbi->dbi_oflags &= ~DB_RDONLY;
00895 } else {
00896 oflags |= DB_RDONLY;
00897
00898 dbi->dbi_oflags |= DB_RDONLY;
00899 }
00900
00901 } else {
00902
00903 const char * dbf = rpmGetPath(dbhome, "/__db.001", NULL);
00904
00905
00906 if (access(dbf, F_OK) == -1) {
00907
00908 dbi->dbi_oeflags |= DB_CREATE;
00909 dbi->dbi_eflags &= ~DB_JOINENV;
00910 } else {
00911
00912 if (dbi->dbi_eflags & DB_PRIVATE) {
00913 dbi->dbi_eflags &= ~DB_JOINENV;
00914 } else {
00915 dbi->dbi_eflags |= DB_JOINENV;
00916 dbi->dbi_oeflags &= ~DB_CREATE;
00917 dbi->dbi_oeflags &= ~DB_THREAD;
00918 }
00919 }
00920 dbf = _free(dbf);
00921 }
00922 }
00923
00924
00925
00926
00927 if ((oflags & DB_CREATE) && (oflags & DB_RDONLY)) {
00928
00929 const char * dbfn = (dbfile ? dbfile : tagName(dbi->dbi_rpmtag));
00930
00931 const char * dbf = rpmGetPath(dbhome, "/", dbfn, NULL);
00932
00933
00934 if (access(dbf, F_OK) == -1) {
00935
00936 oflags &= ~DB_RDONLY;
00937 } else {
00938
00939 oflags &= ~DB_CREATE;
00940 }
00941
00942
00943 if (!(oflags & DB_RDONLY) && access(dbf, W_OK) == 0) {
00944 dbi->dbi_oflags &= ~DB_RDONLY;
00945 } else {
00946 dbi->dbi_oflags |= DB_RDONLY;
00947 }
00948 dbf = _free(dbf);
00949 }
00950
00951
00952
00953
00954 if (oflags & DB_RDONLY)
00955 dbi->dbi_verify_on_close = 0;
00956
00957 if (dbi->dbi_use_dbenv) {
00958
00959 if (rpmdb->db_dbenv == NULL) {
00960 rc = db_init(dbi, dbhome, dbfile, dbsubfile, &dbenv);
00961 if (rc == 0) {
00962 rpmdb->db_dbenv = dbenv;
00963 rpmdb->db_opens = 1;
00964 }
00965 } else {
00966 dbenv = rpmdb->db_dbenv;
00967 rpmdb->db_opens++;
00968 }
00969
00970 }
00971
00972 rpmMessage(RPMMESS_DEBUG, _("opening db index %s/%s %s mode=0x%x\n"),
00973 dbhome, (dbfile ? dbfile : tagName(dbi->dbi_rpmtag)),
00974 prDbiOpenFlags(oflags, 0), dbi->dbi_mode);
00975
00976 if (rc == 0) {
00977 static int _lockdbfd = 0;
00978
00979
00980 rc = db_create(&db, dbenv, dbi->dbi_cflags);
00981
00982 rc = cvtdberr(dbi, "db_create", rc, _debug);
00983 if (rc == 0 && db != NULL) {
00984 if (rc == 0 && dbi->dbi_lorder) {
00985 rc = db->set_lorder(db, dbi->dbi_lorder);
00986 rc = cvtdberr(dbi, "db->set_lorder", rc, _debug);
00987 }
00988 if (rc == 0 && dbi->dbi_cachesize) {
00989 rc = db->set_cachesize(db, 0, dbi->dbi_cachesize, 0);
00990 rc = cvtdberr(dbi, "db->set_cachesize", rc, _debug);
00991 }
00992 if (rc == 0 && dbi->dbi_pagesize) {
00993 rc = db->set_pagesize(db, dbi->dbi_pagesize);
00994 rc = cvtdberr(dbi, "db->set_pagesize", rc, _debug);
00995 }
00996
00997 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3) || (DB_VERSION_MAJOR == 4)
00998 if (rc == 0 &&
00999 rpmdb->db_malloc && rpmdb->db_realloc && rpmdb->db_free)
01000 {
01001 rc = db->set_alloc(db,
01002 rpmdb->db_malloc, rpmdb->db_realloc, rpmdb->db_free);
01003 rc = cvtdberr(dbi, "db->set_alloc", rc, _debug);
01004 }
01005 #else
01006 if (rc == 0 && rpmdb->db_malloc) {
01007 rc = db->set_malloc(db, rpmdb->db_malloc);
01008 rc = cvtdberr(dbi, "db->set_malloc", rc, _debug);
01009 }
01010 #endif
01011 if (rc == 0 && oflags & DB_CREATE) {
01012 switch(dbi->dbi_type) {
01013 default:
01014 case DB_HASH:
01015 if (dbi->dbi_h_ffactor) {
01016 rc = db->set_h_ffactor(db, dbi->dbi_h_ffactor);
01017 rc = cvtdberr(dbi, "db->set_h_ffactor", rc, _debug);
01018 if (rc) break;
01019 }
01020 if (dbi->dbi_h_nelem) {
01021 rc = db->set_h_nelem(db, dbi->dbi_h_nelem);
01022 rc = cvtdberr(dbi, "db->set_h_nelem", rc, _debug);
01023 if (rc) break;
01024 }
01025 if (dbi->dbi_h_flags) {
01026 rc = db->set_flags(db, dbi->dbi_h_flags);
01027 rc = cvtdberr(dbi, "db->set_h_flags", rc, _debug);
01028 if (rc) break;
01029 }
01030
01031 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 2) || (DB_VERSION_MAJOR == 4)
01032 if (dbi->dbi_h_hash_fcn) {
01033 rc = db->set_h_hash(db, dbi->dbi_h_hash_fcn);
01034 rc = cvtdberr(dbi, "db->set_h_hash", rc, _debug);
01035 if (rc) break;
01036 }
01037 if (dbi->dbi_h_dup_compare_fcn) {
01038 rc = db->set_dup_compare(db, dbi->dbi_h_dup_compare_fcn);
01039 rc = cvtdberr(dbi, "db->set_dup_compare", rc, _debug);
01040 if (rc) break;
01041 }
01042 #endif
01043 break;
01044 case DB_BTREE:
01045 if (dbi->dbi_bt_flags) {
01046 rc = db->set_flags(db, dbi->dbi_bt_flags);
01047 rc = cvtdberr(dbi, "db->set_bt_flags", rc, _debug);
01048 if (rc) break;
01049 }
01050 if (dbi->dbi_bt_minkey) {
01051 rc = db->set_bt_minkey(db, dbi->dbi_bt_minkey);
01052 rc = cvtdberr(dbi, "db->set_bt_minkey", rc, _debug);
01053 if (rc) break;
01054 }
01055
01056 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 2) || (DB_VERSION_MAJOR == 4)
01057 if (dbi->dbi_bt_compare_fcn) {
01058 rc = db->set_bt_compare(db, dbi->dbi_bt_compare_fcn);
01059 rc = cvtdberr(dbi, "db->set_bt_compare", rc, _debug);
01060 if (rc) break;
01061 }
01062 if (dbi->dbi_bt_dup_compare_fcn) {
01063 rc = db->set_dup_compare(db, dbi->dbi_bt_dup_compare_fcn);
01064 rc = cvtdberr(dbi, "db->set_dup_compare", rc, _debug);
01065 if (rc) break;
01066 }
01067 if (dbi->dbi_bt_prefix_fcn) {
01068 rc = db->set_bt_prefix(db, dbi->dbi_bt_prefix_fcn);
01069 rc = cvtdberr(dbi, "db->set_bt_prefix", rc, _debug);
01070 if (rc) break;
01071 }
01072 #endif
01073 break;
01074 case DB_RECNO:
01075 if (dbi->dbi_re_delim) {
01076 rc = db->set_re_delim(db, dbi->dbi_re_delim);
01077 rc = cvtdberr(dbi, "db->set_re_selim", rc, _debug);
01078 if (rc) break;
01079 }
01080 if (dbi->dbi_re_len) {
01081 rc = db->set_re_len(db, dbi->dbi_re_len);
01082 rc = cvtdberr(dbi, "db->set_re_len", rc, _debug);
01083 if (rc) break;
01084 }
01085 if (dbi->dbi_re_pad) {
01086 rc = db->set_re_pad(db, dbi->dbi_re_pad);
01087 rc = cvtdberr(dbi, "db->set_re_pad", rc, _debug);
01088 if (rc) break;
01089 }
01090 if (dbi->dbi_re_source) {
01091 rc = db->set_re_source(db, dbi->dbi_re_source);
01092 rc = cvtdberr(dbi, "db->set_re_source", rc, _debug);
01093 if (rc) break;
01094 }
01095 break;
01096 case DB_QUEUE:
01097 if (dbi->dbi_q_extentsize) {
01098 rc = db->set_q_extentsize(db, dbi->dbi_q_extentsize);
01099 rc = cvtdberr(dbi, "db->set_q_extentsize", rc, _debug);
01100 if (rc) break;
01101 }
01102 break;
01103 }
01104 }
01105
01106 if (rc == 0) {
01107 const char * dbfullpath;
01108 const char * dbpath;
01109 char * t;
01110 int nb;
01111
01112 nb = strlen(dbhome);
01113 if (dbfile) nb += 1 + strlen(dbfile);
01114 dbfullpath = t = alloca(nb + 1);
01115
01116 t = stpcpy(t, dbhome);
01117 if (dbfile)
01118 t = stpcpy( stpcpy( t, "/"), dbfile);
01119 #ifdef HACK
01120 dbpath = (!dbi->dbi_use_dbenv && !dbi->dbi_temporary)
01121 ? dbfullpath : dbfile;
01122 #else
01123 dbpath = (!dbi->dbi_temporary)
01124 ? dbfullpath : dbfile;
01125 #endif
01126
01127 rc = db->open(db, dbpath, dbsubfile,
01128 dbi->dbi_type, oflags, dbi->dbi_perms);
01129
01130 if (rc == 0 && dbi->dbi_type == DB_UNKNOWN) {
01131 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3 && DB_VERSION_PATCH == 11) \
01132 || (DB_VERSION_MAJOR == 4)
01133 DBTYPE dbi_type = DB_UNKNOWN;
01134 xx = db->get_type(db, &dbi_type);
01135 if (xx == 0)
01136 dbi->dbi_type = dbi_type;
01137 #else
01138 dbi->dbi_type = db->get_type(db);
01139 #endif
01140 }
01141 }
01142
01143
01144 _printit = (rc > 0 ? 0 : _debug);
01145 xx = cvtdberr(dbi, "db->open", rc, _printit);
01146
01147 dbi->dbi_txnid = NULL;
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164 if (rc == 0 && dbi->dbi_lockdbfd &&
01165 (!dbi->dbi_use_dbenv || _lockdbfd++ == 0))
01166 {
01167 int fdno = -1;
01168
01169 if (!(db->fd(db, &fdno) == 0 && fdno >= 0)) {
01170 rc = 1;
01171 } else {
01172 struct flock l;
01173 memset(&l, 0, sizeof(l));
01174 l.l_whence = 0;
01175 l.l_start = 0;
01176 l.l_len = 0;
01177 l.l_type = (dbi->dbi_mode & (O_RDWR|O_WRONLY))
01178 ? F_WRLCK : F_RDLCK;
01179 l.l_pid = 0;
01180
01181 rc = fcntl(fdno, F_SETLK, (void *) &l);
01182 if (rc) {
01183
01184 rc = ((dbi->dbi_use_dbenv &&
01185 (dbi->dbi_eflags & DB_INIT_CDB))
01186 ? 0 : 1);
01187 rpmError( (rc ? RPMERR_FLOCK : RPMWARN_FLOCK),
01188 _("cannot get %s lock on %s/%s\n"),
01189 ((dbi->dbi_mode & (O_RDWR|O_WRONLY))
01190 ? _("exclusive") : _("shared")),
01191 dbhome, (dbfile ? dbfile : ""));
01192 } else if (dbfile) {
01193 rpmMessage(RPMMESS_DEBUG,
01194 _("locked db index %s/%s\n"),
01195 dbhome, dbfile);
01196 }
01197 }
01198 }
01199 }
01200 }
01201
01202 dbi->dbi_db = db;
01203
01204 if (rc == 0 && dbi->dbi_db != NULL && dbip != NULL) {
01205 dbi->dbi_vec = &db3vec;
01206 *dbip = dbi;
01207 } else {
01208 dbi->dbi_verify_on_close = 0;
01209 (void) db3close(dbi, 0);
01210 }
01211
01212 urlfn = _free(urlfn);
01213
01214
01215 return rc;
01216
01217 }
01218
01221
01222
01223 struct _dbiVec db3vec = {
01224 DB_VERSION_MAJOR, DB_VERSION_MINOR, DB_VERSION_PATCH,
01225 db3open, db3close, db3sync, db3associate, db3join,
01226 db3copen, db3cclose, db3cdup, db3cdel, db3cget, db3cpget, db3cput, db3ccount,
01227 db3byteswapped, db3stat
01228 };
01229
01230