diff options
author | Yousong Zhou <yszhou4tech@gmail.com> | 2015-04-01 00:20:18 +0800 |
---|---|---|
committer | Felix Fietkau <nbd@openwrt.org> | 2015-03-31 18:42:41 +0200 |
commit | 3c7f3556b0039a19ddd3e263286085f6896da0eb (patch) | |
tree | cb6318648d0885d8bcbc1f24e9cd424d848cf8a6 | |
parent | 3b3c554567154ad984e4e1146a3ada6ff99925f4 (diff) | |
download | uci-3c7f3556b0039a19ddd3e263286085f6896da0eb.tar.gz |
Fix delta path handling.
- Make ctx->savedir sit at the end of ctx->delta_path.
- Add notes to uci_set_savedir() and uci_add_delta_path() to document
the behaviour changes.
-rw-r--r-- | delta.c | 39 | ||||
-rw-r--r-- | libuci.c | 1 | ||||
-rw-r--r-- | uci.h | 6 |
3 files changed, 38 insertions, 8 deletions
@@ -99,10 +99,25 @@ static void uci_delta_save(struct uci_context *ctx, FILE *f, int uci_set_savedir(struct uci_context *ctx, const char *dir) { char *sdir; + struct uci_element *e, *tmp; + bool exists = false; UCI_HANDLE_ERR(ctx); UCI_ASSERT(ctx, dir != NULL); + /* Move dir to the end of ctx->delta_path */ + uci_foreach_element_safe(&ctx->delta_path, tmp, e) { + if (!strcmp(e->name, dir)) { + exists = true; + uci_list_del(&e->list); + break; + } + } + if (!exists) + UCI_INTERNAL(uci_add_delta_path, ctx, dir); + else + uci_list_add(&ctx->delta_path, &e->list); + sdir = uci_strdup(ctx, dir); if (ctx->savedir != uci_savedir) free(ctx->savedir); @@ -113,13 +128,21 @@ int uci_set_savedir(struct uci_context *ctx, const char *dir) int uci_add_delta_path(struct uci_context *ctx, const char *dir) { struct uci_element *e; + struct uci_list *savedir; UCI_HANDLE_ERR(ctx); UCI_ASSERT(ctx, dir != NULL); - if (!strcmp(dir, ctx->savedir)) - return -1; + + /* Duplicate delta path is not allowed */ + uci_foreach_element(&ctx->delta_path, e) { + if (!strcmp(e->name, dir)) + UCI_THROW(ctx, UCI_ERR_DUPLICATE); + } + e = uci_alloc_generic(ctx, UCI_TYPE_PATH, dir, sizeof(struct uci_element)); - uci_list_add(&ctx->delta_path, &e->list); + /* Keep savedir at the end of ctx->delta_path list */ + savedir = ctx->delta_path.prev; + uci_list_insert(savedir->prev, &e->list); return 0; } @@ -297,21 +320,25 @@ __private int uci_load_delta(struct uci_context *ctx, struct uci_package *p, boo if ((asprintf(&filename, "%s/%s", e->name, p->e.name) < 0) || !filename) UCI_THROW(ctx, UCI_ERR_MEM); - uci_load_delta_file(ctx, p, filename, NULL, false); + changes += uci_load_delta_file(ctx, p, filename, NULL, false); free(filename); } if ((asprintf(&filename, "%s/%s", ctx->savedir, p->e.name) < 0) || !filename) UCI_THROW(ctx, UCI_ERR_MEM); + UCI_TRAP_SAVE(ctx, done); + f = uci_open_stream(ctx, filename, NULL, SEEK_SET, flush, false); + UCI_TRAP_RESTORE(ctx); - changes = uci_load_delta_file(ctx, p, filename, &f, flush); if (flush && f && (changes > 0)) { - rewind(f); if (ftruncate(fileno(f), 0) < 0) { + free(filename); uci_close_stream(f); UCI_THROW(ctx, UCI_ERR_IO); } } + +done: free(filename); uci_close_stream(f); ctx->err = 0; @@ -60,6 +60,7 @@ struct uci_context *uci_alloc_context(void) ctx->confdir = (char *) uci_confdir; ctx->savedir = (char *) uci_savedir; + uci_add_delta_path(ctx, uci_savedir); uci_list_add(&ctx->backends, &uci_file_backend.e.list); ctx->backend = &uci_file_backend; @@ -252,6 +252,8 @@ extern int uci_list_configs(struct uci_context *ctx, char ***list); * uci_set_savedir: override the default delta save directory * @ctx: uci context * @dir: directory name + * + * This will also try adding the specified dir to the end of delta pathes. */ extern int uci_set_savedir(struct uci_context *ctx, const char *dir); @@ -269,8 +271,8 @@ extern int uci_set_confdir(struct uci_context *ctx, const char *dir); * * This function allows you to add directories, which contain 'overlays' * for the active config, that will never be committed. - * Caller of this API should ensure that no duplicate entries (including the - * default search path, e.g. `UCI_SAVEDIR') should be added. + * + * Adding a duplicate directory will cause UCI_ERR_DUPLICATE be returned. */ extern int uci_add_delta_path(struct uci_context *ctx, const char *dir); |