From 4f27765f0d0b33788e37c81958f8497f72163500 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 5 Sep 2009 01:10:42 +0200 Subject: [PATCH] ucimap: add support for saving lists to uci --- test/references/ucimap_example_2.result | 3 +- ucimap-example.c | 8 +++ ucimap.c | 115 +++++++++++++++++++++----------- 3 files changed, 85 insertions(+), 41 deletions(-) diff --git a/test/references/ucimap_example_2.result b/test/references/ucimap_example_2.result index d333b5b..04f6598 100644 --- a/test/references/ucimap_example_2.result +++ b/test/references/ucimap_example_2.result @@ -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 diff --git a/ucimap-example.c b/ucimap-example.c index 1fd9530..1b2f601 100644 --- a/ucimap-example.c +++ b/ucimap-example.c @@ -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); } diff --git a/ucimap.c b/ucimap.c index 0d16bb4..4621ebf 100644 --- 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); } -- 2.11.0