summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libsystemd/sd-bus/bus-introspect.c21
-rw-r--r--src/libsystemd/sd-bus/bus-introspect.h2
-rw-r--r--src/libsystemd/sd-bus/bus-objects.c66
-rw-r--r--src/libsystemd/sd-bus/bus-objects.h10
-rw-r--r--src/libsystemd/sd-bus/test-bus-introspect.c17
5 files changed, 75 insertions, 41 deletions
diff --git a/src/libsystemd/sd-bus/bus-introspect.c b/src/libsystemd/sd-bus/bus-introspect.c
index 022eddb10f..beab80687d 100644
--- a/src/libsystemd/sd-bus/bus-introspect.c
+++ b/src/libsystemd/sd-bus/bus-introspect.c
@@ -172,13 +172,10 @@ int introspect_write_interface(struct introspect *i, const sd_bus_vtable *v) {
return 0;
}
-int introspect_finish(struct introspect *i, sd_bus *bus, sd_bus_message *m, sd_bus_message **reply) {
- sd_bus_message *q;
+int introspect_finish(struct introspect *i, char **ret) {
int r;
assert(i);
- assert(m);
- assert(reply);
fputs("</node>\n", i->f);
@@ -186,25 +183,17 @@ int introspect_finish(struct introspect *i, sd_bus *bus, sd_bus_message *m, sd_b
if (r < 0)
return r;
- r = sd_bus_message_new_method_return(m, &q);
- if (r < 0)
- return r;
-
- r = sd_bus_message_append(q, "s", i->introspection);
- if (r < 0) {
- sd_bus_message_unref(q);
- return r;
- }
+ i->f = safe_fclose(i->f);
+ *ret = TAKE_PTR(i->introspection);
- *reply = q;
return 0;
}
void introspect_free(struct introspect *i) {
assert(i);
- safe_fclose(i->f);
+ /* Normally introspect_finish() does all the work, this is just a backup for error paths */
+ safe_fclose(i->f);
free(i->introspection);
- zero(*i);
}
diff --git a/src/libsystemd/sd-bus/bus-introspect.h b/src/libsystemd/sd-bus/bus-introspect.h
index bb2dd7ef7b..ccbb543d0c 100644
--- a/src/libsystemd/sd-bus/bus-introspect.h
+++ b/src/libsystemd/sd-bus/bus-introspect.h
@@ -18,5 +18,5 @@ int introspect_begin(struct introspect *i, bool trusted);
int introspect_write_default_interfaces(struct introspect *i, bool object_manager);
int introspect_write_child_nodes(struct introspect *i, Set *s, const char *prefix);
int introspect_write_interface(struct introspect *i, const sd_bus_vtable *v);
-int introspect_finish(struct introspect *i, sd_bus *bus, sd_bus_message *m, sd_bus_message **reply);
+int introspect_finish(struct introspect *i, char **ret);
void introspect_free(struct introspect *i);
diff --git a/src/libsystemd/sd-bus/bus-objects.c b/src/libsystemd/sd-bus/bus-objects.c
index 650cee63af..22db75479c 100644
--- a/src/libsystemd/sd-bus/bus-objects.c
+++ b/src/libsystemd/sd-bus/bus-objects.c
@@ -883,15 +883,15 @@ static int bus_node_exists(
return 0;
}
-static int process_introspect(
+int introspect_path(
sd_bus *bus,
- sd_bus_message *m,
+ const char *path,
struct node *n,
bool require_fallback,
- bool *found_object) {
+ bool *found_object,
+ char **ret,
+ sd_bus_error *error) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_set_free_free_ Set *s = NULL;
const char *previous_interface = NULL;
_cleanup_(introspect_free) struct introspect intro = {};
@@ -899,14 +899,9 @@ static int process_introspect(
bool empty;
int r;
- assert(bus);
- assert(m);
- assert(n);
- assert(found_object);
-
- r = get_child_nodes(bus, m->path, n, 0, &s, &error);
+ r = get_child_nodes(bus, path, n, 0, &s, error);
if (r < 0)
- return bus_maybe_reply_error(m, r, &error);
+ return r;
if (bus->nodes_modified)
return 0;
@@ -924,9 +919,9 @@ static int process_introspect(
if (require_fallback && !c->is_fallback)
continue;
- r = node_vtable_get_userdata(bus, m->path, c, NULL, &error);
+ r = node_vtable_get_userdata(bus, path, c, NULL, error);
if (r < 0)
- return bus_maybe_reply_error(m, r, &error);
+ return r;
if (bus->nodes_modified)
return 0;
if (r == 0)
@@ -957,20 +952,55 @@ static int process_introspect(
if (empty) {
/* Nothing?, let's see if we exist at all, and if not
* refuse to do anything */
- r = bus_node_exists(bus, n, m->path, require_fallback);
+ r = bus_node_exists(bus, n, path, require_fallback);
if (r <= 0)
- return bus_maybe_reply_error(m, r, &error);
+ return r;
if (bus->nodes_modified)
return 0;
}
*found_object = true;
- r = introspect_write_child_nodes(&intro, s, m->path);
+ r = introspect_write_child_nodes(&intro, s, path);
+ if (r < 0)
+ return r;
+
+ r = introspect_finish(&intro, ret);
+ if (r < 0)
+ return r;
+
+ return 1;
+}
+
+static int process_introspect(
+ sd_bus *bus,
+ sd_bus_message *m,
+ struct node *n,
+ bool require_fallback,
+ bool *found_object) {
+
+ _cleanup_free_ char *s = NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ int r;
+
+ assert(bus);
+ assert(m);
+ assert(n);
+ assert(found_object);
+
+ r = introspect_path(bus, m->path, n, require_fallback, found_object, &s, &error);
+ if (r < 0)
+ return bus_maybe_reply_error(m, r, &error);
+ if (r == 0)
+ /* nodes_modified == true */
+ return 0;
+
+ r = sd_bus_message_new_method_return(m, &reply);
if (r < 0)
return r;
- r = introspect_finish(&intro, bus, m, &reply);
+ r = sd_bus_message_append(reply, "s", s);
if (r < 0)
return r;
diff --git a/src/libsystemd/sd-bus/bus-objects.h b/src/libsystemd/sd-bus/bus-objects.h
index b45fe6323e..7f38853da1 100644
--- a/src/libsystemd/sd-bus/bus-objects.h
+++ b/src/libsystemd/sd-bus/bus-objects.h
@@ -2,8 +2,18 @@
#pragma once
#include "bus-internal.h"
+#include "bus-introspect.h"
const sd_bus_vtable* bus_vtable_next(const sd_bus_vtable *vtable, const sd_bus_vtable *v);
bool bus_vtable_has_names(const sd_bus_vtable *vtable);
int bus_process_object(sd_bus *bus, sd_bus_message *m);
void bus_node_gc(sd_bus *b, struct node *n);
+
+int introspect_path(
+ sd_bus *bus,
+ const char *path,
+ struct node *n,
+ bool require_fallback,
+ bool *found_object,
+ char **ret,
+ sd_bus_error *error);
diff --git a/src/libsystemd/sd-bus/test-bus-introspect.c b/src/libsystemd/sd-bus/test-bus-introspect.c
index 968de40e5a..797b19f9f1 100644
--- a/src/libsystemd/sd-bus/test-bus-introspect.c
+++ b/src/libsystemd/sd-bus/test-bus-introspect.c
@@ -27,10 +27,9 @@ static const sd_bus_vtable vtable[] = {
SD_BUS_VTABLE_END
};
-int main(int argc, char *argv[]) {
- _cleanup_(introspect_free) struct introspect intro = {};
-
- test_setup_logging(LOG_DEBUG);
+static void test_manual_introspection(void) {
+ struct introspect intro = {};
+ _cleanup_free_ char *s = NULL;
assert_se(introspect_begin(&intro, false) >= 0);
@@ -38,8 +37,14 @@ int main(int argc, char *argv[]) {
assert_se(introspect_write_interface(&intro, vtable) >= 0);
fputs(" </interface>\n", intro.f);
- fflush(intro.f);
- fputs(intro.introspection, stdout);
+ assert_se(introspect_finish(&intro, &s) == 0);
+ fputs(s, stdout);
+}
+
+int main(int argc, char *argv[]) {
+ test_setup_logging(LOG_DEBUG);
+
+ test_manual_introspection();
return 0;
}