summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--meson.build3
-rw-r--r--src/config-ini.c8
-rw-r--r--src/config-ini.h4
-rw-r--r--src/config-load.c142
-rw-r--r--src/config-load.h2
-rw-r--r--src/pnc.c2
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 <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, &section->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);
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;
}