From 4b1ddfb8358bcd57560406db26d7041c9c0cb90b Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 3 Feb 2008 00:03:56 +0100 Subject: [PATCH] implement overwriting import --- cli.c | 15 ++++++++++--- file.c | 71 +++++++++++++++++++++++++++++++++++++--------------------- uci.h | 3 ++- 3 files changed, 60 insertions(+), 29 deletions(-) diff --git a/cli.c b/cli.c index 828c7b9..1a478bb 100644 --- a/cli.c +++ b/cli.c @@ -91,7 +91,7 @@ static int package_cmd(int cmd, char *package) } switch(cmd) { case CMD_COMMIT: - if (uci_commit(ctx, &p) != UCI_OK) + if (uci_commit(ctx, &p, false) != UCI_OK) uci_perror(ctx, appname); break; case CMD_EXPORT: @@ -128,8 +128,17 @@ static int uci_do_import(int argc, char **argv) package = NULL; } ret = uci_import(ctx, input, name, &package, (name != NULL)); - if ((ret == UCI_OK) && (flags & CLI_FLAG_MERGE)) { - ret = uci_save(ctx, package); + if (ret == UCI_OK) { + if (flags & CLI_FLAG_MERGE) { + ret = uci_save(ctx, package); + } else { + struct uci_element *e; + /* loop through all config sections and overwrite existing data */ + uci_foreach_element(&ctx->root, e) { + struct uci_package *p = uci_to_package(e); + ret = uci_commit(ctx, &p, true); + } + } } if (ret != UCI_OK) { diff --git a/file.c b/file.c index 9f47ef2..8e7f0ce 100644 --- a/file.c +++ b/file.c @@ -745,7 +745,8 @@ static void uci_load_history(struct uci_context *ctx, struct uci_package *p, boo UCI_TRAP_SAVE(ctx, done); f = uci_open_stream(ctx, filename, SEEK_SET, flush, false); - uci_parse_history(ctx, f, p); + if (p) + uci_parse_history(ctx, f, p); UCI_TRAP_RESTORE(ctx); done: @@ -760,6 +761,18 @@ done: } +static char *uci_config_path(struct uci_context *ctx, const char *name) +{ + char *filename; + + if (strchr(name, '/')) + UCI_THROW(ctx, UCI_ERR_INVAL); + filename = uci_malloc(ctx, strlen(name) + sizeof(UCI_CONFDIR) + 2); + sprintf(filename, UCI_CONFDIR "/%s", name); + + return filename; +} + int uci_load(struct uci_context *ctx, const char *name, struct uci_package **package) { char *filename; @@ -783,10 +796,7 @@ int uci_load(struct uci_context *ctx, const char *name, struct uci_package **pac break; default: /* config in /etc/config */ - if (strchr(name, '/')) - UCI_THROW(ctx, UCI_ERR_INVAL); - filename = uci_malloc(ctx, strlen(name) + sizeof(UCI_CONFDIR) + 2); - sprintf(filename, UCI_CONFDIR "/%s", name); + filename = uci_config_path(ctx, name); confdir = true; break; } @@ -824,7 +834,7 @@ int uci_save(struct uci_context *ctx, struct uci_package *p) * does not modify the uci_package pointer */ if (!p->confdir) - return uci_commit(ctx, &p); + return uci_commit(ctx, &p, false); if (uci_list_empty(&p->history)) return 0; @@ -866,7 +876,7 @@ done: return 0; } -int uci_commit(struct uci_context *ctx, struct uci_package **package) +int uci_commit(struct uci_context *ctx, struct uci_package **package, bool overwrite) { struct uci_package *p; FILE *f = NULL; @@ -878,7 +888,13 @@ int uci_commit(struct uci_context *ctx, struct uci_package **package) p = *package; UCI_ASSERT(ctx, p != NULL); - UCI_ASSERT(ctx, p->path != NULL); + if (!p->path) { + if (overwrite) + p->path = uci_config_path(ctx, p->e.name); + else + 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); @@ -886,23 +902,28 @@ int uci_commit(struct uci_context *ctx, struct uci_package **package) /* flush unsaved changes and reload from history file */ UCI_TRAP_SAVE(ctx, done); if (p->confdir) { - name = uci_strdup(ctx, p->e.name); - path = uci_strdup(ctx, p->path); - if (!uci_list_empty(&p->history)) - UCI_INTERNAL(uci_save, ctx, p); - uci_free_package(&p); - uci_file_cleanup(ctx); - UCI_INTERNAL(uci_import, ctx, f, name, &p, true); - - p->path = path; - p->confdir = true; - *package = p; - - /* freed together with the uci_package */ - path = NULL; - - /* check for updated history, just in case */ - uci_load_history(ctx, p, true); + if (!overwrite) { + name = uci_strdup(ctx, p->e.name); + path = uci_strdup(ctx, p->path); + if (!uci_list_empty(&p->history)) + UCI_INTERNAL(uci_save, ctx, p); + uci_free_package(&p); + uci_file_cleanup(ctx); + UCI_INTERNAL(uci_import, ctx, f, name, &p, true); + + p->path = path; + p->confdir = true; + *package = p; + + /* freed together with the uci_package */ + path = NULL; + + /* check for updated history, just in case */ + uci_load_history(ctx, p, true); + } else { + /* flush history */ + uci_load_history(ctx, NULL, true); + } } rewind(f); diff --git a/uci.h b/uci.h index 6b5de9a..574a384 100644 --- a/uci.h +++ b/uci.h @@ -214,11 +214,12 @@ extern int uci_save(struct uci_context *ctx, struct uci_package *p); * uci_commit: commit changes to a package * @ctx: uci context * @p: uci_package struct pointer + * @overwrite: overwrite existing config data and flush history * * committing may reload the whole uci_package data, * the supplied pointer is updated accordingly */ -extern int uci_commit(struct uci_context *ctx, struct uci_package **p); +extern int uci_commit(struct uci_context *ctx, struct uci_package **p, bool overwrite); /** * uci_list_configs: List available uci config files -- 2.41.1