static char buf[16];
unsigned char *ip = (unsigned char *) data->data[0];
- sprintf(buf, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
- *str = buf;
+ if (ip) {
+ sprintf(buf, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
+ *str = buf;
+ } else {
+ *str = NULL;
+ }
return 0;
}
struct list_head *p;
struct uci_network *net;
struct uci_alias *alias;
+ bool set = false;
int i;
INIT_LIST_HEAD(&ifs);
ctx = uci_alloc_context();
ucimap_init(&network_map);
+ if ((argc >= 2) && !strcmp(argv[1], "-s")) {
+ uci_set_savedir(ctx, "./test/save");
+ set = true;
+ }
+
uci_set_confdir(ctx, "./test/config");
uci_load(ctx, "network", &pkg);
net->test,
(net->enabled ? "on" : "off"));
- for (i = 0; i < net->aliases->n_items; i++) {
- alias = net->aliases->item[i].ptr;
+ if (net->aliases->n_items > 0) {
+ printf("Configured aliases:");
+ for (i = 0; i < net->aliases->n_items; i++) {
+ alias = net->aliases->item[i].ptr;
+ printf(" %s", alias->name);
+ }
+ printf("\n");
+ }
+ list_for_each_entry(alias, &net->alias, list) {
+ for (i = 0; i < net->aliases->n_items; i++) {
+ if (alias == net->aliases->item[i].ptr)
+ goto next_alias;
+ }
printf("New alias: %s\n", alias->name);
+next_alias:
+ continue;
+ }
+ if (set && !strcmp(net->name, "lan")) {
+ ucimap_free_item(&net->map, &net->ipaddr);
+ ucimap_set_changed(&net->map, &net->ipaddr);
+ ucimap_store_section(&network_map, pkg, &net->map);
+ uci_save(ctx, pkg);
}
-#if 0
- memcpy(net->ipaddr, "\x01\x03\x04\x05", 4);
- ucimap_set_changed(&net->map, &net->ipaddr);
- ucimap_store_section(&network_map, pkg, &net->map);
- uci_save(ctx, pkg);
-#endif
}
#include <limits.h>
#include <stdio.h>
#include <ctype.h>
+#include <errno.h>
#include "ucimap.h"
#include "uci_internal.h"
struct uci_alloc {
- enum ucimap_type type;
- union {
- void **ptr;
- } data;
+ void *ptr;
};
struct uci_alloc_custom {
return 0;
}
-static void
-ucimap_free_item(struct uci_alloc *a)
-{
- switch(a->type & UCIMAP_TYPE) {
- case UCIMAP_SIMPLE:
- case UCIMAP_LIST:
- free(a->data.ptr);
- break;
- }
-}
-
static void
ucimap_add_alloc(struct ucimap_section_data *sd, void *ptr)
{
struct uci_alloc *a = &sd->allocmap[sd->allocmap_len++];
- a->type = UCIMAP_SIMPLE;
- a->data.ptr = ptr;
+ a->ptr = ptr;
}
void
sd->sm->free(map, section);
for (i = 0; i < sd->allocmap_len; i++) {
- ucimap_free_item(&sd->allocmap[i]);
+ free(sd->allocmap[i].ptr);
}
if (sd->alloc_custom) {
return true;
}
+void
+ucimap_free_item(struct ucimap_section_data *sd, void *item)
+{
+ struct uci_alloc_custom *ac;
+ struct uci_alloc *a;
+ void *ptr = *((void **) item);
+ int i;
+
+ if (!ptr)
+ return;
+
+ *((void **)item) = NULL;
+ for (i = 0, a = sd->allocmap; i < sd->allocmap_len; i++, a++) {
+ if (a->ptr != ptr)
+ continue;
+
+ if (i != sd->allocmap_len - 1)
+ a->ptr = sd->allocmap[sd->allocmap_len - 1].ptr;
+
+ sd->allocmap_len--;
+ return;
+ }
+
+ for (i = 0, ac = sd->alloc_custom; i < sd->alloc_custom_len; i++, ac++) {
+ if (ac->ptr != ptr)
+ continue;
+
+ if (i != sd->alloc_custom_len - 1)
+ memcpy(ac, &sd->alloc_custom[sd->alloc_custom_len - 1],
+ sizeof(struct uci_alloc_custom));
+
+ ac->om->free(ac->section, ac->om, ac->ptr);
+ sd->alloc_custom_len--;
+ return;
+ }
+}
+
+int
+ucimap_resize_list(struct ucimap_section_data *sd, struct ucimap_list **list, int items)
+{
+ struct ucimap_list *new;
+ struct uci_alloc *a;
+ int i, offset = 0;
+ int size = sizeof(struct ucimap_list) + items * sizeof(union ucimap_data);
+
+ if (!*list) {
+ new = calloc(1, size);
+
+ ucimap_add_alloc(sd, new);
+ goto set;
+ }
+
+ for (i = 0, a = sd->allocmap; i < sd->allocmap_len; i++, a++) {
+ if (a->ptr != *list)
+ continue;
+
+ goto realloc;
+ }
+ return -ENOENT;
+
+realloc:
+ if (items > (*list)->size)
+ offset = (items - (*list)->size) * sizeof(union ucimap_data);
+
+ a->ptr = realloc(a->ptr, size);
+ if (offset)
+ memset((char *) a->ptr + offset, 0, size - offset);
+ new = a->ptr;
+
+set:
+ new->size = items;
+ *list = new;
+ return 0;
+}
+
static void
ucimap_add_fixup(struct ucimap_section_data *sd, union ucimap_data *data, struct uci_optmap *om, const char *str)
{
char *s;
int val;
- if (ucimap_is_list(om->type) && !ucimap_is_fixup(om->type))
+ 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");
+ return;
+ }
+
data = &data->list->item[data->list->n_items++];
+ }
switch(om->type & UCIMAP_SUBTYPE) {
case UCIMAP_STRING:
n_alloc_custom += n_elements_custom;
size = sizeof(struct ucimap_list) +
n_elements * sizeof(union ucimap_data);
+
data->list = malloc(size);
+ if (!data->list)
+ goto error_mem;
+
+ data->list->size = n_elements;
memset(data->list, 0, size);
} else {
ucimap_count_alloc(om, &n_alloc, &n_alloc_custom);
if (om->format(ucimap_section_ptr(sd), om, data, &str) < 0)
continue;
+
+ if (!str)
+ str = "";
}
if (!str)
continue;
bool done;
};
-
-struct uci_listmap {
- struct list_head list;
- union ucimap_data data;
-};
-
struct uci_sectionmap {
/* type string for the uci section */
const char *type;
struct ucimap_list {
int n_items;
+ int size;
union ucimap_data item[];
};
extern void ucimap_parse(struct uci_map *map, struct uci_package *pkg);
extern int ucimap_parse_section(struct uci_map *map, struct uci_sectionmap *sm, struct ucimap_section_data *sd, struct uci_section *s);
extern void ucimap_free_section(struct uci_map *map, struct ucimap_section_data *sd);
+extern int ucimap_resize_list(struct ucimap_section_data *sd, struct ucimap_list **list, int items);
+extern void ucimap_free_item(struct ucimap_section_data *sd, void *item);
#endif