Remove unused functions and static vars
[platform/core/system/resourced.git] / src / common / config-parser.c
1 /*
2  * resourced
3  *
4  * Copyright (c) 2013 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the License);
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 #include <stdio.h>
20 #include <string.h>
21 #include <errno.h>
22 #include <assert.h>
23 #include <limits.h>
24
25 #include "util.h"
26 #include "trace.h"
27 #include "config-parser.h"
28
29 #define MAX_SECTION     64
30
31 static inline char *trim_str(char *s)
32 {
33         char *t;
34         /* left trim */
35         s += strspn(s, WHITESPACE);
36
37         /* right trim */
38         for (t = strchr(s, 0); t > s; t--)
39                 if (!strchr(WHITESPACE, t[-1]))
40                         break;
41         *t = 0;
42         return s;
43 }
44
45 int config_parse(const char *file_name, int cb(struct parse_result *result,
46                         void *user_data), void *user_data)
47 {
48         FILE *f = NULL;
49         struct parse_result result;
50         /* use stack for parsing */
51         char line[LINE_MAX];
52         char section[MAX_SECTION];
53         char *start, *end, *name, *value;
54         int lineno = 0, ret = 0;
55
56         if (!file_name || !cb) {
57                 ret = -EINVAL;
58                 goto error;
59         }
60
61         /* open conf file */
62         f = fopen(file_name, "r");
63         if (!f) {
64                 _E("Failed to open file %s", file_name);
65                 ret = -EIO;
66                 goto error;
67         }
68
69         /* parsing line by line */
70         while (fgets(line, LINE_MAX, f) != NULL) {
71                 lineno++;
72
73                 start = line;
74                 truncate_nl(start);
75                 start = trim_str(start);
76
77                 if (*start == COMMENT) {
78                         continue;
79                 } else if (*start == '[') {
80                         /* parse section */
81                         end = strchr(start, ']');
82                         if (!end || *end != ']') {
83                                 ret = -EBADMSG;
84                                 goto error;
85                         }
86
87                         *end = '\0';
88                         strncpy(section, start + 1, sizeof(section)-1);
89                         section[MAX_SECTION-1] = '\0';
90                 } else if (*start) {
91                         /* parse name & value */
92                         end = strchr(start, '=');
93                         if (!end || *end != '=') {
94                                 ret = -EBADMSG;
95                                 goto error;
96                         }
97                         *end = '\0';
98                         name = trim_str(start);
99                         value = trim_str(end + 1);
100                         end = strchr(value, COMMENT);
101                         if (end && *end == COMMENT) {
102                                 *end = '\0';
103                                 value = trim_str(value);
104                         }
105
106                         result.section = section;
107                         result.name = name;
108                         result.value = value;
109                         /* callback with parse result */
110                         ret = cb(&result, user_data);
111                         if (ret < 0) {
112                                 ret = -EBADMSG;
113                                 goto error;
114                         }
115                 }
116         }
117         _D("Success to load %s", file_name);
118         fclose(f);
119         return 0;
120
121 error:
122         if (f)
123                 fclose(f);
124         _E("Failed to read %s:%d!", file_name, lineno);
125         return ret;
126 }
127
128 static int config_table_lookup(void *table,
129                                const char *section,
130                                const char *lvalue,
131                                ConfigParserCallback *func,
132                                int *ltype,
133                                void **data)
134 {
135         ConfigTableItem *t;
136
137         assert(table);
138         assert(lvalue);
139         assert(func);
140         assert(ltype);
141         assert(data);
142
143         for (t = table; t->lvalue; t++) {
144
145                 if (!streq(lvalue, t->lvalue))
146                         continue;
147
148                 if (!streq_ptr(section, t->section))
149                         continue;
150
151                 *func = t->cb;
152                 *ltype = t->ltype;
153                 *data = t->data;
154                 return 1;
155         }
156
157         return 0;
158 }
159
160 /* Run the user supplied parser for an assignment */
161 static int config_parse_table(const char *filename,
162                               unsigned line,
163                               void *table,
164                               const char *section,
165                               const char *lvalue,
166                               const char *rvalue)
167 {
168         ConfigParserCallback cb = NULL;
169         int ltype = 0;
170         void *data = NULL;
171         int r;
172
173         assert(filename);
174         assert(section);
175         assert(lvalue);
176         assert(rvalue);
177
178         r = config_table_lookup(table,
179                                 section,
180                                 lvalue,
181                                 &cb,
182                                 &ltype,
183                                 &data);
184         if (r <= 0)
185                 return r;
186
187         if (cb)
188                 return cb(filename,
189                           line,
190                           section,
191                           lvalue,
192                           ltype,
193                           rvalue,
194                           data);
195
196         return 0;
197 }
198
199 int config_parse_new(const char *filename, void *table)
200 {
201         _cleanup_fclose_ FILE *f = NULL;
202         char *sections[MAX_SECTION] = { 0 };
203         char *section = NULL, *n, *e, l[LINE_MAX];
204         size_t len;
205         int i, r, num_section = 0;
206         bool already;
207         unsigned line = 0;
208
209         assert(filename);
210
211         f = fopen(filename, "r");
212         if (!f) {
213                 _E("Failed to open file %s", filename);
214                 return -errno;
215         }
216
217         while (!feof(f)) {
218                 _cleanup_free_ char *lvalue = NULL, *rvalue = NULL;
219                 char *rs = NULL;
220
221                 if (fgets(l, LINE_MAX, f) == NULL) {
222                         if (feof(f))
223                                 break;
224
225                         _E("Failed to parse configuration file '%s': %m", filename);
226                         r = -errno;
227                         goto finish;
228                 }
229
230                 line++;
231                 truncate_nl(l);
232
233                 if (strchr(COMMENTS NEWLINE, *l))
234                         continue;
235
236                 if (*l == '[') {
237                         len = strlen(l);
238                         if (l[len-1] != ']') {
239                                 _E("Error: Invalid section header: %s", l);
240                                 r = -EBADMSG;
241                                 goto finish;
242                         }
243
244                         n = strndup(l+1, len-2);
245                         if (!n) {
246                                 r = -ENOMEM;
247                                 goto finish;
248                         }
249
250                         already = false;
251                         for (i = 0; i < num_section; i++) {
252                                 if (streq(n, sections[i])) {
253                                         section = sections[i];
254                                         already = true;
255                                         free(n);
256                                         break;
257                                 }
258                         }
259
260                         if (already)
261                                 continue;
262
263                         section = n;
264                         sections[num_section] = n;
265                         num_section++;
266                         if (num_section > MAX_SECTION) {
267                                 _E("Error: max number of section reached: %d", num_section);
268                                 r = -EOVERFLOW;
269                                 goto finish;
270                         }
271
272                         continue;
273                 }
274
275                 if (!section)
276                         continue;
277
278                 e = strchr(l, '=');
279                 if (e == NULL) {
280                         _D("Warning: config: no '=' character in line '%s'.", l);
281                         continue;
282                 }
283
284                 lvalue = strndup(l, e-l);
285                 if (!lvalue) {
286                         r = -ENOMEM;
287                         goto finish;
288                 }
289
290                 strstrip(lvalue);
291
292                 rs = strstrip(e+1);
293                 rvalue = strdup(rs);
294                 if (!rvalue) {
295                         r = -ENOMEM;
296                         goto finish;
297                 }
298
299                 strstrip(rvalue);
300
301                 r = config_parse_table(filename,
302                                        line,
303                                        table,
304                                        section,
305                                        lvalue,
306                                        rvalue);
307                 if (r < 0)
308                         goto finish;
309         }
310
311         r = 0;
312
313 finish:
314         for (i = 0; i < num_section; i++)
315                 if (sections[i])
316                         free(sections[i]);
317
318         return r;
319 }
320
321 int config_parse_bool(const char *filename,
322                       unsigned line,
323                       const char *section,
324                       const char *lvalue,
325                       int ltype,
326                       const char *rvalue,
327                       void *data)
328 {
329         int k;
330         bool *b = data;
331
332         assert(filename);
333         assert(lvalue);
334         assert(rvalue);
335         assert(data);
336
337         k = parse_boolean(rvalue);
338         if (k < 0) {
339                 _E("Failed to parse boolean value, ignoring: %s", rvalue);
340                 return 0;
341         }
342
343         *b = !!k;
344
345         return 0;
346 }
347
348 #define DEFINE_PARSER(type, vartype, conv_func)          \
349         int config_parse_##type(                                        \
350                                 const char *filename,                   \
351                                 unsigned line,                          \
352                                 const char *section,                    \
353                                 const char *lvalue,                     \
354                                 int ltype,                              \
355                                 const char *rvalue,                     \
356                                 void *data) {                           \
357                                                                                                                 \
358                 vartype *i = data;                                      \
359                                                                         \
360                 assert(filename);                                       \
361                 assert(lvalue);                                         \
362                 assert(rvalue);                                         \
363                 assert(data);                                           \
364                                                                         \
365                 *i = conv_func(rvalue);                          \
366                 return 0;                                               \
367                 }
368
369 DEFINE_PARSER(int, int, atoi)
370 DEFINE_PARSER(float, float, atof)
371
372 int config_parse_string(const char *filename,
373                         unsigned line,
374                         const char *section,
375                         const char *lvalue,
376                         int ltype,
377                         const char *rvalue,
378                         void *data)
379 {
380         char **s = data, *n;
381
382         assert(filename);
383         assert(lvalue);
384         assert(rvalue);
385         assert(data);
386
387         if (is_empty(rvalue))
388                 n = NULL;
389         else {
390                 n = strdup(rvalue);
391                 if (!n)
392                         return -ENOMEM;
393         }
394
395         free(*s);
396         *s = n;
397
398         return 0;
399 }
400
401 int config_parse_bytes(const char *filename,
402                        unsigned line,
403                        const char *section,
404                        const char *lvalue,
405                        int ltype,
406                        const char *rvalue,
407                        void *data)
408 {
409         size_t *s = data;
410         int r;
411
412         assert(filename);
413         assert(lvalue);
414         assert(rvalue);
415         assert(data);
416
417         if (is_empty(rvalue))
418                 *s = 0;
419         else {
420                 r = parse_bytes(rvalue, s);
421                 if (r < 0)
422                         return r;
423         }
424
425         return 0;
426 }