sd-bus: split introspection into the content creation and reply creation parts

Just moving code around, in preparation to allow the content creation
part to be used in other places.

On the surface of things, introspect_path() should be in bus-introspect.c, but
introspect_path() uses many static helper functions in bus-objects.c, so moving
it would require all of them to be exposed, which is too much trouble.

test-bus-introspect is updated to actually write the closing bracket.
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2019-04-19 12:14:35 +02:00
parent 2abda6d1e4
commit dff9e25a76
5 changed files with 75 additions and 41 deletions

View file

@ -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;
i->f = safe_fclose(i->f);
*ret = TAKE_PTR(i->introspection);
r = sd_bus_message_append(q, "s", i->introspection);
if (r < 0) {
sd_bus_message_unref(q);
return r;
}
*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);
}

View file

@ -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);

View file

@ -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, bus, m, &reply);
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 = sd_bus_message_append(reply, "s", s);
if (r < 0)
return r;

View file

@ -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);

View file

@ -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;
}