LCOV - code coverage report
Current view: top level - libsystemd/sd-bus - bus-introspect.c (source / functions) Hit Total Coverage
Test: systemd test coverage Lines: 97 105 92.4 %
Date: 2015-07-29 18:47:03 Functions: 8 8 100.0 %

          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 "util.h"
      23             : #include "bus-introspect.h"
      24             : #include "bus-signature.h"
      25             : #include "bus-internal.h"
      26             : #include "bus-protocol.h"
      27             : 
      28           5 : int introspect_begin(struct introspect *i, bool trusted) {
      29           5 :         assert(i);
      30             : 
      31           5 :         zero(*i);
      32           5 :         i->trusted = trusted;
      33             : 
      34           5 :         i->f = open_memstream(&i->introspection, &i->size);
      35           5 :         if (!i->f)
      36           0 :                 return -ENOMEM;
      37             : 
      38           5 :         fputs(BUS_INTROSPECT_DOCTYPE
      39             :               "<node>\n", i->f);
      40             : 
      41           5 :         return 0;
      42             : }
      43             : 
      44           4 : int introspect_write_default_interfaces(struct introspect *i, bool object_manager) {
      45           4 :         assert(i);
      46             : 
      47           4 :         fputs(BUS_INTROSPECT_INTERFACE_PEER
      48             :               BUS_INTROSPECT_INTERFACE_INTROSPECTABLE
      49             :               BUS_INTROSPECT_INTERFACE_PROPERTIES, i->f);
      50             : 
      51           4 :         if (object_manager)
      52           2 :                 fputs(BUS_INTROSPECT_INTERFACE_OBJECT_MANAGER, i->f);
      53             : 
      54           4 :         return 0;
      55             : }
      56             : 
      57           4 : int introspect_write_child_nodes(struct introspect *i, Set *s, const char *prefix) {
      58             :         char *node;
      59             : 
      60           4 :         assert(i);
      61           4 :         assert(prefix);
      62             : 
      63          25 :         while ((node = set_steal_first(s))) {
      64             :                 const char *e;
      65             : 
      66          17 :                 e = object_path_startswith(node, prefix);
      67          17 :                 if (e && e[0])
      68          17 :                         fprintf(i->f, " <node name=\"%s\"/>\n", e);
      69             : 
      70          17 :                 free(node);
      71             :         }
      72             : 
      73           4 :         return 0;
      74             : }
      75             : 
      76          36 : static void introspect_write_flags(struct introspect *i, int type, int flags) {
      77          36 :         if (flags & SD_BUS_VTABLE_DEPRECATED)
      78           4 :                 fputs("   <annotation name=\"org.freedesktop.DBus.Deprecated\" value=\"true\"/>\n", i->f);
      79             : 
      80          36 :         if (type == _SD_BUS_VTABLE_METHOD && (flags & SD_BUS_VTABLE_METHOD_NO_REPLY))
      81           1 :                 fputs("   <annotation name=\"org.freedesktop.DBus.Method.NoReply\" value=\"true\"/>\n", i->f);
      82             : 
      83          36 :         if (type == _SD_BUS_VTABLE_PROPERTY || type == _SD_BUS_VTABLE_WRITABLE_PROPERTY) {
      84          15 :                 if (flags & SD_BUS_VTABLE_PROPERTY_CONST)
      85           2 :                         fputs("   <annotation name=\"org.freedesktop.DBus.Property.EmitsChangedSignal\" value=\"const\"/>\n", i->f);
      86          13 :                 else if (flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION)
      87           2 :                         fputs("   <annotation name=\"org.freedesktop.DBus.Property.EmitsChangedSignal\" value=\"invalidates\"/>\n", i->f);
      88          11 :                 else if (!(flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE))
      89           9 :                         fputs("   <annotation name=\"org.freedesktop.DBus.Property.EmitsChangedSignal\" value=\"false\"/>\n", i->f);
      90             :         }
      91             : 
      92          36 :         if (!i->trusted &&
      93          43 :             (type == _SD_BUS_VTABLE_METHOD || type == _SD_BUS_VTABLE_WRITABLE_PROPERTY) &&
      94          26 :             !(flags & SD_BUS_VTABLE_UNPRIVILEGED))
      95          26 :                 fputs("   <annotation name=\"org.freedesktop.systemd1.Privileged\" value=\"true\"/>\n", i->f);
      96          36 : }
      97             : 
      98          53 : static int introspect_write_arguments(struct introspect *i, const char *signature, const char *direction) {
      99             :         int r;
     100             : 
     101             :         for (;;) {
     102             :                 size_t l;
     103             : 
     104          53 :                 if (!*signature)
     105          80 :                         return 0;
     106             : 
     107          13 :                 r = signature_element_length(signature, &l);
     108          13 :                 if (r < 0)
     109           0 :                         return r;
     110             : 
     111          13 :                 fprintf(i->f, "   <arg type=\"%.*s\"", (int) l, signature);
     112             : 
     113          13 :                 if (direction)
     114           8 :                         fprintf(i->f, " direction=\"%s\"/>\n", direction);
     115             :                 else
     116           5 :                         fputs("/>\n", i->f);
     117             : 
     118          13 :                 signature += l;
     119          13 :         }
     120             : }
     121             : 
     122           4 : int introspect_write_interface(struct introspect *i, const sd_bus_vtable *v) {
     123           4 :         assert(i);
     124           4 :         assert(v);
     125             : 
     126          44 :         for (; v->type != _SD_BUS_VTABLE_END; v++) {
     127             : 
     128             :                 /* Ignore methods, signals and properties that are
     129             :                  * marked "hidden", but do show the interface
     130             :                  * itself */
     131             : 
     132          40 :                 if (v->type != _SD_BUS_VTABLE_START && (v->flags & SD_BUS_VTABLE_HIDDEN))
     133           0 :                         continue;
     134             : 
     135          40 :                 switch (v->type) {
     136             : 
     137             :                 case _SD_BUS_VTABLE_START:
     138           4 :                         if (v->flags & SD_BUS_VTABLE_DEPRECATED)
     139           0 :                                 fputs("  <annotation name=\"org.freedesktop.DBus.Deprecated\" value=\"true\"/>\n", i->f);
     140           4 :                         break;
     141             : 
     142             :                 case _SD_BUS_VTABLE_METHOD:
     143          19 :                         fprintf(i->f, "  <method name=\"%s\">\n", v->x.method.member);
     144          19 :                         introspect_write_arguments(i, strempty(v->x.method.signature), "in");
     145          19 :                         introspect_write_arguments(i, strempty(v->x.method.result), "out");
     146          19 :                         introspect_write_flags(i, v->type, v->flags);
     147          19 :                         fputs("  </method>\n", i->f);
     148          19 :                         break;
     149             : 
     150             :                 case _SD_BUS_VTABLE_PROPERTY:
     151             :                 case _SD_BUS_VTABLE_WRITABLE_PROPERTY:
     152          15 :                         fprintf(i->f, "  <property name=\"%s\" type=\"%s\" access=\"%s\">\n",
     153             :                                 v->x.property.member,
     154             :                                 v->x.property.signature,
     155          15 :                                 v->type == _SD_BUS_VTABLE_WRITABLE_PROPERTY ? "readwrite" : "read");
     156          15 :                         introspect_write_flags(i, v->type, v->flags);
     157          15 :                         fputs("  </property>\n", i->f);
     158          15 :                         break;
     159             : 
     160             :                 case _SD_BUS_VTABLE_SIGNAL:
     161           2 :                         fprintf(i->f, "  <signal name=\"%s\">\n", v->x.signal.member);
     162           2 :                         introspect_write_arguments(i, strempty(v->x.signal.signature), NULL);
     163           2 :                         introspect_write_flags(i, v->type, v->flags);
     164           2 :                         fputs("  </signal>\n", i->f);
     165           2 :                         break;
     166             :                 }
     167             : 
     168             :         }
     169             : 
     170           4 :         return 0;
     171             : }
     172             : 
     173           4 : int introspect_finish(struct introspect *i, sd_bus *bus, sd_bus_message *m, sd_bus_message **reply) {
     174             :         sd_bus_message *q;
     175             :         int r;
     176             : 
     177           4 :         assert(i);
     178           4 :         assert(m);
     179           4 :         assert(reply);
     180             : 
     181           4 :         fputs("</node>\n", i->f);
     182           4 :         fflush(i->f);
     183             : 
     184           4 :         if (ferror(i->f))
     185           0 :                 return -ENOMEM;
     186             : 
     187           4 :         r = sd_bus_message_new_method_return(m, &q);
     188           4 :         if (r < 0)
     189           0 :                 return r;
     190             : 
     191           4 :         r = sd_bus_message_append(q, "s", i->introspection);
     192           4 :         if (r < 0) {
     193           0 :                 sd_bus_message_unref(q);
     194           0 :                 return r;
     195             :         }
     196             : 
     197           4 :         *reply = q;
     198           4 :         return 0;
     199             : }
     200             : 
     201           5 : void introspect_free(struct introspect *i) {
     202           5 :         assert(i);
     203             : 
     204           5 :         if (i->f)
     205           5 :                 fclose(i->f);
     206             : 
     207           5 :         if (i->introspection)
     208           5 :                 free(i->introspection);
     209             : 
     210           5 :         zero(*i);
     211           5 : }

Generated by: LCOV version 1.11