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"
23 #include "bus-message.h"
24 #include "string-util.h"
26 bool object_path_is_valid(const char *p
) {
39 for (slash
= true, q
= p
+1; *q
; q
++)
49 (*q
>= 'a' && *q
<= 'z') ||
50 (*q
>= 'A' && *q
<= 'Z') ||
51 (*q
>= '0' && *q
<= '9') ||
66 char* object_path_startswith(const char *a
, const char *b
) {
69 if (!object_path_is_valid(a
) ||
70 !object_path_is_valid(b
))
89 bool interface_name_is_valid(const char *p
) {
91 bool dot
, found_dot
= false;
96 for (dot
= true, q
= p
; *q
; q
++)
101 found_dot
= dot
= true;
106 (*q
>= 'a' && *q
<= 'z') ||
107 (*q
>= 'A' && *q
<= 'Z') ||
108 (!dot
&& *q
>= '0' && *q
<= '9') ||
129 bool service_name_is_valid(const char *p
) {
131 bool dot
, found_dot
= false, unique
;
136 unique
= p
[0] == ':';
138 for (dot
= true, q
= unique
? p
+1 : p
; *q
; q
++)
143 found_dot
= dot
= true;
148 (*q
>= 'a' && *q
<= 'z') ||
149 (*q
>= 'A' && *q
<= 'Z') ||
150 ((!dot
|| unique
) && *q
>= '0' && *q
<= '9') ||
151 *q
== '_' || *q
== '-';
171 char* service_name_startswith(const char *a
, const char *b
) {
174 if (!service_name_is_valid(a
) ||
175 !service_name_is_valid(b
))
178 p
= startswith(a
, b
);
186 return (char*) p
+ 1;
191 bool member_name_is_valid(const char *p
) {
197 for (q
= p
; *q
; q
++) {
201 (*q
>= 'a' && *q
<= 'z') ||
202 (*q
>= 'A' && *q
<= 'Z') ||
203 (*q
>= '0' && *q
<= '9') ||
217 * Complex pattern match
218 * This checks whether @a is a 'complex-prefix' of @b, or @b is a
219 * 'complex-prefix' of @a, based on strings that consist of labels with @c as
220 * spearator. This function returns true if:
221 * - both strings are equal
222 * - either is a prefix of the other and ends with @c
223 * The second rule makes sure that either string needs to be fully included in
224 * the other, and the string which is considered the prefix needs to end with a
227 static bool complex_pattern_check(char c
, const char *a
, const char *b
) {
228 bool separator
= false;
238 return (separator
&& (*a
== 0 || *b
== 0));
249 bool namespace_complex_pattern(const char *pattern
, const char *value
) {
250 return complex_pattern_check('.', pattern
, value
);
253 bool path_complex_pattern(const char *pattern
, const char *value
) {
254 return complex_pattern_check('/', pattern
, value
);
258 * Simple pattern match
259 * This checks whether @a is a 'simple-prefix' of @b, based on strings that
260 * consist of labels with @c as separator. This function returns true, if:
261 * - if @a and @b are equal
262 * - if @a is a prefix of @b, and the first following character in @b (or the
263 * last character in @a) is @c
264 * The second rule basically makes sure that if @a is a prefix of @b, then @b
265 * must follow with a new label separated by @c. It cannot extend the label.
267 static bool simple_pattern_check(char c
, const char *a
, const char *b
) {
268 bool separator
= false;
278 return *a
== 0 && (*b
== c
|| separator
);
289 bool namespace_simple_pattern(const char *pattern
, const char *value
) {
290 return simple_pattern_check('.', pattern
, value
);
293 bool path_simple_pattern(const char *pattern
, const char *value
) {
294 return simple_pattern_check('/', pattern
, value
);
297 int bus_message_type_from_string(const char *s
, uint8_t *u
) {
298 if (streq(s
, "signal"))
299 *u
= SD_BUS_MESSAGE_SIGNAL
;
300 else if (streq(s
, "method_call"))
301 *u
= SD_BUS_MESSAGE_METHOD_CALL
;
302 else if (streq(s
, "error"))
303 *u
= SD_BUS_MESSAGE_METHOD_ERROR
;
304 else if (streq(s
, "method_return"))
305 *u
= SD_BUS_MESSAGE_METHOD_RETURN
;
312 const char *bus_message_type_to_string(uint8_t u
) {
313 if (u
== SD_BUS_MESSAGE_SIGNAL
)
315 else if (u
== SD_BUS_MESSAGE_METHOD_CALL
)
316 return "method_call";
317 else if (u
== SD_BUS_MESSAGE_METHOD_ERROR
)
319 else if (u
== SD_BUS_MESSAGE_METHOD_RETURN
)
320 return "method_return";
325 char *bus_address_escape(const char *v
) {
329 r
= new(char, strlen(v
)*3+1);
333 for (a
= v
, b
= r
; *a
; a
++) {
335 if ((*a
>= '0' && *a
<= '9') ||
336 (*a
>= 'a' && *a
<= 'z') ||
337 (*a
>= 'A' && *a
<= 'Z') ||
342 *(b
++) = hexchar(*a
>> 4);
343 *(b
++) = hexchar(*a
& 0xF);
351 int bus_maybe_reply_error(sd_bus_message
*m
, int r
, sd_bus_error
*error
) {
355 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
)
356 sd_bus_reply_method_errno(m
, r
, error
);
358 } else if (sd_bus_error_is_set(error
)) {
359 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
)
360 sd_bus_reply_method_error(m
, error
);
364 log_debug("Failed to process message [type=%s sender=%s path=%s interface=%s member=%s signature=%s]: %s",
365 bus_message_type_to_string(m
->header
->type
),
370 strna(m
->root_container
.signature
),
371 bus_error_message(error
, r
));