add new command del_list
authorLuka Perkov <openwrt@lukaperkov.net>
Fri, 9 Nov 2012 10:40:10 +0000 (11:40 +0100)
committerFelix Fietkau <nbd@openwrt.org>
Fri, 9 Nov 2012 10:40:10 +0000 (11:40 +0100)
cli.c
delta.c
list.c
uci.h

diff --git a/cli.c b/cli.c
index 144cdde..f5dfce0 100644 (file)
--- a/cli.c
+++ b/cli.c
@@ -38,6 +38,7 @@ enum {
        CMD_GET,
        CMD_SET,
        CMD_ADD_LIST,
+       CMD_DEL_LIST,
        CMD_DEL,
        CMD_RENAME,
        CMD_REVERT,
@@ -133,6 +134,7 @@ static void uci_usage(void)
                "\tcommit     [<config>]\n"
                "\tadd        <config> <section-type>\n"
                "\tadd_list   <config>.<section>.<option>=<string>\n"
+               "\tdel_list   <config>.<section>.<option>=<string>\n"
                "\tshow       [<config>[.<section>[.<option>]]]\n"
                "\tget        <config>.<section>[.<option>]\n"
                "\tset        <config>.<section>[.<option>]=<value>\n"
@@ -242,6 +244,9 @@ static void uci_show_changes(struct uci_package *p)
                case UCI_CMD_LIST_ADD:
                        op = "+=";
                        break;
+               case UCI_CMD_LIST_DEL:
+                       op = "-=";
+                       break;
                default:
                        break;
                }
@@ -418,7 +423,9 @@ static int uci_do_section_cmd(int cmd, int argc, char **argv)
                return 1;
        }
 
-       if (ptr.value && (cmd != CMD_SET) && (cmd != CMD_ADD_LIST) && (cmd != CMD_RENAME) && (cmd != CMD_REORDER))
+       if (ptr.value && (cmd != CMD_SET) &&
+           (cmd != CMD_ADD_LIST) && (cmd != CMD_DEL_LIST) &&
+           (cmd != CMD_RENAME) && (cmd != CMD_REORDER))
                return 1;
 
        e = ptr.last;
@@ -453,6 +460,9 @@ static int uci_do_section_cmd(int cmd, int argc, char **argv)
        case CMD_ADD_LIST:
                ret = uci_add_list(ctx, &ptr);
                break;
+       case CMD_DEL_LIST:
+               ret = uci_del_list(ctx, &ptr);
+               break;
        case CMD_REORDER:
                if (!ptr.s || !ptr.value) {
                        ctx->err = UCI_ERR_NOTFOUND;
@@ -585,11 +595,14 @@ static int uci_cmd(int argc, char **argv)
                cmd = CMD_ADD;
        else if (!strcasecmp(argv[0], "add_list"))
                cmd = CMD_ADD_LIST;
+       else if (!strcasecmp(argv[0], "del_list"))
+               cmd = CMD_DEL_LIST;
        else
                cmd = -1;
 
        switch(cmd) {
                case CMD_ADD_LIST:
+               case CMD_DEL_LIST:
                case CMD_GET:
                case CMD_SET:
                case CMD_DEL:
diff --git a/delta.c b/delta.c
index 24784f8..0a24f31 100644 (file)
--- a/delta.c
+++ b/delta.c
@@ -114,6 +114,9 @@ static inline int uci_parse_delta_tuple(struct uci_context *ctx, char **buf, str
        case '|':
                c = UCI_CMD_LIST_ADD;
                break;
+       case '_':
+               c = UCI_CMD_LIST_DEL;
+               break;
        }
 
        if (c != UCI_CMD_CHANGE)
@@ -138,6 +141,9 @@ static inline int uci_parse_delta_tuple(struct uci_context *ctx, char **buf, str
        case UCI_CMD_LIST_ADD:
                if (!ptr->option)
                        goto error;
+       case UCI_CMD_LIST_DEL:
+               if (!ptr->option)
+                       goto error;
        }
 
        return c;
@@ -176,6 +182,9 @@ static void uci_parse_delta_line(struct uci_context *ctx, struct uci_package *p,
        case UCI_CMD_LIST_ADD:
                UCI_INTERNAL(uci_add_list, ctx, &ptr);
                break;
+       case UCI_CMD_LIST_DEL:
+               UCI_INTERNAL(uci_del_list, ctx, &ptr);
+               break;
        case UCI_CMD_ADD:
        case UCI_CMD_CHANGE:
                UCI_INTERNAL(uci_set, ctx, &ptr);
@@ -460,6 +469,9 @@ int uci_save(struct uci_context *ctx, struct uci_package *p)
                case UCI_CMD_LIST_ADD:
                        prefix = "|";
                        break;
+               case UCI_CMD_LIST_DEL:
+                       prefix = "_";
+                       break;
                default:
                        break;
                }
diff --git a/list.c b/list.c
index cf6d970..006e2a0 100644 (file)
--- a/list.c
+++ b/list.c
@@ -612,6 +612,38 @@ int uci_add_list(struct uci_context *ctx, struct uci_ptr *ptr)
        return 0;
 }
 
+int uci_del_list(struct uci_context *ctx, struct uci_ptr *ptr)
+{
+       /* NB: pass on internal flag to uci_del_element */
+       bool internal = ctx && ctx->internal;
+       struct uci_element *e, *tmp;
+       struct uci_package *p;
+
+       UCI_HANDLE_ERR(ctx);
+
+       uci_expand_ptr(ctx, ptr, false);
+       UCI_ASSERT(ctx, ptr->s);
+       UCI_ASSERT(ctx, ptr->value);
+
+       if (!(ptr->o && ptr->option))
+               return 0;
+
+       if ((ptr->o->type != UCI_TYPE_LIST))
+               return 0;
+
+       p = ptr->p;
+       if (!internal && p->has_delta)
+               uci_add_delta(ctx, &p->delta, UCI_CMD_LIST_DEL, ptr->section, ptr->option, ptr->value);
+
+       uci_foreach_element_safe(&ptr->o->v.list, tmp, e) {
+               if (!strcmp(ptr->value, uci_to_option(e)->e.name)) {
+                       uci_free_option(uci_to_option(e));
+               }
+       }
+
+       return 0;
+}
+
 int uci_set(struct uci_context *ctx, struct uci_ptr *ptr)
 {
        /* NB: UCI_INTERNAL use means without delta tracking */
diff --git a/uci.h b/uci.h
index 6d13ea6..68b53f5 100644 (file)
--- a/uci.h
+++ b/uci.h
@@ -187,6 +187,14 @@ extern int uci_set(struct uci_context *ctx, struct uci_ptr *ptr);
  */
 extern int uci_add_list(struct uci_context *ctx, struct uci_ptr *ptr);
 
+/**
+ * uci_del_list: Remove a string from an element list
+ * @ctx: uci context
+ * @ptr: uci pointer (with value)
+ *
+ */
+extern int uci_del_list(struct uci_context *ctx, struct uci_ptr *ptr);
+
 /**
  * uci_reorder: Reposition a section
  * @ctx: uci context
@@ -489,6 +497,7 @@ enum uci_command {
        UCI_CMD_RENAME,
        UCI_CMD_REORDER,
        UCI_CMD_LIST_ADD,
+       UCI_CMD_LIST_DEL,
 };
 
 struct uci_delta