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