ucimap: add support for saving lists to uci
authorFelix Fietkau <nbd@openwrt.org>
Fri, 4 Sep 2009 23:10:42 +0000 (01:10 +0200)
committerFelix Fietkau <nbd@openwrt.org>
Fri, 4 Sep 2009 23:10:42 +0000 (01:10 +0200)
test/references/ucimap_example_2.result
ucimap-example.c
ucimap.c

index d333b5b..04f6598 100644 (file)
@@ -4,8 +4,7 @@ New network section 'lan'
        ipaddr: 0.0.0.0
        test: 123
        enabled: off
-New alias: a
-New alias: b
+Configured aliases: a b
 New network section 'wan'
        type: dhcp
        ifname: eth1
index 1fd9530..1b2f601 100644 (file)
@@ -257,6 +257,7 @@ int main(int argc, char **argv)
 
        list_for_each(p, &ifs) {
                const unsigned char *ipaddr;
+               int n_aliases = 0;
 
                net = list_entry(p, struct uci_network, list);
                ipaddr = net->ipaddr;
@@ -285,6 +286,7 @@ int main(int argc, char **argv)
                        printf("\n");
                }
                list_for_each_entry(alias, &net->alias, list) {
+                       n_aliases++;
                        for (i = 0; i < net->aliases->n_items; i++) {
                                if (alias == net->aliases->item[i].ptr)
                                        goto next_alias;
@@ -296,6 +298,12 @@ next_alias:
                if (set && !strcmp(net->name, "lan")) {
                        ucimap_free_item(&net->map, &net->ipaddr);
                        ucimap_set_changed(&net->map, &net->ipaddr);
+                       ucimap_resize_list(&net->map, &net->aliases, n_aliases);
+                       net->aliases->n_items = 0;
+                       list_for_each_entry(alias, &net->alias, list) {
+                               net->aliases->item[net->aliases->n_items++].ptr = alias;
+                       }
+                       ucimap_set_changed(&net->map, &net->aliases);
                        ucimap_store_section(&network_map, pkg, &net->map);
                        uci_save(ctx, pkg);
                }
index 0d16bb4..4621ebf 100644 (file)
--- a/ucimap.c
+++ b/ucimap.c
@@ -103,6 +103,12 @@ ucimap_section_ptr(struct ucimap_section_data *sd)
        return ((char *) sd - sd->sm->smap_offset);
 }
 
+static inline struct ucimap_section_data *
+ucimap_ptr_section(struct uci_sectionmap *sm, void *ptr) {
+       ptr = (char *) ptr + sm->smap_offset;
+       return ptr;
+}
+
 static inline union ucimap_data *
 ucimap_get_data(struct ucimap_section_data *sd, struct uci_optmap *om)
 {
@@ -730,6 +736,53 @@ ucimap_set_changed(struct ucimap_section_data *sd, void *field)
        }
 }
 
+static char *
+ucimap_data_to_string(struct ucimap_section_data *sd, struct uci_optmap *om, union ucimap_data *data)
+{
+       static char buf[32];
+       char *str = NULL;
+
+       switch(om->type & UCIMAP_SUBTYPE) {
+       case UCIMAP_STRING:
+               str = data->s;
+               break;
+       case UCIMAP_INT:
+               sprintf(buf, "%d", data->i);
+               str = buf;
+               break;
+       case UCIMAP_BOOL:
+               sprintf(buf, "%d", !!data->b);
+               str = buf;
+               break;
+       case UCIMAP_SECTION:
+               if (data->ptr)
+                       str = (char *) ucimap_ptr_section(om->data.sm, data->ptr)->section_name;
+               else
+                       str = "";
+               break;
+       case UCIMAP_CUSTOM:
+               break;
+       default:
+               return NULL;
+       }
+
+       if (om->format) {
+               union ucimap_data tdata;
+
+               if (ucimap_is_custom(om->type)) {
+                       tdata.s = (char *)data;
+                       data = &tdata;
+               }
+
+               if (om->format(ucimap_section_ptr(sd), om, data, &str) < 0)
+                       return NULL;
+
+               if (!str)
+                       str = "";
+       }
+       return str;
+}
+
 int
 ucimap_store_section(struct uci_map *map, struct uci_package *p, struct ucimap_section_data *sd)
 {
@@ -752,57 +805,41 @@ ucimap_store_section(struct uci_map *map, struct uci_package *p, struct ucimap_s
 
        ucimap_foreach_option(sm, om) {
                union ucimap_data *data;
-               static char buf[32];
-               char *str = NULL;
 
                i++;
-               if (ucimap_is_list(om->type))
-                       continue;
-
                data = ucimap_get_data(sd, om);
                if (!TEST_BIT(sd->cmap, i - 1))
                        continue;
 
                ucimap_fill_ptr(&ptr, s, om->name);
-               switch(om->type & UCIMAP_SUBTYPE) {
-               case UCIMAP_STRING:
-                       str = data->s;
-                       break;
-               case UCIMAP_INT:
-                       sprintf(buf, "%d", data->i);
-                       str = buf;
-                       break;
-               case UCIMAP_BOOL:
-                       sprintf(buf, "%d", !!data->b);
-                       str = buf;
-                       break;
-               case UCIMAP_CUSTOM:
-                       break;
-               default:
-                       continue;
-               }
-               if (om->format) {
-                       union ucimap_data tdata, *data;
+               if (ucimap_is_list(om->type)) {
+                       struct ucimap_list *list = data->list;
+                       bool first = true;
+                       int j;
 
-                       data = ucimap_get_data(sd, om);
-                       if (ucimap_is_custom(om->type)) {
-                               tdata.s = (char *)data;
-                               data = &tdata;
-                       }
+                       for (j = 0; j < list->n_items; j++) {
+                               ptr.value = ucimap_data_to_string(sd, om, &list->item[j]);
+                               if (!ptr.value)
+                                       continue;
 
-                       if (om->format(ucimap_section_ptr(sd), om, data, &str) < 0)
+                               if (first) {
+                                       ret = uci_set(s->package->ctx, &ptr);
+                                       first = false;
+                               } else {
+                                       ret = uci_add_list(s->package->ctx, &ptr);
+                               }
+                               if (ret)
+                                       return ret;
+                       }
+               } else {
+                       ptr.value = ucimap_data_to_string(sd, om, data);
+                       if (!ptr.value)
                                continue;
 
-                       if (!str)
-                               str = "";
+                       ret = uci_set(s->package->ctx, &ptr);
+                       if (ret)
+                               return ret;
                }
-               if (!str)
-                       continue;
-               ptr.value = str;
-
-               ret = uci_set(s->package->ctx, &ptr);
-               if (ret)
-                       return ret;
 
                CLR_BIT(sd->cmap, i - 1);
        }