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