fe7c01e81465e33258b54fb6f5f78fecb7c3f832
[tools/librpm-tizen.git] / lib / backend / dbconfig.c
1 /** \ingroup rpmdb
2  * \file lib/dbconfig.c
3  */
4
5 #include "system.h"
6
7 #include <popt.h>
8
9 #include <rpm/rpmtypes.h>
10 #include <rpm/rpmmacro.h>
11 #include <rpm/rpmstring.h>
12 #include <rpm/rpmlog.h>
13 #include <rpm/argv.h>
14 #include "lib/rpmdb_internal.h"
15 #include "debug.h"
16
17 static struct dbiIndex_s staticdbi;
18 static struct dbConfig_s staticcfg;
19 static int db_eflags;
20
21 /** \ingroup dbi
22  */
23 static const struct poptOption rdbOptions[] = {
24  /* Environment options */
25    
26  { "cdb",       0,POPT_BIT_SET, &db_eflags, DB_INIT_CDB,
27         NULL, NULL },
28  { "lock",      0,POPT_BIT_SET, &db_eflags, DB_INIT_LOCK,
29         NULL, NULL },
30  { "log",       0,POPT_BIT_SET, &db_eflags, DB_INIT_LOG,
31         NULL, NULL },
32  { "txn",       0,POPT_BIT_SET, &db_eflags, DB_INIT_TXN,
33         NULL, NULL },
34  { "recover",   0,POPT_BIT_SET, &db_eflags, DB_RECOVER,
35         NULL, NULL },
36  { "recover_fatal", 0,POPT_BIT_SET,     &db_eflags, DB_RECOVER_FATAL,
37         NULL, NULL },
38  { "lockdown",  0,POPT_BIT_SET, &db_eflags, DB_LOCKDOWN,
39         NULL, NULL },
40  { "private",   0,POPT_BIT_SET, &db_eflags, DB_PRIVATE,
41         NULL, NULL },
42
43  { "deadlock",  0,POPT_BIT_SET, &staticcfg.db_verbose, DB_VERB_DEADLOCK,
44         NULL, NULL },
45  { "recovery",  0,POPT_BIT_SET, &staticcfg.db_verbose, DB_VERB_RECOVERY,
46         NULL, NULL },
47  { "waitsfor",  0,POPT_BIT_SET, &staticcfg.db_verbose, DB_VERB_WAITSFOR,
48         NULL, NULL },
49  { "verbose",   0,POPT_ARG_VAL,         &staticcfg.db_verbose, -1,
50         NULL, NULL },
51
52  { "cachesize", 0,POPT_ARG_INT,         &staticcfg.db_cachesize, 0,
53         NULL, NULL },
54  { "mmapsize", 0,POPT_ARG_INT,          &staticcfg.db_mmapsize, 0,
55         NULL, NULL },
56  { "mp_mmapsize", 0,POPT_ARG_INT,       &staticcfg.db_mmapsize, 0,
57         NULL, NULL },
58  { "mp_size",   0,POPT_ARG_INT,         &staticcfg.db_cachesize, 0,
59         NULL, NULL },
60
61 #if 0
62  { "nofsync",   0,POPT_ARG_NONE,        &staticcfg.db_no_fsync, 0,
63         NULL, NULL },
64 #endif
65
66  /* Per-dbi options */
67  { "nommap",    0,POPT_BIT_SET,         &staticdbi.dbi_oflags, DB_NOMMAP,
68         NULL, NULL },
69
70  { "nodbsync",  0,POPT_ARG_NONE,        &staticdbi.dbi_no_dbsync, 0,
71         NULL, NULL },
72  { "lockdbfd",  0,POPT_ARG_NONE,        &staticdbi.dbi_lockdbfd, 0,
73         NULL, NULL },
74  { "nofsync",   0,POPT_BIT_SET,         &staticdbi.dbi_oflags, DB_NOFSYNC,
75         NULL, NULL },
76
77     POPT_TABLEEND
78 };
79
80 dbiIndex dbiFree(dbiIndex dbi)
81 {
82     if (dbi) {
83         free(dbi);
84     }
85     return NULL;
86 }
87
88 dbiIndex dbiNew(rpmdb rdb, rpmDbiTagVal rpmtag)
89 {
90     dbiIndex dbi = xcalloc(1, sizeof(*dbi));
91     char *dbOpts;
92
93     dbOpts = rpmExpand("%{_dbi_config_", rpmTagGetName(rpmtag), "}", NULL);
94     
95     if (!(dbOpts && *dbOpts && *dbOpts != '%')) {
96         dbOpts = _free(dbOpts);
97         dbOpts = rpmExpand("%{_dbi_config}", NULL);
98         if (!(dbOpts && *dbOpts && *dbOpts != '%')) {
99             dbOpts = _free(dbOpts);
100         }
101     }
102
103     /* Parse the options for the database element(s). */
104     if (dbOpts && *dbOpts && *dbOpts != '%') {
105         char *o, *oe;
106         char *p, *pe;
107
108         memset(&staticdbi, 0, sizeof(staticdbi));
109 /*=========*/
110         for (o = dbOpts; o && *o; o = oe) {
111             const struct poptOption *opt;
112             const char * tok;
113             unsigned int argInfo;
114
115             /* Skip leading white space. */
116             while (*o && risspace(*o))
117                 o++;
118
119             /* Find and terminate next key=value pair. Save next start point. */
120             for (oe = o; oe && *oe; oe++) {
121                 if (risspace(*oe))
122                     break;
123                 if (oe[0] == ':' && !(oe[1] == '/' && oe[2] == '/'))
124                     break;
125             }
126             if (oe && *oe)
127                 *oe++ = '\0';
128             if (*o == '\0')
129                 continue;
130
131             /* Separate key from value, save value start (if any). */
132             for (pe = o; pe && *pe && *pe != '='; pe++)
133                 {};
134             p = (pe ? *pe++ = '\0', pe : NULL);
135
136             /* Skip over negation at start of token. */
137             for (tok = o; *tok == '!'; tok++)
138                 {};
139
140             /* Find key in option table. */
141             for (opt = rdbOptions; opt->longName != NULL; opt++) {
142                 if (!rstreq(tok, opt->longName))
143                     continue;
144                 break;
145             }
146             if (opt->longName == NULL) {
147                 rpmlog(RPMLOG_ERR,
148                         _("unrecognized db option: \"%s\" ignored.\n"), o);
149                 continue;
150             }
151
152             /* Toggle the flags for negated tokens, if necessary. */
153             argInfo = opt->argInfo;
154             if (argInfo == POPT_BIT_SET && *o == '!' && ((tok - o) % 2))
155                 argInfo = POPT_BIT_CLR;
156
157             /* Save value in template as appropriate. */
158             switch (argInfo & POPT_ARG_MASK) {
159
160             case POPT_ARG_NONE:
161                 (void) poptSaveInt((int *)opt->arg, argInfo, 1L);
162                 break;
163             case POPT_ARG_VAL:
164                 (void) poptSaveInt((int *)opt->arg, argInfo, (long)opt->val);
165                 break;
166             case POPT_ARG_STRING:
167             {   char ** t = opt->arg;
168                 if (t) {
169 /* FIX: opt->arg annotation in popt.h */
170                     *t = _free(*t);
171                     *t = xstrdup( (p ? p : "") );
172                 }
173             }   break;
174
175             case POPT_ARG_INT:
176             case POPT_ARG_LONG:
177               { long aLong = strtol(p, &pe, 0);
178                 if (pe) {
179                     if (!rstrncasecmp(pe, "Mb", 2))
180                         aLong *= 1024 * 1024;
181                     else if (!rstrncasecmp(pe, "Kb", 2))
182                         aLong *= 1024;
183                     else if (*pe != '\0') {
184                         rpmlog(RPMLOG_ERR,
185                                 _("%s has invalid numeric value, skipped\n"),
186                                 opt->longName);
187                         continue;
188                     }
189                 }
190
191                 if ((argInfo & POPT_ARG_MASK) == POPT_ARG_LONG) {
192                     if (aLong == LONG_MIN || aLong == LONG_MAX) {
193                         rpmlog(RPMLOG_ERR,
194                                 _("%s has too large or too small long value, skipped\n"),
195                                 opt->longName);
196                         continue;
197                     }
198                     (void) poptSaveLong((long *)opt->arg, argInfo, aLong);
199                     break;
200                 } else {
201                     if (aLong > INT_MAX || aLong < INT_MIN) {
202                         rpmlog(RPMLOG_ERR,
203                                 _("%s has too large or too small integer value, skipped\n"),
204                                 opt->longName);
205                         continue;
206                     }
207                     (void) poptSaveInt((int *)opt->arg, argInfo, aLong);
208                 }
209               } break;
210             default:
211                 break;
212             }
213         }
214 /*=========*/
215     }
216
217     dbOpts = _free(dbOpts);
218
219     *dbi = staticdbi;   /* structure assignment */
220     memset(&staticdbi, 0, sizeof(staticdbi));
221
222     /* FIX: figger lib/dbi refcounts */
223     dbi->dbi_rpmdb = rdb;
224     dbi->dbi_file = rpmTagGetName(rpmtag);
225     dbi->dbi_type = (rpmtag == RPMDBI_PACKAGES) ? DBI_PRIMARY : DBI_SECONDARY;
226     dbi->dbi_byteswapped = -1;  /* -1 unknown, 0 native order, 1 alien order */
227
228     /* XXX FIXME: Get environment configuration out of here! */
229     if (rdb->db_dbenv == NULL) {
230         struct dbConfig_s * cfg = &rdb->cfg;
231         *cfg = staticcfg;       /* structure assignment */
232         /* Throw in some defaults if configuration didn't set any */
233         if (!cfg->db_mmapsize) cfg->db_mmapsize = 16 * 1024 * 1024;
234         if (!cfg->db_cachesize) cfg->db_cachesize = 8 * 1024 * 1024;
235     }
236
237     /* FIX: *(rdbOptions->arg) reachable */
238     return dbi;
239 }
240
241 char * prDbiOpenFlags(int dbflags, int print_dbenv_flags)
242 {
243     ARGV_t flags = NULL;
244     const struct poptOption *opt;
245     char *buf;
246
247     for (opt = rdbOptions; opt->longName != NULL; opt++) {
248         if (opt->argInfo != POPT_BIT_SET)
249             continue;
250         if (print_dbenv_flags) {
251             if (!(opt->arg == &db_eflags))
252                 continue;
253         } else {
254             if (!(opt->arg == &staticdbi.dbi_oflags))
255                 continue;
256         }
257         if ((dbflags & opt->val) != opt->val)
258             continue;
259         argvAdd(&flags, opt->longName);
260         dbflags &= ~opt->val;
261     }
262     if (dbflags) {
263         char *df = NULL;
264         rasprintf(&df, "0x%x", (unsigned)dbflags);
265         argvAdd(&flags, df);
266         free(df);
267     }
268     buf = argvJoin(flags, ":");
269     argvFree(flags);
270         
271     return buf ? buf : xstrdup("(none)");
272 }