00001
00005 #include "system.h"
00006
00007 #include <db3/db.h>
00008
00009 #include <rpmlib.h>
00010 #include <rpmmacro.h>
00011
00012 #include "rpmdb.h"
00013 #include "debug.h"
00014
00015
00016
00017
00018
00019 #if DB_VERSION_MAJOR == 3
00020 #define __USE_DB3 1
00021
00022 struct _dbiIndex db3dbi;
00023
00027 struct dbOption {
00028 const char * longName;
00029 int argInfo;
00030 void * arg;
00031 int val;
00032 };
00033
00034 #define _POPT_SET_BIT (POPT_ARG_VAL|POPT_ARGFLAG_OR)
00035
00036
00039 struct dbOption rdbOptions[] = {
00040
00041 { "xa_create", _POPT_SET_BIT, &db3dbi.dbi_cflags, DB_XA_CREATE },
00042
00043 { "create", _POPT_SET_BIT, &db3dbi.dbi_oeflags, DB_CREATE },
00044 { "nommap", _POPT_SET_BIT, &db3dbi.dbi_oeflags, DB_NOMMAP },
00045 { "thread", _POPT_SET_BIT, &db3dbi.dbi_oeflags, DB_THREAD },
00046
00047 { "force", _POPT_SET_BIT, &db3dbi.dbi_eflags, DB_FORCE },
00048 { "cdb", _POPT_SET_BIT, &db3dbi.dbi_eflags, DB_INIT_CDB },
00049 { "lock", _POPT_SET_BIT, &db3dbi.dbi_eflags, DB_INIT_LOCK },
00050 { "log", _POPT_SET_BIT, &db3dbi.dbi_eflags, DB_INIT_LOG },
00051 { "mpool", _POPT_SET_BIT, &db3dbi.dbi_eflags, DB_INIT_MPOOL },
00052 { "txn", _POPT_SET_BIT, &db3dbi.dbi_eflags, DB_INIT_TXN },
00053 { "recover", _POPT_SET_BIT, &db3dbi.dbi_eflags, DB_RECOVER },
00054 { "recover_fatal", _POPT_SET_BIT, &db3dbi.dbi_eflags, DB_RECOVER_FATAL },
00055 { "shared", _POPT_SET_BIT, &db3dbi.dbi_eflags, DB_SYSTEM_MEM },
00056 { "txn_nosync", _POPT_SET_BIT, &db3dbi.dbi_eflags, DB_TXN_NOSYNC },
00057 { "use_environ_root", _POPT_SET_BIT, &db3dbi.dbi_eflags, DB_USE_ENVIRON_ROOT },
00058 { "use_environ", _POPT_SET_BIT, &db3dbi.dbi_eflags, DB_USE_ENVIRON },
00059 { "lockdown", _POPT_SET_BIT, &db3dbi.dbi_eflags, DB_LOCKDOWN },
00060 { "private", _POPT_SET_BIT, &db3dbi.dbi_eflags, DB_PRIVATE },
00061
00062 { "txn_sync", _POPT_SET_BIT, &db3dbi.dbi_tflags, DB_TXN_SYNC },
00063 { "txn_nowait",_POPT_SET_BIT, &db3dbi.dbi_tflags, DB_TXN_NOWAIT },
00064
00065 { "excl", _POPT_SET_BIT, &db3dbi.dbi_oflags, DB_EXCL },
00066 { "rdonly", _POPT_SET_BIT, &db3dbi.dbi_oflags, DB_RDONLY },
00067 { "truncate", _POPT_SET_BIT, &db3dbi.dbi_oflags, DB_TRUNCATE },
00068 { "fcntl_locking",_POPT_SET_BIT, &db3dbi.dbi_oflags, DB_FCNTL_LOCKING },
00069
00070 { "btree", POPT_ARG_VAL, &db3dbi.dbi_type, DB_BTREE },
00071 { "hash", POPT_ARG_VAL, &db3dbi.dbi_type, DB_HASH },
00072 { "recno", POPT_ARG_VAL, &db3dbi.dbi_type, DB_RECNO },
00073 { "queue", POPT_ARG_VAL, &db3dbi.dbi_type, DB_QUEUE },
00074 { "unknown", POPT_ARG_VAL, &db3dbi.dbi_type, DB_UNKNOWN },
00075
00076 { "root", POPT_ARG_STRING, &db3dbi.dbi_root, 0 },
00077 { "home", POPT_ARG_STRING, &db3dbi.dbi_home, 0 },
00078 { "file", POPT_ARG_STRING, &db3dbi.dbi_file, 0 },
00079 { "subfile", POPT_ARG_STRING, &db3dbi.dbi_subfile, 0 },
00080 { "mode", POPT_ARG_INT, &db3dbi.dbi_mode, 0 },
00081 { "perms", POPT_ARG_INT, &db3dbi.dbi_perms, 0 },
00082
00083 { "teardown", POPT_ARG_NONE, &db3dbi.dbi_tear_down, 0 },
00084 { "usecursors",POPT_ARG_NONE, &db3dbi.dbi_use_cursors, 0 },
00085 { "usedbenv", POPT_ARG_NONE, &db3dbi.dbi_use_dbenv, 0 },
00086 { "rmwcursor", POPT_ARG_NONE, &db3dbi.dbi_get_rmw_cursor, 0 },
00087 { "nofsync", POPT_ARG_NONE, &db3dbi.dbi_no_fsync, 0 },
00088 { "nodbsync", POPT_ARG_NONE, &db3dbi.dbi_no_dbsync, 0 },
00089 { "lockdbfd", POPT_ARG_NONE, &db3dbi.dbi_lockdbfd, 0 },
00090 { "temporary", POPT_ARG_NONE, &db3dbi.dbi_temporary, 0 },
00091 { "debug", POPT_ARG_NONE, &db3dbi.dbi_debug, 0 },
00092
00093 { "cachesize", POPT_ARG_INT, &db3dbi.dbi_cachesize, 0 },
00094 { "errpfx", POPT_ARG_STRING, &db3dbi.dbi_errpfx, 0 },
00095 { "region_init", POPT_ARG_VAL, &db3dbi.dbi_region_init, 1 },
00096 { "tas_spins", POPT_ARG_INT, &db3dbi.dbi_tas_spins, 0 },
00097
00098 { "chkpoint", _POPT_SET_BIT, &db3dbi.dbi_verbose, DB_VERB_CHKPOINT },
00099 { "deadlock", _POPT_SET_BIT, &db3dbi.dbi_verbose, DB_VERB_DEADLOCK },
00100 { "recovery", _POPT_SET_BIT, &db3dbi.dbi_verbose, DB_VERB_RECOVERY },
00101 { "waitsfor", _POPT_SET_BIT, &db3dbi.dbi_verbose, DB_VERB_WAITSFOR },
00102 { "verbose", POPT_ARG_VAL, &db3dbi.dbi_verbose, -1 },
00103
00104 { "lk_oldest", POPT_ARG_VAL, &db3dbi.dbi_lk_detect, DB_LOCK_OLDEST },
00105 { "lk_random", POPT_ARG_VAL, &db3dbi.dbi_lk_detect, DB_LOCK_RANDOM },
00106 { "lk_youngest", POPT_ARG_VAL, &db3dbi.dbi_lk_detect, DB_LOCK_YOUNGEST },
00107
00108 { "lk_max", POPT_ARG_INT, &db3dbi.dbi_lk_max, 0 },
00109
00110 { "lg_bsize", POPT_ARG_INT, &db3dbi.dbi_lg_bsize, 0 },
00111 { "lg_max", POPT_ARG_INT, &db3dbi.dbi_lg_max, 0 },
00112
00113
00114 { "tx_max", POPT_ARG_INT, &db3dbi.dbi_tx_max, 0 },
00115
00116 { "lorder", POPT_ARG_INT, &db3dbi.dbi_lorder, 0 },
00117
00118 { "mp_mmapsize", POPT_ARG_INT, &db3dbi.dbi_mp_mmapsize, 0 },
00119 { "mp_size", POPT_ARG_INT, &db3dbi.dbi_mp_size, 0 },
00120 { "pagesize", POPT_ARG_INT, &db3dbi.dbi_pagesize, 0 },
00121
00122
00123
00124
00125
00126 { "bt_dup", _POPT_SET_BIT, &db3dbi.dbi_bt_flags, DB_DUP },
00127 { "bt_dupsort",_POPT_SET_BIT, &db3dbi.dbi_bt_flags, DB_DUPSORT },
00128 { "bt_recnum", _POPT_SET_BIT, &db3dbi.dbi_bt_flags, DB_RECNUM },
00129 { "bt_revsplitoff", _POPT_SET_BIT, &db3dbi.dbi_bt_flags, DB_REVSPLITOFF },
00130
00131 { "h_dup", _POPT_SET_BIT, &db3dbi.dbi_h_flags, DB_DUP },
00132 { "h_dupsort", _POPT_SET_BIT, &db3dbi.dbi_h_flags, DB_DUPSORT },
00133 { "h_ffactor", POPT_ARG_INT, &db3dbi.dbi_h_ffactor, 0 },
00134 { "h_nelem", POPT_ARG_INT, &db3dbi.dbi_h_nelem, 0 },
00135
00136 { "re_renumber", _POPT_SET_BIT, &db3dbi.dbi_re_flags, DB_RENUMBER },
00137 { "re_snapshot",_POPT_SET_BIT, &db3dbi.dbi_re_flags, DB_SNAPSHOT },
00138 { "re_delim", POPT_ARG_INT, &db3dbi.dbi_re_delim, 0 },
00139 { "re_len", POPT_ARG_INT, &db3dbi.dbi_re_len, 0 },
00140 { "re_pad", POPT_ARG_INT, &db3dbi.dbi_re_pad, 0 },
00141 { "re_source", POPT_ARG_STRING, &db3dbi.dbi_re_source, 0 },
00142
00143 { NULL, 0, NULL, 0 }
00144 };
00145
00146
00147 static int dbSaveLong(const struct dbOption * opt, long aLong) {
00148 if (opt->argInfo & POPT_ARGFLAG_NOT)
00149 aLong = ~aLong;
00150 switch (opt->argInfo & POPT_ARGFLAG_LOGICALOPS) {
00151 case 0:
00152 *((long *) opt->arg) = aLong;
00153 break;
00154 case POPT_ARGFLAG_OR:
00155 *((long *) opt->arg) |= aLong;
00156 break;
00157 case POPT_ARGFLAG_AND:
00158 *((long *) opt->arg) &= aLong;
00159 break;
00160 case POPT_ARGFLAG_XOR:
00161 *((long *) opt->arg) ^= aLong;
00162 break;
00163 default:
00164 return POPT_ERROR_BADOPERATION;
00165 break;
00166 }
00167 return 0;
00168 }
00169
00170 static int dbSaveInt(const struct dbOption * opt, long aLong) {
00171 if (opt->argInfo & POPT_ARGFLAG_NOT)
00172 aLong = ~aLong;
00173 switch (opt->argInfo & POPT_ARGFLAG_LOGICALOPS) {
00174 case 0:
00175 *((int *) opt->arg) = aLong;
00176 break;
00177 case POPT_ARGFLAG_OR:
00178 *((int *) opt->arg) |= aLong;
00179 break;
00180 case POPT_ARGFLAG_AND:
00181 *((int *) opt->arg) &= aLong;
00182 break;
00183 case POPT_ARGFLAG_XOR:
00184 *((int *) opt->arg) ^= aLong;
00185 break;
00186 default:
00187 return POPT_ERROR_BADOPERATION;
00188 break;
00189 }
00190 return 0;
00191 }
00192
00193 void db3Free(dbiIndex dbi) {
00194 if (dbi) {
00195 if (dbi->dbi_root) free((void *)dbi->dbi_root);
00196 if (dbi->dbi_home) free((void *)dbi->dbi_home);
00197 if (dbi->dbi_file) free((void *)dbi->dbi_file);
00198 if (dbi->dbi_subfile) free((void *)dbi->dbi_subfile);
00199 if (dbi->dbi_errpfx) free((void *)dbi->dbi_errpfx);
00200 if (dbi->dbi_re_source) free((void *)dbi->dbi_re_source);
00201 if (dbi->dbi_dbenv) free(dbi->dbi_dbenv);
00202 if (dbi->dbi_dbinfo) free(dbi->dbi_dbinfo);
00203 free((void *)dbi);
00204 }
00205 }
00206
00207 static const char *db3_config_default =
00208 "db3:hash:mpool:cdb:usecursors:verbose:mp_mmapsize=8Mb:mp_size=512Kb:pagesize=512:perms=0644";
00209
00210 dbiIndex db3New(rpmdb rpmdb, int rpmtag)
00211 {
00212 dbiIndex dbi = xcalloc(1, sizeof(*dbi));
00213 char dbiTagMacro[128];
00214 char * dbOpts;
00215
00216 sprintf(dbiTagMacro, "%%{_dbi_config_%s}", tagName(rpmtag));
00217 dbOpts = rpmExpand(dbiTagMacro, NULL);
00218 if (!(dbOpts && *dbOpts && *dbOpts != '%')) {
00219 if (dbOpts) {
00220 free(dbOpts);
00221 dbOpts = NULL;
00222 }
00223 dbOpts = rpmExpand("%{_dbi_config}", NULL);
00224 if (!(dbOpts && *dbOpts && *dbOpts != '%')) {
00225 dbOpts = rpmExpand(db3_config_default, NULL);
00226 }
00227 }
00228
00229 if (dbOpts && *dbOpts && *dbOpts != '%') {
00230 char *o, *oe;
00231 char *p, *pe;
00232 for (o = dbOpts; o && *o; o = oe) {
00233 struct dbOption *opt;
00234
00235 while (*o && isspace(*o))
00236 o++;
00237 for (oe = o; oe && *oe; oe++) {
00238 if (isspace(*oe))
00239 break;
00240 if (oe[0] == ':' && !(oe[1] == '/' && oe[2] == '/'))
00241 break;
00242 }
00243 if (oe && *oe)
00244 *oe++ = '\0';
00245 if (*o == '\0')
00246 continue;
00247 for (pe = o; pe && *pe && *pe != '='; pe++)
00248 ;
00249 p = (pe ? *pe++ = '\0', pe : NULL);
00250
00251 for (opt = rdbOptions; opt->longName != NULL; opt++) {
00252 if (strcmp(o, opt->longName))
00253 continue;
00254 break;
00255 }
00256 if (opt->longName == NULL) {
00257 rpmError(RPMERR_DBCONFIG,
00258 _("unrecognized db option: \"%s\" ignored\n"), o);
00259 continue;
00260 }
00261
00262 switch (opt->argInfo & POPT_ARG_MASK) {
00263 long aLong;
00264
00265 case POPT_ARG_NONE:
00266 (void) dbSaveInt(opt, 1L);
00267 break;
00268 case POPT_ARG_VAL:
00269 (void) dbSaveInt(opt, (long)opt->val);
00270 break;
00271 case POPT_ARG_STRING:
00272 { const char ** t = opt->arg;
00273 if (*t) free((void *)*t);
00274 *t = xstrdup( (p ? p : "") );
00275 } break;
00276
00277 case POPT_ARG_INT:
00278 case POPT_ARG_LONG:
00279 aLong = strtol(p, &pe, 0);
00280 if (pe) {
00281 if (!xstrncasecmp(pe, "Mb", 2))
00282 aLong *= 1024 * 1024;
00283 else if (!xstrncasecmp(pe, "Kb", 2))
00284 aLong *= 1024;
00285 else if (*pe != '\0') {
00286 rpmError(RPMERR_DBCONFIG,
00287 _("%s has invalid numeric value, skipped\n"),
00288 opt->longName);
00289 continue;
00290 }
00291 }
00292
00293 if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_LONG) {
00294 if (aLong == LONG_MIN || aLong == LONG_MAX) {
00295 rpmError(RPMERR_DBCONFIG,
00296 _("%s has too large or too small long value, skipped\n"),
00297 opt->longName);
00298 continue;
00299 }
00300 (void) dbSaveLong(opt, aLong);
00301 break;
00302 } else {
00303 if (aLong > INT_MAX || aLong < INT_MIN) {
00304 rpmError(RPMERR_DBCONFIG,
00305 _("%s has too large or too small integer value, skipped\n"),
00306 opt->longName);
00307 continue;
00308 }
00309 (void) dbSaveInt(opt, aLong);
00310 }
00311 break;
00312 default:
00313 break;
00314 }
00315 }
00316 }
00317
00318 free(dbOpts);
00319
00320 *dbi = db3dbi;
00321 memset(&db3dbi, 0, sizeof(db3dbi));
00322
00323 if (!(dbi->dbi_perms & 0600))
00324 dbi->dbi_perms = 0644;
00325 dbi->dbi_mode = rpmdb->db_mode;
00326 dbi->dbi_rpmdb = rpmdb;
00327 dbi->dbi_rpmtag = rpmtag;
00328
00329 switch (rpmtag) {
00330 case RPMDBI_PACKAGES:
00331 case RPMDBI_DEPENDS:
00332 dbi->dbi_jlen = 1 * sizeof(int_32);
00333 break;
00334 default:
00335 dbi->dbi_jlen = 2 * sizeof(int_32);
00336 break;
00337 }
00338 return dbi;
00339 }
00340
00341 const char *const prDbiOpenFlags(int dbflags, int print_dbenv_flags)
00342 {
00343 static char buf[256];
00344 struct dbOption *opt;
00345 char * oe;
00346
00347 oe = buf;
00348 *oe = '\0';
00349 for (opt = rdbOptions; opt->longName != NULL; opt++) {
00350 if (opt->argInfo != _POPT_SET_BIT)
00351 continue;
00352 if (print_dbenv_flags) {
00353 if (!(opt->arg == &db3dbi.dbi_oeflags ||
00354 opt->arg == &db3dbi.dbi_eflags))
00355 continue;
00356 } else {
00357 if (!(opt->arg == &db3dbi.dbi_oeflags ||
00358 opt->arg == &db3dbi.dbi_oflags))
00359 continue;
00360 }
00361 if ((dbflags & opt->val) != opt->val)
00362 continue;
00363 if (oe != buf)
00364 *oe++ = ':';
00365 oe = stpcpy(oe, opt->longName);
00366 dbflags &= ~opt->val;
00367 }
00368 if (dbflags) {
00369 if (oe != buf)
00370 *oe++ = ':';
00371 sprintf(oe, "0x%x", (unsigned)dbflags);
00372 }
00373 return buf;
00374 }
00375
00376 #endif