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 #if 0 /// UNNEEDED by elogind
174 char* service_name_startswith(const char *a, const char *b) {
177 if (!service_name_is_valid(a) ||
178 !service_name_is_valid(b))
181 p = startswith(a, b);
189 return (char*) p + 1;
195 bool member_name_is_valid(const char *p) {
201 for (q = p; *q; q++) {
205 (*q >= 'a' && *q <= 'z') ||
206 (*q >= 'A' && *q <= 'Z') ||
207 (*q >= '0' && *q <= '9') ||
221 * Complex pattern match
222 * This checks whether @a is a 'complex-prefix' of @b, or @b is a
223 * 'complex-prefix' of @a, based on strings that consist of labels with @c as
224 * spearator. This function returns true if:
225 * - both strings are equal
226 * - either is a prefix of the other and ends with @c
227 * The second rule makes sure that either string needs to be fully included in
228 * the other, and the string which is considered the prefix needs to end with a
231 static bool complex_pattern_check(char c, const char *a, const char *b) {
232 bool separator = false;
242 return (separator && (*a == 0 || *b == 0));
253 bool namespace_complex_pattern(const char *pattern, const char *value) {
254 return complex_pattern_check('.', pattern, value);
257 bool path_complex_pattern(const char *pattern, const char *value) {
258 return complex_pattern_check('/', pattern, value);
262 * Simple pattern match
263 * This checks whether @a is a 'simple-prefix' of @b, based on strings that
264 * consist of labels with @c as separator. This function returns true, if:
265 * - if @a and @b are equal
266 * - if @a is a prefix of @b, and the first following character in @b (or the
267 * last character in @a) is @c
268 * The second rule basically makes sure that if @a is a prefix of @b, then @b
269 * must follow with a new label separated by @c. It cannot extend the label.
271 static bool simple_pattern_check(char c, const char *a, const char *b) {
272 bool separator = false;
282 return *a == 0 && (*b == c || separator);
293 bool namespace_simple_pattern(const char *pattern, const char *value) {
294 return simple_pattern_check('.', pattern, value);
297 bool path_simple_pattern(const char *pattern, const char *value) {
298 return simple_pattern_check('/', pattern, value);
301 int bus_message_type_from_string(const char *s, uint8_t *u) {
302 if (streq(s, "signal"))
303 *u = SD_BUS_MESSAGE_SIGNAL;
304 else if (streq(s, "method_call"))
305 *u = SD_BUS_MESSAGE_METHOD_CALL;
306 else if (streq(s, "error"))
307 *u = SD_BUS_MESSAGE_METHOD_ERROR;
308 else if (streq(s, "method_return"))
309 *u = SD_BUS_MESSAGE_METHOD_RETURN;
316 const char *bus_message_type_to_string(uint8_t u) {
317 if (u == SD_BUS_MESSAGE_SIGNAL)
319 else if (u == SD_BUS_MESSAGE_METHOD_CALL)
320 return "method_call";
321 else if (u == SD_BUS_MESSAGE_METHOD_ERROR)
323 else if (u == SD_BUS_MESSAGE_METHOD_RETURN)
324 return "method_return";
329 char *bus_address_escape(const char *v) {
333 r = new(char, strlen(v)*3+1);
337 for (a = v, b = r; *a; a++) {
339 if ((*a >= '0' && *a <= '9') ||
340 (*a >= 'a' && *a <= 'z') ||
341 (*a >= 'A' && *a <= 'Z') ||
346 *(b++) = hexchar(*a >> 4);
347 *(b++) = hexchar(*a & 0xF);
355 int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error) {
359 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
360 sd_bus_reply_method_errno(m, r, error);
362 } else if (sd_bus_error_is_set(error)) {
363 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
364 sd_bus_reply_method_error(m, error);
368 log_debug("Failed to process message [type=%s sender=%s path=%s interface=%s member=%s signature=%s]: %s",
369 bus_message_type_to_string(m->header->type),
374 strna(m->root_container.signature),
375 bus_error_message(error, r));