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-message.h"
23 #include "bus-internal.h"
25 bool object_path_is_valid(const char *p
) {
38 for (slash
= true, q
= p
+1; *q
; q
++)
48 (*q
>= 'a' && *q
<= 'z') ||
49 (*q
>= 'A' && *q
<= 'Z') ||
50 (*q
>= '0' && *q
<= '9') ||
65 char* object_path_startswith(const char *a
, const char *b
) {
68 if (!object_path_is_valid(a
) ||
69 !object_path_is_valid(b
))
88 bool interface_name_is_valid(const char *p
) {
90 bool dot
, found_dot
= false;
95 for (dot
= true, q
= p
; *q
; q
++)
100 found_dot
= dot
= true;
105 (*q
>= 'a' && *q
<= 'z') ||
106 (*q
>= 'A' && *q
<= 'Z') ||
107 (!dot
&& *q
>= '0' && *q
<= '9') ||
128 bool service_name_is_valid(const char *p
) {
130 bool dot
, found_dot
= false, unique
;
135 unique
= p
[0] == ':';
137 for (dot
= true, q
= unique
? p
+1 : p
; *q
; q
++)
142 found_dot
= dot
= true;
147 (*q
>= 'a' && *q
<= 'z') ||
148 (*q
>= 'A' && *q
<= 'Z') ||
149 ((!dot
|| unique
) && *q
>= '0' && *q
<= '9') ||
150 *q
== '_' || *q
== '-';
170 char* service_name_startswith(const char *a
, const char *b
) {
173 if (!service_name_is_valid(a
) ||
174 !service_name_is_valid(b
))
177 p
= startswith(a
, b
);
185 return (char*) p
+ 1;
190 bool member_name_is_valid(const char *p
) {
196 for (q
= p
; *q
; q
++) {
200 (*q
>= 'a' && *q
<= 'z') ||
201 (*q
>= 'A' && *q
<= 'Z') ||
202 (*q
>= '0' && *q
<= '9') ||
216 * Complex pattern match
217 * This checks whether @a is a 'complex-prefix' of @b, or @b is a
218 * 'complex-prefix' of @a, based on strings that consist of labels with @c as
219 * spearator. This function returns true if:
220 * - both strings are equal
221 * - either is a prefix of the other and ends with @c
222 * The second rule makes sure that either string needs to be fully included in
223 * the other, and the string which is considered the prefix needs to end with a
226 static bool complex_pattern_check(char c
, const char *a
, const char *b
) {
227 bool separator
= false;
237 return (separator
&& (*a
== 0 || *b
== 0));
248 bool namespace_complex_pattern(const char *pattern
, const char *value
) {
249 return complex_pattern_check('.', pattern
, value
);
252 bool path_complex_pattern(const char *pattern
, const char *value
) {
253 return complex_pattern_check('/', pattern
, value
);
257 * Simple pattern match
258 * This checks whether @a is a 'simple-prefix' of @b, based on strings that
259 * consist of labels with @c as separator. This function returns true, if:
260 * - if @a and @b are equal
261 * - if @a is a prefix of @b, and the first following character in @b (or the
262 * last character in @a) is @c
263 * The second rule basically makes sure that if @a is a prefix of @b, then @b
264 * must follow with a new label separated by @c. It cannot extend the label.
266 static bool simple_pattern_check(char c
, const char *a
, const char *b
) {
267 bool separator
= false;
277 return *a
== 0 && (*b
== c
|| separator
);
288 bool namespace_simple_pattern(const char *pattern
, const char *value
) {
289 return simple_pattern_check('.', pattern
, value
);
292 bool path_simple_pattern(const char *pattern
, const char *value
) {
293 return simple_pattern_check('/', pattern
, value
);
296 int bus_message_type_from_string(const char *s
, uint8_t *u
) {
297 if (streq(s
, "signal"))
298 *u
= SD_BUS_MESSAGE_SIGNAL
;
299 else if (streq(s
, "method_call"))
300 *u
= SD_BUS_MESSAGE_METHOD_CALL
;
301 else if (streq(s
, "error"))
302 *u
= SD_BUS_MESSAGE_METHOD_ERROR
;
303 else if (streq(s
, "method_return"))
304 *u
= SD_BUS_MESSAGE_METHOD_RETURN
;
311 const char *bus_message_type_to_string(uint8_t u
) {
312 if (u
== SD_BUS_MESSAGE_SIGNAL
)
314 else if (u
== SD_BUS_MESSAGE_METHOD_CALL
)
315 return "method_call";
316 else if (u
== SD_BUS_MESSAGE_METHOD_ERROR
)
318 else if (u
== SD_BUS_MESSAGE_METHOD_RETURN
)
319 return "method_return";
324 char *bus_address_escape(const char *v
) {
328 r
= new(char, strlen(v
)*3+1);
332 for (a
= v
, b
= r
; *a
; a
++) {
334 if ((*a
>= '0' && *a
<= '9') ||
335 (*a
>= 'a' && *a
<= 'z') ||
336 (*a
>= 'A' && *a
<= 'Z') ||
341 *(b
++) = hexchar(*a
>> 4);
342 *(b
++) = hexchar(*a
& 0xF);
350 int bus_maybe_reply_error(sd_bus_message
*m
, int r
, sd_bus_error
*error
) {
354 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
)
355 sd_bus_reply_method_errno(m
, r
, error
);
357 } else if (sd_bus_error_is_set(error
)) {
358 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
)
359 sd_bus_reply_method_error(m
, error
);
363 log_debug("Failed to process message [type=%s sender=%s path=%s interface=%s member=%s signature=%s]: %s",
364 bus_message_type_to_string(m
->header
->type
),
369 strna(m
->root_container
.signature
),
370 bus_error_message(error
, r
));