4 * Copyright (c) 2013 Samsung Electronics Co., Ltd.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
27 #include "config-parser.h"
29 #define MAX_SECTION 64
31 int config_parse(const char *file_name, int cb(struct parse_result *result,
32 void *user_data), void *user_data)
35 struct parse_result result;
36 /* use stack for parsing */
38 char section[MAX_SECTION];
39 char *start, *end, *name, *value;
40 int lineno = 0, ret = 0;
42 if (!file_name || !cb) {
48 f = fopen(file_name, "r");
50 _E("[DEBUG] Failed to open file %s", file_name);
55 /* parsing line by line */
56 while (fgets(line, LINE_MAX, f) != NULL) {
61 start = strstrip(start);
63 if (*start == COMMENT) {
65 } else if (*start == '[') {
67 end = strchr(start, ']');
68 if (!end || *end != ']') {
74 strncpy(section, start + 1, sizeof(section)-1);
75 section[MAX_SECTION-1] = '\0';
77 /* parse name & value */
78 end = strchr(start, '=');
79 if (!end || *end != '=') {
84 name = strstrip(start);
85 value = strstrip(end + 1);
86 end = strchr(value, COMMENT);
87 if (end && *end == COMMENT) {
89 value = strstrip(value);
92 result.section = section;
95 /* callback with parse result */
96 ret = cb(&result, user_data);
103 _D("[DEBUG] Success to load %s", file_name);
110 _E("[DEBUG] Failed to read %s:%d!", file_name, lineno);
114 static int config_table_lookup(void *table,
117 ConfigParserCallback *func,
129 for (t = table; t->lvalue; t++) {
131 if (!streq(lvalue, t->lvalue))
134 if (!streq_ptr(section, t->section))
146 /* Run the user supplied parser for an assignment */
147 static int config_parse_table(const char *filename,
154 ConfigParserCallback cb = NULL;
164 r = config_table_lookup(table,
185 int config_parse_new(const char *filename, void *table)
187 _cleanup_fclose_ FILE *f = NULL;
188 char *sections[MAX_SECTION] = { 0 };
189 char *section = NULL, *n, *e, l[LINE_MAX];
191 int i, r, num_section = 0;
197 f = fopen(filename, "r");
199 const int saved_errno = errno;
200 _E("Failed to open file %s", filename); // can modify errno
205 _cleanup_free_ char *lvalue = NULL, *rvalue = NULL;
208 if (fgets(l, LINE_MAX, f) == NULL) {
212 _E("Failed to parse configuration file '%s': %m", filename);
220 if (strchr(COMMENTS NEWLINE, *l))
225 if (l[len-1] != ']') {
226 _E("Error: Invalid section header: %s", l);
231 n = strndup(l+1, len-2);
238 for (i = 0; i < num_section; i++) {
239 if (streq(n, sections[i])) {
240 section = sections[i];
251 sections[num_section] = n;
253 if (num_section > MAX_SECTION) {
254 _E("Error: max number of section reached: %d", num_section);
267 _D("Warning: config: no '=' character in line '%s'.", l);
271 lvalue = strndup(l, e-l);
288 r = config_parse_table(filename,
301 for (i = 0; i < num_section; i++)
308 int config_parse_dir(const char *dir, ConfigParseFunc fp, void *data)
310 _cleanup_closedir_ DIR *d = NULL;
315 _E("Failed to open dir: %s", dir);
319 for (errno = 0, de = readdir(d);; errno = 0, de = readdir(d)) {
324 } else if (streq(de->d_name, ".") || streq(de->d_name, "..")) {
328 _cleanup_free_ char *path = NULL;
331 if (de->d_type != DT_REG)
334 r = asprintf(&path, "%s/%s", dir, de->d_name);
339 /* Do not just break loop until parse all file of
340 * dir. Just only put log */
342 _D("Failed to parse config: %s", de->d_name);
348 int config_parse_bool(const char *filename,
364 k = parse_boolean(rvalue);
366 _E("Failed to parse boolean value, ignoring: %s", rvalue);
375 #define DEFINE_PARSER(type, vartype, conv_func) \
376 int config_parse_##type( \
377 const char *filename, \
379 const char *section, \
380 const char *lvalue, \
382 const char *rvalue, \
392 *i = conv_func(rvalue); \
396 DEFINE_PARSER(int, int, atoi)
397 DEFINE_PARSER(float, float, atof)
398 DEFINE_PARSER(long, long, atol)
400 int config_parse_string(const char *filename,
415 if (is_empty(rvalue))
429 int config_parse_bytes(const char *filename,
445 if (is_empty(rvalue))
448 r = parse_bytes(rvalue, s);
456 int config_parse_strv(const char *filename,
465 char **o = NULL, **v = NULL, **vv = NULL;
473 if (is_empty(rvalue))
476 r = str_to_strv(rvalue, &v, WHITESPACE);
482 r = strv_attach(o, v, &vv, true);