X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fuci.git;a=blobdiff_plain;f=file.c;h=d320ba6c3cd66d49bd708d0756826c80511f3548;hp=7049b3393d78f29dfc87efecbf22e964bf543c42;hb=ce0ffab4085e9970eaa0c40709dbacc99ccec2eb;hpb=c57e7c394391fe559f3d67562e88ff90d6ad901f diff --git a/file.c b/file.c index 7049b33..d320ba6 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. @@ -61,6 +55,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 +69,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 +122,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: @@ -298,7 +294,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; @@ -343,7 +339,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 +356,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) +void uci_file_commit(struct uci_context *ctx, struct uci_package **package, bool overwrite) { - 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) -{ - 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 +370,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 +388,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 +422,6 @@ done: uci_close_stream(f); if (ctx->errno) UCI_THROW(ctx, ctx->errno); - - return 0; } @@ -498,7 +442,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 +450,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 +479,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, +);