From 9e059f898ae1b0528cdde553fd51c661901e283a Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sat, 29 Dec 2018 17:00:31 +0100 Subject: Load config dirs --- meson.build | 3 +- src/config-ini.c | 8 +-- src/config-ini.h | 4 +- src/config-load.c | 142 ++++++++++++++++++++++++++++++++++++++++++++---------- src/config-load.h | 2 +- src/pnc.c | 2 +- 6 files changed, 124 insertions(+), 37 deletions(-) diff --git a/meson.build b/meson.build index aaa8cf6..f8089e4 100644 --- a/meson.build +++ b/meson.build @@ -1,4 +1,5 @@ -project('pnc', 'c') +project('pnc', 'c', default_options : ['c_std=c11']) +add_project_arguments('-D_DEFAULT_SOURCE', language : 'c') cc = meson.get_compiler('c') ubox_dep = cc.find_library('ubox') 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 #include -#include #include #include @@ -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 +#include + 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 +#include + +#include +#include #include -#include +#include #include #include +#include -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 -bool read_config_file(const char *path); +bool read_config(const char *path); diff --git a/src/pnc.c b/src/pnc.c index 651d140..942ba2f 100644 --- a/src/pnc.c +++ b/src/pnc.c @@ -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; } -- cgit v1.2.3