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", xx, _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", xx, _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 #if HAVE_LIBPTHREAD
00217 #if HAVE_PTHREAD_H
00218 #include <pthread.h>
00219 #endif
00220
00225 static int db3_pthread_nptl(void)
00226
00227 {
00228 pthread_mutex_t mutex;
00229 pthread_mutexattr_t mutexattr, *mutexattrp = NULL;
00230 pthread_cond_t cond;
00231 pthread_condattr_t condattr, *condattrp = NULL;
00232 int ret = 0;
00233
00234 ret = pthread_mutexattr_init(&mutexattr);
00235 if (ret == 0) {
00236 ret = pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED);
00237 mutexattrp = &mutexattr;
00238 }
00239
00240 if (ret == 0)
00241 ret = pthread_mutex_init(&mutex, mutexattrp);
00242 if (mutexattrp != NULL)
00243 pthread_mutexattr_destroy(mutexattrp);
00244 if (ret)
00245 return ret;
00246 (void) pthread_mutex_destroy(&mutex);
00247
00248 ret = pthread_condattr_init(&condattr);
00249 if (ret == 0) {
00250 ret = pthread_condattr_setpshared(&condattr, PTHREAD_PROCESS_SHARED);
00251 condattrp = &condattr;
00252 }
00253
00254 if (ret == 0)
00255 ret = pthread_cond_init(&cond, condattrp);
00256
00257 if (condattrp != NULL)
00258 (void)pthread_condattr_destroy(condattrp);
00259 if (ret == 0)
00260 (void) pthread_cond_destroy(&cond);
00261 return ret;
00262 }
00263 #endif
00264
00265
00266 static int db_init(dbiIndex dbi, const char * dbhome,
00267 const char * dbfile,
00268 const char * dbsubfile,
00269 DB_ENV ** dbenvp)
00270
00271
00272
00273 {
00274 rpmdb rpmdb = dbi->dbi_rpmdb;
00275 DB_ENV *dbenv = NULL;
00276 int eflags;
00277 int rc;
00278
00279 if (dbenvp == NULL)
00280 return 1;
00281
00282
00283
00284 if (rpmdb->db_errfile == NULL)
00285 rpmdb->db_errfile = stderr;
00286
00287
00288 eflags = (dbi->dbi_oeflags | dbi->dbi_eflags);
00289 if (eflags & DB_JOINENV) eflags &= DB_JOINENV;
00290
00291 if (dbfile)
00292 rpmMessage(RPMMESS_DEBUG, _("opening db environment %s/%s %s\n"),
00293 dbhome, dbfile, prDbiOpenFlags(eflags, 1));
00294
00295
00296 if (dbi->dbi_host == NULL)
00297 dbi->dbi_ecflags &= ~DB_CLIENT;
00298
00299
00300 if ((dbi->dbi_eflags & DB_SYSTEM_MEM) && dbi->dbi_shmkey == 0) {
00301 #if defined(HAVE_FTOK)
00302 dbi->dbi_shmkey = ftok(dbhome, 0);
00303 #else
00304 dbi->dbi_shmkey = 0x44631380;
00305 #endif
00306 }
00307
00308 rc = db_env_create(&dbenv, dbi->dbi_ecflags);
00309 rc = cvtdberr(dbi, "db_env_create", rc, _debug);
00310 if (dbenv == NULL || rc)
00311 goto errxit;
00312
00313 { int xx;
00314
00315
00316
00317
00318
00319
00320
00321 dbenv->set_errcall(dbenv, rpmdb->db_errcall);
00322 dbenv->set_errfile(dbenv, rpmdb->db_errfile);
00323 dbenv->set_errpfx(dbenv, rpmdb->db_errpfx);
00324
00325
00326
00327
00328
00329
00330
00331 if ((dbi->dbi_ecflags & DB_CLIENT) && dbi->dbi_host) {
00332 const char * home;
00333 int retry = 0;
00334
00335 if ((home = strrchr(dbhome, '/')) != NULL)
00336 dbhome = ++home;
00337
00338 while (retry++ < 5) {
00339
00340 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3) || (DB_VERSION_MAJOR == 4)
00341 xx = dbenv->set_rpc_server(dbenv, NULL, dbi->dbi_host,
00342 dbi->dbi_cl_timeout, dbi->dbi_sv_timeout, 0);
00343 xx = cvtdberr(dbi, "dbenv->set_server", xx, _debug);
00344 #else
00345 xx = dbenv->set_server(dbenv, dbi->dbi_host,
00346 dbi->dbi_cl_timeout, dbi->dbi_sv_timeout, 0);
00347 xx = cvtdberr(dbi, "dbenv->set_server", xx, _debug);
00348 #endif
00349 if (!xx)
00350 break;
00351 sleep(15);
00352 }
00353 } else {
00354 xx = dbenv->set_verbose(dbenv, DB_VERB_CHKPOINT,
00355 (dbi->dbi_verbose & DB_VERB_CHKPOINT));
00356 xx = dbenv->set_verbose(dbenv, DB_VERB_DEADLOCK,
00357 (dbi->dbi_verbose & DB_VERB_DEADLOCK));
00358 xx = dbenv->set_verbose(dbenv, DB_VERB_RECOVERY,
00359 (dbi->dbi_verbose & DB_VERB_RECOVERY));
00360 xx = dbenv->set_verbose(dbenv, DB_VERB_WAITSFOR,
00361 (dbi->dbi_verbose & DB_VERB_WAITSFOR));
00362
00363 if (dbi->dbi_mmapsize) {
00364 xx = dbenv->set_mp_mmapsize(dbenv, dbi->dbi_mmapsize);
00365 xx = cvtdberr(dbi, "dbenv->set_mp_mmapsize", xx, _debug);
00366 }
00367 if (dbi->dbi_tmpdir) {
00368 const char * root;
00369 const char * tmpdir;
00370
00371 root = (dbi->dbi_root ? dbi->dbi_root : rpmdb->db_root);
00372 if ((root[0] == '/' && root[1] == '\0') || rpmdb->db_chrootDone)
00373 root = NULL;
00374
00375 tmpdir = rpmGenPath(root, dbi->dbi_tmpdir, NULL);
00376
00377 xx = dbenv->set_tmp_dir(dbenv, tmpdir);
00378 xx = cvtdberr(dbi, "dbenv->set_tmp_dir", xx, _debug);
00379 tmpdir = _free(tmpdir);
00380 }
00381 }
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394 if (dbi->dbi_cachesize) {
00395 xx = dbenv->set_cachesize(dbenv, 0, dbi->dbi_cachesize, 0);
00396 xx = cvtdberr(dbi, "dbenv->set_cachesize", xx, _debug);
00397 }
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407 if (dbi->dbi_no_fsync) {
00408 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR != 0) || (DB_VERSION_MAJOR == 4)
00409 xx = db_env_set_func_fsync(db3_fsync_disable);
00410 #else
00411 xx = dbenv->set_func_fsync(dbenv, db3_fsync_disable);
00412 #endif
00413 xx = cvtdberr(dbi, "db_env_set_func_fsync", xx, _debug);
00414 }
00415
00416 if (dbi->dbi_shmkey) {
00417 xx = dbenv->set_shm_key(dbenv, dbi->dbi_shmkey);
00418 xx = cvtdberr(dbi, "dbenv->set_shm_key", xx, _debug);
00419 }
00420 }
00421
00422 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR != 0) || (DB_VERSION_MAJOR == 4)
00423 rc = dbenv->open(dbenv, dbhome, eflags, dbi->dbi_perms);
00424 #else
00425 rc = dbenv->open(dbenv, dbhome, NULL, eflags, dbi->dbi_perms);
00426 #endif
00427 rc = cvtdberr(dbi, "dbenv->open", rc, _debug);
00428 if (rc)
00429 goto errxit;
00430
00431 *dbenvp = dbenv;
00432
00433 return 0;
00434
00435 errxit:
00436 if (dbenv) {
00437 int xx;
00438 xx = dbenv->close(dbenv, 0);
00439 xx = cvtdberr(dbi, "dbenv->close", xx, _debug);
00440 }
00441 return rc;
00442 }
00443
00444
00445 static int db3sync(dbiIndex dbi, unsigned int flags)
00446
00447
00448 {
00449 DB * db = dbi->dbi_db;
00450 int rc = 0;
00451 int _printit;
00452
00453 if (db != NULL)
00454 rc = db->sync(db, flags);
00455
00456 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1)
00457 _printit = _debug;
00458 #else
00459 _printit = (rc == DB_INCOMPLETE ? 0 : _debug);
00460 #endif
00461 rc = cvtdberr(dbi, "db->sync", rc, _printit);
00462 return rc;
00463 }
00464
00465 static int db3cdup(dbiIndex dbi, DBC * dbcursor, DBC ** dbcp,
00466 unsigned int flags)
00467
00468
00469 {
00470 int rc;
00471
00472 if (dbcp) *dbcp = NULL;
00473 rc = dbcursor->c_dup(dbcursor, dbcp, flags);
00474 rc = cvtdberr(dbi, "dbcursor->c_dup", rc, _debug);
00475
00476 return rc;
00477
00478 }
00479
00480 static int db3cclose(dbiIndex dbi, DBC * dbcursor,
00481 unsigned int flags)
00482
00483
00484 {
00485 int rc = -2;
00486
00487
00488 if (dbcursor != NULL) {
00489 rc = dbcursor->c_close(dbcursor);
00490 rc = cvtdberr(dbi, "dbcursor->c_close", rc, _debug);
00491 }
00492 return rc;
00493 }
00494
00495 static int db3copen(dbiIndex dbi, DB_TXN * txnid,
00496 DBC ** dbcp, unsigned int dbiflags)
00497
00498
00499 {
00500 DB * db = dbi->dbi_db;
00501 DBC * dbcursor = NULL;
00502 int flags;
00503 int rc;
00504
00505 assert(db != NULL);
00506 if ((dbiflags & DB_WRITECURSOR) &&
00507 (dbi->dbi_eflags & DB_INIT_CDB) && !(dbi->dbi_oflags & DB_RDONLY))
00508 {
00509 flags = DB_WRITECURSOR;
00510 } else
00511 flags = 0;
00512
00513 rc = db->cursor(db, txnid, &dbcursor, flags);
00514 rc = cvtdberr(dbi, "db->cursor", rc, _debug);
00515
00516 if (dbcp)
00517 *dbcp = dbcursor;
00518 else
00519 (void) db3cclose(dbi, dbcursor, 0);
00520
00521 return rc;
00522 }
00523
00524 static int db3cput(dbiIndex dbi, DBC * dbcursor, DBT * key, DBT * data,
00525 unsigned int flags)
00526
00527
00528 {
00529 DB * db = dbi->dbi_db;
00530 int rc;
00531
00532 assert(db != NULL);
00533 if (dbcursor == NULL) {
00534 rc = db->put(db, dbi->dbi_txnid, key, data, 0);
00535 rc = cvtdberr(dbi, "db->put", rc, _debug);
00536 } else {
00537 rc = dbcursor->c_put(dbcursor, key, data, DB_KEYLAST);
00538 rc = cvtdberr(dbi, "dbcursor->c_put", rc, _debug);
00539 }
00540
00541 return rc;
00542 }
00543
00544 static int db3cdel(dbiIndex dbi, DBC * dbcursor, DBT * key, DBT * data,
00545 unsigned int flags)
00546
00547
00548 {
00549 DB * db = dbi->dbi_db;
00550 int rc;
00551
00552 assert(db != NULL);
00553 if (dbcursor == NULL) {
00554 rc = db->del(db, dbi->dbi_txnid, key, flags);
00555 rc = cvtdberr(dbi, "db->del", rc, _debug);
00556 } else {
00557 int _printit;
00558
00559
00560 rc = dbcursor->c_get(dbcursor, key, data, DB_SET);
00561
00562 _printit = (rc == DB_NOTFOUND ? 0 : _debug);
00563 rc = cvtdberr(dbi, "dbcursor->c_get", rc, _printit);
00564
00565 if (rc == 0) {
00566 rc = dbcursor->c_del(dbcursor, flags);
00567 rc = cvtdberr(dbi, "dbcursor->c_del", rc, _debug);
00568 }
00569 }
00570
00571 return rc;
00572 }
00573
00574 static int db3cget(dbiIndex dbi, DBC * dbcursor, DBT * key, DBT * data,
00575 unsigned int flags)
00576
00577
00578 {
00579 DB * db = dbi->dbi_db;
00580 int _printit;
00581 int rc;
00582
00583 assert(db != NULL);
00584 if (dbcursor == NULL) {
00585
00586 rc = db->get(db, dbi->dbi_txnid, key, data, 0);
00587
00588 _printit = (rc == DB_NOTFOUND ? 0 : _debug);
00589 rc = cvtdberr(dbi, "db->get", rc, _printit);
00590 } else {
00591
00592 rc = dbcursor->c_get(dbcursor, key, data, flags);
00593
00594 _printit = (rc == DB_NOTFOUND ? 0 : _debug);
00595 rc = cvtdberr(dbi, "dbcursor->c_get", rc, _printit);
00596 }
00597
00598 return rc;
00599 }
00600
00601 static int db3cpget(dbiIndex dbi, DBC * dbcursor, DBT * key, DBT * pkey,
00602 DBT * data, unsigned int flags)
00603
00604
00605 {
00606 DB * db = dbi->dbi_db;
00607 int _printit;
00608 int rc;
00609
00610 assert(db != NULL);
00611 assert(dbcursor != NULL);
00612
00613
00614 rc = dbcursor->c_pget(dbcursor, key, pkey, data, flags);
00615
00616 _printit = (rc == DB_NOTFOUND ? 0 : _debug);
00617 rc = cvtdberr(dbi, "dbcursor->c_pget", rc, _printit);
00618
00619 return rc;
00620 }
00621
00622 static int db3ccount(dbiIndex dbi, DBC * dbcursor,
00623 unsigned int * countp,
00624 unsigned int flags)
00625
00626
00627 {
00628 db_recno_t count = 0;
00629 int rc = 0;
00630
00631 flags = 0;
00632 rc = dbcursor->c_count(dbcursor, &count, flags);
00633 rc = cvtdberr(dbi, "dbcursor->c_count", rc, _debug);
00634 if (rc) return rc;
00635 if (countp) *countp = count;
00636
00637 return rc;
00638 }
00639
00640 static int db3byteswapped(dbiIndex dbi)
00641 {
00642 DB * db = dbi->dbi_db;
00643 int rc = 0;
00644
00645 if (db != NULL) {
00646 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3 && DB_VERSION_PATCH == 11) \
00647 || (DB_VERSION_MAJOR == 4)
00648 int isswapped = 0;
00649 rc = db->get_byteswapped(db, &isswapped);
00650 if (rc == 0)
00651 rc = isswapped;
00652 #else
00653 rc = db->get_byteswapped(db);
00654 #endif
00655 }
00656
00657 return rc;
00658 }
00659
00660 static int db3stat(dbiIndex dbi, unsigned int flags)
00661
00662
00663 {
00664 DB * db = dbi->dbi_db;
00665 int rc = 0;
00666
00667 assert(db != NULL);
00668 #if defined(DB_FAST_STAT)
00669 if (flags)
00670 flags = DB_FAST_STAT;
00671 else
00672 #endif
00673 flags = 0;
00674 dbi->dbi_stats = _free(dbi->dbi_stats);
00675
00676 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3) || (DB_VERSION_MAJOR == 4)
00677 rc = db->stat(db, &dbi->dbi_stats, flags);
00678 #else
00679 rc = db->stat(db, &dbi->dbi_stats, NULL, flags);
00680 #endif
00681 rc = cvtdberr(dbi, "db->stat", rc, _debug);
00682 return rc;
00683 }
00684
00685 static int db3associate(dbiIndex dbi, dbiIndex dbisecondary,
00686 int (*callback)(DB *, const DBT *, const DBT *, DBT *),
00687 unsigned int flags)
00688
00689
00690 {
00691 DB * db = dbi->dbi_db;
00692 DB * secondary = dbisecondary->dbi_db;
00693 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1)
00694 DB_TXN * txnid = NULL;
00695 #endif
00696 int rc;
00697
00698
00699 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1)
00700 rc = db->associate(db, txnid, secondary, callback, flags);
00701 #else
00702 rc = db->associate(db, secondary, callback, flags);
00703 #endif
00704
00705 rc = cvtdberr(dbi, "db->associate", rc, _debug);
00706 return rc;
00707 }
00708
00709 static int db3join(dbiIndex dbi, DBC ** curslist, DBC ** dbcp,
00710 unsigned int flags)
00711
00712
00713 {
00714 DB * db = dbi->dbi_db;
00715 int rc;
00716
00717
00718 rc = db->join(db, curslist, dbcp, flags);
00719
00720 rc = cvtdberr(dbi, "db->join", rc, _debug);
00721 return rc;
00722 }
00723
00724
00725 static int db3close( dbiIndex dbi, unsigned int flags)
00726
00727
00728
00729 {
00730 rpmdb rpmdb = dbi->dbi_rpmdb;
00731 const char * urlfn = NULL;
00732 const char * root;
00733 const char * home;
00734 const char * dbhome;
00735 const char * dbfile;
00736 const char * dbsubfile;
00737 DB * db = dbi->dbi_db;
00738 int _printit;
00739 int rc = 0, xx;
00740
00741 flags = 0;
00742
00743
00744
00745
00746 root = (dbi->dbi_root ? dbi->dbi_root : rpmdb->db_root);
00747 if ((root[0] == '/' && root[1] == '\0') || rpmdb->db_chrootDone)
00748 root = NULL;
00749 home = (dbi->dbi_home ? dbi->dbi_home : rpmdb->db_home);
00750
00751
00752
00753
00754
00755
00756 urlfn = rpmGenPath(root, home, NULL);
00757
00758 (void) urlPath(urlfn, &dbhome);
00759 if (dbi->dbi_temporary) {
00760 dbfile = NULL;
00761 dbsubfile = NULL;
00762 } else {
00763 #ifdef HACK
00764 dbfile = (dbi->dbi_file ? dbi->dbi_file : db3basename);
00765 dbsubfile = (dbi->dbi_subfile ? dbi->dbi_subfile : tagName(dbi->dbi_rpmtag));
00766 #else
00767 dbfile = (dbi->dbi_file ? dbi->dbi_file : tagName(dbi->dbi_rpmtag));
00768 dbsubfile = NULL;
00769 #endif
00770 }
00771
00772 if (db) {
00773 rc = db->close(db, 0);
00774
00775 _printit = (rc == ENOENT ? 0 : _debug);
00776 rc = cvtdberr(dbi, "db->close", rc, _printit);
00777 db = dbi->dbi_db = NULL;
00778
00779 rpmMessage(RPMMESS_DEBUG, _("closed db index %s/%s\n"),
00780 dbhome, (dbfile ? dbfile : tagName(dbi->dbi_rpmtag)));
00781
00782 }
00783
00784 if (rpmdb->db_dbenv != NULL && dbi->dbi_use_dbenv) {
00785 if (rpmdb->db_opens == 1) {
00786
00787 xx = db_fini(dbi, (dbhome ? dbhome : ""), dbfile, dbsubfile);
00788
00789 rpmdb->db_dbenv = NULL;
00790 }
00791 rpmdb->db_opens--;
00792 }
00793
00794 if (dbi->dbi_verify_on_close && !dbi->dbi_temporary) {
00795 DB_ENV * dbenv = NULL;
00796
00797
00798 rc = db_env_create(&dbenv, 0);
00799
00800 rc = cvtdberr(dbi, "db_env_create", rc, _debug);
00801 if (rc || dbenv == NULL) goto exit;
00802
00803
00804 dbenv->set_errcall(dbenv, rpmdb->db_errcall);
00805 dbenv->set_errfile(dbenv, rpmdb->db_errfile);
00806 dbenv->set_errpfx(dbenv, rpmdb->db_errpfx);
00807
00808
00809 xx = dbenv->set_verbose(dbenv, DB_VERB_CHKPOINT,
00810 (dbi->dbi_verbose & DB_VERB_CHKPOINT));
00811 xx = dbenv->set_verbose(dbenv, DB_VERB_DEADLOCK,
00812 (dbi->dbi_verbose & DB_VERB_DEADLOCK));
00813 xx = dbenv->set_verbose(dbenv, DB_VERB_RECOVERY,
00814 (dbi->dbi_verbose & DB_VERB_RECOVERY));
00815 xx = dbenv->set_verbose(dbenv, DB_VERB_WAITSFOR,
00816 (dbi->dbi_verbose & DB_VERB_WAITSFOR));
00817
00818 if (dbi->dbi_tmpdir) {
00819
00820 const char * tmpdir = rpmGenPath(root, dbi->dbi_tmpdir, NULL);
00821
00822 rc = dbenv->set_tmp_dir(dbenv, tmpdir);
00823 rc = cvtdberr(dbi, "dbenv->set_tmp_dir", rc, _debug);
00824 tmpdir = _free(tmpdir);
00825 if (rc) goto exit;
00826 }
00827
00828 rc = dbenv->open(dbenv, dbhome,
00829 DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE | DB_USE_ENVIRON, 0);
00830 rc = cvtdberr(dbi, "dbenv->open", rc, _debug);
00831 if (rc) goto exit;
00832
00833
00834 rc = db_create(&db, dbenv, 0);
00835
00836 rc = cvtdberr(dbi, "db_create", rc, _debug);
00837
00838 if (db != NULL) {
00839
00840 const char * dbf = rpmGetPath(dbhome, "/", dbfile, NULL);
00841
00842
00843 rc = db->verify(db, dbf, NULL, NULL, flags);
00844 rc = cvtdberr(dbi, "db->verify", rc, _debug);
00845
00846 rpmMessage(RPMMESS_DEBUG, _("verified db index %s/%s\n"),
00847 (dbhome ? dbhome : ""),
00848 (dbfile ? dbfile : tagName(dbi->dbi_rpmtag)));
00849
00850 xx = db->close(db, 0);
00851
00852 _printit = (xx == ENOENT ? 0 : _debug);
00853 xx = cvtdberr(dbi, "db->close", xx, _printit);
00854 db = NULL;
00855 if (rc == 0 && xx) rc = xx;
00856
00857 dbf = _free(dbf);
00858 }
00859 xx = dbenv->close(dbenv, 0);
00860 xx = cvtdberr(dbi, "dbenv->close", xx, _debug);
00861 if (rc == 0 && xx) rc = xx;
00862 }
00863
00864 exit:
00865 dbi->dbi_db = NULL;
00866
00867 urlfn = _free(urlfn);
00868
00869 dbi = db3Free(dbi);
00870
00871 return rc;
00872 }
00873
00874
00875 static int db3open(rpmdb rpmdb, rpmTag rpmtag, dbiIndex * dbip)
00876
00877
00878
00879 {
00880
00881 extern struct _dbiVec db3vec;
00882
00883 const char * urlfn = NULL;
00884 const char * root;
00885 const char * home;
00886 const char * dbhome;
00887 const char * dbfile;
00888 const char * dbsubfile;
00889 dbiIndex dbi = NULL;
00890 int rc = 0;
00891 int xx;
00892
00893 DB * db = NULL;
00894 DB_ENV * dbenv = NULL;
00895 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1)
00896 DB_TXN * txnid = NULL;
00897 #endif
00898 u_int32_t oflags;
00899 int _printit;
00900
00901 if (dbip)
00902 *dbip = NULL;
00903
00904
00905
00906
00907
00908 if ((dbi = db3New(rpmdb, rpmtag)) == NULL)
00909
00910 return 1;
00911
00912
00913 dbi->dbi_api = DB_VERSION_MAJOR;
00914
00915
00916
00917
00918 root = (dbi->dbi_root ? dbi->dbi_root : rpmdb->db_root);
00919 if ((root[0] == '/' && root[1] == '\0') || rpmdb->db_chrootDone)
00920 root = NULL;
00921 home = (dbi->dbi_home ? dbi->dbi_home : rpmdb->db_home);
00922
00923
00924
00925
00926
00927
00928 urlfn = rpmGenPath(root, home, NULL);
00929
00930 (void) urlPath(urlfn, &dbhome);
00931 if (dbi->dbi_temporary) {
00932 dbfile = NULL;
00933 dbsubfile = NULL;
00934 } else {
00935 #ifdef HACK
00936 dbfile = (dbi->dbi_file ? dbi->dbi_file : db3basename);
00937 dbsubfile = (dbi->dbi_subfile ? dbi->dbi_subfile : tagName(dbi->dbi_rpmtag));
00938 #else
00939 dbfile = (dbi->dbi_file ? dbi->dbi_file : tagName(dbi->dbi_rpmtag));
00940 dbsubfile = NULL;
00941 #endif
00942 }
00943
00944 oflags = (dbi->dbi_oeflags | dbi->dbi_oflags);
00945 oflags &= ~DB_TRUNCATE;
00946
00947 #if 0
00948 if ( dbi->dbi_mode & O_EXCL) oflags |= DB_EXCL;
00949 #endif
00950
00951
00952
00953
00954 if (dbi->dbi_temporary) {
00955 oflags |= DB_CREATE;
00956 dbi->dbi_oeflags |= DB_CREATE;
00957 oflags &= ~DB_RDONLY;
00958 dbi->dbi_oflags &= ~DB_RDONLY;
00959 } else {
00960 if (!(dbi->dbi_mode & (O_RDWR|O_WRONLY))) oflags |= DB_RDONLY;
00961 if (dbi->dbi_mode & O_CREAT) {
00962 oflags |= DB_CREATE;
00963 dbi->dbi_oeflags |= DB_CREATE;
00964 }
00965 #ifdef DANGEROUS
00966 if ( dbi->dbi_mode & O_TRUNC) oflags |= DB_TRUNCATE;
00967 #endif
00968 }
00969
00970
00971
00972
00973 (void) rpmioMkpath(dbhome, 0755, getuid(), getgid());
00974
00975
00976
00977
00978 if (dbi->dbi_use_dbenv) {
00979
00980 #if HAVE_LIBPTHREAD
00981 if (rpmdb->db_dbenv == NULL) {
00982
00983 xx = db3_pthread_nptl();
00984 if (xx) {
00985 dbi->dbi_eflags |= DB_PRIVATE;
00986 rpmMessage(RPMMESS_DEBUG, _("unshared posix mutexes found(%d), adding DB_PRIVATE, using fcntl lock\n"), xx);
00987 }
00988 }
00989 #endif
00990
00991 if (access(dbhome, W_OK) == -1) {
00992
00993
00994 oflags &= ~DB_CREATE;
00995
00996
00997 if (dbi->dbi_eflags & DB_PRIVATE) {
00998 dbi->dbi_eflags &= ~DB_JOINENV;
00999 } else {
01000 dbi->dbi_eflags |= DB_JOINENV;
01001 dbi->dbi_oeflags &= ~DB_CREATE;
01002 dbi->dbi_oeflags &= ~DB_THREAD;
01003
01004 dbi->dbi_use_dbenv = 0;
01005 }
01006
01007
01008 if (dbi->dbi_temporary) {
01009 oflags |= DB_CREATE;
01010 dbi->dbi_oeflags |= DB_CREATE;
01011 oflags &= ~DB_RDONLY;
01012 dbi->dbi_oflags &= ~DB_RDONLY;
01013 } else {
01014 oflags |= DB_RDONLY;
01015
01016 dbi->dbi_oflags |= DB_RDONLY;
01017 }
01018
01019 } else {
01020
01021 const char * dbf = rpmGetPath(dbhome, "/__db.001", NULL);
01022
01023
01024 if (access(dbf, F_OK) == -1) {
01025
01026 dbi->dbi_oeflags |= DB_CREATE;
01027 dbi->dbi_eflags &= ~DB_JOINENV;
01028 } else {
01029
01030 if (dbi->dbi_eflags & DB_PRIVATE) {
01031 dbi->dbi_eflags &= ~DB_JOINENV;
01032 } else {
01033 dbi->dbi_eflags |= DB_JOINENV;
01034 dbi->dbi_oeflags &= ~DB_CREATE;
01035 dbi->dbi_oeflags &= ~DB_THREAD;
01036 }
01037 }
01038 dbf = _free(dbf);
01039 }
01040 }
01041
01042
01043
01044
01045 if ((oflags & DB_CREATE) && (oflags & DB_RDONLY)) {
01046
01047 const char * dbfn = (dbfile ? dbfile : tagName(dbi->dbi_rpmtag));
01048
01049 const char * dbf = rpmGetPath(dbhome, "/", dbfn, NULL);
01050
01051
01052 if (access(dbf, F_OK) == -1) {
01053
01054 oflags &= ~DB_RDONLY;
01055 } else {
01056
01057 oflags &= ~DB_CREATE;
01058 }
01059
01060
01061 if (!(oflags & DB_RDONLY) && access(dbf, W_OK) == 0) {
01062 dbi->dbi_oflags &= ~DB_RDONLY;
01063 } else {
01064 dbi->dbi_oflags |= DB_RDONLY;
01065 }
01066 dbf = _free(dbf);
01067 }
01068
01069
01070
01071
01072 if (oflags & DB_RDONLY)
01073 dbi->dbi_verify_on_close = 0;
01074
01075 if (dbi->dbi_use_dbenv) {
01076
01077 if (rpmdb->db_dbenv == NULL) {
01078 rc = db_init(dbi, dbhome, dbfile, dbsubfile, &dbenv);
01079 if (rc == 0) {
01080 rpmdb->db_dbenv = dbenv;
01081 rpmdb->db_opens = 1;
01082 }
01083 } else {
01084 dbenv = rpmdb->db_dbenv;
01085 rpmdb->db_opens++;
01086 }
01087
01088 }
01089
01090 rpmMessage(RPMMESS_DEBUG, _("opening db index %s/%s %s mode=0x%x\n"),
01091 dbhome, (dbfile ? dbfile : tagName(dbi->dbi_rpmtag)),
01092 prDbiOpenFlags(oflags, 0), dbi->dbi_mode);
01093
01094 if (rc == 0) {
01095 static int _lockdbfd = 0;
01096
01097
01098 rc = db_create(&db, dbenv, dbi->dbi_cflags);
01099
01100 rc = cvtdberr(dbi, "db_create", rc, _debug);
01101 if (rc == 0 && db != NULL) {
01102
01103
01104 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3) || (DB_VERSION_MAJOR == 4)
01105 if (rc == 0 &&
01106 rpmdb->db_malloc && rpmdb->db_realloc && rpmdb->db_free)
01107 {
01108 rc = db->set_alloc(db,
01109 rpmdb->db_malloc, rpmdb->db_realloc, rpmdb->db_free);
01110 rc = cvtdberr(dbi, "db->set_alloc", rc, _debug);
01111 }
01112 #else
01113 if (rc == 0 && rpmdb->db_malloc) {
01114 rc = db->set_malloc(db, rpmdb->db_malloc);
01115 rc = cvtdberr(dbi, "db->set_malloc", rc, _debug);
01116 }
01117 #endif
01118
01119
01120 if (rc == 0 && !dbi->dbi_use_dbenv && dbi->dbi_cachesize) {
01121 rc = db->set_cachesize(db, 0, dbi->dbi_cachesize, 0);
01122 rc = cvtdberr(dbi, "db->set_cachesize", rc, _debug);
01123 }
01124
01125
01126
01127
01128
01129
01130 if (rc == 0 && dbi->dbi_lorder) {
01131 rc = db->set_lorder(db, dbi->dbi_lorder);
01132 rc = cvtdberr(dbi, "db->set_lorder", rc, _debug);
01133 }
01134 if (rc == 0 && dbi->dbi_pagesize) {
01135 rc = db->set_pagesize(db, dbi->dbi_pagesize);
01136 rc = cvtdberr(dbi, "db->set_pagesize", rc, _debug);
01137 }
01138
01139 if (rc == 0 && oflags & DB_CREATE) {
01140 switch(dbi->dbi_type) {
01141 default:
01142 case DB_HASH:
01143 if (dbi->dbi_h_ffactor) {
01144 rc = db->set_h_ffactor(db, dbi->dbi_h_ffactor);
01145 rc = cvtdberr(dbi, "db->set_h_ffactor", rc, _debug);
01146 if (rc) break;
01147 }
01148 if (dbi->dbi_h_nelem) {
01149 rc = db->set_h_nelem(db, dbi->dbi_h_nelem);
01150 rc = cvtdberr(dbi, "db->set_h_nelem", rc, _debug);
01151 if (rc) break;
01152 }
01153 if (dbi->dbi_h_flags) {
01154 rc = db->set_flags(db, dbi->dbi_h_flags);
01155 rc = cvtdberr(dbi, "db->set_h_flags", rc, _debug);
01156 if (rc) break;
01157 }
01158
01159 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 2) || (DB_VERSION_MAJOR == 4)
01160 if (dbi->dbi_h_hash_fcn) {
01161 rc = db->set_h_hash(db, dbi->dbi_h_hash_fcn);
01162 rc = cvtdberr(dbi, "db->set_h_hash", rc, _debug);
01163 if (rc) break;
01164 }
01165 if (dbi->dbi_h_dup_compare_fcn) {
01166 rc = db->set_dup_compare(db, dbi->dbi_h_dup_compare_fcn);
01167 rc = cvtdberr(dbi, "db->set_dup_compare", rc, _debug);
01168 if (rc) break;
01169 }
01170 #endif
01171 break;
01172 case DB_BTREE:
01173
01174 if (dbi->dbi_bt_flags) {
01175 rc = db->set_flags(db, dbi->dbi_bt_flags);
01176 rc = cvtdberr(dbi, "db->set_bt_flags", rc, _debug);
01177 if (rc) break;
01178 }
01179 if (dbi->dbi_bt_minkey) {
01180 rc = db->set_bt_minkey(db, dbi->dbi_bt_minkey);
01181 rc = cvtdberr(dbi, "db->set_bt_minkey", rc, _debug);
01182 if (rc) break;
01183 }
01184
01185 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 2) || (DB_VERSION_MAJOR == 4)
01186 if (dbi->dbi_bt_compare_fcn) {
01187 rc = db->set_bt_compare(db, dbi->dbi_bt_compare_fcn);
01188 rc = cvtdberr(dbi, "db->set_bt_compare", rc, _debug);
01189 if (rc) break;
01190 }
01191 if (dbi->dbi_bt_dup_compare_fcn) {
01192 rc = db->set_dup_compare(db, dbi->dbi_bt_dup_compare_fcn);
01193 rc = cvtdberr(dbi, "db->set_dup_compare", rc, _debug);
01194 if (rc) break;
01195 }
01196 if (dbi->dbi_bt_prefix_fcn) {
01197 rc = db->set_bt_prefix(db, dbi->dbi_bt_prefix_fcn);
01198 rc = cvtdberr(dbi, "db->set_bt_prefix", rc, _debug);
01199 if (rc) break;
01200 }
01201 #endif
01202 break;
01203 case DB_RECNO:
01204 if (dbi->dbi_re_delim) {
01205
01206 rc = db->set_re_delim(db, dbi->dbi_re_delim);
01207 rc = cvtdberr(dbi, "db->set_re_selim", rc, _debug);
01208 if (rc) break;
01209 }
01210 if (dbi->dbi_re_len) {
01211 rc = db->set_re_len(db, dbi->dbi_re_len);
01212 rc = cvtdberr(dbi, "db->set_re_len", rc, _debug);
01213 if (rc) break;
01214 }
01215 if (dbi->dbi_re_pad) {
01216 rc = db->set_re_pad(db, dbi->dbi_re_pad);
01217 rc = cvtdberr(dbi, "db->set_re_pad", rc, _debug);
01218 if (rc) break;
01219 }
01220 if (dbi->dbi_re_source) {
01221 rc = db->set_re_source(db, dbi->dbi_re_source);
01222 rc = cvtdberr(dbi, "db->set_re_source", rc, _debug);
01223 if (rc) break;
01224 }
01225 break;
01226 case DB_QUEUE:
01227 if (dbi->dbi_q_extentsize) {
01228 rc = db->set_q_extentsize(db, dbi->dbi_q_extentsize);
01229 rc = cvtdberr(dbi, "db->set_q_extentsize", rc, _debug);
01230 if (rc) break;
01231 }
01232 break;
01233 }
01234 }
01235
01236 if (rc == 0) {
01237 const char * dbfullpath;
01238 const char * dbpath;
01239 char * t;
01240 int nb;
01241
01242 nb = strlen(dbhome);
01243 if (dbfile) nb += 1 + strlen(dbfile);
01244 dbfullpath = t = alloca(nb + 1);
01245
01246 t = stpcpy(t, dbhome);
01247 if (dbfile)
01248 t = stpcpy( stpcpy( t, "/"), dbfile);
01249 #ifdef HACK
01250 dbpath = (!dbi->dbi_use_dbenv && !dbi->dbi_temporary)
01251 ? dbfullpath : dbfile;
01252 #else
01253 dbpath = (!dbi->dbi_temporary)
01254 ? dbfullpath : dbfile;
01255 #endif
01256
01257 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1)
01258 rc = db->open(db, txnid, dbpath, dbsubfile,
01259 dbi->dbi_type, oflags, dbi->dbi_perms);
01260 #else
01261 rc = db->open(db, dbpath, dbsubfile,
01262 dbi->dbi_type, oflags, dbi->dbi_perms);
01263 #endif
01264
01265 if (rc == 0 && dbi->dbi_type == DB_UNKNOWN) {
01266 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3 && DB_VERSION_PATCH == 11) \
01267 || (DB_VERSION_MAJOR == 4)
01268 DBTYPE dbi_type = DB_UNKNOWN;
01269 xx = db->get_type(db, &dbi_type);
01270 if (xx == 0)
01271 dbi->dbi_type = dbi_type;
01272 #else
01273 dbi->dbi_type = db->get_type(db);
01274 #endif
01275 }
01276 }
01277
01278
01279 _printit = (rc > 0 ? 0 : _debug);
01280 xx = cvtdberr(dbi, "db->open", rc, _printit);
01281
01282 dbi->dbi_txnid = NULL;
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302 if (rc == 0 && dbi->dbi_lockdbfd &&
01303 !((dbi->dbi_ecflags & DB_CLIENT) && dbi->dbi_host) &&
01304 (!dbi->dbi_use_dbenv || _lockdbfd++ == 0))
01305 {
01306 int fdno = -1;
01307
01308 if (!(db->fd(db, &fdno) == 0 && fdno >= 0)) {
01309 rc = 1;
01310 } else {
01311 struct flock l;
01312 memset(&l, 0, sizeof(l));
01313 l.l_whence = 0;
01314 l.l_start = 0;
01315 l.l_len = 0;
01316 l.l_type = (dbi->dbi_mode & (O_RDWR|O_WRONLY))
01317 ? F_WRLCK : F_RDLCK;
01318 l.l_pid = 0;
01319
01320 rc = fcntl(fdno, F_SETLK, (void *) &l);
01321 if (rc) {
01322
01323 rc = ((dbi->dbi_use_dbenv &&
01324 (dbi->dbi_eflags & DB_INIT_CDB) &&
01325 !(dbi->dbi_eflags & DB_PRIVATE))
01326 ? 0 : 1);
01327 rpmError( (rc ? RPMERR_FLOCK : RPMWARN_FLOCK),
01328 _("cannot get %s lock on %s/%s\n"),
01329 ((dbi->dbi_mode & (O_RDWR|O_WRONLY))
01330 ? _("exclusive") : _("shared")),
01331 dbhome, (dbfile ? dbfile : ""));
01332 } else if (dbfile) {
01333 rpmMessage(RPMMESS_DEBUG,
01334 _("locked db index %s/%s\n"),
01335 dbhome, dbfile);
01336 }
01337 }
01338 }
01339 }
01340 }
01341
01342 dbi->dbi_db = db;
01343
01344 if (rc == 0 && dbi->dbi_db != NULL && dbip != NULL) {
01345 dbi->dbi_vec = &db3vec;
01346 *dbip = dbi;
01347 } else {
01348 dbi->dbi_verify_on_close = 0;
01349 (void) db3close(dbi, 0);
01350 }
01351
01352 urlfn = _free(urlfn);
01353
01354
01355 return rc;
01356
01357 }
01358
01361
01362
01363 struct _dbiVec db3vec = {
01364 DB_VERSION_MAJOR, DB_VERSION_MINOR, DB_VERSION_PATCH,
01365 db3open, db3close, db3sync, db3associate, db3join,
01366 db3copen, db3cclose, db3cdup, db3cdel, db3cget, db3cpget, db3cput, db3ccount,
01367 db3byteswapped, db3stat
01368 };
01369
01370