LCOV - code coverage report
Current view: top level - libsystemd/sd-bus - bus-internal.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 143 179 79.9 %
Date: 2019-08-22 15:41:25 Functions: 15 15 100.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include "alloc-util.h"
       4             : #include "bus-internal.h"
       5             : #include "bus-message.h"
       6             : #include "hexdecoct.h"
       7             : #include "string-util.h"
       8             : 
       9         373 : bool object_path_is_valid(const char *p) {
      10             :         const char *q;
      11             :         bool slash;
      12             : 
      13         373 :         if (!p)
      14           0 :                 return false;
      15             : 
      16         373 :         if (p[0] != '/')
      17           3 :                 return false;
      18             : 
      19         370 :         if (p[1] == 0)
      20          48 :                 return true;
      21             : 
      22        4299 :         for (slash = true, q = p+1; *q; q++)
      23        3981 :                 if (*q == '/') {
      24         457 :                         if (slash)
      25           3 :                                 return false;
      26             : 
      27         454 :                         slash = true;
      28             :                 } else {
      29             :                         bool good;
      30             : 
      31        3524 :                         good =
      32        3286 :                                 (*q >= 'a' && *q <= 'z') ||
      33         238 :                                 (*q >= 'A' && *q <= 'Z') ||
      34        7066 :                                 (*q >= '0' && *q <= '9') ||
      35          18 :                                 *q == '_';
      36             : 
      37        3524 :                         if (!good)
      38           1 :                                 return false;
      39             : 
      40        3523 :                         slash = false;
      41             :                 }
      42             : 
      43         318 :         if (slash)
      44           2 :                 return false;
      45             : 
      46         316 :         return (q - p) <= BUS_PATH_SIZE_MAX;
      47             : }
      48             : 
      49          39 : char* object_path_startswith(const char *a, const char *b) {
      50             :         const char *p;
      51             : 
      52          39 :         if (!object_path_is_valid(a) ||
      53          39 :             !object_path_is_valid(b))
      54           1 :                 return NULL;
      55             : 
      56          38 :         if (streq(b, "/"))
      57           6 :                 return (char*) a + 1;
      58             : 
      59          32 :         p = startswith(a, b);
      60          32 :         if (!p)
      61           4 :                 return NULL;
      62             : 
      63          28 :         if (*p == 0)
      64           4 :                 return (char*) p;
      65             : 
      66          24 :         if (*p == '/')
      67          24 :                 return (char*) p + 1;
      68             : 
      69           0 :         return NULL;
      70             : }
      71             : 
      72         240 : bool interface_name_is_valid(const char *p) {
      73             :         const char *q;
      74         240 :         bool dot, found_dot = false;
      75             : 
      76         240 :         if (isempty(p))
      77           0 :                 return false;
      78             : 
      79        6338 :         for (dot = true, q = p; *q; q++)
      80        6098 :                 if (*q == '.') {
      81         607 :                         if (dot)
      82           0 :                                 return false;
      83             : 
      84         607 :                         found_dot = dot = true;
      85             :                 } else {
      86             :                         bool good;
      87             : 
      88        5491 :                         good =
      89        5057 :                                 (*q >= 'a' && *q <= 'z') ||
      90         434 :                                 (*q >= 'A' && *q <= 'Z') ||
      91       10982 :                                 (!dot && *q >= '0' && *q <= '9') ||
      92           0 :                                 *q == '_';
      93             : 
      94        5491 :                         if (!good)
      95           0 :                                 return false;
      96             : 
      97        5491 :                         dot = false;
      98             :                 }
      99             : 
     100         240 :         if (q - p > SD_BUS_MAXIMUM_NAME_LENGTH)
     101           0 :                 return false;
     102             : 
     103         240 :         if (dot)
     104           0 :                 return false;
     105             : 
     106         240 :         if (!found_dot)
     107           0 :                 return false;
     108             : 
     109         240 :         return true;
     110             : }
     111             : 
     112         295 : bool service_name_is_valid(const char *p) {
     113             :         const char *q;
     114         295 :         bool dot, found_dot = false, unique;
     115             : 
     116         295 :         if (isempty(p))
     117           0 :                 return false;
     118             : 
     119         295 :         unique = p[0] == ':';
     120             : 
     121        5693 :         for (dot = true, q = unique ? p+1 : p; *q; q++)
     122        5398 :                 if (*q == '.') {
     123         591 :                         if (dot)
     124           0 :                                 return false;
     125             : 
     126         591 :                         found_dot = dot = true;
     127             :                 } else {
     128             :                         bool good;
     129             : 
     130        4807 :                         good =
     131        4091 :                                 (*q >= 'a' && *q <= 'z') ||
     132         716 :                                 (*q >= 'A' && *q <= 'Z') ||
     133        9616 :                                 ((!dot || unique) && *q >= '0' && *q <= '9') ||
     134           2 :                                 IN_SET(*q, '_', '-');
     135             : 
     136        4807 :                         if (!good)
     137           0 :                                 return false;
     138             : 
     139        4807 :                         dot = false;
     140             :                 }
     141             : 
     142         295 :         if (q - p > SD_BUS_MAXIMUM_NAME_LENGTH)
     143           0 :                 return false;
     144             : 
     145         295 :         if (dot)
     146           0 :                 return false;
     147             : 
     148         295 :         if (!found_dot)
     149           0 :                 return false;
     150             : 
     151         295 :         return true;
     152             : }
     153             : 
     154         364 : bool member_name_is_valid(const char *p) {
     155             :         const char *q;
     156             : 
     157         364 :         if (isempty(p))
     158           0 :                 return false;
     159             : 
     160        3981 :         for (q = p; *q; q++) {
     161             :                 bool good;
     162             : 
     163        3617 :                 good =
     164        3014 :                         (*q >= 'a' && *q <= 'z') ||
     165         603 :                         (*q >= 'A' && *q <= 'Z') ||
     166        7242 :                         (*q >= '0' && *q <= '9') ||
     167           8 :                         *q == '_';
     168             : 
     169        3617 :                 if (!good)
     170           0 :                         return false;
     171             :         }
     172             : 
     173         364 :         if (q - p > SD_BUS_MAXIMUM_NAME_LENGTH)
     174           0 :                 return false;
     175             : 
     176         364 :         return true;
     177             : }
     178             : 
     179             : /*
     180             :  * Complex pattern match
     181             :  * This checks whether @a is a 'complex-prefix' of @b, or @b is a
     182             :  * 'complex-prefix' of @a, based on strings that consist of labels with @c as
     183             :  * separator. This function returns true if:
     184             :  *   - both strings are equal
     185             :  *   - either is a prefix of the other and ends with @c
     186             :  * The second rule makes sure that either string needs to be fully included in
     187             :  * the other, and the string which is considered the prefix needs to end with a
     188             :  * separator.
     189             :  */
     190          22 : static bool complex_pattern_check(char c, const char *a, const char *b) {
     191          22 :         bool separator = false;
     192             : 
     193          22 :         if (!a && !b)
     194           0 :                 return true;
     195             : 
     196          22 :         if (!a || !b)
     197           0 :                 return false;
     198             : 
     199             :         for (;;) {
     200         120 :                 if (*a != *b)
     201          16 :                         return (separator && (*a == 0 || *b == 0));
     202             : 
     203         104 :                 if (*a == 0)
     204           6 :                         return true;
     205             : 
     206          98 :                 separator = *a == c;
     207             : 
     208          98 :                 a++, b++;
     209             :         }
     210             : }
     211             : 
     212          10 : bool namespace_complex_pattern(const char *pattern, const char *value) {
     213          10 :         return complex_pattern_check('.', pattern, value);
     214             : }
     215             : 
     216          12 : bool path_complex_pattern(const char *pattern, const char *value) {
     217          12 :         return complex_pattern_check('/', pattern, value);
     218             : }
     219             : 
     220             : /*
     221             :  * Simple pattern match
     222             :  * This checks whether @a is a 'simple-prefix' of @b, based on strings that
     223             :  * consist of labels with @c as separator. This function returns true, if:
     224             :  *   - if @a and @b are equal
     225             :  *   - if @a is a prefix of @b, and the first following character in @b (or the
     226             :  *     last character in @a) is @c
     227             :  * The second rule basically makes sure that if @a is a prefix of @b, then @b
     228             :  * must follow with a new label separated by @c. It cannot extend the label.
     229             :  */
     230          16 : static bool simple_pattern_check(char c, const char *a, const char *b) {
     231          16 :         bool separator = false;
     232             : 
     233          16 :         if (!a && !b)
     234           0 :                 return true;
     235             : 
     236          16 :         if (!a || !b)
     237           0 :                 return false;
     238             : 
     239             :         for (;;) {
     240          85 :                 if (*a != *b)
     241          13 :                         return *a == 0 && (*b == c || separator);
     242             : 
     243          72 :                 if (*a == 0)
     244           3 :                         return true;
     245             : 
     246          69 :                 separator = *a == c;
     247             : 
     248          69 :                 a++, b++;
     249             :         }
     250             : }
     251             : 
     252          11 : bool namespace_simple_pattern(const char *pattern, const char *value) {
     253          11 :         return simple_pattern_check('.', pattern, value);
     254             : }
     255             : 
     256           5 : bool path_simple_pattern(const char *pattern, const char *value) {
     257           5 :         return simple_pattern_check('/', pattern, value);
     258             : }
     259             : 
     260          34 : int bus_message_type_from_string(const char *s, uint8_t *u) {
     261          34 :         if (streq(s, "signal"))
     262          33 :                 *u = SD_BUS_MESSAGE_SIGNAL;
     263           1 :         else if (streq(s, "method_call"))
     264           1 :                 *u = SD_BUS_MESSAGE_METHOD_CALL;
     265           0 :         else if (streq(s, "error"))
     266           0 :                 *u = SD_BUS_MESSAGE_METHOD_ERROR;
     267           0 :         else if (streq(s, "method_return"))
     268           0 :                 *u = SD_BUS_MESSAGE_METHOD_RETURN;
     269             :         else
     270           0 :                 return -EINVAL;
     271             : 
     272          34 :         return 0;
     273             : }
     274             : 
     275          39 : const char *bus_message_type_to_string(uint8_t u) {
     276          39 :         if (u == SD_BUS_MESSAGE_SIGNAL)
     277           6 :                 return "signal";
     278          33 :         else if (u == SD_BUS_MESSAGE_METHOD_CALL)
     279          20 :                 return "method_call";
     280          13 :         else if (u == SD_BUS_MESSAGE_METHOD_ERROR)
     281           0 :                 return "error";
     282          13 :         else if (u == SD_BUS_MESSAGE_METHOD_RETURN)
     283          13 :                  return "method_return";
     284             :         else
     285           0 :                 return NULL;
     286             : }
     287             : 
     288           7 : char *bus_address_escape(const char *v) {
     289             :         const char *a;
     290             :         char *r, *b;
     291             : 
     292           7 :         r = new(char, strlen(v)*3+1);
     293           7 :         if (!r)
     294           0 :                 return NULL;
     295             : 
     296          51 :         for (a = v, b = r; *a; a++) {
     297             : 
     298          44 :                 if ((*a >= '0' && *a <= '9') ||
     299          40 :                     (*a >= 'a' && *a <= 'z') ||
     300          12 :                     (*a >= 'A' && *a <= 'Z') ||
     301          12 :                     strchr("_-/.", *a))
     302          32 :                         *(b++) = *a;
     303             :                 else {
     304          12 :                         *(b++) = '%';
     305          12 :                         *(b++) = hexchar(*a >> 4);
     306          12 :                         *(b++) = hexchar(*a & 0xF);
     307             :                 }
     308             :         }
     309             : 
     310           7 :         *b = 0;
     311           7 :         return r;
     312             : }
     313             : 
     314          56 : int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error) {
     315          56 :         assert(m);
     316             : 
     317          56 :         if (r < 0) {
     318           0 :                 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
     319           0 :                         sd_bus_reply_method_errno(m, r, error);
     320             : 
     321          56 :         } else if (sd_bus_error_is_set(error)) {
     322           0 :                 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
     323           0 :                         sd_bus_reply_method_error(m, error);
     324             :         } else
     325          56 :                 return r;
     326             : 
     327           0 :         log_debug("Failed to process message type=%s sender=%s destination=%s path=%s interface=%s member=%s cookie=%" PRIu64 " reply_cookie=%" PRIu64 " signature=%s error-name=%s error-message=%s: %s",
     328             :                   bus_message_type_to_string(m->header->type),
     329             :                   strna(sd_bus_message_get_sender(m)),
     330             :                   strna(sd_bus_message_get_destination(m)),
     331             :                   strna(sd_bus_message_get_path(m)),
     332             :                   strna(sd_bus_message_get_interface(m)),
     333             :                   strna(sd_bus_message_get_member(m)),
     334             :                   BUS_MESSAGE_COOKIE(m),
     335             :                   m->reply_cookie,
     336             :                   strna(m->root_container.signature),
     337             :                   strna(m->error.name),
     338             :                   strna(m->error.message),
     339             :                   bus_error_message(error, r));
     340             : 
     341           0 :         return 1;
     342             : }

Generated by: LCOV version 1.14