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 "alloc-util.h"
23 #include "bus-internal.h"
24 #include "bus-message.h"
25 #include "hexdecoct.h"
26 #include "string-util.h"
28 bool object_path_is_valid(const char *p) {
41 for (slash = true, q = p+1; *q; q++)
51 (*q >= 'a' && *q <= 'z') ||
52 (*q >= 'A' && *q <= 'Z') ||
53 (*q >= '0' && *q <= '9') ||
68 char* object_path_startswith(const char *a, const char *b) {
71 if (!object_path_is_valid(a) ||
72 !object_path_is_valid(b))
91 bool interface_name_is_valid(const char *p) {
93 bool dot, found_dot = false;
98 for (dot = true, q = p; *q; q++)
103 found_dot = dot = true;
108 (*q >= 'a' && *q <= 'z') ||
109 (*q >= 'A' && *q <= 'Z') ||
110 (!dot && *q >= '0' && *q <= '9') ||
131 bool service_name_is_valid(const char *p) {
133 bool dot, found_dot = false, unique;
138 unique = p[0] == ':';
140 for (dot = true, q = unique ? p+1 : p; *q; q++)
145 found_dot = dot = true;
150 (*q >= 'a' && *q <= 'z') ||
151 (*q >= 'A' && *q <= 'Z') ||
152 ((!dot || unique) && *q >= '0' && *q <= '9') ||
153 *q == '_' || *q == '-';
173 /// UNNEEDED by elogind
175 char* service_name_startswith(const char *a, const char *b) {
178 if (!service_name_is_valid(a) ||
179 !service_name_is_valid(b))
182 p = startswith(a, b);
190 return (char*) p + 1;
196 bool member_name_is_valid(const char *p) {
202 for (q = p; *q; q++) {
206 (*q >= 'a' && *q <= 'z') ||
207 (*q >= 'A' && *q <= 'Z') ||
208 (*q >= '0' && *q <= '9') ||
222 * Complex pattern match
223 * This checks whether @a is a 'complex-prefix' of @b, or @b is a
224 * 'complex-prefix' of @a, based on strings that consist of labels with @c as
225 * spearator. This function returns true if:
226 * - both strings are equal
227 * - either is a prefix of the other and ends with @c
228 * The second rule makes sure that either string needs to be fully included in
229 * the other, and the string which is considered the prefix needs to end with a
232 static bool complex_pattern_check(char c, const char *a, const char *b) {
233 bool separator = false;
243 return (separator && (*a == 0 || *b == 0));
254 bool namespace_complex_pattern(const char *pattern, const char *value) {
255 return complex_pattern_check('.', pattern, value);
258 bool path_complex_pattern(const char *pattern, const char *value) {
259 return complex_pattern_check('/', pattern, value);
263 * Simple pattern match
264 * This checks whether @a is a 'simple-prefix' of @b, based on strings that
265 * consist of labels with @c as separator. This function returns true, if:
266 * - if @a and @b are equal
267 * - if @a is a prefix of @b, and the first following character in @b (or the
268 * last character in @a) is @c
269 * The second rule basically makes sure that if @a is a prefix of @b, then @b
270 * must follow with a new label separated by @c. It cannot extend the label.
272 static bool simple_pattern_check(char c, const char *a, const char *b) {
273 bool separator = false;
283 return *a == 0 && (*b == c || separator);
294 bool namespace_simple_pattern(const char *pattern, const char *value) {
295 return simple_pattern_check('.', pattern, value);
298 bool path_simple_pattern(const char *pattern, const char *value) {
299 return simple_pattern_check('/', pattern, value);
302 int bus_message_type_from_string(const char *s, uint8_t *u) {
303 if (streq(s, "signal"))
304 *u = SD_BUS_MESSAGE_SIGNAL;
305 else if (streq(s, "method_call"))
306 *u = SD_BUS_MESSAGE_METHOD_CALL;
307 else if (streq(s, "error"))
308 *u = SD_BUS_MESSAGE_METHOD_ERROR;
309 else if (streq(s, "method_return"))
310 *u = SD_BUS_MESSAGE_METHOD_RETURN;
317 const char *bus_message_type_to_string(uint8_t u) {
318 if (u == SD_BUS_MESSAGE_SIGNAL)
320 else if (u == SD_BUS_MESSAGE_METHOD_CALL)
321 return "method_call";
322 else if (u == SD_BUS_MESSAGE_METHOD_ERROR)
324 else if (u == SD_BUS_MESSAGE_METHOD_RETURN)
325 return "method_return";
330 char *bus_address_escape(const char *v) {
334 r = new(char, strlen(v)*3+1);
338 for (a = v, b = r; *a; a++) {
340 if ((*a >= '0' && *a <= '9') ||
341 (*a >= 'a' && *a <= 'z') ||
342 (*a >= 'A' && *a <= 'Z') ||
347 *(b++) = hexchar(*a >> 4);
348 *(b++) = hexchar(*a & 0xF);
356 int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error) {
360 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
361 sd_bus_reply_method_errno(m, r, error);
363 } else if (sd_bus_error_is_set(error)) {
364 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
365 sd_bus_reply_method_error(m, error);
369 log_debug("Failed to process message [type=%s sender=%s path=%s interface=%s member=%s signature=%s]: %s",
370 bus_message_type_to_string(m->header->type),
375 strna(m->root_container.signature),
376 bus_error_message(error, r));