]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
bus-introspect: write <interface> from within introspect_write_interface()
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Mon, 13 Apr 2020 11:34:09 +0000 (13:34 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Sun, 3 May 2020 08:55:51 +0000 (10:55 +0200)
src/libsystemd/sd-bus/bus-introspect.c
src/libsystemd/sd-bus/bus-introspect.h
src/libsystemd/sd-bus/bus-objects.c
src/libsystemd/sd-bus/test-bus-introspect.c

index 07bd98967d6fe8ce8fae4728b2f1c2369724cd67..3e2bfc566bc1cdaa6fb4bc9cceb1878e1ac83030 100644 (file)
@@ -40,12 +40,27 @@ int introspect_write_default_interfaces(struct introspect *i, bool object_manage
         return 0;
 }
 
+static int set_interface_name(struct introspect *intro, const char *interface_name) {
+        if (streq_ptr(intro->interface_name, interface_name))
+                return 0;
+
+        if (intro->interface_name)
+                fputs(" </interface>\n", intro->f);
+
+        if (interface_name)
+                fprintf(intro->f, " <interface name=\"%s\">\n", interface_name);
+
+        return free_and_strdup(&intro->interface_name, interface_name);
+}
+
 int introspect_write_child_nodes(struct introspect *i, Set *s, const char *prefix) {
         char *node;
 
         assert(i);
         assert(prefix);
 
+        assert_se(set_interface_name(i, NULL) >= 0);
+
         while ((node = set_steal_first(s))) {
                 const char *e;
 
@@ -115,13 +130,23 @@ static int introspect_write_arguments(struct introspect *i, const char *signatur
         }
 }
 
-int introspect_write_interface(struct introspect *i, const sd_bus_vtable *v) {
+int introspect_write_interface(
+                struct introspect *i,
+                const char *interface_name,
+                const sd_bus_vtable *v) {
+
         const sd_bus_vtable *vtable = v;
         const char *names = "";
+        int r;
 
         assert(i);
+        assert(interface_name);
         assert(v);
 
+        r = set_interface_name(i, interface_name);
+        if (r < 0)
+                return r;
+
         for (; v->type != _SD_BUS_VTABLE_END; v = bus_vtable_next(vtable, v)) {
 
                 /* Ignore methods, signals and properties that are
@@ -178,6 +203,8 @@ int introspect_finish(struct introspect *i, char **ret) {
 
         assert(i);
 
+        assert_se(set_interface_name(i, NULL) >= 0);
+
         fputs("</node>\n", i->f);
 
         r = fflush_and_check(i->f);
@@ -196,5 +223,6 @@ void introspect_free(struct introspect *i) {
         /* Normally introspect_finish() does all the work, this is just a backup for error paths */
 
         safe_fclose(i->f);
+        free(i->interface_name);
         free(i->introspection);
 }
index ccbb543d0c9d491133fae5327885ba4a2d950365..19d39923e5d7922c8a1cd0bfaf75e641df192ece 100644 (file)
@@ -9,6 +9,7 @@
 
 struct introspect {
         FILE *f;
+        char *interface_name;
         char *introspection;
         size_t size;
         bool trusted;
@@ -17,6 +18,9 @@ struct introspect {
 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_write_interface(
+                struct introspect *i,
+                const char *interface_name,
+                const sd_bus_vtable *v);
 int introspect_finish(struct introspect *i, char **ret);
 void introspect_free(struct introspect *i);
index 913d6eca8a9c3705390398526d6bb97070fd8fc1..eaf230709b62c02de0394891235c48613183e659 100644 (file)
@@ -939,7 +939,6 @@ int introspect_path(
                 sd_bus_error *error) {
 
         _cleanup_set_free_free_ Set *s = NULL;
-        const char *previous_interface = NULL;
         _cleanup_(introspect_free) struct introspect intro = {};
         struct node_vtable *c;
         bool empty;
@@ -984,23 +983,11 @@ int introspect_path(
                 if (c->vtable[0].flags & SD_BUS_VTABLE_HIDDEN)
                         continue;
 
-                if (!streq_ptr(previous_interface, c->interface)) {
-                        if (previous_interface)
-                                fputs(" </interface>\n", intro.f);
-
-                        fprintf(intro.f, " <interface name=\"%s\">\n", c->interface);
-                }
-
-                r = introspect_write_interface(&intro, c->vtable);
+                r = introspect_write_interface(&intro, c->interface, c->vtable);
                 if (r < 0)
                         return r;
-
-                previous_interface = c->interface;
         }
 
-        if (previous_interface)
-                fputs(" </interface>\n", intro.f);
-
         if (empty) {
                 /* Nothing?, let's see if we exist at all, and if not
                  * refuse to do anything */
index 9c8d1434b139565c8888e77832d2f6a58ae8bdcb..cbc31589241c14b1517c6ae0b9017987e65d0025 100644 (file)
@@ -14,11 +14,11 @@ static void test_manual_introspection(const sd_bus_vtable vtable[]) {
 
         assert_se(introspect_begin(&intro, false) >= 0);
 
-        fprintf(intro.f, " <interface name=\"org.foo\">\n");
-        assert_se(introspect_write_interface(&intro, vtable) >= 0);
-        fputs(" </interface>\n", intro.f);
-
+        assert_se(introspect_write_interface(&intro, "org.foo", vtable) >= 0);
+        /* write again to check if output looks OK for a different interface */
+        assert_se(introspect_write_interface(&intro, "org.foo.bar", vtable) >= 0);
         assert_se(introspect_finish(&intro, &s) == 0);
+
         fputs(s, stdout);
         fputs("\n", stdout);
 }