1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
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.
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.
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/>.
22 #include "bus-internal.h"
24 bool object_path_is_valid(const char *p) {
37 for (slash = true, q = p+1; *q; q++)
47 (*q >= 'a' && *q <= 'z') ||
48 (*q >= 'A' && *q <= 'Z') ||
49 (*q >= '0' && *q <= '9') ||
64 char* object_path_startswith(const char *a, const char *b) {
67 if (!object_path_is_valid(a) ||
68 !object_path_is_valid(b))
87 bool interface_name_is_valid(const char *p) {
89 bool dot, found_dot = false;
94 for (dot = true, q = p; *q; q++)
99 found_dot = dot = true;
104 (*q >= 'a' && *q <= 'z') ||
105 (*q >= 'A' && *q <= 'Z') ||
106 (!dot && *q >= '0' && *q <= '9') ||
127 bool service_name_is_valid(const char *p) {
129 bool dot, found_dot = false, unique;
134 unique = p[0] == ':';
136 for (dot = true, q = unique ? p+1 : p; *q; q++)
141 found_dot = dot = true;
146 (*q >= 'a' && *q <= 'z') ||
147 (*q >= 'A' && *q <= 'Z') ||
148 ((!dot || unique) && *q >= '0' && *q <= '9') ||
149 *q == '_' || *q == '-';
169 char* service_name_startswith(const char *a, const char *b) {
172 if (!service_name_is_valid(a) ||
173 !service_name_is_valid(b))
176 p = startswith(a, b);
184 return (char*) p + 1;
189 bool member_name_is_valid(const char *p) {
195 for (q = p; *q; q++) {
199 (*q >= 'a' && *q <= 'z') ||
200 (*q >= 'A' && *q <= 'Z') ||
201 (*q >= '0' && *q <= '9') ||
215 * Complex pattern match
216 * This checks whether @a is a 'complex-prefix' of @b, or @b is a
217 * 'complex-prefix' of @a, based on strings that consist of labels with @c as
218 * spearator. This function returns true if:
219 * - both strings are equal
220 * - either is a prefix of the other and ends with @c
221 * The second rule makes sure that either string needs to be fully included in
222 * the other, and the string which is considered the prefix needs to end with a
225 static bool complex_pattern_check(char c, const char *a, const char *b) {
226 bool separator = false;
236 return (separator && (*a == 0 || *b == 0));
247 bool namespace_complex_pattern(const char *pattern, const char *value) {
248 return complex_pattern_check('.', pattern, value);
251 bool path_complex_pattern(const char *pattern, const char *value) {
252 return complex_pattern_check('/', pattern, value);
256 * Simple pattern match
257 * This checks whether @a is a 'simple-prefix' of @b, based on strings that
258 * consist of labels with @c as separator. This function returns true, if:
259 * - if @a and @b are equal
260 * - if @a is a prefix of @b, and the first following character in @b (or the
261 * last character in @a) is @c
262 * The second rule basically makes sure that if @a is a prefix of @b, then @b
263 * must follow with a new label separated by @c. It cannot extend the label.
265 static bool simple_pattern_check(char c, const char *a, const char *b) {
266 bool separator = false;
276 return *a == 0 && (*b == c || separator);
287 bool namespace_simple_pattern(const char *pattern, const char *value) {
288 return simple_pattern_check('.', pattern, value);
291 bool path_simple_pattern(const char *pattern, const char *value) {
292 return simple_pattern_check('/', pattern, value);
295 int bus_message_type_from_string(const char *s, uint8_t *u) {
296 if (streq(s, "signal"))
297 *u = SD_BUS_MESSAGE_SIGNAL;
298 else if (streq(s, "method_call"))
299 *u = SD_BUS_MESSAGE_METHOD_CALL;
300 else if (streq(s, "error"))
301 *u = SD_BUS_MESSAGE_METHOD_ERROR;
302 else if (streq(s, "method_return"))
303 *u = SD_BUS_MESSAGE_METHOD_RETURN;
310 const char *bus_message_type_to_string(uint8_t u) {
311 if (u == SD_BUS_MESSAGE_SIGNAL)
313 else if (u == SD_BUS_MESSAGE_METHOD_CALL)
314 return "method_call";
315 else if (u == SD_BUS_MESSAGE_METHOD_ERROR)
317 else if (u == SD_BUS_MESSAGE_METHOD_RETURN)
318 return "method_return";
323 char *bus_address_escape(const char *v) {
327 r = new(char, strlen(v)*3+1);
331 for (a = v, b = r; *a; a++) {
333 if ((*a >= '0' && *a <= '9') ||
334 (*a >= 'a' && *a <= 'z') ||
335 (*a >= 'A' && *a <= 'Z') ||
340 *(b++) = hexchar(*a >> 4);
341 *(b++) = hexchar(*a & 0xF);