const char *name;
const char *proto;
const char *ifname;
- unsigned char ipaddr[4];
+ unsigned char *ipaddr;
int test;
bool enabled;
struct ucimap_list *aliases;
static int
network_parse_ip(void *section, struct uci_optmap *om, union ucimap_data *data, const char *str)
{
- unsigned char *target = (unsigned char *) data->s;
+ unsigned char *target;
int tmp[4];
int i;
if (sscanf(str, "%d.%d.%d.%d", &tmp[0], &tmp[1], &tmp[2], &tmp[3]) != 4)
return -1;
+ target = malloc(4);
+ if (!target)
+ return -1;
+
+ *data->data = target;
for (i = 0; i < 4; i++)
target[i] = (char) tmp[i];
network_format_ip(void *sction, struct uci_optmap *om, union ucimap_data *data, char **str)
{
static char buf[16];
- unsigned char *ip = (unsigned char *) data->s;
+ unsigned char *ip = (unsigned char *) data->data[0];
sprintf(buf, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
*str = buf;
return 0;
}
+static void
+network_free_ip(void *section, struct uci_optmap *om, void *ptr)
+{
+ free(ptr);
+}
+
static int
network_init_interface(struct uci_map *map, void *section, struct uci_section *s)
{
.name = "ipaddr",
.parse = network_parse_ip,
.format = network_format_ip,
+ .free = network_free_ip,
}
},
{
ucimap_parse(&network_map, pkg);
list_for_each(p, &ifs) {
+ const unsigned char *ipaddr;
+
net = list_entry(p, struct uci_network, list);
+ ipaddr = net->ipaddr;
+ if (!ipaddr)
+ ipaddr = (const unsigned char *) "\x00\x00\x00\x00";
+
printf("New network section '%s'\n"
" type: %s\n"
" ifname: %s\n"
net->name,
net->proto,
net->ifname,
- net->ipaddr[0], net->ipaddr[1],
- net->ipaddr[2], net->ipaddr[3],
+ ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3],
net->test,
(net->enabled ? "on" : "off"));
} data;
};
+struct uci_alloc_custom {
+ void *section;
+ struct uci_optmap *om;
+ void *ptr;
+};
+
struct uci_fixup {
struct list_head list;
struct uci_sectionmap *sm;
ucimap_free_item(&sd->allocmap[i]);
}
+ if (sd->alloc_custom) {
+ for (i = 0; i < sd->alloc_custom_len; i++) {
+ struct uci_alloc_custom *a = &sd->alloc_custom[i];
+ a->om->free(a->section, a->om, a->ptr);
+ }
+ free(sd->alloc_custom);
+ }
+
free(sd->allocmap);
free(sd);
}
list_add_tail(&f->list, &map->fixup);
}
+static void
+ucimap_add_custom_alloc(struct ucimap_section_data *sd, struct uci_optmap *om, void *ptr)
+{
+ struct uci_alloc_custom *a = &sd->alloc_custom[sd->alloc_custom_len++];
+
+ a->section = ucimap_section_ptr(sd);
+ a->om = om;
+ a->ptr = ptr;
+}
+
static void
ucimap_add_value(union ucimap_data *data, struct uci_optmap *om, struct ucimap_section_data *sd, const char *str)
{
if (om->parse) {
if (om->parse(ucimap_section_ptr(sd), om, &tdata, str) < 0)
return;
+ if (ucimap_is_custom(om->type) && om->free) {
+ if (tdata.ptr != data->ptr)
+ ucimap_add_custom_alloc(sd, om, data->ptr);
+ }
}
if (ucimap_is_custom(om->type))
return;
return false;
}
+static void
+ucimap_count_alloc(struct uci_optmap *om, int *n_alloc, int *n_custom)
+{
+ if (ucimap_is_alloc(om->type))
+ (*n_alloc)++;
+ else if (ucimap_is_custom(om->type) && om->free)
+ (*n_custom)++;
+}
+
int
ucimap_parse_section(struct uci_map *map, struct uci_sectionmap *sm, struct ucimap_section_data *sd, struct uci_section *s)
{
char *section_name;
void *section;
int n_alloc = 2;
+ int n_alloc_custom = 0;
int err;
INIT_LIST_HEAD(&sd->list);
union ucimap_data *data;
struct uci_element *e;
int n_elements = 0;
+ int n_elements_custom = 0;
int size;
data = ucimap_get_data(sd, om);
if (o->type == UCI_TYPE_LIST) {
uci_foreach_element(&o->v.list, tmp) {
- n_elements++;
+ ucimap_count_alloc(om, &n_elements, &n_elements_custom);
}
} 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);
while (*data && !isspace(*data))
data++;
} while (*data);
/* for the duplicated data string */
- if (n_elements > 0)
+ if (n_elements)
n_alloc++;
}
break;
}
/* add one more for the ucimap_list */
n_alloc += n_elements + 1;
+ n_alloc_custom += n_elements_custom;
size = sizeof(struct ucimap_list) +
n_elements * sizeof(union ucimap_data);
data->list = malloc(size);
memset(data->list, 0, size);
- } else if (ucimap_is_alloc(om->type)) {
- n_alloc++;
+ } else {
+ ucimap_count_alloc(om, &n_alloc, &n_alloc_custom);
}
}
- sd->allocmap = malloc(n_alloc * sizeof(struct uci_alloc));
+ sd->allocmap = calloc(n_alloc, sizeof(struct uci_alloc));
if (!sd->allocmap)
goto error_mem;
+ if (n_alloc_custom > 0) {
+ sd->alloc_custom = calloc(n_alloc_custom, sizeof(struct uci_alloc_custom));
+ if (!sd->alloc_custom)
+ goto error_mem;
+ }
+
section_name = strdup(s->e.name);
if (!section_name)
goto error_mem;
sd->section_name = section_name;
- sd->cmap = malloc(BITFIELD_SIZE(sm->n_options));
+ sd->cmap = calloc(1, BITFIELD_SIZE(sm->n_options));
if (!sd->cmap)
goto error_mem;
- memset(sd->cmap, 0, BITFIELD_SIZE(sm->n_options));
ucimap_add_alloc(sd, (void *)section_name);
ucimap_add_alloc(sd, (void *)sd->cmap);
ucimap_foreach_option(sm, om) {
struct uci_sectionmap;
struct uci_optmap;
struct ucimap_list;
+struct uci_alloc;
+struct uci_alloc_custom;
struct uci_map {
struct uci_sectionmap **sections;
bool b;
char *s;
void *ptr;
+ void **data;
struct ucimap_list *list;
};
/* list of allocations done by ucimap */
struct uci_alloc *allocmap;
- unsigned long allocmap_len;
+ struct uci_alloc_custom *alloc_custom;
+ unsigned int allocmap_len;
+ unsigned int alloc_custom_len;
/* map for changed fields */
unsigned char *cmap;
int detected_type;
int (*parse)(void *section, struct uci_optmap *om, union ucimap_data *data, const char *string);
int (*format)(void *section, struct uci_optmap *om, union ucimap_data *data, char **string);
+ void (*free)(void *section, struct uci_optmap *om, void *ptr);
union {
struct {
int base;