CMD_GET,
CMD_SET,
CMD_ADD_LIST,
+ CMD_DEL_LIST,
CMD_DEL,
CMD_RENAME,
CMD_REVERT,
"\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"
case UCI_CMD_LIST_ADD:
op = "+=";
break;
+ case UCI_CMD_LIST_DEL:
+ op = "-=";
+ break;
default:
break;
}
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;
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;
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:
case '|':
c = UCI_CMD_LIST_ADD;
break;
+ case '_':
+ c = UCI_CMD_LIST_DEL;
+ break;
}
if (c != UCI_CMD_CHANGE)
case UCI_CMD_LIST_ADD:
if (!ptr->option)
goto error;
+ case UCI_CMD_LIST_DEL:
+ if (!ptr->option)
+ goto error;
}
return c;
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);
case UCI_CMD_LIST_ADD:
prefix = "|";
break;
+ case UCI_CMD_LIST_DEL:
+ prefix = "_";
+ break;
default:
break;
}
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 */
*/
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
UCI_CMD_RENAME,
UCI_CMD_REORDER,
UCI_CMD_LIST_ADD,
+ UCI_CMD_LIST_DEL,
};
struct uci_delta