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