X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fuci.git;a=blobdiff_plain;f=history.c;h=070930b9093a610ea8a8aa3d547d37d2f97ffd6e;hp=7ac8050291cfee8699e768dea6a55e3ce4e905a6;hb=031b620e1f3a16078da45ce00352508764902786;hpb=e828bcf07c0602746dffcc9927c446d1fe4c3ad9 diff --git a/history.c b/history.c index 7ac8050..070930b 100644 --- a/history.c +++ b/history.c @@ -26,6 +26,42 @@ #include #include +/* record a change that was done to a package */ +static void +uci_add_history(struct uci_context *ctx, struct uci_list *list, int cmd, char *section, char *option, char *value) +{ + struct uci_history *h; + int size = strlen(section) + 1; + char *ptr; + + if (value) + size += strlen(value) + 1; + + h = uci_alloc_element(ctx, history, option, size); + ptr = uci_dataptr(h); + h->cmd = cmd; + h->section = strcpy(ptr, section); + if (value) { + ptr += strlen(ptr) + 1; + h->value = strcpy(ptr, value); + } + uci_list_add(list, &h->e.list); +} + +static void +uci_free_history(struct uci_history *h) +{ + if (!h) + return; + if ((h->section != NULL) && + (h->section != uci_dataptr(h))) { + free(h->section); + free(h->value); + } + uci_free_element(&h->e); +} + + int uci_set_savedir(struct uci_context *ctx, const char *dir) { char *sdir; @@ -85,6 +121,20 @@ static void uci_parse_history_line(struct uci_context *ctx, struct uci_package * if (rename && !uci_validate_str(value, (option || delete))) goto error; + if (ctx->flags & UCI_FLAG_SAVED_HISTORY) { + int cmd; + + /* NB: no distinction between CMD_CHANGE and CMD_ADD possible at this point */ + if(delete) + cmd = UCI_CMD_REMOVE; + else if (rename) + cmd = UCI_CMD_RENAME; + else + cmd = UCI_CMD_CHANGE; + + uci_add_history(ctx, &p->saved_history, cmd, section, option, value); + } + if (rename) UCI_INTERNAL(uci_rename, ctx, p, section, option, value); else if (delete) @@ -97,9 +147,11 @@ error: UCI_THROW(ctx, UCI_ERR_PARSE); } -static void uci_parse_history(struct uci_context *ctx, FILE *stream, struct uci_package *p) +/* returns the number of changes that were successfully parsed */ +static int uci_parse_history(struct uci_context *ctx, FILE *stream, struct uci_package *p) { struct uci_parse_context *pctx; + int changes = 0; /* make sure no memory from previous parse attempts is leaked */ ctx->internal = true; @@ -121,6 +173,7 @@ static void uci_parse_history(struct uci_context *ctx, FILE *stream, struct uci_ UCI_TRAP_SAVE(ctx, error); uci_parse_history_line(ctx, p, pctx->buf); UCI_TRAP_RESTORE(ctx); + changes++; error: continue; } @@ -128,32 +181,38 @@ error: /* no error happened, we can get rid of the parser context now */ ctx->internal = true; uci_cleanup(ctx); + return changes; } -static void uci_load_history_file(struct uci_context *ctx, struct uci_package *p, char *filename, FILE **f, bool flush) +/* returns the number of changes that were successfully parsed */ +static int uci_load_history_file(struct uci_context *ctx, struct uci_package *p, char *filename, FILE **f, bool flush) { FILE *stream = NULL; + int changes = 0; UCI_TRAP_SAVE(ctx, done); stream = uci_open_stream(ctx, filename, SEEK_SET, flush, false); if (p) - uci_parse_history(ctx, stream, p); + changes = uci_parse_history(ctx, stream, p); UCI_TRAP_RESTORE(ctx); done: if (f) *f = stream; else if (stream) uci_close_stream(stream); + return changes; } -static void uci_load_history(struct uci_context *ctx, struct uci_package *p, bool flush) +/* returns the number of changes that were successfully parsed */ +static int uci_load_history(struct uci_context *ctx, struct uci_package *p, bool flush) { struct uci_element *e; char *filename = NULL; FILE *f = NULL; + int changes = 0; if (!p->confdir) - return; + return 0; uci_foreach_element(&ctx->history_path, e) { if ((asprintf(&filename, "%s/%s", e->name, p->e.name) < 0) || !filename) @@ -166,8 +225,8 @@ static void uci_load_history(struct uci_context *ctx, struct uci_package *p, boo if ((asprintf(&filename, "%s/%s", ctx->savedir, p->e.name) < 0) || !filename) UCI_THROW(ctx, UCI_ERR_MEM); - uci_load_history_file(ctx, p, filename, &f, flush); - if (flush && f) { + changes = uci_load_history_file(ctx, p, filename, &f, flush); + if (flush && f && (changes > 0)) { rewind(f); ftruncate(fileno(f), 0); } @@ -175,6 +234,7 @@ static void uci_load_history(struct uci_context *ctx, struct uci_package *p, boo free(filename); uci_close_stream(f); ctx->errno = 0; + return changes; } static void uci_filter_history(struct uci_context *ctx, const char *name, char *section, char *option)