Add librpm-tizen.spec file & Debian packaging.
[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  #ifndef WITH_EXTERNAL_DB
75  { "nofsync",   0,POPT_BIT_SET,         &staticdbi.dbi_oflags, DB_NOFSYNC,
76         NULL, NULL },
77 #endif
78
79     POPT_TABLEEND
80 };
81
82 dbiIndex dbiFree(dbiIndex dbi)
83 {
84     if (dbi) {
85         free(dbi);
86     }
87     return NULL;
88 }
89
90 dbiIndex dbiNew(rpmdb rdb, rpmDbiTagVal rpmtag)
91 {
92     dbiIndex dbi = xcalloc(1, sizeof(*dbi));
93     char *dbOpts;
94
95     dbOpts = rpmExpand("%{_dbi_config_", rpmTagGetName(rpmtag), "}", NULL);
96     
97     if (!(dbOpts && *dbOpts && *dbOpts != '%')) {
98         dbOpts = _free(dbOpts);
99         dbOpts = rpmExpand("%{_dbi_config}", NULL);
100         if (!(dbOpts && *dbOpts && *dbOpts != '%')) {
101             dbOpts = _free(dbOpts);
102         }
103     }
104
105     /* Parse the options for the database element(s). */
106     if (dbOpts && *dbOpts && *dbOpts != '%') {
107         char *o, *oe;
108         char *p, *pe;
109
110         memset(&staticdbi, 0, sizeof(staticdbi));
111 /*=========*/
112         for (o = dbOpts; o && *o; o = oe) {
113             const struct poptOption *opt;
114             const char * tok;
115             unsigned int argInfo;
116
117             /* Skip leading white space. */
118             while (*o && risspace(*o))
119                 o++;
120
121             /* Find and terminate next key=value pair. Save next start point. */
122             for (oe = o; oe && *oe; oe++) {
123                 if (risspace(*oe))
124                     break;
125                 if (oe[0] == ':' && !(oe[1] == '/' && oe[2] == '/'))
126                     break;
127             }
128             if (oe && *oe)
129                 *oe++ = '\0';
130             if (*o == '\0')
131                 continue;
132
133             /* Separate key from value, save value start (if any). */
134             for (pe = o; pe && *pe && *pe != '='; pe++)
135                 {};
136             p = (pe ? *pe++ = '\0', pe : NULL);
137
138             /* Skip over negation at start of token. */
139             for (tok = o; *tok == '!'; tok++)
140                 {};
141
142             /* Find key in option table. */
143             for (opt = rdbOptions; opt->longName != NULL; opt++) {
144                 if (!rstreq(tok, opt->longName))
145                     continue;
146                 break;
147             }
148             if (opt->longName == NULL) {
149                 rpmlog(RPMLOG_ERR,
150                         _("unrecognized db option: \"%s\" ignored.\n"), o);
151                 continue;
152             }
153
154             /* Toggle the flags for negated tokens, if necessary. */
155             argInfo = opt->argInfo;
156             if (argInfo == POPT_BIT_SET && *o == '!' && ((tok - o) % 2))
157                 argInfo = POPT_BIT_CLR;
158
159             /* Save value in template as appropriate. */
160             switch (argInfo & POPT_ARG_MASK) {
161
162             case POPT_ARG_NONE:
163                 (void) poptSaveInt((int *)opt->arg, argInfo, 1L);
164                 break;
165             case POPT_ARG_VAL:
166                 (void) poptSaveInt((int *)opt->arg, argInfo, (long)opt->val);
167                 break;
168             case POPT_ARG_STRING:
169             {   char ** t = opt->arg;
170                 if (t) {
171 /* FIX: opt->arg annotation in popt.h */
172                     *t = _free(*t);
173                     *t = xstrdup( (p ? p : "") );
174                 }
175             }   break;
176
177             case POPT_ARG_INT:
178             case POPT_ARG_LONG:
179               { long aLong = strtol(p, &pe, 0);
180                 if (pe) {
181                     if (!rstrncasecmp(pe, "Mb", 2))
182                         aLong *= 1024 * 1024;
183                     else if (!rstrncasecmp(pe, "Kb", 2))
184                         aLong *= 1024;
185                     else if (*pe != '\0') {
186                         rpmlog(RPMLOG_ERR,
187                                 _("%s has invalid numeric value, skipped\n"),
188                                 opt->longName);
189                         continue;
190                     }
191                 }
192
193                 if ((argInfo & POPT_ARG_MASK) == POPT_ARG_LONG) {
194                     if (aLong == LONG_MIN || aLong == LONG_MAX) {
195                         rpmlog(RPMLOG_ERR,
196                                 _("%s has too large or too small long value, skipped\n"),
197                                 opt->longName);
198                         continue;
199                     }
200                     (void) poptSaveLong((long *)opt->arg, argInfo, aLong);
201                     break;
202                 } else {
203                     if (aLong > INT_MAX || aLong < INT_MIN) {
204                         rpmlog(RPMLOG_ERR,
205                                 _("%s has too large or too small integer value, skipped\n"),
206                                 opt->longName);
207                         continue;
208                     }
209                     (void) poptSaveInt((int *)opt->arg, argInfo, aLong);
210                 }
211               } break;
212             default:
213                 break;
214             }
215         }
216 /*=========*/
217     }
218
219     dbOpts = _free(dbOpts);
220
221     *dbi = staticdbi;   /* structure assignment */
222     memset(&staticdbi, 0, sizeof(staticdbi));
223
224     /* FIX: figger lib/dbi refcounts */
225     dbi->dbi_rpmdb = rdb;
226     dbi->dbi_file = rpmTagGetName(rpmtag);
227     dbi->dbi_type = (rpmtag == RPMDBI_PACKAGES) ? DBI_PRIMARY : DBI_SECONDARY;
228     dbi->dbi_byteswapped = -1;  /* -1 unknown, 0 native order, 1 alien order */
229
230     /* XXX FIXME: Get environment configuration out of here! */
231     if (rdb->db_dbenv == NULL) {
232         struct dbConfig_s * cfg = &rdb->cfg;
233         *cfg = staticcfg;       /* structure assignment */
234         /* Throw in some defaults if configuration didn't set any */
235         if (!cfg->db_mmapsize) cfg->db_mmapsize = 16 * 1024 * 1024;
236         if (!cfg->db_cachesize) cfg->db_cachesize = 8 * 1024 * 1024;
237     }
238
239     /* FIX: *(rdbOptions->arg) reachable */
240     return dbi;
241 }
242
243 char * prDbiOpenFlags(int dbflags, int print_dbenv_flags)
244 {
245     ARGV_t flags = NULL;
246     const struct poptOption *opt;
247     char *buf;
248
249     for (opt = rdbOptions; opt->longName != NULL; opt++) {
250         if (opt->argInfo != POPT_BIT_SET)
251             continue;
252         if (print_dbenv_flags) {
253             if (!(opt->arg == &db_eflags))
254                 continue;
255         } else {
256             if (!(opt->arg == &staticdbi.dbi_oflags))
257                 continue;
258         }
259         if ((dbflags & opt->val) != opt->val)
260             continue;
261         argvAdd(&flags, opt->longName);
262         dbflags &= ~opt->val;
263     }
264     if (dbflags) {
265         char *df = NULL;
266         rasprintf(&df, "0x%x", (unsigned)dbflags);
267         argvAdd(&flags, df);
268         free(df);
269     }
270     buf = argvJoin(flags, ":");
271     argvFree(flags);
272         
273     return buf ? buf : xstrdup("(none)");
274 }