Initial import
[project/libubox.git] / ucix.c
1 /*
2 * ucix
3 * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
4 * Copyright (C) 2010 Steven Barth <steven@midlink.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
19 *
20 */
21
22 #include <string.h>
23 #include <stdlib.h>
24
25 #include "ucix.h"
26
27 struct uci_ptr uci_ptr;
28
29 int ucix_get_ptr(struct uci_context *ctx, const char *p, const char *s, const char *o, const char *t)
30 {
31 memset(&uci_ptr, 0, sizeof(uci_ptr));
32 uci_ptr.package = p;
33 uci_ptr.section = s;
34 uci_ptr.option = o;
35 uci_ptr.value = t;
36 return uci_lookup_ptr(ctx, &uci_ptr, NULL, true);
37 }
38
39 struct uci_context* ucix_init(const char *config_file, int state)
40 {
41 struct uci_context *ctx = uci_alloc_context();
42 uci_set_confdir(ctx, "/etc/config");
43 if(state)
44 uci_set_savedir(ctx, "/var/state/");
45 else
46 uci_set_savedir(ctx, "/tmp/.uci/");
47 if(uci_load(ctx, config_file, NULL) != UCI_OK)
48 {
49 printf("%s/%s is missing or corrupt\n", ctx->confdir, config_file);
50 return NULL;
51 }
52 return ctx;
53 }
54
55 struct uci_context* ucix_init_path(const char *vpath, const char *config_file, int state)
56 {
57 struct uci_context *ctx;
58 char buf[256];
59 if(!vpath)
60 return ucix_init(config_file, state);
61 ctx = uci_alloc_context();
62 buf[255] = '\0';
63 snprintf(buf, 255, "%s%s", vpath, "/etc/config");
64 uci_set_confdir(ctx, buf);
65 snprintf(buf, 255, "%s%s", vpath, (state)?("/var/state"):("/tmp/.uci"));
66 uci_add_delta_path(ctx, buf);
67 if(uci_load(ctx, config_file, NULL) != UCI_OK)
68 {
69 printf("%s/%s is missing or corrupt\n", ctx->confdir, config_file);
70 return NULL;
71 }
72 return ctx;
73 }
74
75 int ucix_get_option_list(struct uci_context *ctx, const char *p,
76 const char *s, const char *o, struct list_head *l)
77 {
78 struct uci_element *e = NULL;
79 if(ucix_get_ptr(ctx, p, s, o, NULL))
80 return 1;
81 if (!(uci_ptr.flags & UCI_LOOKUP_COMPLETE))
82 return 1;
83 e = uci_ptr.last;
84 switch (e->type)
85 {
86 case UCI_TYPE_OPTION:
87 switch(uci_ptr.o->type) {
88 case UCI_TYPE_LIST:
89 uci_foreach_element(&uci_ptr.o->v.list, e)
90 {
91 struct ucilist *ul = malloc(sizeof(struct ucilist));
92 ul->val = strdup((e->name)?(e->name):(""));
93 list_add_tail(&ul->list, l);
94 }
95 break;
96 default:
97 break;
98 }
99 break;
100 default:
101 return 1;
102 }
103
104 return 0;
105 }
106
107 char* ucix_get_option(struct uci_context *ctx, const char *p, const char *s, const char *o)
108 {
109 struct uci_element *e = NULL;
110 const char *value = NULL;
111 if(ucix_get_ptr(ctx, p, s, o, NULL))
112 return NULL;
113 if (!(uci_ptr.flags & UCI_LOOKUP_COMPLETE))
114 return NULL;
115 e = uci_ptr.last;
116 switch (e->type)
117 {
118 case UCI_TYPE_SECTION:
119 value = uci_to_section(e)->type;
120 break;
121 case UCI_TYPE_OPTION:
122 switch(uci_ptr.o->type) {
123 case UCI_TYPE_STRING:
124 value = uci_ptr.o->v.string;
125 break;
126 default:
127 value = NULL;
128 break;
129 }
130 break;
131 default:
132 return 0;
133 }
134
135 return (value) ? (strdup(value)):(NULL);
136 }
137
138 void ucix_add_list(struct uci_context *ctx, const char *p, const char *s, const char *o, struct list_head *vals)
139 {
140 struct list_head *q;
141 list_for_each(q, vals)
142 {
143 struct ucilist *ul = container_of(q, struct ucilist, list);
144 if(ucix_get_ptr(ctx, p, s, o, (ul->val)?(ul->val):("")))
145 return;
146 uci_add_list(ctx, &uci_ptr);
147 }
148 }
149
150 void ucix_for_each_section_type(struct uci_context *ctx,
151 const char *p, const char *t,
152 void (*cb)(const char*, void*), void *priv)
153 {
154 struct uci_element *e;
155 if(ucix_get_ptr(ctx, p, NULL, NULL, NULL))
156 return;
157 uci_foreach_element(&uci_ptr.p->sections, e)
158 if (!strcmp(t, uci_to_section(e)->type))
159 cb(e->name, priv);
160 }
161
162 void ucix_for_each_section_option(struct uci_context *ctx,
163 const char *p, const char *s,
164 void (*cb)(const char*, const char*, void*), void *priv)
165 {
166 struct uci_element *e;
167 if(ucix_get_ptr(ctx, p, s, NULL, NULL))
168 return;
169 uci_foreach_element(&uci_ptr.s->options, e)
170 {
171 struct uci_option *o = uci_to_option(e);
172 cb(o->e.name, o->v.string, priv);
173 }
174 }
175
176