Fix delta path handling.
authorYousong Zhou <yszhou4tech@gmail.com>
Tue, 31 Mar 2015 16:20:18 +0000 (00:20 +0800)
committerFelix Fietkau <nbd@openwrt.org>
Tue, 31 Mar 2015 16:42:41 +0000 (18:42 +0200)
 - 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.

delta.c
libuci.c
uci.h

diff --git a/delta.c b/delta.c
index cdd46bcc5896f1c3742656453d1ff3dc11cd525c..357f5c79126064b9d857e612d110680ce91f16c9 100644 (file)
--- a/delta.c
+++ b/delta.c
@@ -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;
index b17cda14049b7f33b4289fd7e981e9962ab1efd1..a9e70e883ee3d55009bc3fe01edc87ae24733194 100644 (file)
--- a/libuci.c
+++ b/libuci.c
@@ -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;
diff --git a/uci.h b/uci.h
index abba660826c33fd64acc3e46a2d6f5f1510dfd04..c5583ed0f798a081e964ba120760c59d179b36e2 100644 (file)
--- a/uci.h
+++ b/uci.h
@@ -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);