* This file contains the code for parsing uci config files
*/
+#define _GNU_SOURCE
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/file.h>
#include <stdbool.h>
#include <unistd.h>
#include <fcntl.h>
case '"':
parse_double_quote(ctx, str, target);
break;
+ case '#':
+ **str = 0;
+ /* fall through */
case 0:
goto done;
case '\\':
char *tmp;
tmp = next_arg(ctx, str, false, false);
- if (tmp && *tmp)
+ if (tmp && *tmp && (ctx->flags & UCI_FLAG_STRICT))
uci_parse_error(ctx, *str, "too many arguments");
}
static void uci_parse_config(struct uci_context *ctx, char **str)
{
struct uci_parse_context *pctx = ctx->pctx;
- struct uci_section *s;
char *name = NULL;
char *type = NULL;
char *pbrk = NULL;
word = strtok_r(word, " \t", &pbrk);
+ if (!word)
+ continue;
+
switch(word[0]) {
+ case '#':
+ return;
case 'p':
if ((word[1] == 0) || !strcmp(word + 1, "ackage"))
uci_parse_package(ctx, &word, single);
uci_foreach_element(&p->sections, s) {
struct uci_section *sec = uci_to_section(s);
fprintf(stream, "\nconfig '%s'", uci_escape(ctx, sec->type));
- if (!sec->anonymous)
+ if (!sec->anonymous || (ctx->flags & UCI_FLAG_EXPORT_NAME))
fprintf(stream, " '%s'", uci_escape(ctx, sec->e.name));
fprintf(stream, "\n");
uci_foreach_element(&sec->options, o) {
* the appropriate 'package <name>' string to specify the config name
* NB: the config file can still override the package name
*/
- if (name)
+ if (name) {
+ UCI_ASSERT(ctx, uci_validate_name(name));
pctx->name = name;
+ }
while (!feof(pctx->file)) {
uci_getln(ctx, 0);
}
UCI_INTERNAL(uci_parse_tuple, ctx, buf, &package, §ion, &option, &value);
- if (!package || !section || (!delete && !value))
- goto error;
- if (strcmp(package, p->e.name) != 0)
+ if (!package || (strcmp(package, p->e.name) != 0))
goto error;
if (!uci_validate_name(section))
goto error;
if (option && !uci_validate_name(option))
goto error;
+ if ((rename || !delete) && !uci_validate_name(value))
+ goto error;
if (rename)
UCI_INTERNAL(uci_rename, ctx, p, section, option, value);
if (!p->confdir)
return;
+
if ((asprintf(&filename, "%s/%s", UCI_SAVEDIR, p->e.name) < 0) || !filename)
UCI_THROW(ctx, UCI_ERR_MEM);
{
char *filename;
- if (strchr(name, '/'))
- UCI_THROW(ctx, UCI_ERR_INVAL);
+ UCI_ASSERT(ctx, uci_validate_name(name));
filename = uci_malloc(ctx, strlen(name) + sizeof(UCI_CONFDIR) + 2);
sprintf(filename, UCI_CONFDIR "/%s", name);
FILE *file = NULL;
UCI_HANDLE_ERR(ctx);
- UCI_ASSERT(ctx, uci_validate_name(name));
switch (name[0]) {
case '.':
if (!overwrite) {
name = uci_strdup(ctx, p->e.name);
path = uci_strdup(ctx, p->path);
+ /* dump our own changes to the history file */
if (!uci_list_empty(&p->history))
UCI_INTERNAL(uci_save, ctx, p);
+
+ /*
+ * other processes might have modified the config
+ * as well. dump and reload
+ */
uci_free_package(&p);
uci_file_cleanup(ctx);
UCI_INTERNAL(uci_import, ctx, f, name, &p, true);