2 * ucimap - library for mapping uci sections into data structures
3 * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2
7 * as published by the Free Software Foundation
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
22 ucimap_init(struct uci_map *map)
24 INIT_LIST_HEAD(&map->sdata);
29 ucimap_free_section(struct uci_map *map, struct uci_sectmap_data *sd)
34 section = (char *) section + sizeof(struct uci_sectmap_data);
35 if (!list_empty(&sd->list))
38 if (sd->sm->free_section)
39 sd->sm->free_section(map, section);
41 for (i = 0; i < sd->allocmap_len; i++) {
42 free(sd->allocmap[i]);
50 ucimap_cleanup(struct uci_map *map)
52 struct list_head *ptr, *tmp;
54 list_for_each_safe(ptr, tmp, &map->sdata) {
55 struct uci_sectmap_data *sd = list_entry(ptr, struct uci_sectmap_data, list);
56 ucimap_free_section(map, sd);
62 ucimap_parse_options(struct uci_map *map, struct uci_sectmap *sm, struct uci_sectmap_data *sd, struct uci_section *s)
64 struct uci_element *e;
69 section = (unsigned char *) section + sizeof(struct uci_sectmap_data);
70 uci_foreach_element(&s->options, e) {
71 struct uci_optmap *om = NULL;
73 for (i = 0; i < sm->n_options; i++) {
74 if (strcmp(e->name, sm->options[i].name) == 0) {
83 if(o->type != UCI_TYPE_STRING)
89 if ((om->data.s.maxlen > 0) &&
90 (strlen(o->v.string) > om->data.s.maxlen))
93 ptr = (char **) ((char *) section + om->offset);
94 *ptr = strdup(o->v.string);
95 sd->allocmap[sd->allocmap_len++] = *ptr;
98 bool *ptr = (bool *)((char *)section + om->offset);
99 if (strcmp(o->v.string, "on"))
101 else if (strcmp(o->v.string, "1"))
103 else if (strcmp(o->v.string, "enabled"))
109 int *ptr = (int *)((char *)section + om->offset);
113 val = strtol(o->v.string, &eptr, om->data.i.base);
114 if (!eptr || *eptr == '\0')
127 ucimap_parse_section(struct uci_map *map, struct uci_sectmap *sm, struct uci_section *s)
129 struct uci_sectmap_data *sd = NULL;
130 void *section = NULL;
133 sd = malloc(sm->alloc_len + sizeof(struct uci_sectmap_data));
137 memset(sd, 0, sm->alloc_len + sizeof(struct uci_sectmap_data));
138 INIT_LIST_HEAD(&sd->list);
141 sd->allocmap = malloc(sm->n_options * sizeof(void *));
145 sd->section_name = strdup(s->e.name);
146 if (!sd->section_name)
149 sd->cmap = malloc(BITFIELD_SIZE(sm->n_options));
153 memset(sd->cmap, 0, BITFIELD_SIZE(sm->n_options));
154 sd->allocmap[sd->allocmap_len++] = (void *)sd->section_name;
155 sd->allocmap[sd->allocmap_len++] = (void *)sd->cmap;
157 section = (char *)sd + sizeof(struct uci_sectmap_data);
159 err = sm->init_section(map, section, s);
163 list_add(&sd->list, &map->sdata);
164 err = ucimap_parse_options(map, sm, sd, s);
168 err = sm->add_section(map, section);
181 ucimap_free_section(map, sd);
186 ucimap_fill_ptr(struct uci_ptr *ptr, struct uci_section *s, const char *option)
188 struct uci_package *p = s->package;
190 memset(ptr, 0, sizeof(struct uci_ptr));
192 ptr->package = p->e.name;
195 ptr->section = s->e.name;
198 ptr->option = option;
199 return uci_lookup_ptr(p->ctx, ptr, NULL, false);
203 ucimap_set_changed(void *section, void *field)
205 char *sptr = (char *)section - sizeof(struct uci_sectmap_data);
206 struct uci_sectmap_data *sd = (struct uci_sectmap_data *) sptr;
207 struct uci_sectmap *sm = sd->sm;
208 int ofs = (char *)field - (char *)section;
211 for (i = 0; i < sm->n_options; i++) {
212 if (sm->options[i].offset == ofs) {
213 SET_BIT(sd->cmap, i);
220 ucimap_store_section(struct uci_map *map, struct uci_package *p, void *section)
222 char *sptr = (char *)section - sizeof(struct uci_sectmap_data);
223 struct uci_sectmap_data *sd = (struct uci_sectmap_data *) sptr;
224 struct uci_sectmap *sm = sd->sm;
225 struct uci_section *s = NULL;
226 struct uci_element *e;
230 uci_foreach_element(&p->sections, e) {
231 if (!strcmp(e->name, sd->section_name)) {
232 s = uci_to_section(e);
237 return UCI_ERR_NOTFOUND;
239 for (i = 0; i < sm->n_options; i++) {
240 struct uci_optmap *om = &sm->options[i];
242 const char *str = NULL;
243 void *p = (char *)section + om->offset;
245 if (!TEST_BIT(sd->cmap, i))
248 ucimap_fill_ptr(&ptr, s, om->name);
251 str = *((char **) p);
254 sprintf(buf, "%d", *((int *) p));
258 sprintf(buf, "%d", !!*((bool *)p));
264 ret = uci_set(s->package->ctx, &ptr);
268 CLR_BIT(sd->cmap, i);
276 ucimap_parse(struct uci_map *map, struct uci_package *pkg)
278 struct uci_element *e;
281 uci_foreach_element(&pkg->sections, e) {
282 struct uci_section *s = uci_to_section(e);
284 for (i = 0; i < map->n_sections; i++) {
285 if (strcmp(s->type, map->sections[i].type) != 0)
287 ucimap_parse_section(map, &map->sections[i], s);