X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fuci.git;a=blobdiff_plain;f=file.c;h=5360ef764a15cb9b9d3bbd5e17c64135fac26c45;hp=7049b3393d78f29dfc87efecbf22e964bf543c42;hb=d4bab379481c8ef0d5710a616660f1d7144d768f;hpb=c57e7c394391fe559f3d67562e88ff90d6ad901f diff --git a/file.c b/file.c index 7049b33..5360ef7 100644 --- a/file.c +++ b/file.c @@ -25,13 +25,7 @@ #include #include -/* - * Clean up all extra memory used by the parser and exporter - */ -static void uci_file_cleanup(struct uci_context *ctx) -{ -} - +static struct uci_backend uci_file_backend; /* * verify that the end of the line or command is reached. @@ -41,6 +35,7 @@ static void assert_eol(struct uci_context *ctx, char **str) { char *tmp; + skip_whitespace(ctx, str); tmp = next_arg(ctx, str, false, false); if (*tmp && (ctx->flags & UCI_FLAG_STRICT)) uci_parse_error(ctx, *str, "too many arguments"); @@ -61,6 +56,7 @@ static void uci_switch_config(struct uci_context *ctx) /* add the last config to main config file list */ if (pctx->package) { + pctx->package->backend = ctx->backend; uci_list_add(&ctx->root, &pctx->package->e.list); pctx->package = NULL; @@ -74,7 +70,7 @@ static void uci_switch_config(struct uci_context *ctx) * if an older config under the same name exists, unload it * ignore errors here, e.g. if the config was not found */ - e = uci_lookup_list(ctx, &ctx->root, name); + e = uci_lookup_list(&ctx->root, name); if (e) UCI_THROW(ctx, UCI_ERR_DUPLICATE); pctx->package = uci_alloc_package(ctx, name); @@ -127,7 +123,8 @@ static void uci_parse_config(struct uci_context *ctx, char **str) if (pctx->merge) { UCI_TRAP_SAVE(ctx, error); - uci_set(ctx, pctx->package, name, NULL, type, NULL); + if (uci_set(ctx, pctx->package, name, NULL, type, NULL) != UCI_OK) + goto error; UCI_TRAP_RESTORE(ctx); return; error: @@ -173,19 +170,17 @@ error: static void uci_parse_line(struct uci_context *ctx, bool single) { struct uci_parse_context *pctx = ctx->pctx; - char *word, *brk = NULL; - - for (word = strtok_r(pctx->buf, ";", &brk); - word; - word = strtok_r(NULL, ";", &brk)) { - - char *pbrk = NULL; - word = strtok_r(word, " \t", &pbrk); + char *word, *brk; + word = pctx->buf; + do { + brk = NULL; + word = strtok_r(word, " \t", &brk); if (!word) - continue; + return; switch(word[0]) { + case 0: case '#': return; case 'p': @@ -204,7 +199,7 @@ static void uci_parse_line(struct uci_context *ctx, bool single) uci_parse_error(ctx, word, "unterminated command"); break; } - } + } while (1); } /* max number of characters that escaping adds to the string */ @@ -298,7 +293,7 @@ int uci_import(struct uci_context *ctx, FILE *stream, const char *name, struct u UCI_HANDLE_ERR(ctx); /* make sure no memory from previous parse attempts is leaked */ - uci_file_cleanup(ctx); + uci_cleanup(ctx); uci_alloc_parse_context(ctx); pctx = ctx->pctx; @@ -334,6 +329,8 @@ error: } uci_fixup_section(ctx, ctx->pctx->section); + if (!pctx->package && name) + uci_switch_config(ctx); if (package) *package = pctx->package; if (pctx->merge) @@ -343,7 +340,7 @@ error: uci_switch_config(ctx); /* no error happened, we can get rid of the parser context now */ - uci_file_cleanup(ctx); + uci_cleanup(ctx); return 0; } @@ -360,62 +357,13 @@ static char *uci_config_path(struct uci_context *ctx, const char *name) return filename; } -int uci_load(struct uci_context *ctx, const char *name, struct uci_package **package) -{ - char *filename; - bool confdir; - FILE *file = NULL; - - UCI_HANDLE_ERR(ctx); - - switch (name[0]) { - case '.': - /* relative path outside of /etc/config */ - if (name[1] != '/') - UCI_THROW(ctx, UCI_ERR_NOTFOUND); - /* fall through */ - case '/': - /* absolute path outside of /etc/config */ - filename = uci_strdup(ctx, name); - name = strrchr(name, '/') + 1; - confdir = false; - break; - default: - /* config in /etc/config */ - filename = uci_config_path(ctx, name); - confdir = true; - break; - } - - file = uci_open_stream(ctx, filename, SEEK_SET, false, false); - ctx->errno = 0; - UCI_TRAP_SAVE(ctx, done); - UCI_INTERNAL(uci_import, ctx, file, name, package, true); - UCI_TRAP_RESTORE(ctx); - - if (*package) { - (*package)->path = filename; - (*package)->confdir = confdir; - uci_load_history(ctx, *package, false); - } - -done: - uci_close_stream(file); - return ctx->errno; -} - -int uci_commit(struct uci_context *ctx, struct uci_package **package, bool overwrite) +void uci_file_commit(struct uci_context *ctx, struct uci_package **package, bool overwrite) { - struct uci_package *p; + struct uci_package *p = *package; FILE *f = NULL; char *name = NULL; char *path = NULL; - UCI_HANDLE_ERR(ctx); - UCI_ASSERT(ctx, package != NULL); - p = *package; - - UCI_ASSERT(ctx, p != NULL); if (!p->path) { if (overwrite) p->path = uci_config_path(ctx, p->e.name); @@ -423,13 +371,12 @@ int uci_commit(struct uci_context *ctx, struct uci_package **package, bool overw UCI_THROW(ctx, UCI_ERR_INVAL); } - /* open the config file for writing now, so that it is locked */ f = uci_open_stream(ctx, p->path, SEEK_SET, true, true); /* flush unsaved changes and reload from history file */ UCI_TRAP_SAVE(ctx, done); - if (p->confdir) { + if (p->has_history) { if (!overwrite) { name = uci_strdup(ctx, p->e.name); path = uci_strdup(ctx, p->path); @@ -442,11 +389,11 @@ int uci_commit(struct uci_context *ctx, struct uci_package **package, bool overw * as well. dump and reload */ uci_free_package(&p); - uci_file_cleanup(ctx); + uci_cleanup(ctx); UCI_INTERNAL(uci_import, ctx, f, name, &p, true); p->path = path; - p->confdir = true; + p->has_history = true; *package = p; /* freed together with the uci_package */ @@ -476,8 +423,6 @@ done: uci_close_stream(f); if (ctx->errno) UCI_THROW(ctx, ctx->errno); - - return 0; } @@ -498,7 +443,7 @@ static inline char *get_filename(char *path) return p; } -int uci_list_configs(struct uci_context *ctx, char ***list) +static char **uci_list_config_files(struct uci_context *ctx) { char **configs; glob_t globbuf; @@ -506,8 +451,6 @@ int uci_list_configs(struct uci_context *ctx, char ***list) char *buf; char *dir; - UCI_HANDLE_ERR(ctx); - dir = uci_malloc(ctx, strlen(ctx->confdir) + 1 + sizeof("/*")); sprintf(dir, "%s/*", ctx->confdir); if (glob(dir, GLOB_MARK, NULL, &globbuf) != 0) @@ -537,9 +480,57 @@ int uci_list_configs(struct uci_context *ctx, char ***list) strcpy(buf, p); buf += strlen(buf) + 1; } - *list = configs; free(dir); + return configs; +} - return 0; +static struct uci_package *uci_file_load(struct uci_context *ctx, const char *name) +{ + struct uci_package *package = NULL; + char *filename; + bool confdir; + FILE *file = NULL; + + switch (name[0]) { + case '.': + /* relative path outside of /etc/config */ + if (name[1] != '/') + UCI_THROW(ctx, UCI_ERR_NOTFOUND); + /* fall through */ + case '/': + /* absolute path outside of /etc/config */ + filename = uci_strdup(ctx, name); + name = strrchr(name, '/') + 1; + confdir = false; + break; + default: + /* config in /etc/config */ + filename = uci_config_path(ctx, name); + confdir = true; + break; + } + + file = uci_open_stream(ctx, filename, SEEK_SET, false, false); + ctx->errno = 0; + UCI_TRAP_SAVE(ctx, done); + UCI_INTERNAL(uci_import, ctx, file, name, &package, true); + UCI_TRAP_RESTORE(ctx); + + if (package) { + package->path = filename; + package->has_history = confdir; + uci_load_history(ctx, package, false); + } + +done: + uci_close_stream(file); + if (ctx->errno) + UCI_THROW(ctx, ctx->errno); + return package; } +static UCI_BACKEND(uci_file_backend, "file", + .load = uci_file_load, + .commit = uci_file_commit, + .list_configs = uci_list_config_files, +);