diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/config-ini.c | 8 | ||||
-rw-r--r-- | src/config-ini.h | 4 | ||||
-rw-r--r-- | src/config-load.c | 142 | ||||
-rw-r--r-- | src/config-load.h | 2 | ||||
-rw-r--r-- | src/pnc.c | 2 |
5 files changed, 122 insertions, 36 deletions
diff --git a/src/config-ini.c b/src/config-ini.c index 7cfa1ff..30275fa 100644 --- a/src/config-ini.c +++ b/src/config-ini.c @@ -3,7 +3,6 @@ #include <ctype.h> #include <errno.h> -#include <stdio.h> #include <stdlib.h> #include <string.h> @@ -67,11 +66,7 @@ static ini_section_t * add_section(ini_file_t *file, const char *name) { return section; } -ini_file_t * read_ini_file(const char *filename) { - FILE *f = fopen(filename, "r"); - if (!f) - return NULL; - +ini_file_t * read_ini_file(FILE *f) { ini_file_t *file = calloc(1, sizeof(*file)); if (!file) goto error; @@ -135,7 +130,6 @@ ini_file_t * read_ini_file(const char *filename) { error: free(line); - fclose(f); if (err) { free_ini_file(file); diff --git a/src/config-ini.h b/src/config-ini.h index 802195d..58f6608 100644 --- a/src/config-ini.h +++ b/src/config-ini.h @@ -2,6 +2,8 @@ #include <libubox/list.h> +#include <stdio.h> + typedef struct { struct list_head node; char *key; @@ -18,5 +20,5 @@ typedef struct { struct list_head sections; } ini_file_t; -ini_file_t * read_ini_file(const char *filename); +ini_file_t * read_ini_file(FILE *f); void free_ini_file(ini_file_t *file); diff --git a/src/config-load.c b/src/config-load.c index 9335813..28b5953 100644 --- a/src/config-load.c +++ b/src/config-load.c @@ -2,54 +2,144 @@ #include "config-ini.h" #include "types.h" +#include <libubox/avl.h> +#include <libubox/avl-cmp.h> + +#include <sys/types.h> +#include <dirent.h> #include <errno.h> -#include <stdio.h> +#include <fcntl.h> #include <stdlib.h> #include <string.h> +#include <unistd.h> -static const char * simple_basename(const char *path) { - const char *slash = strrchr(path, '/'); - return slash ? (slash+1) : path; -} +typedef enum { + LOAD_TYPE_INTERFACE, + LOAD_TYPE_SUBCONFIG, + LOAD_TYPE_GENERATOR, + LOAD_TYPE_DEVICE, + N_LOAD_TYPES, +} load_type_t; + +typedef struct { + struct avl_node node; + char *type; + ini_file_t *data; +} load_object_t; + +typedef struct { + struct avl_tree objects[N_LOAD_TYPES]; +} load_ctx_t; static const char * extname(const char *filename) { const char *dot = strrchr(filename, '.'); return dot ? (dot+1) : NULL; } -static interface_config_t * read_interface_config(const char *path) { - ini_file_t *file = read_ini_file(path); - ini_section_t *section; - ini_field_t *field; - - list_for_each_entry(section, &file->sections, node) { - printf("%s\n", section->name); - - list_for_each_entry(field, §ion->fields, node) - printf("%s.%s=%s\n", section->name, field->key, field->value); - } - - free_ini_file(file); - - return NULL; +static void free_object(load_object_t *obj) { + free_ini_file(obj->data); + free(obj->type); + free(NODE_NAME(obj)); + free(obj); } -bool read_config_file(const char *path) { - const char *filename = simple_basename(path); +static bool read_config_file(load_ctx_t *ctx, int dirfd, const char *filename) { const char *ext = extname(filename); if (!ext) { errno = EINVAL; return false; } + load_type_t type; + if (strcmp(ext, "interface") == 0) + type = LOAD_TYPE_INTERFACE; + else if (strcmp(ext, "sub") == 0) + type = LOAD_TYPE_SUBCONFIG; + else if (strcmp(ext, "gen") == 0) + type = LOAD_TYPE_GENERATOR; + else if (strcmp(ext, "bridge") == 0) + type = LOAD_TYPE_DEVICE; + else + return true; + + int fd = openat(dirfd, filename, O_RDONLY); + if (fd < 0) + return false; + + FILE *f = fdopen(fd, "r"); + if (!f) { + close(fd); + return false; + } + + ini_file_t *data = read_ini_file(f); + fclose(f); + + if (!data) + return false; + + load_object_t *obj = calloc(1, sizeof(*obj)); + if (!obj) { + free_ini_file(data); + return false; + } + obj->data = data; + char *name = strndup(filename, (ext - filename) - 1); + if (!name) { + free_object(obj); + return false; + } + NODE_NAME(obj) = name; - if (strcmp(ext, "interface") == 0) { - interface_config_t *iface = read_interface_config(path); - free(iface); + obj->type = strdup(ext); + if (!obj->type) { + free_object(obj); + return false; } - free(name); + avl_insert(&ctx->objects[type], &obj->node); return true; } + +static bool read_config_dir(load_ctx_t *ctx, const char *path) { + DIR *dir = opendir(path); + if (!dir) + return false; + + int fd = dirfd(dir); + + struct dirent *ent; + while ((ent = readdir(dir)) != NULL) { + if (ent->d_type == DT_REG) + read_config_file(ctx, fd, ent->d_name); + } + + closedir(dir); + + return true; +} + +bool read_config(const char *path) { + load_ctx_t ctx; + for (size_t i = 0; i < N_LOAD_TYPES; i++) + avl_init(&ctx.objects[i], avl_strcmp, true, NULL); + + bool ret = read_config_dir(&ctx, path); + + for (size_t i = 0; i < N_LOAD_TYPES; i++) { + load_object_t *obj; + avl_for_each_element(&ctx.objects[i], obj, node) { + printf("%s(%u): %s\n", obj->type, (unsigned)i, NODE_NAME(obj)); + } + } + + for (size_t i = 0; i < N_LOAD_TYPES; i++) { + load_object_t *obj, *tmp; + avl_for_each_element_safe(&ctx.objects[i], obj, node, tmp) + free_object(obj); + } + + return ret; +} diff --git a/src/config-load.h b/src/config-load.h index 0c278ee..e2b4736 100644 --- a/src/config-load.h +++ b/src/config-load.h @@ -2,4 +2,4 @@ #include <stdbool.h> -bool read_config_file(const char *path); +bool read_config(const char *path); @@ -1,6 +1,6 @@ #include "config-load.h" int main(int argc, char *argv[]) { - read_config_file(argv[1]); + read_config(argv[1]); return 0; } |