diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/dbus-job.c | 67 | ||||
-rw-r--r-- | src/dbus-unit.c | 81 |
2 files changed, 148 insertions, 0 deletions
diff --git a/src/dbus-job.c b/src/dbus-job.c index 0f76c7d843..667eb04a69 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 + "<node>\n", f); + + fputs(BUS_INTROSPECTABLE_INTERFACE, f); + fputs(BUS_PEER_INTERFACE, f); + + HASHMAP_FOREACH(j, m->jobs, i) + fprintf(f, "<node name=\"job/%lu\"/>", (unsigned long) j->id); + + fputs("</node>\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 b65481d193..45eba8ab55 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 + "<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, "<node name=\"%s\"/>", p); + free(p); + } + + fputs("</node>\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 = { |