e2a6780ec5e1ccaab3e7a4a7c269c9480923b7ab
[project/mountd.git] / ucix.c
1 #include <string.h>
2 #include <stdlib.h>
3
4 #include "include/ucix.h"
5
6 static struct uci_ptr ptr;
7
8 static inline int ucix_get_ptr(struct uci_context *ctx, const char *p, const char *s, const char *o, const char *t)
9 {
10         memset(&ptr, 0, sizeof(ptr));
11         ptr.package = p;
12         ptr.section = s;
13         ptr.option = o;
14         ptr.value = t;
15         return uci_lookup_ptr(ctx, &ptr, NULL, true);
16 }
17
18 struct uci_context* ucix_init(const char *config_file)
19 {
20         struct uci_context *ctx = uci_alloc_context();
21         uci_add_delta_path(ctx, "/var/state");
22         if(uci_load(ctx, config_file, NULL) != UCI_OK)
23         {
24                 printf("%s/%s is missing or corrupt\n", ctx->savedir, config_file);
25                 return NULL;
26         }
27         return ctx;
28 }
29
30 struct uci_context* ucix_init_path(const char *path, const char *config_file)
31 {
32         struct uci_context *ctx = uci_alloc_context();
33         if(path)
34         {
35                 uci_set_savedir(ctx, path);
36         }
37         if(uci_load(ctx, config_file, NULL) != UCI_OK)
38         {
39                 printf("%s/%s is missing or corrupt\n", ctx->savedir, config_file);
40                 return NULL;
41         }
42         return ctx;
43 }
44
45 void ucix_cleanup(struct uci_context *ctx)
46 {
47         uci_free_context(ctx);
48 }
49
50 int ucix_save(struct uci_context *ctx, const char *p)
51 {
52         if(ucix_get_ptr(ctx, p, NULL, NULL, NULL))
53                 return 1;
54         uci_set_savedir(ctx, "/tmp/.uci/");
55         uci_save(ctx, ptr.p);
56         return 0;
57 }
58
59 int ucix_save_state(struct uci_context *ctx, const char *p)
60 {
61         if(ucix_get_ptr(ctx, p, NULL, NULL, NULL))
62                 return 1;
63         uci_set_savedir(ctx, "/var/state/");
64         uci_save(ctx, ptr.p);
65         return 0;
66 }
67
68 int ucix_get_option_list(struct uci_context *ctx, const char *p,
69         const char *s, const char *o, struct list_head *l)
70 {
71         struct uci_element *e = NULL;
72         if(ucix_get_ptr(ctx, p, s, o, NULL))
73                 return 1;
74         if (!(ptr.flags & UCI_LOOKUP_COMPLETE))
75                 return 1;
76         e = ptr.last;
77         switch (e->type)
78         {
79         case UCI_TYPE_OPTION:
80                 switch(ptr.o->type) {
81                         case UCI_TYPE_LIST:
82                                 uci_foreach_element(&ptr.o->v.list, e)
83                                 {
84                                         struct ucilist *ul = malloc(sizeof(struct ucilist));
85                                         ul->val = strdup((e->name)?(e->name):(""));
86                                         INIT_LIST_HEAD(&ul->list);
87                                         list_add(&ul->list, l);
88                                 }
89                                 break;
90                         default:
91                                 break;
92                 }
93                 break;
94         default:
95                 return 1;
96         }
97
98         return 0;
99 }
100
101 char* ucix_get_option(struct uci_context *ctx, const char *p, const char *s, const char *o)
102 {
103         struct uci_element *e = NULL;
104         const char *value = NULL;
105         if(ucix_get_ptr(ctx, p, s, o, NULL))
106                 return NULL;
107         if (!(ptr.flags & UCI_LOOKUP_COMPLETE))
108                 return NULL;
109         e = ptr.last;
110         switch (e->type)
111         {
112         case UCI_TYPE_SECTION:
113                 value = uci_to_section(e)->type;
114                 break;
115         case UCI_TYPE_OPTION:
116                 switch(ptr.o->type) {
117                         case UCI_TYPE_STRING:
118                                 value = ptr.o->v.string;
119                                 break;
120                         default:
121                                 value = NULL;
122                                 break;
123                 }
124                 break;
125         default:
126                 return 0;
127         }
128
129         return (value) ? (strdup(value)):(NULL);
130 }
131
132 int ucix_get_option_int(struct uci_context *ctx, const char *p, const char *s, const char *o, int def)
133 {
134         char *tmp = ucix_get_option(ctx, p, s, o);
135         int ret = def;
136
137         if (tmp)
138         {
139                 ret = atoi(tmp);
140                 free(tmp);
141         }
142         return ret;
143 }
144
145 void ucix_add_section(struct uci_context *ctx, const char *p, const char *s, const char *t)
146 {
147         if(ucix_get_ptr(ctx, p, s, NULL, t))
148                 return;
149         uci_set(ctx, &ptr);
150 }
151
152 void ucix_add_option(struct uci_context *ctx, const char *p, const char *s, const char *o, const char *t)
153 {
154         if(ucix_get_ptr(ctx, p, s, o, (t)?(t):("")))
155                 return;
156         uci_set(ctx, &ptr);
157 }
158
159 void ucix_add_option_int(struct uci_context *ctx, const char *p, const char *s, const char *o, int t)
160 {
161         char tmp[64];
162         snprintf(tmp, 64, "%d", t);
163         ucix_add_option(ctx, p, s, o, tmp);
164 }
165
166 void ucix_del(struct uci_context *ctx, const char *p, const char *s, const char *o)
167 {
168         if(!ucix_get_ptr(ctx, p, s, o, NULL))
169                 uci_delete(ctx, &ptr);
170 }
171
172 void ucix_revert(struct uci_context *ctx, const char *p, const char *s, const char *o)
173 {
174         if(!ucix_get_ptr(ctx, p, s, o, NULL))
175                 uci_revert(ctx, &ptr);
176 }
177
178 void ucix_for_each_section_type(struct uci_context *ctx,
179         const char *p, const char *t,
180         void (*cb)(const char*, void*), void *priv)
181 {
182         struct uci_element *e;
183         if(ucix_get_ptr(ctx, p, NULL, NULL, NULL))
184                 return;
185         uci_foreach_element(&ptr.p->sections, e)
186                 if (!strcmp(t, uci_to_section(e)->type))
187                         cb(e->name, priv);
188 }
189
190 void ucix_for_each_section_option(struct uci_context *ctx,
191         const char *p, const char *s,
192         void (*cb)(const char*, const char*, void*), void *priv)
193 {
194         struct uci_element *e;
195         if(ucix_get_ptr(ctx, p, s, NULL, NULL))
196                 return;
197         uci_foreach_element(&ptr.s->options, e)
198         {
199                 struct uci_option *o = uci_to_option(e);
200                 cb(o->e.name, o->v.string, priv);
201         }
202 }
203
204 int ucix_commit(struct uci_context *ctx, const char *p)
205 {
206         if(ucix_get_ptr(ctx, p, NULL, NULL, NULL))
207                 return 1;
208         return uci_commit(ctx, &ptr.p, false);
209 }