Load config dirs
This commit is contained in:
parent
f4881eb5e2
commit
9e059f898a
6 changed files with 125 additions and 38 deletions
|
@ -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')
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
char *name = strndup(filename, (ext - filename) - 1);
|
||||
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;
|
||||
|
||||
if (strcmp(ext, "interface") == 0) {
|
||||
interface_config_t *iface = read_interface_config(path);
|
||||
free(iface);
|
||||
int fd = openat(dirfd, filename, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return false;
|
||||
|
||||
FILE *f = fdopen(fd, "r");
|
||||
if (!f) {
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
free(name);
|
||||
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;
|
||||
|
||||
obj->type = strdup(ext);
|
||||
if (!obj->type) {
|
||||
free_object(obj);
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Reference in a new issue