2 This file is part of systemd.
4 Copyright 2013 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 #include "alloc-util.h"
21 #include "bus-internal.h"
22 #include "bus-message.h"
23 #include "hexdecoct.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 IN_SET(*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
));