X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fuci.git;a=blobdiff_plain;f=file.c;h=a58ac559e55aedda25730ea2a0d4a86f978d5e53;hp=c513c87a1676b4aba003d1e93accb08f52465b0b;hb=289e14f9fa5472589b85bdae102aece71d858ecd;hpb=056acf9447468508200d02225dfd833c3311132b diff --git a/file.c b/file.c index c513c87..a58ac55 100644 --- a/file.c +++ b/file.c @@ -24,6 +24,7 @@ #include #include #include +#include static struct uci_backend uci_file_backend; @@ -101,6 +102,8 @@ static void uci_parse_package(struct uci_context *ctx, char **str, bool single) static void uci_parse_config(struct uci_context *ctx, char **str) { struct uci_parse_context *pctx = ctx->pctx; + struct uci_element *e; + struct uci_ptr ptr; char *name = NULL; char *type = NULL; @@ -121,29 +124,36 @@ static void uci_parse_config(struct uci_context *ctx, char **str) name = next_arg(ctx, str, false, true); assert_eol(ctx, str); - if (pctx->merge) { - UCI_TRAP_SAVE(ctx, error); - if (uci_set(ctx, pctx->package, name, NULL, type, NULL) != UCI_OK) - goto error; - UCI_TRAP_RESTORE(ctx); - return; -error: - UCI_THROW(ctx, ctx->err); - } else - pctx->section = uci_alloc_section(pctx->package, type, name); + if (!name) { + ctx->internal = !pctx->merge; + UCI_NESTED(uci_add_section, ctx, pctx->package, type, &pctx->section); + } else { + UCI_NESTED(uci_fill_ptr, ctx, &ptr, &pctx->package->e, false); + e = uci_lookup_list(&pctx->package->sections, name); + if (e) + ptr.s = uci_to_section(e); + ptr.section = name; + ptr.value = type; + + ctx->internal = !pctx->merge; + UCI_NESTED(uci_set, ctx, &ptr); + pctx->section = uci_to_section(ptr.last); + } } /* * parse the 'option' uci command (open a value) */ -static void uci_parse_option(struct uci_context *ctx, char **str) +static void uci_parse_option(struct uci_context *ctx, char **str, bool list) { struct uci_parse_context *pctx = ctx->pctx; + struct uci_element *e; + struct uci_ptr ptr; char *name = NULL; char *value = NULL; if (!pctx->section) - uci_parse_error(ctx, *str, "option command found before the first section"); + uci_parse_error(ctx, *str, "option/list command found before the first section"); /* command string null-terminated by strtok */ *str += strlen(*str) + 1; @@ -152,18 +162,20 @@ static void uci_parse_option(struct uci_context *ctx, char **str) value = next_arg(ctx, str, false, false); assert_eol(ctx, str); - if (pctx->merge) { - UCI_TRAP_SAVE(ctx, error); - uci_set(ctx, pctx->package, pctx->section->e.name, name, value, NULL); - UCI_TRAP_RESTORE(ctx); - return; -error: - UCI_THROW(ctx, ctx->err); - } else - uci_alloc_option(pctx->section, name, value); + UCI_NESTED(uci_fill_ptr, ctx, &ptr, &pctx->section->e, false); + e = uci_lookup_list(&pctx->section->options, name); + if (e) + ptr.o = uci_to_option(e); + ptr.option = name; + ptr.value = value; + + ctx->internal = !pctx->merge; + if (list) + UCI_NESTED(uci_add_list, ctx, &ptr); + else + UCI_NESTED(uci_set, ctx, &ptr); } - /* * parse a complete input line, split up combined commands by ';' */ @@ -186,19 +198,33 @@ static void uci_parse_line(struct uci_context *ctx, bool single) case 'p': if ((word[1] == 0) || !strcmp(word + 1, "ackage")) uci_parse_package(ctx, &word, single); + else + goto invalid; break; case 'c': if ((word[1] == 0) || !strcmp(word + 1, "onfig")) uci_parse_config(ctx, &word); + else + goto invalid; break; case 'o': if ((word[1] == 0) || !strcmp(word + 1, "ption")) - uci_parse_option(ctx, &word); + uci_parse_option(ctx, &word, false); + else + goto invalid; break; - default: - uci_parse_error(ctx, word, "unterminated command"); + case 'l': + if ((word[1] == 0) || !strcmp(word + 1, "ist")) + uci_parse_option(ctx, &word, true); + else + goto invalid; break; + default: + goto invalid; } + continue; +invalid: + uci_parse_error(ctx, word, "invalid command"); } while (1); } @@ -255,7 +281,7 @@ static char *uci_escape(struct uci_context *ctx, const char *str) static void uci_export_package(struct uci_package *p, FILE *stream, bool header) { struct uci_context *ctx = p->ctx; - struct uci_element *s, *o; + struct uci_element *s, *o, *i; if (header) fprintf(stream, "package '%s'\n", uci_escape(ctx, p->e.name)); @@ -267,8 +293,21 @@ static void uci_export_package(struct uci_package *p, FILE *stream, bool header) fprintf(stream, "\n"); uci_foreach_element(&sec->options, o) { struct uci_option *opt = uci_to_option(o); - fprintf(stream, "\toption '%s'", uci_escape(ctx, opt->e.name)); - fprintf(stream, " '%s'\n", uci_escape(ctx, opt->value)); + switch(opt->type) { + case UCI_TYPE_STRING: + fprintf(stream, "\toption '%s'", uci_escape(ctx, opt->e.name)); + fprintf(stream, " '%s'\n", uci_escape(ctx, opt->v.string)); + break; + case UCI_TYPE_LIST: + uci_foreach_element(&opt->v.list, i) { + fprintf(stream, "\tlist '%s'", uci_escape(ctx, opt->e.name)); + fprintf(stream, " '%s'\n", uci_escape(ctx, i->name)); + } + break; + default: + fprintf(stream, "\t# unknown type for option '%s'\n", uci_escape(ctx, opt->e.name)); + break; + } } } fprintf(stream, "\n"); @@ -481,6 +520,9 @@ static char **uci_list_config_files(struct uci_context *ctx) if (!p) continue; + if (!uci_validate_name(p)) + continue; + configs[i] = buf; strcpy(buf, p); buf += strlen(buf) + 1;