LCOV - code coverage report
Current view: top level - libsystemd/sd-bus - bus-introspect.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 106 110 96.4 %
Date: 2019-08-23 13:36:53 Functions: 8 8 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 64 83 77.1 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include "bus-internal.h"
       4                 :            : #include "bus-introspect.h"
       5                 :            : #include "bus-objects.h"
       6                 :            : #include "bus-protocol.h"
       7                 :            : #include "bus-signature.h"
       8                 :            : #include "fd-util.h"
       9                 :            : #include "fileio.h"
      10                 :            : #include "memory-util.h"
      11                 :            : #include "string-util.h"
      12                 :            : 
      13                 :         36 : int introspect_begin(struct introspect *i, bool trusted) {
      14         [ -  + ]:         36 :         assert(i);
      15                 :            : 
      16         [ +  - ]:         36 :         zero(*i);
      17                 :         36 :         i->trusted = trusted;
      18                 :            : 
      19                 :         36 :         i->f = open_memstream_unlocked(&i->introspection, &i->size);
      20         [ -  + ]:         36 :         if (!i->f)
      21                 :          0 :                 return -ENOMEM;
      22                 :            : 
      23                 :         36 :         fputs(BUS_INTROSPECT_DOCTYPE
      24                 :            :               "<node>\n", i->f);
      25                 :            : 
      26                 :         36 :         return 0;
      27                 :            : }
      28                 :            : 
      29                 :         20 : int introspect_write_default_interfaces(struct introspect *i, bool object_manager) {
      30         [ -  + ]:         20 :         assert(i);
      31                 :            : 
      32                 :         20 :         fputs(BUS_INTROSPECT_INTERFACE_PEER
      33                 :            :               BUS_INTROSPECT_INTERFACE_INTROSPECTABLE
      34                 :            :               BUS_INTROSPECT_INTERFACE_PROPERTIES, i->f);
      35                 :            : 
      36         [ +  + ]:         20 :         if (object_manager)
      37                 :          8 :                 fputs(BUS_INTROSPECT_INTERFACE_OBJECT_MANAGER, i->f);
      38                 :            : 
      39                 :         20 :         return 0;
      40                 :            : }
      41                 :            : 
      42                 :         20 : int introspect_write_child_nodes(struct introspect *i, Set *s, const char *prefix) {
      43                 :            :         char *node;
      44                 :            : 
      45         [ -  + ]:         20 :         assert(i);
      46         [ -  + ]:         20 :         assert(prefix);
      47                 :            : 
      48         [ +  + ]:         52 :         while ((node = set_steal_first(s))) {
      49                 :            :                 const char *e;
      50                 :            : 
      51                 :         32 :                 e = object_path_startswith(node, prefix);
      52   [ +  -  +  - ]:         32 :                 if (e && e[0])
      53                 :         32 :                         fprintf(i->f, " <node name=\"%s\"/>\n", e);
      54                 :            : 
      55                 :         32 :                 free(node);
      56                 :            :         }
      57                 :            : 
      58                 :         20 :         return 0;
      59                 :            : }
      60                 :            : 
      61                 :        372 : static void introspect_write_flags(struct introspect *i, int type, uint64_t flags) {
      62         [ +  + ]:        372 :         if (flags & SD_BUS_VTABLE_DEPRECATED)
      63                 :         16 :                 fputs("   <annotation name=\"org.freedesktop.DBus.Deprecated\" value=\"true\"/>\n", i->f);
      64                 :            : 
      65   [ +  +  +  + ]:        372 :         if (type == _SD_BUS_VTABLE_METHOD && (flags & SD_BUS_VTABLE_METHOD_NO_REPLY))
      66                 :          4 :                 fputs("   <annotation name=\"org.freedesktop.DBus.Method.NoReply\" value=\"true\"/>\n", i->f);
      67                 :            : 
      68   [ +  +  +  + ]:        372 :         if (IN_SET(type, _SD_BUS_VTABLE_PROPERTY, _SD_BUS_VTABLE_WRITABLE_PROPERTY)) {
      69         [ +  + ]:        160 :                 if (flags & SD_BUS_VTABLE_PROPERTY_EXPLICIT)
      70                 :         20 :                         fputs("   <annotation name=\"org.freedesktop.systemd1.Explicit\" value=\"true\"/>\n", i->f);
      71                 :            : 
      72         [ +  + ]:        160 :                 if (flags & SD_BUS_VTABLE_PROPERTY_CONST)
      73                 :         20 :                         fputs("   <annotation name=\"org.freedesktop.DBus.Property.EmitsChangedSignal\" value=\"const\"/>\n", i->f);
      74         [ +  + ]:        140 :                 else if (flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION)
      75                 :         36 :                         fputs("   <annotation name=\"org.freedesktop.DBus.Property.EmitsChangedSignal\" value=\"invalidates\"/>\n", i->f);
      76         [ +  + ]:        104 :                 else if (!(flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE))
      77                 :         84 :                         fputs("   <annotation name=\"org.freedesktop.DBus.Property.EmitsChangedSignal\" value=\"false\"/>\n", i->f);
      78                 :            :         }
      79                 :            : 
      80         [ +  - ]:        372 :         if (!i->trusted &&
      81   [ +  +  +  + ]:        372 :             IN_SET(type, _SD_BUS_VTABLE_METHOD, _SD_BUS_VTABLE_WRITABLE_PROPERTY) &&
      82         [ +  - ]:        232 :             !(flags & SD_BUS_VTABLE_UNPRIVILEGED))
      83                 :        232 :                 fputs("   <annotation name=\"org.freedesktop.systemd1.Privileged\" value=\"true\"/>\n", i->f);
      84                 :        372 : }
      85                 :            : 
      86                 :            : /* Note that "names" is both an input and an output parameter. It initially points to the first argument name in a
      87                 :            :    NULL-separated list of strings, and is then advanced with each argument, and the resulting pointer is returned. */
      88                 :        624 : static int introspect_write_arguments(struct introspect *i, const char *signature, const char **names, const char *direction) {
      89                 :            :         int r;
      90                 :            : 
      91                 :        244 :         for (;;) {
      92                 :            :                 size_t l;
      93                 :            : 
      94         [ +  + ]:        624 :                 if (!*signature)
      95                 :        380 :                         return 0;
      96                 :            : 
      97                 :        244 :                 r = signature_element_length(signature, &l);
      98         [ -  + ]:        244 :                 if (r < 0)
      99                 :          0 :                         return r;
     100                 :            : 
     101                 :        244 :                 fprintf(i->f, "   <arg type=\"%.*s\"", (int) l, signature);
     102                 :            : 
     103         [ +  + ]:        244 :                 if (**names != '\0') {
     104                 :         84 :                         fprintf(i->f, " name=\"%s\"", *names);
     105                 :         84 :                         *names += strlen(*names) + 1;
     106                 :            :                 }
     107                 :            : 
     108         [ +  + ]:        244 :                 if (direction)
     109                 :        164 :                         fprintf(i->f, " direction=\"%s\"/>\n", direction);
     110                 :            :                 else
     111                 :         80 :                         fputs("/>\n", i->f);
     112                 :            : 
     113                 :        244 :                 signature += l;
     114                 :            :         }
     115                 :            : }
     116                 :            : 
     117                 :         40 : int introspect_write_interface(struct introspect *i, const sd_bus_vtable *v) {
     118                 :         40 :         const sd_bus_vtable *vtable = v;
     119                 :         40 :         const char *names = "";
     120                 :            : 
     121         [ -  + ]:         40 :         assert(i);
     122         [ -  + ]:         40 :         assert(v);
     123                 :            : 
     124         [ +  + ]:        452 :         for (; v->type != _SD_BUS_VTABLE_END; v = bus_vtable_next(vtable, v)) {
     125                 :            : 
     126                 :            :                 /* Ignore methods, signals and properties that are
     127                 :            :                  * marked "hidden", but do show the interface
     128                 :            :                  * itself */
     129                 :            : 
     130   [ +  +  -  + ]:        412 :                 if (v->type != _SD_BUS_VTABLE_START && (v->flags & SD_BUS_VTABLE_HIDDEN))
     131                 :          0 :                         continue;
     132                 :            : 
     133   [ +  +  +  +  :        412 :                 switch (v->type) {
                      - ]
     134                 :            : 
     135                 :         40 :                 case _SD_BUS_VTABLE_START:
     136         [ +  + ]:         40 :                         if (v->flags & SD_BUS_VTABLE_DEPRECATED)
     137                 :          4 :                                 fputs("  <annotation name=\"org.freedesktop.DBus.Deprecated\" value=\"true\"/>\n", i->f);
     138                 :         40 :                         break;
     139                 :            : 
     140                 :        168 :                 case _SD_BUS_VTABLE_METHOD:
     141                 :        168 :                         fprintf(i->f, "  <method name=\"%s\">\n", v->x.method.member);
     142         [ +  + ]:        168 :                         if (bus_vtable_has_names(vtable))
     143                 :        160 :                                 names = strempty(v->x.method.names);
     144                 :        168 :                         introspect_write_arguments(i, strempty(v->x.method.signature), &names, "in");
     145                 :        168 :                         introspect_write_arguments(i, strempty(v->x.method.result), &names, "out");
     146                 :        168 :                         introspect_write_flags(i, v->type, v->flags);
     147                 :        168 :                         fputs("  </method>\n", i->f);
     148                 :        168 :                         break;
     149                 :            : 
     150                 :        160 :                 case _SD_BUS_VTABLE_PROPERTY:
     151                 :            :                 case _SD_BUS_VTABLE_WRITABLE_PROPERTY:
     152                 :        160 :                         fprintf(i->f, "  <property name=\"%s\" type=\"%s\" access=\"%s\">\n",
     153                 :            :                                 v->x.property.member,
     154                 :            :                                 v->x.property.signature,
     155         [ +  + ]:        160 :                                 v->type == _SD_BUS_VTABLE_WRITABLE_PROPERTY ? "readwrite" : "read");
     156                 :        160 :                         introspect_write_flags(i, v->type, v->flags);
     157                 :        160 :                         fputs("  </property>\n", i->f);
     158                 :        160 :                         break;
     159                 :            : 
     160                 :         44 :                 case _SD_BUS_VTABLE_SIGNAL:
     161                 :         44 :                         fprintf(i->f, "  <signal name=\"%s\">\n", v->x.signal.member);
     162         [ +  - ]:         44 :                         if (bus_vtable_has_names(vtable))
     163                 :         44 :                                 names = strempty(v->x.method.names);
     164                 :         44 :                         introspect_write_arguments(i, strempty(v->x.signal.signature), &names, NULL);
     165                 :         44 :                         introspect_write_flags(i, v->type, v->flags);
     166                 :         44 :                         fputs("  </signal>\n", i->f);
     167                 :         44 :                         break;
     168                 :            :                 }
     169                 :            : 
     170                 :        412 :         }
     171                 :            : 
     172                 :         40 :         return 0;
     173                 :            : }
     174                 :            : 
     175                 :         36 : int introspect_finish(struct introspect *i, char **ret) {
     176                 :            :         int r;
     177                 :            : 
     178         [ -  + ]:         36 :         assert(i);
     179                 :            : 
     180                 :         36 :         fputs("</node>\n", i->f);
     181                 :            : 
     182                 :         36 :         r = fflush_and_check(i->f);
     183         [ -  + ]:         36 :         if (r < 0)
     184                 :          0 :                 return r;
     185                 :            : 
     186                 :         36 :         i->f = safe_fclose(i->f);
     187                 :         36 :         *ret = TAKE_PTR(i->introspection);
     188                 :            : 
     189                 :         36 :         return 0;
     190                 :            : }
     191                 :            : 
     192                 :         20 : void introspect_free(struct introspect *i) {
     193         [ -  + ]:         20 :         assert(i);
     194                 :            : 
     195                 :            :         /* Normally introspect_finish() does all the work, this is just a backup for error paths */
     196                 :            : 
     197                 :         20 :         safe_fclose(i->f);
     198                 :         20 :         free(i->introspection);
     199                 :         20 : }

Generated by: LCOV version 1.14