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
);