00001
00005 #include "system.h"
00006
00007 #if defined(__LCLINT__)
00008
00009 typedef unsigned int u_int32_t;
00010 typedef unsigned short u_int16_t;
00011 typedef unsigned char u_int8_t;
00012
00013 typedef int int32_t;
00014
00015
00016 #endif
00017
00018 #include <db3/db.h>
00019
00020 #include <rpmlib.h>
00021 #include <rpmmacro.h>
00022
00023 #include "rpmdb.h"
00024 #include "debug.h"
00025
00026
00027
00028
00029
00030 #if (DB_VERSION_MAJOR == 3) || (DB_VERSION_MAJOR == 4)
00031 #define __USE_DB3 1
00032
00033
00034
00035 struct _dbiIndex db3dbi;
00036
00037
00041 struct dbOption {
00042 const char * longName;
00043 const char shortName;
00044 int argInfo;
00045 void * arg;
00046 int val;
00047 const char * descrip;
00048 const char * argDescrip;
00049 };
00050
00051
00054
00055 struct dbOption rdbOptions[] = {
00056
00057 { "client", 0,POPT_BIT_SET, &db3dbi.dbi_ecflags, DB_CLIENT,
00058 NULL, NULL },
00059
00060 { "xa_create", 0,POPT_BIT_SET, &db3dbi.dbi_cflags, DB_XA_CREATE,
00061 NULL, NULL },
00062
00063 { "create", 0,POPT_BIT_SET, &db3dbi.dbi_oeflags, DB_CREATE,
00064 NULL, NULL },
00065 { "thread", 0,POPT_BIT_SET, &db3dbi.dbi_oeflags, DB_THREAD,
00066 NULL, NULL },
00067
00068 { "force", 0,POPT_BIT_SET, &db3dbi.dbi_eflags, DB_FORCE,
00069 NULL, NULL },
00070 { "cdb", 0,POPT_BIT_SET, &db3dbi.dbi_eflags, DB_INIT_CDB,
00071 NULL, NULL },
00072 { "lock", 0,POPT_BIT_SET, &db3dbi.dbi_eflags, DB_INIT_LOCK,
00073 NULL, NULL },
00074 { "log", 0,POPT_BIT_SET, &db3dbi.dbi_eflags, DB_INIT_LOG,
00075 NULL, NULL },
00076 { "mpool", 0,POPT_BIT_SET, &db3dbi.dbi_eflags, DB_INIT_MPOOL,
00077 NULL, NULL },
00078 { "txn", 0,POPT_BIT_SET, &db3dbi.dbi_eflags, DB_INIT_TXN,
00079 NULL, NULL },
00080 { "joinenv", 0,POPT_BIT_SET, &db3dbi.dbi_eflags, DB_JOINENV,
00081 NULL, NULL },
00082 { "recover", 0,POPT_BIT_SET, &db3dbi.dbi_eflags, DB_RECOVER,
00083 NULL, NULL },
00084 { "recover_fatal", 0,POPT_BIT_SET, &db3dbi.dbi_eflags, DB_RECOVER_FATAL,
00085 NULL, NULL },
00086 { "shared", 0,POPT_BIT_SET, &db3dbi.dbi_eflags, DB_SYSTEM_MEM,
00087 NULL, NULL },
00088 { "txn_nosync", 0,POPT_BIT_SET, &db3dbi.dbi_eflags, DB_TXN_NOSYNC,
00089 NULL, NULL },
00090 { "use_environ_root", 0,POPT_BIT_SET, &db3dbi.dbi_eflags, DB_USE_ENVIRON_ROOT,
00091 NULL, NULL },
00092 { "use_environ", 0,POPT_BIT_SET, &db3dbi.dbi_eflags, DB_USE_ENVIRON,
00093 NULL, NULL },
00094 { "lockdown", 0,POPT_BIT_SET, &db3dbi.dbi_eflags, DB_LOCKDOWN,
00095 NULL, NULL },
00096 { "private", 0,POPT_BIT_SET, &db3dbi.dbi_eflags, DB_PRIVATE,
00097 NULL, NULL },
00098
00099 { "txn_sync", 0,POPT_BIT_SET, &db3dbi.dbi_tflags, DB_TXN_SYNC,
00100 NULL, NULL },
00101 { "txn_nowait",0,POPT_BIT_SET, &db3dbi.dbi_tflags, DB_TXN_NOWAIT,
00102 NULL, NULL },
00103
00104 { "excl", 0,POPT_BIT_SET, &db3dbi.dbi_oflags, DB_EXCL,
00105 NULL, NULL },
00106 { "nommap", 0,POPT_BIT_SET, &db3dbi.dbi_oflags, DB_NOMMAP,
00107 NULL, NULL },
00108 { "rdonly", 0,POPT_BIT_SET, &db3dbi.dbi_oflags, DB_RDONLY,
00109 NULL, NULL },
00110 { "truncate", 0,POPT_BIT_SET, &db3dbi.dbi_oflags, DB_TRUNCATE,
00111 NULL, NULL },
00112 { "fcntl_locking",0,POPT_BIT_SET, &db3dbi.dbi_oflags, DB_FCNTL_LOCKING,
00113 NULL, NULL },
00114
00115 { "btree", 0,POPT_ARG_VAL, &db3dbi.dbi_type, DB_BTREE,
00116 NULL, NULL },
00117 { "hash", 0,POPT_ARG_VAL, &db3dbi.dbi_type, DB_HASH,
00118 NULL, NULL },
00119 { "recno", 0,POPT_ARG_VAL, &db3dbi.dbi_type, DB_RECNO,
00120 NULL, NULL },
00121 { "queue", 0,POPT_ARG_VAL, &db3dbi.dbi_type, DB_QUEUE,
00122 NULL, NULL },
00123 { "unknown", 0,POPT_ARG_VAL, &db3dbi.dbi_type, DB_UNKNOWN,
00124 NULL, NULL },
00125
00126 { "root", 0,POPT_ARG_STRING, &db3dbi.dbi_root, 0,
00127 NULL, NULL },
00128 { "home", 0,POPT_ARG_STRING, &db3dbi.dbi_home, 0,
00129 NULL, NULL },
00130 { "file", 0,POPT_ARG_STRING, &db3dbi.dbi_file, 0,
00131 NULL, NULL },
00132 { "subfile", 0,POPT_ARG_STRING, &db3dbi.dbi_subfile, 0,
00133 NULL, NULL },
00134 { "mode", 0,POPT_ARG_INT, &db3dbi.dbi_mode, 0,
00135 NULL, NULL },
00136 { "perms", 0,POPT_ARG_INT, &db3dbi.dbi_perms, 0,
00137 NULL, NULL },
00138 { "shmkey", 0,POPT_ARG_LONG, &db3dbi.dbi_shmkey, 0,
00139 NULL, NULL },
00140 { "tmpdir", 0,POPT_ARG_STRING, &db3dbi.dbi_tmpdir, 0,
00141 NULL, NULL },
00142
00143 { "host", 0,POPT_ARG_STRING, &db3dbi.dbi_host, 0,
00144 NULL, NULL },
00145 { "server", 0,POPT_ARG_STRING, &db3dbi.dbi_host, 0,
00146 NULL, NULL },
00147 { "cl_timeout", 0,POPT_ARG_LONG, &db3dbi.dbi_cl_timeout, 0,
00148 NULL, NULL },
00149 { "sv_timeout", 0,POPT_ARG_LONG, &db3dbi.dbi_sv_timeout, 0,
00150 NULL, NULL },
00151
00152 { "verify", 0,POPT_ARG_NONE, &db3dbi.dbi_verify_on_close, 0,
00153 NULL, NULL },
00154 { "teardown", 0,POPT_ARG_NONE, &db3dbi.dbi_tear_down, 0,
00155 NULL, NULL },
00156 { "usecursors",0,POPT_ARG_NONE, &db3dbi.dbi_use_cursors, 0,
00157 NULL, NULL },
00158 { "usedbenv", 0,POPT_ARG_NONE, &db3dbi.dbi_use_dbenv, 0,
00159 NULL, NULL },
00160 { "rmwcursor", 0,POPT_ARG_NONE, &db3dbi.dbi_get_rmw_cursor, 0,
00161 NULL, NULL },
00162 { "nofsync", 0,POPT_ARG_NONE, &db3dbi.dbi_no_fsync, 0,
00163 NULL, NULL },
00164 { "nodbsync", 0,POPT_ARG_NONE, &db3dbi.dbi_no_dbsync, 0,
00165 NULL, NULL },
00166 { "lockdbfd", 0,POPT_ARG_NONE, &db3dbi.dbi_lockdbfd, 0,
00167 NULL, NULL },
00168 { "temporary", 0,POPT_ARG_NONE, &db3dbi.dbi_temporary, 0,
00169 NULL, NULL },
00170 { "debug", 0,POPT_ARG_NONE, &db3dbi.dbi_debug, 0,
00171 NULL, NULL },
00172
00173 { "cachesize", 0,POPT_ARG_INT, &db3dbi.dbi_cachesize, 0,
00174 NULL, NULL },
00175 { "errpfx", 0,POPT_ARG_STRING, &db3dbi.dbi_errpfx, 0,
00176 NULL, NULL },
00177 { "region_init", 0,POPT_ARG_VAL, &db3dbi.dbi_region_init, 1,
00178 NULL, NULL },
00179 { "tas_spins", 0,POPT_ARG_INT, &db3dbi.dbi_tas_spins, 0,
00180 NULL, NULL },
00181
00182 { "chkpoint", 0,POPT_BIT_SET, &db3dbi.dbi_verbose, DB_VERB_CHKPOINT,
00183 NULL, NULL },
00184 { "deadlock", 0,POPT_BIT_SET, &db3dbi.dbi_verbose, DB_VERB_DEADLOCK,
00185 NULL, NULL },
00186 { "recovery", 0,POPT_BIT_SET, &db3dbi.dbi_verbose, DB_VERB_RECOVERY,
00187 NULL, NULL },
00188 { "waitsfor", 0,POPT_BIT_SET, &db3dbi.dbi_verbose, DB_VERB_WAITSFOR,
00189 NULL, NULL },
00190 { "verbose", 0,POPT_ARG_VAL, &db3dbi.dbi_verbose, -1,
00191 NULL, NULL },
00192
00193 { "lk_oldest", 0,POPT_ARG_VAL, &db3dbi.dbi_lk_detect, DB_LOCK_OLDEST,
00194 NULL, NULL },
00195 { "lk_random", 0,POPT_ARG_VAL, &db3dbi.dbi_lk_detect, DB_LOCK_RANDOM,
00196 NULL, NULL },
00197 { "lk_youngest",0, POPT_ARG_VAL, &db3dbi.dbi_lk_detect, DB_LOCK_YOUNGEST,
00198 NULL, NULL },
00199
00200 { "lk_max", 0,POPT_ARG_INT, &db3dbi.dbi_lk_max, 0,
00201 NULL, NULL },
00202
00203 { "lg_bsize", 0,POPT_ARG_INT, &db3dbi.dbi_lg_bsize, 0,
00204 NULL, NULL },
00205 { "lg_max", 0,POPT_ARG_INT, &db3dbi.dbi_lg_max, 0,
00206 NULL, NULL },
00207
00208
00209 { "tx_max", 0,POPT_ARG_INT, &db3dbi.dbi_tx_max, 0,
00210 NULL, NULL },
00211
00212 { "lorder", 0,POPT_ARG_INT, &db3dbi.dbi_lorder, 0,
00213 NULL, NULL },
00214
00215 { "mp_mmapsize", 0,POPT_ARG_INT, &db3dbi.dbi_mp_mmapsize, 0,
00216 NULL, NULL },
00217 { "mp_size", 0,POPT_ARG_INT, &db3dbi.dbi_mp_size, 0,
00218 NULL, NULL },
00219 { "pagesize", 0,POPT_ARG_INT, &db3dbi.dbi_pagesize, 0,
00220 NULL, NULL },
00221
00222
00223
00224
00225
00226 { "bt_dup", 0,POPT_BIT_SET, &db3dbi.dbi_bt_flags, DB_DUP,
00227 NULL, NULL },
00228 { "bt_dupsort",0,POPT_BIT_SET, &db3dbi.dbi_bt_flags, DB_DUPSORT,
00229 NULL, NULL },
00230 { "bt_recnum", 0,POPT_BIT_SET, &db3dbi.dbi_bt_flags, DB_RECNUM,
00231 NULL, NULL },
00232 { "bt_revsplitoff", 0,POPT_BIT_SET, &db3dbi.dbi_bt_flags, DB_REVSPLITOFF,
00233 NULL, NULL },
00234
00235 { "h_dup", 0,POPT_BIT_SET, &db3dbi.dbi_h_flags, DB_DUP,
00236 NULL, NULL },
00237 { "h_dupsort", 0,POPT_BIT_SET, &db3dbi.dbi_h_flags, DB_DUPSORT,
00238 NULL, NULL },
00239 { "h_ffactor", 0,POPT_ARG_INT, &db3dbi.dbi_h_ffactor, 0,
00240 NULL, NULL },
00241 { "h_nelem", 0,POPT_ARG_INT, &db3dbi.dbi_h_nelem, 0,
00242 NULL, NULL },
00243
00244 { "re_renumber", 0,POPT_BIT_SET, &db3dbi.dbi_re_flags, DB_RENUMBER,
00245 NULL, NULL },
00246 { "re_snapshot",0,POPT_BIT_SET, &db3dbi.dbi_re_flags, DB_SNAPSHOT,
00247 NULL, NULL },
00248 { "re_delim", 0,POPT_ARG_INT, &db3dbi.dbi_re_delim, 0,
00249 NULL, NULL },
00250 { "re_len", 0,POPT_ARG_INT, &db3dbi.dbi_re_len, 0,
00251 NULL, NULL },
00252 { "re_pad", 0,POPT_ARG_INT, &db3dbi.dbi_re_pad, 0,
00253 NULL, NULL },
00254 { "re_source", 0,POPT_ARG_STRING, &db3dbi.dbi_re_source, 0,
00255 NULL, NULL },
00256
00257 { "q_extentsize", 0,POPT_ARG_INT, &db3dbi.dbi_q_extentsize, 0,
00258 NULL, NULL },
00259
00260 { NULL, 0,0, NULL, 0, NULL, NULL }
00261 };
00262
00263
00264 static int dbSaveLong(const struct dbOption * opt, int argInfo, long aLong)
00265
00266 {
00267 if (argInfo & POPT_ARGFLAG_NOT)
00268 aLong = ~aLong;
00269 if (opt->arg != NULL)
00270 switch (argInfo & POPT_ARGFLAG_LOGICALOPS) {
00271 case 0:
00272 *((long *) opt->arg) = aLong;
00273 break;
00274 case POPT_ARGFLAG_OR:
00275 *((long *) opt->arg) |= aLong;
00276 break;
00277 case POPT_ARGFLAG_AND:
00278 *((long *) opt->arg) &= aLong;
00279 break;
00280 case POPT_ARGFLAG_XOR:
00281 *((long *) opt->arg) ^= aLong;
00282 break;
00283 default:
00284 return POPT_ERROR_BADOPERATION;
00285 break;
00286 }
00287 return 0;
00288 }
00289
00290 static int dbSaveInt(const struct dbOption * opt, int argInfo, long aLong)
00291
00292 {
00293 if (argInfo & POPT_ARGFLAG_NOT)
00294 aLong = ~aLong;
00295 if (opt->arg != NULL)
00296 switch (argInfo & POPT_ARGFLAG_LOGICALOPS) {
00297 case 0:
00298 *((int *) opt->arg) = aLong;
00299 break;
00300 case POPT_ARGFLAG_OR:
00301 *((int *) opt->arg) |= aLong;
00302 break;
00303 case POPT_ARGFLAG_AND:
00304 *((int *) opt->arg) &= aLong;
00305 break;
00306 case POPT_ARGFLAG_XOR:
00307 *((int *) opt->arg) ^= aLong;
00308 break;
00309 default:
00310 return POPT_ERROR_BADOPERATION;
00311 break;
00312 }
00313 return 0;
00314 }
00315
00316 dbiIndex db3Free(dbiIndex dbi)
00317 {
00318 if (dbi) {
00319 dbi->dbi_root = _free(dbi->dbi_root);
00320 dbi->dbi_home = _free(dbi->dbi_home);
00321 dbi->dbi_file = _free(dbi->dbi_file);
00322 dbi->dbi_subfile = _free(dbi->dbi_subfile);
00323 dbi->dbi_host = _free(dbi->dbi_host);
00324 dbi->dbi_errpfx = _free(dbi->dbi_errpfx);
00325 dbi->dbi_re_source = _free(dbi->dbi_re_source);
00326 dbi->dbi_stats = _free(dbi->dbi_stats);
00327 dbi = _free(dbi);
00328 }
00329 return dbi;
00330 }
00331
00333
00334 static const char *db3_config_default =
00335 "db3:hash:mpool:cdb:usecursors:verbose:mp_mmapsize=8Mb:mp_size=512Kb:pagesize=512:perms=0644";
00336
00337 dbiIndex db3New(rpmdb rpmdb, int rpmtag)
00338 {
00339 dbiIndex dbi = xcalloc(1, sizeof(*dbi));
00340 char dbiTagMacro[128];
00341 char * dbOpts;
00342
00343 sprintf(dbiTagMacro, "%%{_dbi_config_%s}", tagName(rpmtag));
00344
00345 dbOpts = rpmExpand(dbiTagMacro, NULL);
00346
00347 if (!(dbOpts && *dbOpts && *dbOpts != '%')) {
00348 dbOpts = _free(dbOpts);
00349
00350 dbOpts = rpmExpand("%{_dbi_config}", NULL);
00351
00352 if (!(dbOpts && *dbOpts && *dbOpts != '%')) {
00353
00354 dbOpts = rpmExpand(db3_config_default, NULL);
00355
00356 }
00357 }
00358
00359
00360
00361 if (dbOpts && *dbOpts && *dbOpts != '%') {
00362 char *o, *oe;
00363 char *p, *pe;
00364
00365 memset(&db3dbi, 0, sizeof(db3dbi));
00366 for (o = dbOpts; o && *o; o = oe) {
00367 struct dbOption *opt;
00368 const char * tok;
00369 int argInfo;
00370
00371
00372 while (*o && xisspace(*o))
00373 o++;
00374
00375
00376 for (oe = o; oe && *oe; oe++) {
00377 if (xisspace(*oe))
00378 break;
00379 if (oe[0] == ':' && !(oe[1] == '/' && oe[2] == '/'))
00380 break;
00381 }
00382 if (oe && *oe)
00383 *oe++ = '\0';
00384 if (*o == '\0')
00385 continue;
00386
00387
00388 for (pe = o; pe && *pe && *pe != '='; pe++)
00389 {};
00390 p = (pe ? *pe++ = '\0', pe : NULL);
00391
00392
00393 for (tok = o; *tok == '!'; tok++)
00394 {};
00395
00396
00397 for (opt = rdbOptions; opt->longName != NULL; opt++) {
00398 if (strcmp(tok, opt->longName))
00399 continue;
00400 break;
00401 }
00402 if (opt->longName == NULL) {
00403 rpmError(RPMERR_DBCONFIG,
00404 _("unrecognized db option: \"%s\" ignored.\n"), o);
00405 continue;
00406 }
00407
00408
00409 argInfo = opt->argInfo;
00410 if (argInfo == POPT_BIT_SET && *o == '!' && ((tok - o) % 2))
00411 argInfo = POPT_BIT_CLR;
00412
00413
00414 switch (argInfo & POPT_ARG_MASK) {
00415
00416 case POPT_ARG_NONE:
00417 (void) dbSaveInt(opt, argInfo, 1L);
00418 break;
00419 case POPT_ARG_VAL:
00420 (void) dbSaveInt(opt, argInfo, (long)opt->val);
00421 break;
00422 case POPT_ARG_STRING:
00423 { const char ** t = opt->arg;
00424
00425 if (t) {
00426 *t = _free(*t);
00427 *t = xstrdup( (p ? p : "") );
00428 }
00429
00430 } break;
00431
00432 case POPT_ARG_INT:
00433 case POPT_ARG_LONG:
00434 { long aLong = strtol(p, &pe, 0);
00435 if (pe) {
00436 if (!xstrncasecmp(pe, "Mb", 2))
00437 aLong *= 1024 * 1024;
00438 else if (!xstrncasecmp(pe, "Kb", 2))
00439 aLong *= 1024;
00440 else if (*pe != '\0') {
00441 rpmError(RPMERR_DBCONFIG,
00442 _("%s has invalid numeric value, skipped\n"),
00443 opt->longName);
00444 continue;
00445 }
00446 }
00447
00448 if ((argInfo & POPT_ARG_MASK) == POPT_ARG_LONG) {
00449 if (aLong == LONG_MIN || aLong == LONG_MAX) {
00450 rpmError(RPMERR_DBCONFIG,
00451 _("%s has too large or too small long value, skipped\n"),
00452 opt->longName);
00453 continue;
00454 }
00455 (void) dbSaveLong(opt, argInfo, aLong);
00456 break;
00457 } else {
00458 if (aLong > INT_MAX || aLong < INT_MIN) {
00459 rpmError(RPMERR_DBCONFIG,
00460 _("%s has too large or too small integer value, skipped\n"),
00461 opt->longName);
00462 continue;
00463 }
00464 (void) dbSaveInt(opt, argInfo, aLong);
00465 }
00466 } break;
00467 default:
00468 break;
00469 }
00470 }
00471 }
00472
00473
00474 dbOpts = _free(dbOpts);
00475
00476
00477 *dbi = db3dbi;
00478
00479 memset(&db3dbi, 0, sizeof(db3dbi));
00480
00481 if (!(dbi->dbi_perms & 0600))
00482 dbi->dbi_perms = 0644;
00483 dbi->dbi_mode = rpmdb->db_mode;
00484
00485 dbi->dbi_rpmdb = rpmdb;
00486
00487 dbi->dbi_rpmtag = rpmtag;
00488
00489
00490
00491
00492
00493 switch (rpmtag) {
00494 case RPMDBI_PACKAGES:
00495 case RPMDBI_DEPENDS:
00496 dbi->dbi_jlen = 1 * sizeof(int_32);
00497 break;
00498 default:
00499 dbi->dbi_jlen = 2 * sizeof(int_32);
00500 break;
00501 }
00502
00503
00504 dbi->dbi_use_cursors = 1;
00505
00506 if (!dbi->dbi_use_dbenv) {
00507 dbi->dbi_use_dbenv = 1;
00508 dbi->dbi_eflags |= (DB_INIT_MPOOL|DB_JOINENV);
00509 dbi->dbi_mp_mmapsize = 8 * 1024 * 1024;
00510 dbi->dbi_mp_size = 512 * 1024;
00511 dbi->dbi_tear_down = 1;
00512 }
00513
00514 if ((dbi->dbi_bt_flags | dbi->dbi_h_flags) & DB_DUP)
00515 dbi->dbi_permit_dups = 1;
00516
00517
00518 return dbi;
00519
00520 }
00521
00522 const char *const prDbiOpenFlags(int dbflags, int print_dbenv_flags)
00523 {
00524 static char buf[256];
00525 struct dbOption *opt;
00526 char * oe;
00527
00528 oe = buf;
00529 *oe = '\0';
00530 for (opt = rdbOptions; opt->longName != NULL; opt++) {
00531 if (opt->argInfo != POPT_BIT_SET)
00532 continue;
00533 if (print_dbenv_flags) {
00534 if (!(opt->arg == &db3dbi.dbi_oeflags ||
00535 opt->arg == &db3dbi.dbi_eflags))
00536 continue;
00537 } else {
00538 if (!(opt->arg == &db3dbi.dbi_oeflags ||
00539 opt->arg == &db3dbi.dbi_oflags))
00540 continue;
00541 }
00542 if ((dbflags & opt->val) != opt->val)
00543 continue;
00544 if (oe != buf)
00545 *oe++ = ':';
00546 oe = stpcpy(oe, opt->longName);
00547 dbflags &= ~opt->val;
00548 }
00549 if (dbflags) {
00550 if (oe != buf)
00551 *oe++ = ':';
00552 sprintf(oe, "0x%x", (unsigned)dbflags);
00553 }
00554 return buf;
00555 }
00556
00557 #endif