mirror of
https://github.com/systemd/systemd.git
synced 2024-11-07 18:27:04 +03:00
bus: automatically generate minimal introspection data to find installed objects
This commit is contained in:
parent
94bbf1ba6d
commit
0a72c2bdef
@ -100,4 +100,46 @@ enum {
|
|||||||
_SD_BUS_MESSAGE_HEADER_MAX
|
_SD_BUS_MESSAGE_HEADER_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define SD_BUS_INTROSPECT_DOCTYPE \
|
||||||
|
"<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n" \
|
||||||
|
"\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
|
||||||
|
|
||||||
|
#define SD_BUS_INTROSPECT_INTERFACE_PROPERTIES \
|
||||||
|
" <interface name=\"org.freedesktop.DBus.Properties\">\n" \
|
||||||
|
" <method name=\"Get\">\n" \
|
||||||
|
" <arg name=\"interface\" direction=\"in\" type=\"s\"/>\n" \
|
||||||
|
" <arg name=\"property\" direction=\"in\" type=\"s\"/>\n" \
|
||||||
|
" <arg name=\"value\" direction=\"out\" type=\"v\"/>\n" \
|
||||||
|
" </method>\n" \
|
||||||
|
" <method name=\"GetAll\">\n" \
|
||||||
|
" <arg name=\"interface\" direction=\"in\" type=\"s\"/>\n" \
|
||||||
|
" <arg name=\"properties\" direction=\"out\" type=\"a{sv}\"/>\n" \
|
||||||
|
" </method>\n" \
|
||||||
|
" <method name=\"Set\">\n" \
|
||||||
|
" <arg name=\"interface\" direction=\"in\" type=\"s\"/>\n" \
|
||||||
|
" <arg name=\"property\" direction=\"in\" type=\"s\"/>\n" \
|
||||||
|
" <arg name=\"value\" direction=\"in\" type=\"v\"/>\n" \
|
||||||
|
" </method>\n" \
|
||||||
|
" <signal name=\"PropertiesChanged\">\n" \
|
||||||
|
" <arg type=\"s\" name=\"interface\"/>\n" \
|
||||||
|
" <arg type=\"a{sv}\" name=\"changed_properties\"/>\n" \
|
||||||
|
" <arg type=\"as\" name=\"invalidated_properties\"/>\n" \
|
||||||
|
" </signal>\n" \
|
||||||
|
" </interface>\n"
|
||||||
|
|
||||||
|
#define SD_BUS_INTROSPECT_INTERFACE_INTROSPECTABLE \
|
||||||
|
" <interface name=\"org.freedesktop.DBus.Introspectable\">\n" \
|
||||||
|
" <method name=\"Introspect\">\n" \
|
||||||
|
" <arg name=\"data\" type=\"s\" direction=\"out\"/>\n" \
|
||||||
|
" </method>\n" \
|
||||||
|
" </interface>\n"
|
||||||
|
|
||||||
|
#define SD_BUS_INTROSPECT_INTERFACE_PEER \
|
||||||
|
"<interface name=\"org.freedesktop.DBus.Peer\">\n" \
|
||||||
|
" <method name=\"Ping\"/>\n" \
|
||||||
|
" <method name=\"GetMachineId\">\n" \
|
||||||
|
" <arg type=\"s\" name=\"machine_uuid\" direction=\"out\"/>\n" \
|
||||||
|
" </method>\n" \
|
||||||
|
"</interface>\n"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "macro.h"
|
#include "macro.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
|
#include "set.h"
|
||||||
|
|
||||||
#include "sd-bus.h"
|
#include "sd-bus.h"
|
||||||
#include "bus-internal.h"
|
#include "bus-internal.h"
|
||||||
@ -1553,7 +1554,10 @@ static int process_object(sd_bus *bus, sd_bus_message *m) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found)
|
/* We found some handlers but none wanted to take this, then
|
||||||
|
* return this -- with one exception, we can handle
|
||||||
|
* introspection minimally ourselves */
|
||||||
|
if (!found || sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect"))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
sd_bus_error_set(&error,
|
sd_bus_error_set(&error,
|
||||||
@ -1571,6 +1575,98 @@ static int process_object(sd_bus *bus, sd_bus_message *m) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int process_introspect(sd_bus *bus, sd_bus_message *m) {
|
||||||
|
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
|
||||||
|
_cleanup_free_ char *introspection = NULL;
|
||||||
|
_cleanup_set_free_free_ Set *s = NULL;
|
||||||
|
_cleanup_fclose_ FILE *f = NULL;
|
||||||
|
struct object_callback *c;
|
||||||
|
Iterator i;
|
||||||
|
size_t size = 0;
|
||||||
|
char *node;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(bus);
|
||||||
|
assert(m);
|
||||||
|
|
||||||
|
if (!sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect"))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!m->path)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
s = set_new(string_hash_func, string_compare_func);
|
||||||
|
if (!s)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
HASHMAP_FOREACH(c, bus->object_callbacks, i) {
|
||||||
|
const char *e;
|
||||||
|
char *a, *p;
|
||||||
|
|
||||||
|
if (streq(c->path, "/"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (streq(m->path, "/"))
|
||||||
|
e = c->path;
|
||||||
|
else {
|
||||||
|
e = startswith(c->path, m->path);
|
||||||
|
if (!e || *e != '/')
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
a = strdup(e+1);
|
||||||
|
if (!a)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
p = strchr(a, '/');
|
||||||
|
if (p)
|
||||||
|
*p = 0;
|
||||||
|
|
||||||
|
r = set_put(s, a);
|
||||||
|
if (r < 0) {
|
||||||
|
free(a);
|
||||||
|
|
||||||
|
if (r != -EEXIST)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
f = open_memstream(&introspection, &size);
|
||||||
|
if (!f)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
fputs(SD_BUS_INTROSPECT_DOCTYPE, f);
|
||||||
|
fputs("<node>\n", f);
|
||||||
|
fputs(SD_BUS_INTROSPECT_INTERFACE_PEER, f);
|
||||||
|
fputs(SD_BUS_INTROSPECT_INTERFACE_INTROSPECTABLE, f);
|
||||||
|
|
||||||
|
while ((node = set_steal_first(s))) {
|
||||||
|
fprintf(f, " <node name=\"%s\"/>\n", node);
|
||||||
|
free(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
fputs("</node>\n", f);
|
||||||
|
|
||||||
|
fflush(f);
|
||||||
|
|
||||||
|
if (ferror(f))
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
r = sd_bus_message_new_method_return(bus, m, &reply);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = sd_bus_message_append(reply, "s", introspection);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = sd_bus_send(bus, reply, NULL);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int process_message(sd_bus *bus, sd_bus_message *m) {
|
static int process_message(sd_bus *bus, sd_bus_message *m) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -1589,7 +1685,11 @@ static int process_message(sd_bus *bus, sd_bus_message *m) {
|
|||||||
if (r != 0)
|
if (r != 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
return process_object(bus, m);
|
r = process_object(bus, m);
|
||||||
|
if (r != 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
return process_introspect(bus, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int process_running(sd_bus *bus, sd_bus_message **ret) {
|
static int process_running(sd_bus *bus, sd_bus_message **ret) {
|
||||||
|
@ -29,9 +29,10 @@
|
|||||||
#include "sd-bus-protocol.h"
|
#include "sd-bus-protocol.h"
|
||||||
|
|
||||||
/* TODO:
|
/* TODO:
|
||||||
* - implicitly add stub introspection calls
|
|
||||||
* - server side
|
* - server side
|
||||||
* - allow installing match callbacks,
|
* - allow installing match callbacks
|
||||||
|
* - anonymous auth
|
||||||
|
* - default policy
|
||||||
*
|
*
|
||||||
* Later:
|
* Later:
|
||||||
* - add page donation logic
|
* - add page donation logic
|
||||||
|
Loading…
Reference in New Issue
Block a user