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')
|
cc = meson.get_compiler('c')
|
||||||
ubox_dep = cc.find_library('ubox')
|
ubox_dep = cc.find_library('ubox')
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
@ -67,11 +66,7 @@ static ini_section_t * add_section(ini_file_t *file, const char *name) {
|
||||||
return section;
|
return section;
|
||||||
}
|
}
|
||||||
|
|
||||||
ini_file_t * read_ini_file(const char *filename) {
|
ini_file_t * read_ini_file(FILE *f) {
|
||||||
FILE *f = fopen(filename, "r");
|
|
||||||
if (!f)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
ini_file_t *file = calloc(1, sizeof(*file));
|
ini_file_t *file = calloc(1, sizeof(*file));
|
||||||
if (!file)
|
if (!file)
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -135,7 +130,6 @@ ini_file_t * read_ini_file(const char *filename) {
|
||||||
|
|
||||||
error:
|
error:
|
||||||
free(line);
|
free(line);
|
||||||
fclose(f);
|
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
free_ini_file(file);
|
free_ini_file(file);
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
#include <libubox/list.h>
|
#include <libubox/list.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
struct list_head node;
|
struct list_head node;
|
||||||
char *key;
|
char *key;
|
||||||
|
@ -18,5 +20,5 @@ typedef struct {
|
||||||
struct list_head sections;
|
struct list_head sections;
|
||||||
} ini_file_t;
|
} 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);
|
void free_ini_file(ini_file_t *file);
|
||||||
|
|
|
@ -2,54 +2,144 @@
|
||||||
#include "config-ini.h"
|
#include "config-ini.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
|
#include <libubox/avl.h>
|
||||||
|
#include <libubox/avl-cmp.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <dirent.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
#include <fcntl.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
static const char * simple_basename(const char *path) {
|
typedef enum {
|
||||||
const char *slash = strrchr(path, '/');
|
LOAD_TYPE_INTERFACE,
|
||||||
return slash ? (slash+1) : path;
|
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) {
|
static const char * extname(const char *filename) {
|
||||||
const char *dot = strrchr(filename, '.');
|
const char *dot = strrchr(filename, '.');
|
||||||
return dot ? (dot+1) : NULL;
|
return dot ? (dot+1) : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static interface_config_t * read_interface_config(const char *path) {
|
static void free_object(load_object_t *obj) {
|
||||||
ini_file_t *file = read_ini_file(path);
|
free_ini_file(obj->data);
|
||||||
ini_section_t *section;
|
free(obj->type);
|
||||||
ini_field_t *field;
|
free(NODE_NAME(obj));
|
||||||
|
free(obj);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool read_config_file(const char *path) {
|
static bool read_config_file(load_ctx_t *ctx, int dirfd, const char *filename) {
|
||||||
const char *filename = simple_basename(path);
|
|
||||||
const char *ext = extname(filename);
|
const char *ext = extname(filename);
|
||||||
if (!ext) {
|
if (!ext) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return false;
|
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) {
|
int fd = openat(dirfd, filename, O_RDONLY);
|
||||||
interface_config_t *iface = read_interface_config(path);
|
if (fd < 0)
|
||||||
free(iface);
|
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;
|
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>
|
#include <stdbool.h>
|
||||||
|
|
||||||
bool read_config_file(const char *path);
|
bool read_config(const char *path);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "config-load.h"
|
#include "config-load.h"
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
read_config_file(argv[1]);
|
read_config(argv[1]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue