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 Lesser General Public License for more details.
15 static bool uci_list_set_pos(struct uci_list
*head
, struct uci_list
*ptr
, int pos
)
17 struct uci_list
*old_head
= ptr
->prev
;
18 struct uci_list
*new_head
= head
;
19 struct uci_element
*p
= NULL
;
22 uci_foreach_element(head
, p
) {
28 uci_list_add(new_head
->next
, ptr
);
30 return (old_head
!= new_head
);
34 * uci_alloc_generic allocates a new uci_element with payload
35 * payload is appended to the struct to save memory and reduce fragmentation
37 __private
struct uci_element
*
38 uci_alloc_generic(struct uci_context
*ctx
, int type
, const char *name
, int size
)
40 struct uci_element
*e
;
44 ptr
= uci_malloc(ctx
, datalen
);
45 e
= (struct uci_element
*) ptr
;
48 UCI_TRAP_SAVE(ctx
, error
);
49 e
->name
= uci_strdup(ctx
, name
);
50 UCI_TRAP_RESTORE(ctx
);
52 uci_list_init(&e
->list
);
57 UCI_THROW(ctx
, ctx
->err
);
64 uci_free_element(struct uci_element
*e
)
67 if (!uci_list_empty(&e
->list
))
68 uci_list_del(&e
->list
);
72 static struct uci_option
*
73 uci_alloc_option(struct uci_section
*s
, const char *name
, const char *value
, struct uci_list
*after
)
75 struct uci_package
*p
= s
->package
;
76 struct uci_context
*ctx
= p
->ctx
;
79 o
= uci_alloc_element(ctx
, option
, name
, strlen(value
) + 1);
80 o
->type
= UCI_TYPE_STRING
;
81 o
->v
.string
= uci_dataptr(o
);
83 strcpy(o
->v
.string
, value
);
84 uci_list_insert(after
? after
: s
->options
.prev
, &o
->e
.list
);
90 uci_free_option(struct uci_option
*o
)
92 struct uci_element
*e
, *tmp
;
96 if ((o
->v
.string
!= uci_dataptr(o
)) &&
97 (o
->v
.string
!= NULL
))
101 uci_foreach_element_safe(&o
->v
.list
, tmp
, e
) {
108 uci_free_element(&o
->e
);
111 static struct uci_option
*
112 uci_alloc_list(struct uci_section
*s
, const char *name
, struct uci_list
*after
)
114 struct uci_package
*p
= s
->package
;
115 struct uci_context
*ctx
= p
->ctx
;
116 struct uci_option
*o
;
118 o
= uci_alloc_element(ctx
, option
, name
, 0);
119 o
->type
= UCI_TYPE_LIST
;
121 uci_list_init(&o
->v
.list
);
122 uci_list_insert(after
? after
: s
->options
.prev
, &o
->e
.list
);
127 /* Based on an efficient hash function published by D. J. Bernstein */
128 static unsigned int djbhash(unsigned int hash
, char *str
)
130 int len
= strlen(str
);
137 for(i
= 0; i
< len
; i
++) {
138 hash
= ((hash
<< 5) + hash
) + str
[i
];
140 return (hash
& 0x7FFFFFFF);
143 /* fix up an unnamed section, e.g. after adding options to it */
144 static void uci_fixup_section(struct uci_context
*ctx
, struct uci_section
*s
)
146 unsigned int hash
= ~0U;
147 struct uci_element
*e
;
154 * Generate a name for unnamed sections. This is used as reference
155 * when locating or updating the section from apps/scripts.
156 * To make multiple concurrent versions somewhat safe for updating,
157 * the name is generated from a hash of its type and name/value
158 * pairs of its option, and it is prefixed by a counter value.
159 * If the order of the unnamed sections changes for some reason,
160 * updates to them will be rejected.
162 hash
= djbhash(hash
, s
->type
);
163 uci_foreach_element(&s
->options
, e
) {
164 struct uci_option
*o
;
165 hash
= djbhash(hash
, e
->name
);
166 o
= uci_to_option(e
);
168 case UCI_TYPE_STRING
:
169 hash
= djbhash(hash
, o
->v
.string
);
175 sprintf(buf
, "cfg%02x%04x", s
->package
->n_section
, hash
% (1 << 16));
176 s
->e
.name
= uci_strdup(ctx
, buf
);
179 /* transfer options between two sections */
180 static void uci_section_transfer_options(struct uci_section
*dst
, struct uci_section
*src
)
182 struct uci_element
*e
;
184 /* transfer the option list by inserting the new list HEAD and removing the old */
185 uci_list_insert(&src
->options
, &dst
->options
);
186 uci_list_del(&src
->options
);
188 /* update pointer to section in options */
189 uci_foreach_element(&dst
->options
, e
) {
190 struct uci_option
*o
;
192 o
= uci_to_option(e
);
197 static struct uci_section
*
198 uci_alloc_section(struct uci_package
*p
, const char *type
, const char *name
, struct uci_list
*after
)
200 struct uci_context
*ctx
= p
->ctx
;
201 struct uci_section
*s
;
203 if (name
&& !name
[0])
206 s
= uci_alloc_element(ctx
, section
, name
, strlen(type
) + 1);
207 uci_list_init(&s
->options
);
208 s
->type
= uci_dataptr(s
);
210 strcpy(s
->type
, type
);
215 uci_list_insert(after
? after
: p
->sections
.prev
, &s
->e
.list
);
221 uci_free_section(struct uci_section
*s
)
223 struct uci_element
*o
, *tmp
;
225 uci_foreach_element_safe(&s
->options
, tmp
, o
) {
226 uci_free_option(uci_to_option(o
));
228 if ((s
->type
!= uci_dataptr(s
)) &&
231 uci_free_element(&s
->e
);
234 __private
struct uci_package
*
235 uci_alloc_package(struct uci_context
*ctx
, const char *name
)
237 struct uci_package
*p
;
239 p
= uci_alloc_element(ctx
, package
, name
, 0);
241 uci_list_init(&p
->sections
);
242 uci_list_init(&p
->delta
);
243 uci_list_init(&p
->saved_delta
);
248 uci_free_package(struct uci_package
**package
)
250 struct uci_element
*e
, *tmp
;
251 struct uci_package
*p
= *package
;
257 uci_foreach_element_safe(&p
->sections
, tmp
, e
) {
258 uci_free_section(uci_to_section(e
));
260 uci_foreach_element_safe(&p
->delta
, tmp
, e
) {
261 uci_free_delta(uci_to_delta(e
));
263 uci_foreach_element_safe(&p
->saved_delta
, tmp
, e
) {
264 uci_free_delta(uci_to_delta(e
));
266 uci_free_element(&p
->e
);
271 uci_free_any(struct uci_element
**e
)
274 case UCI_TYPE_SECTION
:
275 uci_free_section(uci_to_section(*e
));
277 case UCI_TYPE_OPTION
:
278 uci_free_option(uci_to_option(*e
));
286 __private
struct uci_element
*
287 uci_lookup_list(struct uci_list
*list
, const char *name
)
289 struct uci_element
*e
;
291 uci_foreach_element(list
, e
) {
292 if (!strcmp(e
->name
, name
))
298 static struct uci_element
*
299 uci_lookup_ext_section(struct uci_context
*ctx
, struct uci_ptr
*ptr
)
301 char *idxstr
, *t
, *section
, *name
;
302 struct uci_element
*e
= NULL
;
303 struct uci_section
*s
;
306 section
= uci_strdup(ctx
, ptr
->section
);
307 name
= idxstr
= section
+ 1;
309 if (section
[0] != '@')
312 /* parse the section index part */
313 idxstr
= strchr(idxstr
, '[');
319 t
= strchr(idxstr
, ']');
327 idx
= strtol(idxstr
, &t
, 10);
333 else if (!uci_validate_type(name
))
336 /* if the given index is negative, it specifies the section number from
337 * the end of the list */
340 uci_foreach_element(&ptr
->p
->sections
, e
) {
341 s
= uci_to_section(e
);
342 if (name
&& (strcmp(s
->type
, name
) != 0))
351 uci_foreach_element(&ptr
->p
->sections
, e
) {
352 s
= uci_to_section(e
);
353 if (name
&& (strcmp(s
->type
, name
) != 0))
365 memset(ptr
, 0, sizeof(struct uci_ptr
));
366 UCI_THROW(ctx
, UCI_ERR_INVAL
);
370 ptr
->section
= e
->name
;
375 uci_lookup_next(struct uci_context
*ctx
, struct uci_element
**e
, struct uci_list
*list
, const char *name
)
379 *e
= uci_lookup_list(list
, name
);
381 UCI_THROW(ctx
, UCI_ERR_NOTFOUND
);
387 uci_lookup_ptr(struct uci_context
*ctx
, struct uci_ptr
*ptr
, char *str
, bool extended
)
389 struct uci_element
*e
;
392 UCI_ASSERT(ctx
, ptr
!= NULL
);
395 UCI_INTERNAL(uci_parse_ptr
, ctx
, ptr
, str
);
397 ptr
->flags
|= UCI_LOOKUP_DONE
;
399 /* look up the package first */
403 e
= uci_lookup_list(&ctx
->root
, ptr
->package
);
406 UCI_INTERNAL(uci_load
, ctx
, ptr
->package
, &ptr
->p
);
409 ptr
->last
= &ptr
->p
->e
;
411 ptr
->p
= uci_to_package(e
);
415 if (!ptr
->section
&& !ptr
->s
)
418 /* if the section name validates as a regular name, pass through
419 * to the regular uci_lookup function call */
422 } else if (ptr
->flags
& UCI_LOOKUP_EXTENDED
) {
424 e
= uci_lookup_ext_section(ctx
, ptr
);
426 UCI_THROW(ctx
, UCI_ERR_INVAL
);
428 e
= uci_lookup_list(&ptr
->p
->sections
, ptr
->section
);
435 ptr
->s
= uci_to_section(e
);
438 e
= uci_lookup_list(&ptr
->s
->options
, ptr
->option
);
442 ptr
->o
= uci_to_option(e
);
447 ptr
->flags
|= UCI_LOOKUP_COMPLETE
;
452 UCI_THROW(ctx
, UCI_ERR_NOTFOUND
);
453 /* not a chance here */
454 return UCI_ERR_NOTFOUND
;
457 __private
struct uci_element
*
458 uci_expand_ptr(struct uci_context
*ctx
, struct uci_ptr
*ptr
, bool complete
)
460 UCI_ASSERT(ctx
, ptr
!= NULL
);
462 if (!(ptr
->flags
& UCI_LOOKUP_DONE
))
463 UCI_INTERNAL(uci_lookup_ptr
, ctx
, ptr
, NULL
, 1);
464 if (complete
&& !(ptr
->flags
& UCI_LOOKUP_COMPLETE
))
465 UCI_THROW(ctx
, UCI_ERR_NOTFOUND
);
466 UCI_ASSERT(ctx
, ptr
->p
!= NULL
);
468 /* fill in missing string info */
469 if (ptr
->p
&& !ptr
->package
)
470 ptr
->package
= ptr
->p
->e
.name
;
471 if (ptr
->s
&& !ptr
->section
)
472 ptr
->section
= ptr
->s
->e
.name
;
473 if (ptr
->o
&& !ptr
->option
)
474 ptr
->option
= ptr
->o
->e
.name
;
486 int uci_rename(struct uci_context
*ctx
, struct uci_ptr
*ptr
)
488 /* NB: UCI_INTERNAL use means without delta tracking */
489 bool internal
= ctx
&& ctx
->internal
;
490 struct uci_element
*e
;
491 struct uci_package
*p
;
496 e
= uci_expand_ptr(ctx
, ptr
, true);
499 UCI_ASSERT(ctx
, ptr
->s
);
500 UCI_ASSERT(ctx
, ptr
->value
);
502 if (!internal
&& p
->has_delta
)
503 uci_add_delta(ctx
, &p
->delta
, UCI_CMD_RENAME
, ptr
->section
, ptr
->option
, ptr
->value
);
505 n
= uci_strdup(ctx
, ptr
->value
);
509 if (e
->type
== UCI_TYPE_SECTION
)
510 uci_to_section(e
)->anonymous
= false;
515 int uci_reorder_section(struct uci_context
*ctx
, struct uci_section
*s
, int pos
)
517 struct uci_package
*p
= s
->package
;
518 bool internal
= ctx
&& ctx
->internal
;
519 bool changed
= false;
524 changed
= uci_list_set_pos(&s
->package
->sections
, &s
->e
.list
, pos
);
525 if (!internal
&& p
->has_delta
&& changed
) {
526 sprintf(order
, "%d", pos
);
527 uci_add_delta(ctx
, &p
->delta
, UCI_CMD_REORDER
, s
->e
.name
, NULL
, order
);
533 int uci_add_section(struct uci_context
*ctx
, struct uci_package
*p
, const char *type
, struct uci_section
**res
)
535 bool internal
= ctx
&& ctx
->internal
;
536 struct uci_section
*s
;
539 UCI_ASSERT(ctx
, p
!= NULL
);
540 s
= uci_alloc_section(p
, type
, NULL
, NULL
);
541 if (s
&& s
->anonymous
)
542 uci_fixup_section(ctx
, s
);
544 if (!internal
&& p
->has_delta
)
545 uci_add_delta(ctx
, &p
->delta
, UCI_CMD_ADD
, s
->e
.name
, NULL
, type
);
550 int uci_delete(struct uci_context
*ctx
, struct uci_ptr
*ptr
)
552 /* NB: pass on internal flag to uci_del_element */
553 bool internal
= ctx
&& ctx
->internal
;
554 struct uci_package
*p
;
555 struct uci_element
*e1
, *e2
, *tmp
;
560 e1
= uci_expand_ptr(ctx
, ptr
, true);
563 UCI_ASSERT(ctx
, ptr
->s
);
565 if (ptr
->o
&& ptr
->o
->type
== UCI_TYPE_LIST
&& ptr
->value
&& *ptr
->value
) {
566 if (!sscanf(ptr
->value
, "%d", &index
))
569 uci_foreach_element_safe(&ptr
->o
->v
.list
, tmp
, e2
) {
571 if (!internal
&& p
->has_delta
)
572 uci_add_delta(ctx
, &p
->delta
, UCI_CMD_REMOVE
, ptr
->section
, ptr
->option
, ptr
->value
);
573 uci_free_option(uci_to_option(e2
));
582 if (!internal
&& p
->has_delta
)
583 uci_add_delta(ctx
, &p
->delta
, UCI_CMD_REMOVE
, ptr
->section
, ptr
->option
, NULL
);
589 else if (ptr
->section
)
595 int uci_add_list(struct uci_context
*ctx
, struct uci_ptr
*ptr
)
597 /* NB: UCI_INTERNAL use means without delta tracking */
598 bool internal
= ctx
&& ctx
->internal
;
599 struct uci_element
*volatile e1
= NULL
, *volatile e2
= NULL
;
603 uci_expand_ptr(ctx
, ptr
, false);
604 UCI_ASSERT(ctx
, ptr
->s
);
605 UCI_ASSERT(ctx
, ptr
->value
);
607 if (ptr
->o
&& ptr
->o
->type
!= UCI_TYPE_LIST
&& ptr
->o
->type
!= UCI_TYPE_STRING
) {
608 UCI_THROW(ctx
, UCI_ERR_INVAL
);
611 /* create new item */
612 e1
= uci_alloc_generic(ctx
, UCI_TYPE_ITEM
, ptr
->value
, sizeof(struct uci_option
));
615 /* create new list */
616 UCI_TRAP_SAVE(ctx
, error
);
617 ptr
->o
= uci_alloc_list(ptr
->s
, ptr
->option
, NULL
);
618 UCI_TRAP_RESTORE(ctx
);
619 ptr
->last
= &ptr
->o
->e
;
620 } else if (ptr
->o
->type
== UCI_TYPE_STRING
) {
621 /* create new list and add old string value as item to list */
622 struct uci_option
*old
= ptr
->o
;
623 UCI_TRAP_SAVE(ctx
, error
);
624 e2
= uci_alloc_generic(ctx
, UCI_TYPE_ITEM
, old
->v
.string
, sizeof(struct uci_option
));
625 ptr
->o
= uci_alloc_list(ptr
->s
, ptr
->option
, &old
->e
.list
);
626 UCI_TRAP_RESTORE(ctx
);
627 uci_list_add(&ptr
->o
->v
.list
, &e2
->list
);
629 /* remove old option */
630 if (ptr
->option
== old
->e
.name
)
631 ptr
->option
= ptr
->o
->e
.name
;
632 uci_free_option(old
);
633 ptr
->last
= &ptr
->o
->e
;
636 /* add new item to list */
637 uci_list_add(&ptr
->o
->v
.list
, &e1
->list
);
639 if (!internal
&& ptr
->p
->has_delta
)
640 uci_add_delta(ctx
, &ptr
->p
->delta
, UCI_CMD_LIST_ADD
, ptr
->section
, ptr
->option
, ptr
->value
);
645 uci_free_element(e1
);
647 uci_free_element(e2
);
648 UCI_THROW(ctx
, ctx
->err
);
651 int uci_del_list(struct uci_context
*ctx
, struct uci_ptr
*ptr
)
653 /* NB: pass on internal flag to uci_del_element */
654 bool internal
= ctx
&& ctx
->internal
;
655 struct uci_element
*e
, *tmp
;
656 struct uci_package
*p
;
660 uci_expand_ptr(ctx
, ptr
, false);
661 UCI_ASSERT(ctx
, ptr
->s
);
662 UCI_ASSERT(ctx
, ptr
->value
);
664 if (!(ptr
->o
&& ptr
->option
))
667 if ((ptr
->o
->type
!= UCI_TYPE_LIST
))
671 if (!internal
&& p
->has_delta
)
672 uci_add_delta(ctx
, &p
->delta
, UCI_CMD_LIST_DEL
, ptr
->section
, ptr
->option
, ptr
->value
);
674 uci_foreach_element_safe(&ptr
->o
->v
.list
, tmp
, e
) {
675 if (!strcmp(ptr
->value
, uci_to_option(e
)->e
.name
)) {
676 uci_free_option(uci_to_option(e
));
683 int uci_set(struct uci_context
*ctx
, struct uci_ptr
*ptr
)
685 /* NB: UCI_INTERNAL use means without delta tracking */
686 bool internal
= ctx
&& ctx
->internal
;
689 uci_expand_ptr(ctx
, ptr
, false);
690 UCI_ASSERT(ctx
, ptr
->value
);
691 UCI_ASSERT(ctx
, ptr
->s
|| (!ptr
->option
&& ptr
->section
));
692 if (!ptr
->option
&& ptr
->value
[0]) {
693 UCI_ASSERT(ctx
, uci_validate_type(ptr
->value
));
696 if (!ptr
->o
&& ptr
->s
&& ptr
->option
) {
697 struct uci_element
*e
;
698 e
= uci_lookup_list(&ptr
->s
->options
, ptr
->option
);
700 ptr
->o
= uci_to_option(e
);
702 if (!ptr
->value
[0]) {
703 /* if setting a nonexistant option/section to a nonexistant value,
704 * exit without errors */
705 if (!(ptr
->flags
& UCI_LOOKUP_COMPLETE
))
708 return uci_delete(ctx
, ptr
);
709 } else if (!ptr
->o
&& ptr
->option
) { /* new option */
710 ptr
->o
= uci_alloc_option(ptr
->s
, ptr
->option
, ptr
->value
, NULL
);
711 ptr
->last
= &ptr
->o
->e
;
712 } else if (!ptr
->s
&& ptr
->section
) { /* new section */
713 ptr
->s
= uci_alloc_section(ptr
->p
, ptr
->value
, ptr
->section
, NULL
);
714 ptr
->last
= &ptr
->s
->e
;
715 } else if (ptr
->o
&& ptr
->option
) { /* update option */
716 if (ptr
->o
->type
== UCI_TYPE_STRING
&& !strcmp(ptr
->o
->v
.string
, ptr
->value
))
719 if (ptr
->o
->type
== UCI_TYPE_STRING
&& strlen(ptr
->o
->v
.string
) == strlen(ptr
->value
)) {
720 strcpy(ptr
->o
->v
.string
, ptr
->value
);
722 struct uci_option
*old
= ptr
->o
;
723 ptr
->o
= uci_alloc_option(ptr
->s
, ptr
->option
, ptr
->value
, &old
->e
.list
);
724 if (ptr
->option
== old
->e
.name
)
725 ptr
->option
= ptr
->o
->e
.name
;
726 uci_free_option(old
);
727 ptr
->last
= &ptr
->o
->e
;
729 } else if (ptr
->s
&& ptr
->section
) { /* update section */
730 if (!strcmp(ptr
->s
->type
, ptr
->value
))
733 if (strlen(ptr
->s
->type
) == strlen(ptr
->value
)) {
734 strcpy(ptr
->s
->type
, ptr
->value
);
736 struct uci_section
*old
= ptr
->s
;
737 ptr
->s
= uci_alloc_section(ptr
->p
, ptr
->value
, old
->e
.name
, &old
->e
.list
);
738 uci_section_transfer_options(ptr
->s
, old
);
739 if (ptr
->section
== old
->e
.name
)
740 ptr
->section
= ptr
->s
->e
.name
;
741 uci_free_section(old
);
742 ptr
->s
->package
->n_section
--;
743 ptr
->last
= &ptr
->s
->e
;
746 UCI_THROW(ctx
, UCI_ERR_INVAL
);
749 if (!internal
&& ptr
->p
->has_delta
)
750 uci_add_delta(ctx
, &ptr
->p
->delta
, UCI_CMD_CHANGE
, ptr
->section
, ptr
->option
, ptr
->value
);
755 int uci_unload(struct uci_context
*ctx
, struct uci_package
*p
)
758 UCI_ASSERT(ctx
, p
!= NULL
);
760 uci_free_package(&p
);