X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fuci.git;a=blobdiff_plain;f=history.c;h=649ead19a92b3d9fc6801e0e74a9d3cffa0d7b99;hp=07db1d3b77124236b888503bb5872da505af9e01;hb=6ce771b1095c220f849e70cdcbf23bd09f7fe7d5;hpb=563f8dd6f0eb56780a00f5856bf7fcf40e39d845 diff --git a/history.c b/history.c index 07db1d3..649ead1 100644 --- a/history.c +++ b/history.c @@ -93,6 +93,9 @@ static inline int uci_parse_history_tuple(struct uci_context *ctx, char **buf, s int c = UCI_CMD_CHANGE; switch(**buf) { + case '^': + c = UCI_CMD_REORDER; + break; case '-': c = UCI_CMD_REMOVE; break; @@ -119,6 +122,10 @@ static inline int uci_parse_history_tuple(struct uci_context *ctx, char **buf, s goto error; switch(c) { + case UCI_CMD_REORDER: + if (!ptr->value || ptr->option) + goto error; + break; case UCI_CMD_RENAME: if (!ptr->value || !uci_validate_name(ptr->value)) goto error; @@ -149,6 +156,12 @@ static void uci_parse_history_line(struct uci_context *ctx, struct uci_package * uci_add_history(ctx, &p->saved_history, cmd, ptr.section, ptr.option, ptr.value); switch(cmd) { + case UCI_CMD_REORDER: + expand_ptr(ctx, &ptr, true); + if (!ptr.s) + UCI_THROW(ctx, UCI_ERR_NOTFOUND); + UCI_INTERNAL(uci_reorder_section, ctx, ptr.s, strtoul(ptr.value, NULL, 10)); + break; case UCI_CMD_RENAME: UCI_INTERNAL(uci_rename, ctx, &ptr); break; @@ -160,7 +173,8 @@ static void uci_parse_history_line(struct uci_context *ctx, struct uci_package * break; case UCI_CMD_ADD: case UCI_CMD_CHANGE: - UCI_INTERNAL(uci_set, ctx, p, ptr.section, ptr.option, ptr.value, &e); + UCI_INTERNAL(uci_set, ctx, &ptr); + e = ptr.last; if (!ptr.option && e && (cmd == UCI_CMD_ADD)) uci_to_section(e)->anonymous = true; break; @@ -225,7 +239,7 @@ done: } /* returns the number of changes that were successfully parsed */ -static int uci_load_history(struct uci_context *ctx, struct uci_package *p, bool flush) +__private int uci_load_history(struct uci_context *ctx, struct uci_package *p, bool flush) { struct uci_element *e; char *filename = NULL; @@ -249,7 +263,10 @@ static int uci_load_history(struct uci_context *ctx, struct uci_package *p, bool changes = uci_load_history_file(ctx, p, filename, &f, flush); if (flush && f && (changes > 0)) { rewind(f); - ftruncate(fileno(f), 0); + if (ftruncate(fileno(f), 0) < 0) { + uci_close_stream(f); + UCI_THROW(ctx, UCI_ERR_IO); + } } if (filename) free(filename); @@ -307,7 +324,8 @@ static void uci_filter_history(struct uci_context *ctx, const char *name, const /* rebuild the history file */ rewind(f); - ftruncate(fileno(f), 0); + if (ftruncate(fileno(f), 0) < 0) + UCI_THROW(ctx, UCI_ERR_IO); uci_foreach_element_safe(&list, tmp, e) { fprintf(f, "%s\n", e->name); uci_free_element(e); @@ -317,23 +335,22 @@ static void uci_filter_history(struct uci_context *ctx, const char *name, const done: if (filename) free(filename); - uci_close_stream(f); + uci_close_stream(pctx->file); uci_foreach_element_safe(&list, tmp, e) { uci_free_element(e); } uci_cleanup(ctx); } -int uci_revert(struct uci_context *ctx, struct uci_package **pkg, const char *section, const char *option) +int uci_revert(struct uci_context *ctx, struct uci_ptr *ptr) { - struct uci_package *p; - char *name = NULL; + char *package = NULL; + char *section = NULL; + char *option = NULL; UCI_HANDLE_ERR(ctx); - UCI_ASSERT(ctx, pkg != NULL); - p = *pkg; - UCI_ASSERT(ctx, p != NULL); - UCI_ASSERT(ctx, p->has_history); + expand_ptr(ctx, ptr, false); + UCI_ASSERT(ctx, ptr->p->has_history); /* * - flush unwritten changes @@ -343,20 +360,30 @@ int uci_revert(struct uci_context *ctx, struct uci_package **pkg, const char *se * - reload the package */ UCI_TRAP_SAVE(ctx, error); - UCI_INTERNAL(uci_save, ctx, p); - name = uci_strdup(ctx, p->e.name); + UCI_INTERNAL(uci_save, ctx, ptr->p); - *pkg = NULL; - uci_free_package(&p); - uci_filter_history(ctx, name, section, option); + /* NB: need to clone package, section and option names, + * as they may get freed on uci_free_package() */ + package = uci_strdup(ctx, ptr->p->e.name); + if (ptr->section) + section = uci_strdup(ctx, ptr->section); + if (ptr->option) + option = uci_strdup(ctx, ptr->option); - UCI_INTERNAL(uci_load, ctx, name, &p); + uci_free_package(&ptr->p); + uci_filter_history(ctx, package, section, option); + + UCI_INTERNAL(uci_load, ctx, package, &ptr->p); UCI_TRAP_RESTORE(ctx); ctx->err = 0; error: - if (name) - free(name); + if (package) + free(package); + if (section) + free(section); + if (option) + free(option); if (ctx->err) UCI_THROW(ctx, ctx->err); return 0; @@ -392,6 +419,17 @@ int uci_save(struct uci_context *ctx, struct uci_package *p) if ((asprintf(&filename, "%s/%s", ctx->savedir, p->e.name) < 0) || !filename) UCI_THROW(ctx, UCI_ERR_MEM); + uci_foreach_element(&ctx->hooks, tmp) { + struct uci_hook *hook = uci_to_hook(tmp); + + if (!hook->ops->set) + continue; + + uci_foreach_element(&p->history, e) { + hook->ops->set(hook->ops, p, uci_to_history(e)); + } + } + ctx->err = 0; UCI_TRAP_SAVE(ctx, done); f = uci_open_stream(ctx, filename, SEEK_END, true, true); @@ -411,6 +449,9 @@ int uci_save(struct uci_context *ctx, struct uci_package *p) case UCI_CMD_ADD: prefix = "+"; break; + case UCI_CMD_REORDER: + prefix = "^"; + break; case UCI_CMD_LIST_ADD: prefix = "|"; break;