service: get rid of service_init and service_validate_init, use static avl tree initi...
[project/procd.git] / service / validate.c
1 /*
2 * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 2.1
6 * as published by the Free Software Foundation
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14 #include <libubox/blobmsg_json.h>
15 #include <libubox/avl-cmp.h>
16 #include <json-c/json.h>
17
18 #include "../procd.h"
19
20 #include "service.h"
21
22 enum {
23 SERVICE_VAL_PACKAGE,
24 SERVICE_VAL_TYPE,
25 SERVICE_VAL_DATA,
26 __SERVICE_VAL_MAX
27 };
28
29 static const struct blobmsg_policy service_validate_attrs[__SERVICE_VAL_MAX] = {
30 [SERVICE_VAL_PACKAGE] = { "package", BLOBMSG_TYPE_STRING },
31 [SERVICE_VAL_TYPE] = { "type", BLOBMSG_TYPE_STRING },
32 [SERVICE_VAL_DATA] = { "data", BLOBMSG_TYPE_TABLE },
33 };
34
35 static AVL_TREE(validators, avl_strcmp, true, NULL);
36
37 void
38 service_validate_dump_all(struct blob_buf *b, char *p, char *s)
39 {
40 struct json_object *r = json_object_new_object();
41 struct validate *v;
42
43 if (!r)
44 return;
45
46 avl_for_each_element(&validators, v, avl) {
47 struct json_object *o, *t;
48 struct vrule *vr;
49
50 if (p && strcmp(p, v->package))
51 continue;
52
53 if (s && strcmp(s, v->type))
54 continue;
55
56 json_object_object_get_ex(r, v->package, &o);
57 if (!o) {
58 o = json_object_new_object();
59 json_object_object_add(r, v->package, o);
60 }
61 json_object_object_get_ex(o, v->type, &t);
62 if (!t) {
63 t = json_object_new_object();
64 json_object_object_add(o, v->type, t);
65 }
66 avl_for_each_element(&v->rules, vr, avl)
67 json_object_object_add(t, vr->option, json_object_new_string(vr->rule));
68 }
69 blobmsg_add_object(b, r);
70 json_object_put(r);
71 }
72
73 void
74 service_validate_dump(struct blob_buf *b, struct service *s)
75 {
76 struct validate *v;
77 void *i = blobmsg_open_array(b, "validate");
78
79 list_for_each_entry(v, &s->validators, list) {
80 struct vrule *vr;
81 void *k, *j = blobmsg_open_table(b, "validate");
82
83 blobmsg_add_string(b, "package", v->package);
84 blobmsg_add_string(b, "type", v->type);
85 k = blobmsg_open_table(b, "rules");
86 avl_for_each_element(&v->rules, vr, avl)
87 blobmsg_add_string(b, vr->option, vr->rule);
88 blobmsg_close_table(b, k);
89 blobmsg_close_table(b, j);
90 }
91 blobmsg_close_array(b, i);
92 }
93
94 void
95 service_validate_del(struct service *s)
96 {
97 struct validate *v, *n;
98
99 if (list_empty(&s->validators))
100 return;
101
102 list_for_each_entry_safe(v, n, &s->validators, list) {
103 struct vrule *vr, *a;
104
105 avl_remove_all_elements(&v->rules, vr, avl, a)
106 free(vr);
107
108 avl_delete(&validators, &v->avl);
109 list_del(&v->list);
110 free(v);
111 }
112 }
113
114 void
115 service_validate_add(struct service *s, struct blob_attr *msg)
116 {
117 struct blob_attr *tb[__SERVICE_VAL_MAX];
118 struct validate *v;
119 char *type, *package;
120 struct blob_attr *cur;
121 int rem;
122
123 blobmsg_parse(service_validate_attrs, __SERVICE_VAL_MAX, tb, blobmsg_data(msg), blobmsg_data_len(msg));
124 if (!tb[SERVICE_VAL_PACKAGE] || !tb[SERVICE_VAL_TYPE] || !tb[SERVICE_VAL_DATA])
125 return;
126
127 v = calloc_a(sizeof(*v), &package, blobmsg_data_len(tb[SERVICE_VAL_PACKAGE]) + 1,
128 &type, blobmsg_data_len(tb[SERVICE_VAL_TYPE]) + 1);
129 if (!v)
130 return;
131
132 v->type = type;
133 v->avl.key = v->package = package;
134 strcpy(v->package, blobmsg_get_string(tb[SERVICE_VAL_PACKAGE]));
135 strcpy(v->type, blobmsg_get_string(tb[SERVICE_VAL_TYPE]));
136
137 list_add(&v->list, &s->validators);
138 if (avl_insert(&validators, &v->avl)) {
139 free(v);
140 return;
141 }
142 avl_init(&v->rules, avl_strcmp, false, NULL);
143
144 blobmsg_for_each_attr(cur, tb[SERVICE_VAL_DATA], rem) {
145 char *option;
146 char *rule;
147 struct vrule *vr = calloc_a(sizeof(*vr), &option, strlen(blobmsg_name(cur)) + 1,
148 &rule, strlen(blobmsg_get_string(cur)) + 1);
149
150 vr->avl.key = vr->option = option;
151 vr->rule = rule;
152 strcpy(vr->option, blobmsg_name(cur));
153 strcpy(vr->rule, blobmsg_get_string(cur));
154 if (avl_insert(&v->rules, &vr->avl))
155 free(vr);
156 }
157 }