* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * GNU Lesser General Public License for more details.
*/
/*
- * This file contains ucimap, an API for mapping UCI to C data structures
+ * This file contains ucimap, an API for mapping UCI to C data structures
*/
#include <strings.h>
static inline bool
ucimap_is_alloc(enum ucimap_type type)
{
- switch(type & UCIMAP_SUBTYPE) {
- case UCIMAP_STRING:
- return true;
- default:
- return false;
- }
+ return (type & UCIMAP_SUBTYPE) == UCIMAP_STRING;
}
static inline bool
ucimap_is_fixup(enum ucimap_type type)
{
- switch(type & UCIMAP_SUBTYPE) {
- case UCIMAP_SECTION:
- return true;
- default:
- return false;
- }
+ return (type & UCIMAP_SUBTYPE) == UCIMAP_SECTION;
}
static inline bool
ucimap_free_section(struct uci_map *map, struct ucimap_section_data *sd)
{
void *section;
- int i;
+ unsigned int i;
section = ucimap_section_ptr(sd);
if (sd->ref)
void
ucimap_cleanup(struct uci_map *map)
{
- struct ucimap_section_data *sd;
+ struct ucimap_section_data *sd, *sd_next;
- for (sd = map->sdata; sd; sd = sd->next) {
+ for (sd = map->sdata; sd; sd = sd_next) {
+ sd_next = sd->next;
ucimap_free_section(map, sd);
}
}
return NULL;
}
+static union ucimap_data *
+ucimap_list_append(struct ucimap_list *list)
+{
+ if (unlikely(list->size <= list->n_items)) {
+ /* should not happen */
+ DPRINTF("ERROR: overflow while filling a list (size=%d)\n", list->size);
+ return NULL;
+ }
+ return &list->item[list->n_items++];
+}
+
+
static bool
ucimap_handle_fixup(struct uci_map *map, struct ucimap_fixup *f)
{
void *ptr = ucimap_find_section(map, f);
- struct ucimap_list *list;
+ union ucimap_data *data;
if (!ptr)
return false;
f->data->ptr = ptr;
break;
case UCIMAP_LIST:
- list = f->data->list;
- list->item[list->n_items++].ptr = ptr;
+ data = ucimap_list_append(f->data->list);
+ if (!data)
+ return false;
+
+ data->ptr = ptr;
break;
}
return true;
struct ucimap_alloc_custom *ac;
struct ucimap_alloc *a;
void *ptr = *((void **) item);
- int i;
+ unsigned int i;
if (!ptr)
return;
{
struct ucimap_list *new;
struct ucimap_alloc *a;
- int i, offset = 0;
+ unsigned int i;
+ int offset = 0;
int size = sizeof(struct ucimap_list) + items * sizeof(union ucimap_data);
if (!*list) {
new = calloc(1, size);
+ if (!new)
+ return -ENOMEM;
ucimap_add_alloc(sd, new);
goto set;
offset = (items - (*list)->size) * sizeof(union ucimap_data);
a->ptr = realloc(a->ptr, size);
+ if (!a->ptr)
+ return -ENOMEM;
+
if (offset)
memset((char *) a->ptr + offset, 0, size - offset);
new = a->ptr;
struct ucimap_fixup *f, tmp;
struct uci_map *map = sd->map;
+ tmp.next = NULL;
tmp.sm = om->data.sm;
tmp.name = str;
tmp.type = om->type;
int val;
if (ucimap_is_list(om->type) && !ucimap_is_fixup(om->type)) {
- if (unlikely(data->list->size <= data->list->n_items)) {
- /* should not happen */
- DPRINTF("ERROR: overflow while filling a list\n");
+ data = ucimap_list_append(data->list);
+ if (!data)
return;
- }
-
- data = &data->list->item[data->list->n_items++];
}
switch(om->type & UCIMAP_SUBTYPE) {
case UCIMAP_STRING:
if ((om->data.s.maxlen > 0) &&
- (strlen(str) > om->data.s.maxlen))
+ (strlen(str) > (unsigned) om->data.s.maxlen))
return;
s = strdup(str);
ucimap_add_fixup(sd, data, om, str);
return;
case UCIMAP_CUSTOM:
- tdata.s = (char *) data;
break;
}
if (om->parse) {
- if (om->parse(ucimap_section_ptr(sd), om, &tdata, str) < 0)
+ if (om->parse(ucimap_section_ptr(sd), om, data, str) < 0)
return;
if (ucimap_is_custom(om->type) && om->free) {
if (tdata.ptr != data->ptr)
map->sdata_tail = &sd->next;
}
-static void
+static int
ucimap_add_section(struct ucimap_section_data *sd)
{
+ int r;
struct uci_map *map = sd->map;
sd->next = NULL;
- if (sd->sm->add(map, ucimap_section_ptr(sd)) < 0)
+ r = sd->sm->add(map, ucimap_section_ptr(sd));
+ if (r < 0) {
ucimap_free_section(map, sd);
- else
+ return r;
+ } else
ucimap_add_section_list(map, sd);
+
+ return 0;
}
#ifdef UCI_DEBUG
static bool
ucimap_check_optmap_type(struct uci_sectionmap *sm, struct uci_optmap *om)
{
- unsigned int type;
+ int type;
if (unlikely(sm->type_name != om->type_name) &&
unlikely(strcmp(sm->type_name, om->type_name) != 0)) {
union ucimap_data *data;
struct uci_element *e;
int n_elements = 0;
+ int n_elements_alloc = 0;
int n_elements_custom = 0;
int size;
if (o->type == UCI_TYPE_LIST) {
uci_foreach_element(&o->v.list, tmp) {
- ucimap_count_alloc(om, &n_elements, &n_elements_custom);
+ ucimap_count_alloc(om, &n_elements_alloc, &n_elements_custom);
+ n_elements++;
}
} else if ((o->type == UCI_TYPE_STRING) &&
ucimap_is_list_auto(om->type)) {
break;
n_elements++;
- ucimap_count_alloc(om, &n_elements, &n_elements_custom);
+ ucimap_count_alloc(om, &n_elements_alloc, &n_elements_custom);
while (*data && !isspace(*data))
data++;
break;
}
/* add one more for the ucimap_list */
- n_alloc += n_elements + 1;
+ n_alloc += n_elements_alloc + 1;
n_alloc_custom += n_elements_custom;
size = sizeof(struct ucimap_list) +
n_elements * sizeof(union ucimap_data);
if (!data->list)
goto error_mem;
- data->list->size = n_elements;
memset(data->list, 0, size);
+ data->list->size = n_elements;
} else {
ucimap_count_alloc(om, &n_alloc, &n_alloc_custom);
}
goto error;
if (map->parsed) {
- ucimap_add_section(sd);
+ err = ucimap_add_section(sd);
+ if (err)
+ return err;
} else {
ucimap_add_section_list(map, sd);
}
return 0;
error_mem:
- if (sd->allocmap)
- free(sd->allocmap);
+ free(sd->alloc_custom);
+ free(sd->allocmap);
free(sd);
return UCI_ERR_MEM;
void *section = ucimap_section_ptr(sd);
struct uci_sectionmap *sm = sd->sm;
struct uci_optmap *om;
- int ofs = (char *)field - (char *)section;
+ unsigned int ofs = (char *)field - (char *)section;
int i = 0;
ucimap_foreach_option(sm, om) {
}
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;
struct uci_element *e;
struct ucimap_section_data *sd, **sd_tail;
struct ucimap_fixup *f;
- int i;
+ unsigned int i;
sd_tail = map->sdata_tail;
map->parsed = false;
if (sm->alloc) {
sd = sm->alloc(map, sm, s);
+ if (!sd)
+ continue;
memset(sd, 0, sizeof(struct ucimap_section_data));
} else {
sd = malloc(sm->alloc_len);
+ if (!sd)
+ continue;
memset(sd, 0, sm->alloc_len);
+ sd = ucimap_ptr_section(sm, sd);
}
- if (!sd)
- continue;
ucimap_parse_section(map, sm, sd, s);
}