From 7e840cf19ac6c867b9708257efd93e4a7efaa97e Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 28 Jan 2008 03:41:53 +0100 Subject: [PATCH] allow accessing files outside of /etc/config --- cli.c | 20 +++++++++++++++----- file.c | 26 +++++++++++++++++++------- list.c | 30 ++++++++---------------------- uci.h | 12 ++++++++---- 4 files changed, 50 insertions(+), 38 deletions(-) diff --git a/cli.c b/cli.c index 9530198..8ab3850 100644 --- a/cli.c +++ b/cli.c @@ -65,14 +65,24 @@ static int uci_show(int argc, char **argv) if (!configs) return 0; + if (argc >= 2) { + if (uci_load(ctx, argv[1], &package) != UCI_OK) { + uci_perror(ctx, NULL); + return 1; + } + uci_show_package(package, section); + uci_unload(ctx, package); + return 0; + } + for (p = configs; *p; p++) { if ((argc < 2) || !strcmp(argv[1], *p)) { if (uci_load(ctx, *p, &package) != UCI_OK) { - uci_perror(ctx, "uci_load"); - return 255; + uci_perror(ctx, NULL); + return 1; } uci_show_package(package, section); - uci_unload(ctx, *p); + uci_unload(ctx, package); } } @@ -96,7 +106,7 @@ static int uci_do_export(int argc, char **argv) if (ret) continue; uci_export(ctx, stdout, package); - uci_unload(ctx, *p); + uci_unload(ctx, package); } } return 0; @@ -154,7 +164,7 @@ static int uci_do_get(int argc, char **argv) return 1; } - if (uci_lookup(ctx, &e, package, section, option) != UCI_OK) + if (uci_lookup(ctx, &e, p, section, option) != UCI_OK) return 1; switch(e->type) { diff --git a/file.c b/file.c index 4a56b8a..6eaa5ec 100644 --- a/file.c +++ b/file.c @@ -275,6 +275,7 @@ static void assert_eol(struct uci_context *ctx, char **str) static void uci_switch_config(struct uci_context *ctx) { struct uci_parse_context *pctx; + struct uci_element *e; const char *name; pctx = ctx->pctx; @@ -296,7 +297,9 @@ static void uci_switch_config(struct uci_context *ctx) * ignore errors here, e.g. if the config was not found */ UCI_TRAP_SAVE(ctx, ignore); - uci_unload(ctx, name); + e = uci_lookup_list(ctx, &ctx->root, name); + if (e) + uci_unload(ctx, uci_to_package(e)); UCI_TRAP_RESTORE(ctx); ignore: ctx->errno = 0; @@ -530,7 +533,7 @@ int uci_load(struct uci_context *ctx, const char *name, struct uci_package **pac { struct stat statbuf; char *filename; - bool confpath; + bool confdir; FILE *file; int fd; @@ -539,15 +542,19 @@ int uci_load(struct uci_context *ctx, const char *name, struct uci_package **pac switch (name[0]) { case '.': + if (name[1] != '/') + UCI_THROW(ctx, UCI_ERR_NOTFOUND); + /* fall through */ case '/': /* absolute/relative path outside of /etc/config */ - filename = (char *) name; - confpath = false; + filename = uci_strdup(ctx, name); + name = strrchr(name, '/') + 1; + confdir = false; break; default: filename = uci_malloc(ctx, strlen(name) + sizeof(UCI_CONFDIR) + 2); sprintf(filename, UCI_CONFDIR "/%s", name); - confpath = true; + confdir = true; break; } @@ -557,8 +564,8 @@ int uci_load(struct uci_context *ctx, const char *name, struct uci_package **pac } fd = open(filename, O_RDONLY); - if (filename != name) - free(filename); + if (fd <= 0) + UCI_THROW(ctx, UCI_ERR_IO); flock(fd, LOCK_SH); file = fdopen(fd, "r"); @@ -570,6 +577,11 @@ int uci_load(struct uci_context *ctx, const char *name, struct uci_package **pac uci_import(ctx, file, name, package); UCI_TRAP_RESTORE(ctx); + if (*package) { + (*package)->path = filename; + (*package)->confdir = confdir; + } + done: flock(fd, LOCK_UN); fclose(file); diff --git a/list.c b/list.c index 5561778..a70c2c5 100644 --- a/list.c +++ b/list.c @@ -153,6 +153,8 @@ uci_free_package(struct uci_package *p) if(!p) return; + if (p->path) + free(p->path); uci_foreach_element_safe(&p->sections, tmp, e) { uci_free_section(uci_to_section(e)); } @@ -174,7 +176,7 @@ uci_add_history(struct uci_context *ctx, struct uci_package *p, int cmd, char *s } -static struct uci_element *uci_lookup_list(struct uci_context *ctx, struct uci_list *list, char *name) +static struct uci_element *uci_lookup_list(struct uci_context *ctx, struct uci_list *list, const char *name) { struct uci_element *e; @@ -185,22 +187,16 @@ static struct uci_element *uci_lookup_list(struct uci_context *ctx, struct uci_l UCI_THROW(ctx, UCI_ERR_NOTFOUND); } -int uci_lookup(struct uci_context *ctx, struct uci_element **res, char *package, char *section, char *option) +int uci_lookup(struct uci_context *ctx, struct uci_element **res, struct uci_package *p, char *section, char *option) { struct uci_element *e; - struct uci_package *p; struct uci_section *s; struct uci_option *o; UCI_HANDLE_ERR(ctx); UCI_ASSERT(ctx, res != NULL); - UCI_ASSERT(ctx, package != NULL); + UCI_ASSERT(ctx, p != NULL); - e = uci_lookup_list(ctx, &ctx->root, package); - if (!section) - goto found; - - p = uci_to_package(e); e = uci_lookup_list(ctx, &p->sections, section); if (!option) goto found; @@ -280,8 +276,6 @@ int uci_set(struct uci_context *ctx, char *package, char *section, char *option, UCI_ASSERT(ctx, package != NULL); UCI_ASSERT(ctx, section != NULL); - fprintf(stderr, "uci_set: '%s' '%s' '%s' = '%s'\n", package, section, option, value); - /* * look up the package, section and option (if set) * if the section/option is to be modified and it is not found @@ -338,22 +332,14 @@ notfound: return 0; } -int uci_unload(struct uci_context *ctx, const char *name) +int uci_unload(struct uci_context *ctx, struct uci_package *p) { struct uci_element *e; UCI_HANDLE_ERR(ctx); - UCI_ASSERT(ctx, name != NULL); - - uci_foreach_element(&ctx->root, e) { - if (!strcmp(e->name, name)) - goto found; - } - UCI_THROW(ctx, UCI_ERR_NOTFOUND); - -found: - uci_free_package(uci_to_package(e)); + UCI_ASSERT(ctx, p != NULL); + uci_free_package(p); return 0; } diff --git a/uci.h b/uci.h index 0c79587..4420af7 100644 --- a/uci.h +++ b/uci.h @@ -29,6 +29,7 @@ #define UCI_DEBUG_TYPECAST #endif +#include #include #include @@ -110,9 +111,9 @@ extern int uci_load(struct uci_context *ctx, const char *name, struct uci_packag * uci_unload: Unload a config file from the uci context * * @ctx: uci context - * @name: name of the config file + * @package: pointer to the uci_package struct */ -extern int uci_unload(struct uci_context *ctx, const char *name); +extern int uci_unload(struct uci_context *ctx, struct uci_package *p); /** * uci_cleanup: Clean up after an error @@ -126,14 +127,14 @@ extern int uci_cleanup(struct uci_context *ctx); * * @ctx: uci context * @res: where to store the result - * @package: config package + * @package: uci_package struct * @section: config section (optional) * @option: option to search for (optional) * * If section is omitted, then a pointer to the config package is returned * If option is omitted, then a pointer to the config section is returned */ -extern int uci_lookup(struct uci_context *ctx, struct uci_element **res, char *package, char *section, char *option); +extern int uci_lookup(struct uci_context *ctx, struct uci_element **res, struct uci_package *package, char *section, char *option); /** * uci_set_element_value: Replace an element's value with a new one @@ -214,6 +215,9 @@ struct uci_package struct uci_element e; struct uci_list sections; struct uci_context *ctx; + bool confdir; + char *path; + /* private: */ int n_section; struct uci_list history; -- 2.11.0