From: Lennart Poettering Date: Wed, 13 Oct 2010 01:03:31 +0000 (+0200) Subject: dbus: add introspection to midlevel paths X-Git-Tag: v12~245 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=2cccbca4fdf1cc6b46da105f6588a6bbdcbbb4df dbus: add introspection to midlevel paths --- diff --git a/TODO b/TODO index c1008ab52..e09d4d3e5 100644 --- a/TODO +++ b/TODO @@ -56,8 +56,6 @@ * passphrase agent https://bugs.freedesktop.org/show_bug.cgi?id=30038 -* support dbus introspection in mid-level object paths, i.e. in /org/freedesktop/systemd/units/. - * systemctl auto-pager a la git * fsck setup diff --git a/src/dbus-job.c b/src/dbus-job.c index 0f76c7d84..667eb04a6 100644 --- a/src/dbus-job.c +++ b/src/dbus-job.c @@ -122,11 +122,72 @@ static DBusHandlerResult bus_job_message_handler(DBusConnection *connection, DBu Manager *m = data; Job *j; int r; + DBusMessage *reply; assert(connection); assert(message); assert(m); + if (streq(dbus_message_get_path(message), "/org/freedesktop/systemd1/job")) { + /* Be nice to gdbus and return introspection data for our mid-level paths */ + + if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) { + char *introspection = NULL; + FILE *f; + Iterator i; + size_t size; + + if (!(reply = dbus_message_new_method_return(message))) + goto oom; + + /* We roll our own introspection code here, instead of + * relying on bus_default_message_handler() because we + * need to generate our introspection string + * dynamically. */ + + if (!(f = open_memstream(&introspection, &size))) + goto oom; + + fputs(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE + "\n", f); + + fputs(BUS_INTROSPECTABLE_INTERFACE, f); + fputs(BUS_PEER_INTERFACE, f); + + HASHMAP_FOREACH(j, m->jobs, i) + fprintf(f, "", (unsigned long) j->id); + + fputs("\n", f); + + if (ferror(f)) { + fclose(f); + free(introspection); + goto oom; + } + + fclose(f); + + if (!introspection) + goto oom; + + if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) { + free(introspection); + goto oom; + } + + free(introspection); + + if (!dbus_connection_send(connection, reply, NULL)) + goto oom; + + dbus_message_unref(reply); + + return DBUS_HANDLER_RESULT_HANDLED; + } + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + if ((r = manager_get_job_from_dbus_path(m, dbus_message_get_path(message), &j)) < 0) { if (r == -ENOMEM) @@ -139,6 +200,12 @@ static DBusHandlerResult bus_job_message_handler(DBusConnection *connection, DBu } return bus_job_message_dispatch(j, connection, message); + +oom: + if (reply) + dbus_message_unref(reply); + + return DBUS_HANDLER_RESULT_NEED_MEMORY; } const DBusObjectPathVTable bus_job_vtable = { diff --git a/src/dbus-unit.c b/src/dbus-unit.c index b65481d19..45eba8ab5 100644 --- a/src/dbus-unit.c +++ b/src/dbus-unit.c @@ -454,11 +454,86 @@ static DBusHandlerResult bus_unit_message_handler(DBusConnection *connection, DB Manager *m = data; Unit *u; int r; + DBusMessage *reply; assert(connection); assert(message); assert(m); + if (streq(dbus_message_get_path(message), "/org/freedesktop/systemd1/unit")) { + /* Be nice to gdbus and return introspection data for our mid-level paths */ + + if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) { + char *introspection = NULL; + FILE *f; + Iterator i; + const char *k; + size_t size; + + if (!(reply = dbus_message_new_method_return(message))) + goto oom; + + /* We roll our own introspection code here, instead of + * relying on bus_default_message_handler() because we + * need to generate our introspection string + * dynamically. */ + + if (!(f = open_memstream(&introspection, &size))) + goto oom; + + fputs(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE + "\n", f); + + fputs(BUS_INTROSPECTABLE_INTERFACE, f); + fputs(BUS_PEER_INTERFACE, f); + + HASHMAP_FOREACH_KEY(u, k, m->units, i) { + char *p; + + if (k != u->meta.id) + continue; + + if (!(p = bus_path_escape(k))) { + fclose(f); + free(introspection); + goto oom; + } + + fprintf(f, "", p); + free(p); + } + + fputs("\n", f); + + if (ferror(f)) { + fclose(f); + free(introspection); + goto oom; + } + + fclose(f); + + if (!introspection) + goto oom; + + if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) { + free(introspection); + goto oom; + } + + free(introspection); + + if (!dbus_connection_send(connection, reply, NULL)) + goto oom; + + dbus_message_unref(reply); + + return DBUS_HANDLER_RESULT_HANDLED; + } + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + if ((r = manager_get_unit_from_dbus_path(m, dbus_message_get_path(message), &u)) < 0) { if (r == -ENOMEM) @@ -471,6 +546,12 @@ static DBusHandlerResult bus_unit_message_handler(DBusConnection *connection, DB } return bus_unit_message_dispatch(u, connection, message); + +oom: + if (reply) + dbus_message_unref(reply); + + return DBUS_HANDLER_RESULT_NEED_MEMORY; } const DBusObjectPathVTable bus_unit_vtable = {