LCOV - code coverage report
Current view: top level - libsystemd/sd-bus - bus-internal.c (source / functions) Hit Total Coverage
Test: systemd test coverage Lines: 146 193 75.6 %
Date: 2015-07-29 18:47:03 Functions: 15 16 93.8 %

          Line data    Source code
       1             : /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
       2             : 
       3             : /***
       4             :   This file is part of systemd.
       5             : 
       6             :   Copyright 2013 Lennart Poettering
       7             : 
       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.
      12             : 
      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.
      17             : 
      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/>.
      20             : ***/
      21             : 
      22             : #include "bus-message.h"
      23             : #include "bus-internal.h"
      24             : 
      25       15856 : bool object_path_is_valid(const char *p) {
      26             :         const char *q;
      27             :         bool slash;
      28             : 
      29       15856 :         if (!p)
      30           0 :                 return false;
      31             : 
      32       15856 :         if (p[0] != '/')
      33           3 :                 return false;
      34             : 
      35       15853 :         if (p[1] == 0)
      36       15548 :                 return true;
      37             : 
      38        3112 :         for (slash = true, q = p+1; *q; q++)
      39        2811 :                 if (*q == '/') {
      40         394 :                         if (slash)
      41           3 :                                 return false;
      42             : 
      43         391 :                         slash = true;
      44             :                 } else {
      45             :                         bool good;
      46             : 
      47        2417 :                         good =
      48        4834 :                                 (*q >= 'a' && *q <= 'z') ||
      49         119 :                                 (*q >= 'A' && *q <= 'Z') ||
      50        2494 :                                 (*q >= '0' && *q <= '9') ||
      51          18 :                                 *q == '_';
      52             : 
      53        2417 :                         if (!good)
      54           1 :                                 return false;
      55             : 
      56        2416 :                         slash = false;
      57             :                 }
      58             : 
      59         301 :         if (slash)
      60           2 :                 return false;
      61             : 
      62         299 :         return true;
      63             : }
      64             : 
      65          61 : char* object_path_startswith(const char *a, const char *b) {
      66             :         const char *p;
      67             : 
      68         122 :         if (!object_path_is_valid(a) ||
      69          61 :             !object_path_is_valid(b))
      70           1 :                 return NULL;
      71             : 
      72          60 :         if (streq(b, "/"))
      73          21 :                 return (char*) a + 1;
      74             : 
      75          39 :         p = startswith(a, b);
      76          39 :         if (!p)
      77           4 :                 return NULL;
      78             : 
      79          35 :         if (*p == 0)
      80           4 :                 return (char*) p;
      81             : 
      82          31 :         if (*p == '/')
      83          31 :                 return (char*) p + 1;
      84             : 
      85           0 :         return NULL;
      86             : }
      87             : 
      88       15668 : bool interface_name_is_valid(const char *p) {
      89             :         const char *q;
      90       15668 :         bool dot, found_dot = false;
      91             : 
      92       15668 :         if (isempty(p))
      93           0 :                 return false;
      94             : 
      95      267548 :         for (dot = true, q = p; *q; q++)
      96      251880 :                 if (*q == '.') {
      97       15907 :                         if (dot)
      98           0 :                                 return false;
      99             : 
     100       15907 :                         found_dot = dot = true;
     101             :                 } else {
     102             :                         bool good;
     103             : 
     104      235973 :                         good =
     105      471946 :                                 (*q >= 'a' && *q <= 'z') ||
     106         404 :                                 (*q >= 'A' && *q <= 'Z') ||
     107      235975 :                                 (!dot && *q >= '0' && *q <= '9') ||
     108           0 :                                 *q == '_';
     109             : 
     110      235973 :                         if (!good)
     111           0 :                                 return false;
     112             : 
     113      235973 :                         dot = false;
     114             :                 }
     115             : 
     116       15668 :         if (q - p > 255)
     117           0 :                 return false;
     118             : 
     119       15668 :         if (dot)
     120           0 :                 return false;
     121             : 
     122       15668 :         if (!found_dot)
     123           0 :                 return false;
     124             : 
     125       15668 :         return true;
     126             : }
     127             : 
     128       15617 : bool service_name_is_valid(const char *p) {
     129             :         const char *q;
     130       15617 :         bool dot, found_dot = false, unique;
     131             : 
     132       15617 :         if (isempty(p))
     133           0 :                 return false;
     134             : 
     135       15617 :         unique = p[0] == ':';
     136             : 
     137      127392 :         for (dot = true, q = unique ? p+1 : p; *q; q++)
     138      111775 :                 if (*q == '.') {
     139       15837 :                         if (dot)
     140           0 :                                 return false;
     141             : 
     142       15837 :                         found_dot = dot = true;
     143             :                 } else {
     144             :                         bool good;
     145             : 
     146       95938 :                         good =
     147      191876 :                                 (*q >= 'a' && *q <= 'z') ||
     148      185974 :                                 (*q >= 'A' && *q <= 'Z') ||
     149      123921 :                                 ((!dot || unique) && *q >= '0' && *q <= '9') ||
     150       95938 :                                 *q == '_' || *q == '-';
     151             : 
     152       95938 :                         if (!good)
     153           0 :                                 return false;
     154             : 
     155       95938 :                         dot = false;
     156             :                 }
     157             : 
     158       15617 :         if (q - p > 255)
     159           0 :                 return false;
     160             : 
     161       15617 :         if (dot)
     162           0 :                 return false;
     163             : 
     164       15617 :         if (!found_dot)
     165           0 :                 return false;
     166             : 
     167       15617 :         return true;
     168             : }
     169             : 
     170           8 : char* service_name_startswith(const char *a, const char *b) {
     171             :         const char *p;
     172             : 
     173          16 :         if (!service_name_is_valid(a) ||
     174           8 :             !service_name_is_valid(b))
     175           0 :                 return NULL;
     176             : 
     177           8 :         p = startswith(a, b);
     178           8 :         if (!p)
     179           2 :                 return NULL;
     180             : 
     181           6 :         if (*p == 0)
     182           1 :                 return (char*) p;
     183             : 
     184           5 :         if (*p == '.')
     185           2 :                 return (char*) p + 1;
     186             : 
     187           3 :         return NULL;
     188             : }
     189             : 
     190       15684 : bool member_name_is_valid(const char *p) {
     191             :         const char *q;
     192             : 
     193       15684 :         if (isempty(p))
     194           0 :                 return false;
     195             : 
     196       79377 :         for (q = p; *q; q++) {
     197             :                 bool good;
     198             : 
     199       63693 :                 good =
     200      127386 :                         (*q >= 'a' && *q <= 'z') ||
     201       31618 :                         (*q >= 'A' && *q <= 'Z') ||
     202       63713 :                         (*q >= '0' && *q <= '9') ||
     203           0 :                         *q == '_';
     204             : 
     205       63693 :                 if (!good)
     206           0 :                         return false;
     207             :         }
     208             : 
     209       15684 :         if (q - p > 255)
     210           0 :                 return false;
     211             : 
     212       15684 :         return true;
     213             : }
     214             : 
     215             : /*
     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
     224             :  * separator.
     225             :  */
     226          26 : static bool complex_pattern_check(char c, const char *a, const char *b) {
     227          26 :         bool separator = false;
     228             : 
     229          26 :         if (!a && !b)
     230           0 :                 return true;
     231             : 
     232          26 :         if (!a || !b)
     233           0 :                 return false;
     234             : 
     235             :         for (;;) {
     236         142 :                 if (*a != *b)
     237          19 :                         return (separator && (*a == 0 || *b == 0));
     238             : 
     239         123 :                 if (*a == 0)
     240           7 :                         return true;
     241             : 
     242         116 :                 separator = *a == c;
     243             : 
     244         116 :                 a++, b++;
     245         116 :         }
     246             : }
     247             : 
     248          10 : bool namespace_complex_pattern(const char *pattern, const char *value) {
     249          10 :         return complex_pattern_check('.', pattern, value);
     250             : }
     251             : 
     252          16 : bool path_complex_pattern(const char *pattern, const char *value) {
     253          16 :         return complex_pattern_check('/', pattern, value);
     254             : }
     255             : 
     256             : /*
     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.
     265             :  */
     266          22 : static bool simple_pattern_check(char c, const char *a, const char *b) {
     267          22 :         bool separator = false;
     268             : 
     269          22 :         if (!a && !b)
     270           0 :                 return true;
     271             : 
     272          22 :         if (!a || !b)
     273           0 :                 return false;
     274             : 
     275             :         for (;;) {
     276         124 :                 if (*a != *b)
     277          17 :                         return *a == 0 && (*b == c || separator);
     278             : 
     279         107 :                 if (*a == 0)
     280           5 :                         return true;
     281             : 
     282         102 :                 separator = *a == c;
     283             : 
     284         102 :                 a++, b++;
     285         102 :         }
     286             : }
     287             : 
     288          11 : bool namespace_simple_pattern(const char *pattern, const char *value) {
     289          11 :         return simple_pattern_check('.', pattern, value);
     290             : }
     291             : 
     292          11 : bool path_simple_pattern(const char *pattern, const char *value) {
     293          11 :         return simple_pattern_check('/', pattern, value);
     294             : }
     295             : 
     296          28 : int bus_message_type_from_string(const char *s, uint8_t *u) {
     297          28 :         if (streq(s, "signal"))
     298          12 :                 *u = SD_BUS_MESSAGE_SIGNAL;
     299          16 :         else if (streq(s, "method_call"))
     300           8 :                 *u = SD_BUS_MESSAGE_METHOD_CALL;
     301           8 :         else if (streq(s, "error"))
     302           4 :                 *u = SD_BUS_MESSAGE_METHOD_ERROR;
     303           4 :         else if (streq(s, "method_return"))
     304           4 :                 *u = SD_BUS_MESSAGE_METHOD_RETURN;
     305             :         else
     306           0 :                 return -EINVAL;
     307             : 
     308          28 :         return 0;
     309             : }
     310             : 
     311         128 : const char *bus_message_type_to_string(uint8_t u) {
     312         128 :         if (u == SD_BUS_MESSAGE_SIGNAL)
     313          97 :                 return "signal";
     314          31 :         else if (u == SD_BUS_MESSAGE_METHOD_CALL)
     315          20 :                 return "method_call";
     316          11 :         else if (u == SD_BUS_MESSAGE_METHOD_ERROR)
     317           5 :                 return "error";
     318           6 :         else if (u == SD_BUS_MESSAGE_METHOD_RETURN)
     319           6 :                  return "method_return";
     320             :         else
     321           0 :                 return NULL;
     322             : }
     323             : 
     324           0 : char *bus_address_escape(const char *v) {
     325             :         const char *a;
     326             :         char *r, *b;
     327             : 
     328           0 :         r = new(char, strlen(v)*3+1);
     329           0 :         if (!r)
     330           0 :                 return NULL;
     331             : 
     332           0 :         for (a = v, b = r; *a; a++) {
     333             : 
     334           0 :                 if ((*a >= '0' && *a <= '9') ||
     335           0 :                     (*a >= 'a' && *a <= 'z') ||
     336           0 :                     (*a >= 'A' && *a <= 'Z') ||
     337           0 :                     strchr("_-/.", *a))
     338           0 :                         *(b++) = *a;
     339             :                 else {
     340           0 :                         *(b++) = '%';
     341           0 :                         *(b++) = hexchar(*a >> 4);
     342           0 :                         *(b++) = hexchar(*a & 0xF);
     343             :                 }
     344             :         }
     345             : 
     346           0 :         *b = 0;
     347           0 :         return r;
     348             : }
     349             : 
     350          53 : int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error) {
     351          53 :         assert(m);
     352             : 
     353          53 :         if (r < 0) {
     354           0 :                 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
     355           0 :                         sd_bus_reply_method_errno(m, r, error);
     356             : 
     357          53 :         } else if (sd_bus_error_is_set(error)) {
     358           0 :                 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
     359           0 :                         sd_bus_reply_method_error(m, error);
     360             :         } else
     361          53 :                 return r;
     362             : 
     363           0 :         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),
     365             :                   strna(m->sender),
     366             :                   strna(m->path),
     367             :                   strna(m->interface),
     368             :                   strna(m->member),
     369             :                   strna(m->root_container.signature),
     370             :                   bus_error_message(error, r));
     371             : 
     372           0 :         return 1;
     373             : }

Generated by: LCOV version 1.11