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