]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd-bus/bus-internal.c
bus: we really need to get rid of the :no-sender hack
[thirdparty/systemd.git] / src / libsystemd-bus / bus-internal.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2013 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include "bus-internal.h"
23
24 bool object_path_is_valid(const char *p) {
25 const char *q;
26 bool slash;
27
28 if (!p)
29 return false;
30
31 if (p[0] != '/')
32 return false;
33
34 if (p[1] == 0)
35 return true;
36
37 for (slash = true, q = p+1; *q; q++)
38 if (*q == '/') {
39 if (slash)
40 return false;
41
42 slash = true;
43 } else {
44 bool good;
45
46 good =
47 (*q >= 'a' && *q <= 'z') ||
48 (*q >= 'A' && *q <= 'Z') ||
49 (*q >= '0' && *q <= '9') ||
50 *q == '_';
51
52 if (!good)
53 return false;
54
55 slash = false;
56 }
57
58 if (slash)
59 return false;
60
61 return true;
62 }
63
64 char* object_path_startswith(const char *a, const char *b) {
65 const char *p;
66
67 if (!object_path_is_valid(a) ||
68 !object_path_is_valid(b))
69 return NULL;
70
71 if (streq(b, "/"))
72 return (char*) a + 1;
73
74 p = startswith(a, b);
75 if (!p)
76 return NULL;
77
78 if (*p == 0)
79 return (char*) p;
80
81 if (*p == '/')
82 return (char*) p + 1;
83
84 return NULL;
85 }
86
87 bool interface_name_is_valid(const char *p) {
88 const char *q;
89 bool dot, found_dot = false;
90
91 if (isempty(p))
92 return false;
93
94 for (dot = true, q = p; *q; q++)
95 if (*q == '.') {
96 if (dot)
97 return false;
98
99 found_dot = dot = true;
100 } else {
101 bool good;
102
103 good =
104 (*q >= 'a' && *q <= 'z') ||
105 (*q >= 'A' && *q <= 'Z') ||
106 (!dot && *q >= '0' && *q <= '9') ||
107 *q == '_';
108
109 if (!good)
110 return false;
111
112 dot = false;
113 }
114
115 if (q - p > 255)
116 return false;
117
118 if (dot)
119 return false;
120
121 if (!found_dot)
122 return false;
123
124 return true;
125 }
126
127 bool service_name_is_valid(const char *p) {
128 const char *q;
129 bool dot, found_dot = false, unique;
130
131 if (isempty(p))
132 return false;
133
134 unique = p[0] == ':';
135
136 for (dot = true, q = unique ? p+1 : p; *q; q++)
137 if (*q == '.') {
138 if (dot)
139 return false;
140
141 found_dot = dot = true;
142 } else {
143 bool good;
144
145 good =
146 (*q >= 'a' && *q <= 'z') ||
147 (*q >= 'A' && *q <= 'Z') ||
148 ((!dot || unique) && *q >= '0' && *q <= '9') ||
149 *q == '_' || *q == '-';
150
151 if (!good)
152 return false;
153
154 dot = false;
155 }
156
157 if (q - p > 255)
158 return false;
159
160 if (dot)
161 return false;
162
163 if (!found_dot)
164 return false;
165
166 return true;
167 }
168
169 bool sender_name_is_valid(const char *p) {
170 if (isempty(p))
171 return false;
172
173 /* FIXME: remove after PID 1 bus conversion */
174 if (streq(p, ":no-sender"))
175 return true;
176
177 return service_name_is_valid(p);
178 }
179
180 bool member_name_is_valid(const char *p) {
181 const char *q;
182
183 if (isempty(p))
184 return false;
185
186 for (q = p; *q; q++) {
187 bool good;
188
189 good =
190 (*q >= 'a' && *q <= 'z') ||
191 (*q >= 'A' && *q <= 'Z') ||
192 (*q >= '0' && *q <= '9') ||
193 *q == '_';
194
195 if (!good)
196 return false;
197 }
198
199 if (q - p > 255)
200 return false;
201
202 return true;
203 }
204
205 static bool complex_pattern_check(char c, const char *a, const char *b) {
206 bool separator = false;
207
208 if (!a && !b)
209 return true;
210
211 if (!a || !b)
212 return false;
213
214 for (;;) {
215 if (*a != *b)
216 return (separator && (*a == 0 || *b == 0)) ||
217 (*a == 0 && *b == c && b[1] == 0) ||
218 (*b == 0 && *a == c && a[1] == 0);
219
220 if (*a == 0)
221 return true;
222
223 separator = *a == c;
224
225 a++, b++;
226 }
227 }
228
229 bool namespace_complex_pattern(const char *pattern, const char *value) {
230 return complex_pattern_check('.', pattern, value);
231 }
232
233 bool path_complex_pattern(const char *pattern, const char *value) {
234 return complex_pattern_check('/', pattern, value);
235 }
236
237 static bool simple_pattern_check(char c, const char *a, const char *b) {
238
239 if (!a && !b)
240 return true;
241
242 if (!a || !b)
243 return false;
244
245 for (;;) {
246 if (*a != *b)
247 return *a == 0 && *b == c;
248
249 if (*a == 0)
250 return true;
251
252 a++, b++;
253 }
254 }
255
256 bool namespace_simple_pattern(const char *pattern, const char *value) {
257 return simple_pattern_check('.', pattern, value);
258 }
259
260 bool path_simple_pattern(const char *pattern, const char *value) {
261 return simple_pattern_check('/', pattern, value);
262 }
263
264 int bus_message_type_from_string(const char *s, uint8_t *u) {
265 if (streq(s, "signal"))
266 *u = SD_BUS_MESSAGE_SIGNAL;
267 else if (streq(s, "method_call"))
268 *u = SD_BUS_MESSAGE_METHOD_CALL;
269 else if (streq(s, "error"))
270 *u = SD_BUS_MESSAGE_METHOD_ERROR;
271 else if (streq(s, "method_return"))
272 *u = SD_BUS_MESSAGE_METHOD_RETURN;
273 else
274 return -EINVAL;
275
276 return 0;
277 }
278
279 const char *bus_message_type_to_string(uint8_t u) {
280 if (u == SD_BUS_MESSAGE_SIGNAL)
281 return "signal";
282 else if (u == SD_BUS_MESSAGE_METHOD_CALL)
283 return "method_call";
284 else if (u == SD_BUS_MESSAGE_METHOD_ERROR)
285 return "error";
286 else if (u == SD_BUS_MESSAGE_METHOD_RETURN)
287 return "method_return";
288 else
289 return NULL;
290 }
291
292 char *bus_address_escape(const char *v) {
293 const char *a;
294 char *r, *b;
295
296 r = new(char, strlen(v)*3+1);
297 if (!r)
298 return NULL;
299
300 for (a = v, b = r; *a; a++) {
301
302 if ((*a >= '0' && *a <= '9') ||
303 (*a >= 'a' && *a <= 'z') ||
304 (*a >= 'A' && *a <= 'Z') ||
305 strchr("_-/.", *a))
306 *(b++) = *a;
307 else {
308 *(b++) = '%';
309 *(b++) = hexchar(*a >> 4);
310 *(b++) = hexchar(*a & 0xF);
311 }
312 }
313
314 *b = 0;
315 return r;
316 }