implement uci.changes() in lua binding
[project/uci.git] / history.c
index 089bcef..ea6cf0d 100644 (file)
--- a/history.c
+++ b/history.c
@@ -27,8 +27,8 @@
 #include <ctype.h>
 
 /* 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)
+void
+uci_add_history(struct uci_context *ctx, struct uci_list *list, int cmd, const char *section, const char *option, const char *value)
 {
        struct uci_history *h;
        int size = strlen(section) + 1;
@@ -48,7 +48,7 @@ uci_add_history(struct uci_context *ctx, struct uci_list *list, int cmd, char *s
        uci_list_add(list, &h->e.list);
 }
 
-static void
+void
 uci_free_history(struct uci_history *h)
 {
        if (!h)
@@ -217,7 +217,7 @@ static int uci_load_history(struct uci_context *ctx, struct uci_package *p, bool
        FILE *f = NULL;
        int changes = 0;
 
-       if (!p->confdir)
+       if (!p->has_history)
                return 0;
 
        uci_foreach_element(&ctx->history_path, e) {
@@ -239,11 +239,11 @@ static int uci_load_history(struct uci_context *ctx, struct uci_package *p, bool
        if (filename)
                free(filename);
        uci_close_stream(f);
-       ctx->errno = 0;
+       ctx->err = 0;
        return changes;
 }
 
-static void uci_filter_history(struct uci_context *ctx, const char *name, char *section, char *option)
+static void uci_filter_history(struct uci_context *ctx, const char *name, const char *section, const char *option)
 {
        struct uci_parse_context *pctx;
        struct uci_element *e, *tmp;
@@ -312,7 +312,7 @@ done:
        uci_cleanup(ctx);
 }
 
-int uci_revert(struct uci_context *ctx, struct uci_package **pkg, char *section, char *option)
+int uci_revert(struct uci_context *ctx, struct uci_package **pkg, const char *section, const char *option)
 {
        struct uci_package *p;
        char *name = NULL;
@@ -321,7 +321,7 @@ int uci_revert(struct uci_context *ctx, struct uci_package **pkg, char *section,
        UCI_ASSERT(ctx, pkg != NULL);
        p = *pkg;
        UCI_ASSERT(ctx, p != NULL);
-       UCI_ASSERT(ctx, p->confdir);
+       UCI_ASSERT(ctx, p->has_history);
 
        /* 
         * - flush unwritten changes
@@ -340,13 +340,13 @@ int uci_revert(struct uci_context *ctx, struct uci_package **pkg, char *section,
 
        UCI_INTERNAL(uci_load, ctx, name, &p);
        UCI_TRAP_RESTORE(ctx);
-       ctx->errno = 0;
+       ctx->err = 0;
 
 error:
        if (name)
                free(name);
-       if (ctx->errno)
-               UCI_THROW(ctx, ctx->errno);
+       if (ctx->err)
+               UCI_THROW(ctx, ctx->err);
        return 0;
 }
 
@@ -355,6 +355,7 @@ int uci_save(struct uci_context *ctx, struct uci_package *p)
        FILE *f = NULL;
        char *filename = NULL;
        struct uci_element *e, *tmp;
+       struct stat statbuf;
 
        UCI_HANDLE_ERR(ctx);
        UCI_ASSERT(ctx, p != NULL);
@@ -365,16 +366,21 @@ int uci_save(struct uci_context *ctx, struct uci_package *p)
         * directly.
         * does not modify the uci_package pointer
         */
-       if (!p->confdir)
+       if (!p->has_history)
                return uci_commit(ctx, &p, false);
 
        if (uci_list_empty(&p->history))
                return 0;
 
+       if (stat(ctx->savedir, &statbuf) < 0)
+               mkdir(ctx->savedir, UCI_DIRMODE);
+       else if ((statbuf.st_mode & S_IFMT) != S_IFDIR)
+               UCI_THROW(ctx, UCI_ERR_IO);
+
        if ((asprintf(&filename, "%s/%s", ctx->savedir, p->e.name) < 0) || !filename)
                UCI_THROW(ctx, UCI_ERR_MEM);
 
-       ctx->errno = 0;
+       ctx->err = 0;
        UCI_TRAP_SAVE(ctx, done);
        f = uci_open_stream(ctx, filename, SEEK_END, true, true);
        UCI_TRAP_RESTORE(ctx);
@@ -411,8 +417,8 @@ done:
        uci_close_stream(f);
        if (filename)
                free(filename);
-       if (ctx->errno)
-               UCI_THROW(ctx, ctx->errno);
+       if (ctx->err)
+               UCI_THROW(ctx, ctx->err);
 
        return 0;
 }