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