]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-bus/bus-internal.c
tmpfiles: accurately report creation results
[thirdparty/systemd.git] / src / libsystemd / sd-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 char* service_name_startswith(const char *a, const char *b) {
170 const char *p;
171
172 if (!service_name_is_valid(a) ||
173 !service_name_is_valid(b))
174 return NULL;
175
176 p = startswith(a, b);
177 if (!p)
178 return NULL;
179
180 if (*p == 0)
181 return (char*) p;
182
183 if (*p == '.')
184 return (char*) p + 1;
185
186 return NULL;
187 }
188
189 bool member_name_is_valid(const char *p) {
190 const char *q;
191
192 if (isempty(p))
193 return false;
194
195 for (q = p; *q; q++) {
196 bool good;
197
198 good =
199 (*q >= 'a' && *q <= 'z') ||
200 (*q >= 'A' && *q <= 'Z') ||
201 (*q >= '0' && *q <= '9') ||
202 *q == '_';
203
204 if (!good)
205 return false;
206 }
207
208 if (q - p > 255)
209 return false;
210
211 return true;
212 }
213
214 static bool complex_pattern_check(char c, const char *a, const char *b) {
215 bool separator = false;
216
217 if (!a && !b)
218 return true;
219
220 if (!a || !b)
221 return false;
222
223 for (;;) {
224 if (*a != *b)
225 return (separator && (*a == 0 || *b == 0)) ||
226 (*a == 0 && *b == c && b[1] == 0) ||
227 (*b == 0 && *a == c && a[1] == 0);
228
229 if (*a == 0)
230 return true;
231
232 separator = *a == c;
233
234 a++, b++;
235 }
236 }
237
238 bool namespace_complex_pattern(const char *pattern, const char *value) {
239 return complex_pattern_check('.', pattern, value);
240 }
241
242 bool path_complex_pattern(const char *pattern, const char *value) {
243 return complex_pattern_check('/', pattern, value);
244 }
245
246 static bool simple_pattern_check(char c, const char *a, const char *b) {
247
248 if (!a && !b)
249 return true;
250
251 if (!a || !b)
252 return false;
253
254 for (;;) {
255 if (*a != *b)
256 return *a == 0 && *b == c;
257
258 if (*a == 0)
259 return true;
260
261 a++, b++;
262 }
263 }
264
265 bool namespace_simple_pattern(const char *pattern, const char *value) {
266 return simple_pattern_check('.', pattern, value);
267 }
268
269 bool path_simple_pattern(const char *pattern, const char *value) {
270 return simple_pattern_check('/', pattern, value);
271 }
272
273 int bus_message_type_from_string(const char *s, uint8_t *u) {
274 if (streq(s, "signal"))
275 *u = SD_BUS_MESSAGE_SIGNAL;
276 else if (streq(s, "method_call"))
277 *u = SD_BUS_MESSAGE_METHOD_CALL;
278 else if (streq(s, "error"))
279 *u = SD_BUS_MESSAGE_METHOD_ERROR;
280 else if (streq(s, "method_return"))
281 *u = SD_BUS_MESSAGE_METHOD_RETURN;
282 else
283 return -EINVAL;
284
285 return 0;
286 }
287
288 const char *bus_message_type_to_string(uint8_t u) {
289 if (u == SD_BUS_MESSAGE_SIGNAL)
290 return "signal";
291 else if (u == SD_BUS_MESSAGE_METHOD_CALL)
292 return "method_call";
293 else if (u == SD_BUS_MESSAGE_METHOD_ERROR)
294 return "error";
295 else if (u == SD_BUS_MESSAGE_METHOD_RETURN)
296 return "method_return";
297 else
298 return NULL;
299 }
300
301 char *bus_address_escape(const char *v) {
302 const char *a;
303 char *r, *b;
304
305 r = new(char, strlen(v)*3+1);
306 if (!r)
307 return NULL;
308
309 for (a = v, b = r; *a; a++) {
310
311 if ((*a >= '0' && *a <= '9') ||
312 (*a >= 'a' && *a <= 'z') ||
313 (*a >= 'A' && *a <= 'Z') ||
314 strchr("_-/.", *a))
315 *(b++) = *a;
316 else {
317 *(b++) = '%';
318 *(b++) = hexchar(*a >> 4);
319 *(b++) = hexchar(*a & 0xF);
320 }
321 }
322
323 *b = 0;
324 return r;
325 }