2 * libuci - Library for the Unified Configuration Interface
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 lesser general public license version 2.1
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.
17 /* initialize a list head/item */
18 static inline void uci_list_init(struct uci_list
*ptr
)
24 /* inserts a new list entry between two consecutive entries */
25 static inline void __uci_list_add(struct uci_list
*prev
, struct uci_list
*next
, struct uci_list
*ptr
)
33 /* inserts a new list entry at the tail of the list */
34 static inline void uci_list_add(struct uci_list
*head
, struct uci_list
*ptr
)
36 /* NB: head->prev points at the tail */
37 __uci_list_add(head
->prev
, head
, ptr
);
40 static inline void uci_list_del(struct uci_list
*ptr
)
42 struct uci_list
*next
, *prev
;
51 static void uci_drop_option(struct uci_option
*option
)
62 static struct uci_option
*uci_add_option(struct uci_section
*section
, const char *name
, const char *value
)
64 struct uci_config
*cfg
= section
->config
;
65 struct uci_context
*ctx
= cfg
->ctx
;
66 struct uci_option
*option
= NULL
;
68 UCI_TRAP_SAVE(ctx
, error
);
69 option
= (struct uci_option
*) uci_malloc(ctx
, sizeof(struct uci_option
));
70 option
->name
= uci_strdup(ctx
, name
);
71 option
->value
= uci_strdup(ctx
, value
);
72 uci_list_add(§ion
->options
, &option
->list
);
73 UCI_TRAP_RESTORE(ctx
);
77 uci_drop_option(option
);
78 UCI_THROW(ctx
, ctx
->errno
);
82 static void uci_drop_section(struct uci_section
*section
)
84 struct uci_option
*opt
;
89 uci_foreach_entry(option
, §ion
->options
, opt
) {
90 uci_list_del(&opt
->list
);
101 static struct uci_section
*uci_add_section(struct uci_config
*cfg
, const char *type
, const char *name
)
103 struct uci_section
*section
= NULL
;
104 struct uci_context
*ctx
= cfg
->ctx
;
106 UCI_TRAP_SAVE(ctx
, error
);
108 section
= (struct uci_section
*) uci_malloc(ctx
, sizeof(struct uci_section
));
109 section
->config
= cfg
;
110 uci_list_init(§ion
->list
);
111 uci_list_init(§ion
->options
);
112 section
->type
= uci_strdup(ctx
, type
);
114 section
->name
= uci_strdup(ctx
, name
);
116 asprintf(§ion
->name
, "cfg%d", cfg
->n_section
);
117 uci_list_add(&cfg
->sections
, §ion
->list
);
118 UCI_TRAP_RESTORE(ctx
);
123 uci_drop_section(section
);
124 UCI_THROW(ctx
, ctx
->errno
);
128 static void uci_drop_config(struct uci_config
*cfg
)
130 struct uci_section
*s
;
135 uci_foreach_entry(section
, &cfg
->sections
, s
) {
136 uci_list_del(&s
->list
);
146 static struct uci_config
*uci_alloc_config(struct uci_context
*ctx
, const char *name
)
148 struct uci_config
*cfg
= NULL
;
150 UCI_TRAP_SAVE(ctx
, error
);
151 cfg
= (struct uci_config
*) uci_malloc(ctx
, sizeof(struct uci_config
));
152 uci_list_init(&cfg
->list
);
153 uci_list_init(&cfg
->sections
);
154 cfg
->name
= uci_strdup(ctx
, name
);
156 UCI_TRAP_RESTORE(ctx
);
160 uci_drop_config(cfg
);
161 UCI_THROW(ctx
, ctx
->errno
);
165 int uci_unload(struct uci_context
*ctx
, const char *name
)
167 struct uci_config
*cfg
;
170 UCI_ASSERT(ctx
, name
!= NULL
);
172 uci_foreach_entry(config
, &ctx
->root
, cfg
) {
173 if (!strcmp(cfg
->name
, name
))
176 UCI_THROW(ctx
, UCI_ERR_NOTFOUND
);
179 uci_list_del(&cfg
->list
);
180 uci_drop_config(cfg
);
185 static inline char *get_filename(char *path
)
189 p
= strrchr(path
, '/');
196 char **uci_list_configs()
203 if (glob(UCI_CONFDIR
"/*", GLOB_MARK
, NULL
, &globbuf
) != 0)
206 size
= sizeof(char *) * (globbuf
.gl_pathc
+ 1);
207 for(i
= 0; i
< globbuf
.gl_pathc
; i
++) {
210 p
= get_filename(globbuf
.gl_pathv
[i
]);
214 size
+= strlen(p
) + 1;
217 configs
= malloc(size
);
221 memset(configs
, 0, size
);
222 buf
= (char *) &configs
[globbuf
.gl_pathc
+ 1];
223 for(i
= 0; i
< globbuf
.gl_pathc
; i
++) {
226 p
= get_filename(globbuf
.gl_pathv
[i
]);
232 buf
+= strlen(buf
) + 1;