From: Felix Fietkau Date: Sat, 2 Feb 2008 20:36:56 +0000 (+0100) Subject: implement uci rename X-Git-Url: https://git.archive.openwrt.org/?p=project%2Fuci.git;a=commitdiff_plain;h=b69b459ecce221f92235d0def138ff4af3c22543 implement uci rename --- diff --git a/cli.c b/cli.c index cdd1838..3ade534 100644 --- a/cli.c +++ b/cli.c @@ -20,13 +20,14 @@ static const char *appname = "uci"; static struct uci_context *ctx; enum { /* section cmds */ - CMD_GET = 1, - CMD_SET = 2, - CMD_DEL = 3, + CMD_GET, + CMD_SET, + CMD_DEL, + CMD_RENAME, /* package cmds */ - CMD_SHOW = 4, - CMD_EXPORT = 5, - CMD_COMMIT = 6, + CMD_SHOW, + CMD_EXPORT, + CMD_COMMIT, }; static void uci_usage(int argc, char **argv) @@ -126,13 +127,22 @@ static int uci_do_section_cmd(int cmd, int argc, char **argv) char *section = NULL; char *option = NULL; char *value = NULL; + char **ptr = NULL; struct uci_package *p = NULL; struct uci_element *e = NULL; if (argc != 2) return 255; - if (uci_parse_tuple(ctx, argv[1], &package, §ion, &option, (cmd == CMD_SET ? &value : NULL)) != UCI_OK) + switch(cmd) { + case CMD_SET: + case CMD_RENAME: + ptr = &value; + break; + default: + break; + } + if (uci_parse_tuple(ctx, argv[1], &package, §ion, &option, ptr) != UCI_OK) return 1; if (uci_load(ctx, package, &p) != UCI_OK) { @@ -159,6 +169,12 @@ static int uci_do_section_cmd(int cmd, int argc, char **argv) /* throw the value to stdout */ printf("%s\n", value); break; + case CMD_RENAME: + if (uci_rename(ctx, p, section, option, value) != UCI_OK) { + uci_perror(ctx, appname); + return 1; + } + break; case CMD_SET: if (uci_set(ctx, p, section, option, value) != UCI_OK) { uci_perror(ctx, appname); @@ -166,7 +182,7 @@ static int uci_do_section_cmd(int cmd, int argc, char **argv) } break; case CMD_DEL: - if (uci_del(ctx, p, section, option) != UCI_OK) { + if (uci_delete(ctx, p, section, option) != UCI_OK) { uci_perror(ctx, appname); return 1; } @@ -200,13 +216,19 @@ static int uci_cmd(int argc, char **argv) cmd = CMD_GET; else if (!strcasecmp(argv[0], "set")) cmd = CMD_SET; + else if (!strcasecmp(argv[0], "ren") || + !strcasecmp(argv[0], "rename")) + cmd = CMD_RENAME; else if (!strcasecmp(argv[0], "del")) cmd = CMD_DEL; + else + cmd = -1; switch(cmd) { case CMD_GET: case CMD_SET: case CMD_DEL: + case CMD_RENAME: return uci_do_section_cmd(cmd, argc, argv); case CMD_SHOW: case CMD_EXPORT: diff --git a/file.c b/file.c index c6ea7b4..fe52876 100644 --- a/file.c +++ b/file.c @@ -639,6 +639,7 @@ static void uci_close_stream(FILE *stream) static void uci_parse_history_line(struct uci_context *ctx, struct uci_package *p, char *buf) { bool delete = false; + bool rename = false; char *package = NULL; char *section = NULL; char *option = NULL; @@ -647,6 +648,9 @@ static void uci_parse_history_line(struct uci_context *ctx, struct uci_package * if (buf[0] == '-') { delete = true; buf++; + } else if (buf[0] == '@') { + rename = true; + buf++; } UCI_INTERNAL(uci_parse_tuple, ctx, buf, &package, §ion, &option, &value); @@ -659,8 +663,10 @@ static void uci_parse_history_line(struct uci_context *ctx, struct uci_package * if (option && !uci_validate_name(option)) goto error; - if (delete) - UCI_INTERNAL(uci_del, ctx, p, section, option); + if (rename) + UCI_INTERNAL(uci_rename, ctx, p, section, option, value); + else if (delete) + UCI_INTERNAL(uci_delete, ctx, p, section, option); else UCI_INTERNAL(uci_set, ctx, p, section, option, value); @@ -809,6 +815,8 @@ int uci_save(struct uci_context *ctx, struct uci_package *p) if (h->cmd == UCI_CMD_REMOVE) fprintf(f, "-"); + else if (h->cmd == UCI_CMD_RENAME) + fprintf(f, "@"); fprintf(f, "%s.%s", p->e.name, h->section); if (e->name) diff --git a/list.c b/list.c index 5700605..ae7fce8 100644 --- a/list.c +++ b/list.c @@ -61,23 +61,30 @@ uci_alloc_generic(struct uci_context *ctx, int type, const char *name, int size) int datalen = size; void *ptr; - if (name) - datalen += strlen(name) + 1; ptr = uci_malloc(ctx, datalen); e = (struct uci_element *) ptr; e->type = type; if (name) { - e->name = (char *) ptr + size; - strcpy(e->name, name); + UCI_TRAP_SAVE(ctx, error); + e->name = uci_strdup(ctx, name); + UCI_TRAP_RESTORE(ctx); } uci_list_init(&e->list); + goto done; +error: + free(ptr); + UCI_THROW(ctx, ctx->errno); + +done: return e; } static void uci_free_element(struct uci_element *e) { + if (e->name) + free(e->name); if (!uci_list_empty(&e->list)) uci_list_del(&e->list); free(e); @@ -372,7 +379,33 @@ int uci_set_element_value(struct uci_context *ctx, struct uci_element **element, return 0; } -int uci_del(struct uci_context *ctx, struct uci_package *p, char *section, char *option) +int uci_rename(struct uci_context *ctx, struct uci_package *p, char *section, char *option, char *name) +{ + /* NB: UCI_INTERNAL use means without history tracking */ + bool internal = ctx->internal; + struct uci_element *e; + struct uci_section *s = NULL; + struct uci_option *o = NULL; + + UCI_HANDLE_ERR(ctx); + UCI_ASSERT(ctx, p != NULL); + UCI_ASSERT(ctx, section != NULL); + + UCI_INTERNAL(uci_lookup, ctx, &e, p, section, option); + + if (!internal) + uci_add_history(ctx, p, UCI_CMD_RENAME, section, option, name); + + name = uci_strdup(ctx, name); + if (e->name) + free(e->name); + e->name = name; + + return 0; +} + + +int uci_delete(struct uci_context *ctx, struct uci_package *p, char *section, char *option) { /* NB: pass on internal flag to uci_del_element */ bool internal = ctx->internal; diff --git a/uci.h b/uci.h index 1b6c9fa..93f8bce 100644 --- a/uci.h +++ b/uci.h @@ -177,20 +177,30 @@ extern int uci_set_element_value(struct uci_context *ctx, struct uci_element **e extern int uci_set(struct uci_context *ctx, struct uci_package *p, char *section, char *option, char *value); /** - * uci_del_element: Delete a section or option + * uci_rename: Rename an element + * @ctx: uci context + * @package: package name + * @section: section name + * @option: option name + * @name: new name + */ +extern int uci_rename(struct uci_context *ctx, struct uci_package *p, char *section, char *option, char *name); + +/** + * uci_delete_element: Delete a section or option * @ctx: uci context * @e: element (section or option) */ -extern int uci_del_element(struct uci_context *ctx, struct uci_element *e); +extern int uci_delete_element(struct uci_context *ctx, struct uci_element *e); /** - * uci_del: Delete a section or option + * uci_delete: Delete a section or option * @ctx: uci context * @p: uci package * @section: section name * @option: option name (optional) */ -extern int uci_del(struct uci_context *ctx, struct uci_package *p, char *section, char *option); +extern int uci_delete(struct uci_context *ctx, struct uci_package *p, char *section, char *option); /** * uci_save: save change history for a package @@ -304,7 +314,8 @@ struct uci_option enum uci_command { UCI_CMD_ADD, UCI_CMD_REMOVE, - UCI_CMD_CHANGE + UCI_CMD_CHANGE, + UCI_CMD_RENAME }; struct uci_history