2 This file is part of systemd.
4 Copyright 2013 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 #include "bus-internal.h"
21 #include "bus-introspect.h"
22 #include "bus-protocol.h"
23 #include "bus-signature.h"
26 #include "string-util.h"
29 int introspect_begin(struct introspect
*i
, bool trusted
) {
35 i
->f
= open_memstream(&i
->introspection
, &i
->size
);
39 fputs_unlocked(BUS_INTROSPECT_DOCTYPE
45 int introspect_write_default_interfaces(struct introspect
*i
, bool object_manager
) {
48 fputs_unlocked(BUS_INTROSPECT_INTERFACE_PEER
49 BUS_INTROSPECT_INTERFACE_INTROSPECTABLE
50 BUS_INTROSPECT_INTERFACE_PROPERTIES
, i
->f
);
53 fputs_unlocked(BUS_INTROSPECT_INTERFACE_OBJECT_MANAGER
, i
->f
);
58 int introspect_write_child_nodes(struct introspect
*i
, Set
*s
, const char *prefix
) {
64 while ((node
= set_steal_first(s
))) {
67 e
= object_path_startswith(node
, prefix
);
69 fprintf(i
->f
, " <node name=\"%s\"/>\n", e
);
77 static void introspect_write_flags(struct introspect
*i
, int type
, int flags
) {
78 if (flags
& SD_BUS_VTABLE_DEPRECATED
)
79 fputs_unlocked(" <annotation name=\"org.freedesktop.DBus.Deprecated\" value=\"true\"/>\n", i
->f
);
81 if (type
== _SD_BUS_VTABLE_METHOD
&& (flags
& SD_BUS_VTABLE_METHOD_NO_REPLY
))
82 fputs_unlocked(" <annotation name=\"org.freedesktop.DBus.Method.NoReply\" value=\"true\"/>\n", i
->f
);
84 if (type
== _SD_BUS_VTABLE_PROPERTY
|| type
== _SD_BUS_VTABLE_WRITABLE_PROPERTY
) {
85 if (flags
& SD_BUS_VTABLE_PROPERTY_EXPLICIT
)
86 fputs_unlocked(" <annotation name=\"org.freedesktop.systemd1.Explicit\" value=\"true\"/>\n", i
->f
);
88 if (flags
& SD_BUS_VTABLE_PROPERTY_CONST
)
89 fputs_unlocked(" <annotation name=\"org.freedesktop.DBus.Property.EmitsChangedSignal\" value=\"const\"/>\n", i
->f
);
90 else if (flags
& SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION
)
91 fputs_unlocked(" <annotation name=\"org.freedesktop.DBus.Property.EmitsChangedSignal\" value=\"invalidates\"/>\n", i
->f
);
92 else if (!(flags
& SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
))
93 fputs_unlocked(" <annotation name=\"org.freedesktop.DBus.Property.EmitsChangedSignal\" value=\"false\"/>\n", i
->f
);
97 (type
== _SD_BUS_VTABLE_METHOD
|| type
== _SD_BUS_VTABLE_WRITABLE_PROPERTY
) &&
98 !(flags
& SD_BUS_VTABLE_UNPRIVILEGED
))
99 fputs_unlocked(" <annotation name=\"org.freedesktop.systemd1.Privileged\" value=\"true\"/>\n", i
->f
);
102 static int introspect_write_arguments(struct introspect
*i
, const char *signature
, const char *direction
) {
111 r
= signature_element_length(signature
, &l
);
115 fprintf(i
->f
, " <arg type=\"%.*s\"", (int) l
, signature
);
118 fprintf(i
->f
, " direction=\"%s\"/>\n", direction
);
120 fputs_unlocked("/>\n", i
->f
);
126 int introspect_write_interface(struct introspect
*i
, const sd_bus_vtable
*v
) {
130 for (; v
->type
!= _SD_BUS_VTABLE_END
; v
++) {
132 /* Ignore methods, signals and properties that are
133 * marked "hidden", but do show the interface
136 if (v
->type
!= _SD_BUS_VTABLE_START
&& (v
->flags
& SD_BUS_VTABLE_HIDDEN
))
141 case _SD_BUS_VTABLE_START
:
142 if (v
->flags
& SD_BUS_VTABLE_DEPRECATED
)
143 fputs_unlocked(" <annotation name=\"org.freedesktop.DBus.Deprecated\" value=\"true\"/>\n", i
->f
);
146 case _SD_BUS_VTABLE_METHOD
:
147 fprintf(i
->f
, " <method name=\"%s\">\n", v
->x
.method
.member
);
148 introspect_write_arguments(i
, strempty(v
->x
.method
.signature
), "in");
149 introspect_write_arguments(i
, strempty(v
->x
.method
.result
), "out");
150 introspect_write_flags(i
, v
->type
, v
->flags
);
151 fputs_unlocked(" </method>\n", i
->f
);
154 case _SD_BUS_VTABLE_PROPERTY
:
155 case _SD_BUS_VTABLE_WRITABLE_PROPERTY
:
156 fprintf(i
->f
, " <property name=\"%s\" type=\"%s\" access=\"%s\">\n",
157 v
->x
.property
.member
,
158 v
->x
.property
.signature
,
159 v
->type
== _SD_BUS_VTABLE_WRITABLE_PROPERTY
? "readwrite" : "read");
160 introspect_write_flags(i
, v
->type
, v
->flags
);
161 fputs_unlocked(" </property>\n", i
->f
);
164 case _SD_BUS_VTABLE_SIGNAL
:
165 fprintf(i
->f
, " <signal name=\"%s\">\n", v
->x
.signal
.member
);
166 introspect_write_arguments(i
, strempty(v
->x
.signal
.signature
), NULL
);
167 introspect_write_flags(i
, v
->type
, v
->flags
);
168 fputs_unlocked(" </signal>\n", i
->f
);
177 int introspect_finish(struct introspect
*i
, sd_bus
*bus
, sd_bus_message
*m
, sd_bus_message
**reply
) {
185 fputs_unlocked("</node>\n", i
->f
);
187 r
= fflush_and_check(i
->f
);
191 r
= sd_bus_message_new_method_return(m
, &q
);
195 r
= sd_bus_message_append(q
, "s", i
->introspection
);
197 sd_bus_message_unref(q
);
205 void introspect_free(struct introspect
*i
) {
210 free(i
->introspection
);