Merge pull request #12351 from keszybz/sd-bus-add-symbol

Add symbol to tell the linker that new libsystemd version is needed
This commit is contained in:
Lennart Poettering
2019-04-24 10:23:10 +02:00
committed by GitHub
18 changed files with 935 additions and 223 deletions
+13
View File
@@ -50,6 +50,7 @@ static size_t arg_snaplen = 4096;
static bool arg_list = false;
static bool arg_quiet = false;
static bool arg_verbose = false;
static bool arg_xml_interface = false;
static bool arg_expect_reply = true;
static bool arg_auto_start = true;
static bool arg_allow_interactive_authorization = true;
@@ -948,6 +949,12 @@ static int introspect(int argc, char **argv, void *userdata) {
if (r < 0)
return bus_log_parse_error(r);
if (arg_xml_interface) {
/* Just dump the received XML and finish */
puts(xml);
return 0;
}
/* First, get list of all properties */
r = parse_xml_introspect(argv[2], xml, &ops, members);
if (r < 0)
@@ -2255,6 +2262,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_SIZE,
ARG_LIST,
ARG_VERBOSE,
ARG_XML_INTERFACE,
ARG_EXPECT_REPLY,
ARG_AUTO_START,
ARG_ALLOW_INTERACTIVE_AUTHORIZATION,
@@ -2284,6 +2292,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "list", no_argument, NULL, ARG_LIST },
{ "quiet", no_argument, NULL, 'q' },
{ "verbose", no_argument, NULL, ARG_VERBOSE },
{ "xml-interface", no_argument, NULL, ARG_XML_INTERFACE },
{ "expect-reply", required_argument, NULL, ARG_EXPECT_REPLY },
{ "auto-start", required_argument, NULL, ARG_AUTO_START },
{ "allow-interactive-authorization", required_argument, NULL, ARG_ALLOW_INTERACTIVE_AUTHORIZATION },
@@ -2388,6 +2397,10 @@ static int parse_argv(int argc, char *argv[]) {
arg_verbose = true;
break;
case ARG_XML_INTERFACE:
arg_xml_interface = true;
break;
case ARG_EXPECT_REPLY:
r = parse_boolean(optarg);
if (r < 0)
+5
View File
@@ -676,3 +676,8 @@ LIBSYSTEMD_241 {
global:
sd_bus_close_unref;
} LIBSYSTEMD_240;
LIBSYSTEMD_243 {
global:
sd_bus_object_vtable_format;
} LIBSYSTEMD_241;
+5 -16
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);
}
+1 -1
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);
+85 -59
View File
@@ -22,7 +22,7 @@ static int node_vtable_get_userdata(
sd_bus_error *error) {
sd_bus_slot *s;
void *u, *found_u;
void *u, *found_u = NULL;
int r;
assert(bus);
@@ -883,31 +883,33 @@ 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 ignore_nodes_modified,
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;
struct introspect intro;
_cleanup_(introspect_free) struct introspect intro = {};
struct node_vtable *c;
bool empty;
int r;
assert(bus);
assert(m);
assert(n);
assert(found_object);
if (!n) {
n = hashmap_get(bus->nodes, path);
if (!n)
return -ENOENT;
}
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);
if (bus->nodes_modified)
return r;
if (bus->nodes_modified && !ignore_nodes_modified)
return 0;
r = introspect_begin(&intro, bus->trusted);
@@ -924,15 +926,11 @@ static int process_introspect(
if (require_fallback && !c->is_fallback)
continue;
r = node_vtable_get_userdata(bus, m->path, c, NULL, &error);
if (r < 0) {
r = bus_maybe_reply_error(m, r, &error);
goto finish;
}
if (bus->nodes_modified) {
r = 0;
goto finish;
}
r = node_vtable_get_userdata(bus, path, c, NULL, error);
if (r < 0)
return r;
if (bus->nodes_modified && !ignore_nodes_modified)
return 0;
if (r == 0)
continue;
@@ -942,7 +940,6 @@ static int process_introspect(
continue;
if (!streq_ptr(previous_interface, c->interface)) {
if (previous_interface)
fputs(" </interface>\n", intro.f);
@@ -951,7 +948,7 @@ static int process_introspect(
r = introspect_write_interface(&intro, c->vtable);
if (r < 0)
goto finish;
return r;
previous_interface = c->interface;
}
@@ -962,36 +959,64 @@ 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);
if (r <= 0) {
r = bus_maybe_reply_error(m, r, &error);
goto finish;
}
if (bus->nodes_modified) {
r = 0;
goto finish;
}
r = bus_node_exists(bus, n, path, require_fallback);
if (r <= 0)
return r;
if (bus->nodes_modified && !ignore_nodes_modified)
return 0;
}
*found_object = true;
if (found_object)
*found_object = true;
r = introspect_write_child_nodes(&intro, s, m->path);
r = introspect_write_child_nodes(&intro, s, path);
if (r < 0)
goto finish;
return r;
r = introspect_finish(&intro, bus, m, &reply);
r = introspect_finish(&intro, ret);
if (r < 0)
goto finish;
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, false, 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;
r = sd_bus_send(bus, reply, NULL);
if (r < 0)
goto finish;
return r;
r = 1;
finish:
introspect_free(&intro);
return r;
return 1;
}
static int object_manager_serialize_path(
@@ -1668,7 +1693,7 @@ static bool names_are_valid(const char *signature, const char **names, names_fla
/* the current version of this struct is defined in sd-bus-vtable.h, but we need to list here the historical versions
to make sure the calling code is compatible with one of these */
struct sd_bus_vtable_original {
struct sd_bus_vtable_221 {
uint8_t type:8;
uint64_t flags:56;
union {
@@ -1696,12 +1721,16 @@ struct sd_bus_vtable_original {
} x;
};
/* Structure size up to v241 */
#define VTABLE_ELEMENT_SIZE_ORIGINAL sizeof(struct sd_bus_vtable_original)
/* Current structure size */
#define VTABLE_ELEMENT_SIZE sizeof(struct sd_bus_vtable)
#define VTABLE_ELEMENT_SIZE_221 sizeof(struct sd_bus_vtable_221)
/* Size of the structure when "features" field was added. If the structure definition is augmented, a copy of
* the structure definition will need to be made (similarly to the sd_bus_vtable_221 above), and this
* definition updated to refer to it. */
#define VTABLE_ELEMENT_SIZE_242 sizeof(struct sd_bus_vtable)
static int vtable_features(const sd_bus_vtable *vtable) {
if (vtable[0].x.start.element_size == VTABLE_ELEMENT_SIZE_ORIGINAL)
if (vtable[0].x.start.element_size < VTABLE_ELEMENT_SIZE_242 ||
!vtable[0].x.start.vtable_format_reference)
return 0;
return vtable[0].x.start.features;
}
@@ -1711,13 +1740,7 @@ bool bus_vtable_has_names(const sd_bus_vtable *vtable) {
}
const sd_bus_vtable* bus_vtable_next(const sd_bus_vtable *vtable, const sd_bus_vtable *v) {
if (vtable[0].x.start.element_size == VTABLE_ELEMENT_SIZE_ORIGINAL) {
const struct sd_bus_vtable_original *v2 = (const struct sd_bus_vtable_original *)v;
v2++;
v = (const sd_bus_vtable*)v2;
} else /* current version */
v++;
return v;
return (const sd_bus_vtable*) ((char*) v + vtable[0].x.start.element_size);
}
static int add_object_vtable_internal(
@@ -1744,8 +1767,8 @@ static int add_object_vtable_internal(
assert_return(interface_name_is_valid(interface), -EINVAL);
assert_return(vtable, -EINVAL);
assert_return(vtable[0].type == _SD_BUS_VTABLE_START, -EINVAL);
assert_return(vtable[0].x.start.element_size == VTABLE_ELEMENT_SIZE_ORIGINAL ||
vtable[0].x.start.element_size == VTABLE_ELEMENT_SIZE,
assert_return(vtable[0].x.start.element_size == VTABLE_ELEMENT_SIZE_221 ||
vtable[0].x.start.element_size >= VTABLE_ELEMENT_SIZE_242,
-EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
assert_return(!streq(interface, "org.freedesktop.DBus.Properties") &&
@@ -1928,6 +1951,9 @@ fail:
return r;
}
/* This symbol exists solely to tell the linker that the "new" vtable format is used. */
_public_ const unsigned sd_bus_object_vtable_format = 242;
_public_ int sd_bus_add_object_vtable(
sd_bus *bus,
sd_bus_slot **slot,
+11
View File
@@ -2,8 +2,19 @@
#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 ignore_nodes_modified,
bool *found_object,
char **ret,
sd_bus_error *error);
+16 -28
View File
@@ -4,33 +4,13 @@
#include "log.h"
#include "tests.h"
static int prop_get(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
return -EINVAL;
}
#include "test-vtable-data.h"
static int prop_set(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
return -EINVAL;
}
static void test_manual_introspection(const sd_bus_vtable vtable[]) {
struct introspect intro = {};
_cleanup_free_ char *s = NULL;
static const sd_bus_vtable vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_METHOD("Hello", "ssas", "a(uu)", NULL, 0),
SD_BUS_METHOD("DeprecatedHello", "", "", NULL, SD_BUS_VTABLE_DEPRECATED),
SD_BUS_METHOD("DeprecatedHelloNoReply", "", "", NULL, SD_BUS_VTABLE_DEPRECATED|SD_BUS_VTABLE_METHOD_NO_REPLY),
SD_BUS_SIGNAL("Wowza", "sss", 0),
SD_BUS_SIGNAL("DeprecatedWowza", "ut", SD_BUS_VTABLE_DEPRECATED),
SD_BUS_WRITABLE_PROPERTY("AProperty", "s", prop_get, prop_set, 0, 0),
SD_BUS_PROPERTY("AReadOnlyDeprecatedProperty", "(ut)", prop_get, 0, SD_BUS_VTABLE_DEPRECATED),
SD_BUS_PROPERTY("ChangingProperty", "t", prop_get, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("Invalidating", "t", prop_get, 0, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
SD_BUS_PROPERTY("Constant", "t", prop_get, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_PROPERTY_EXPLICIT),
SD_BUS_VTABLE_END
};
int main(int argc, char *argv[]) {
struct introspect intro;
test_setup_logging(LOG_DEBUG);
log_info("/* %s */", __func__);
assert_se(introspect_begin(&intro, false) >= 0);
@@ -38,10 +18,18 @@ 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);
fputs("\n", stdout);
}
introspect_free(&intro);
int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG);
test_manual_introspection(test_vtable_1);
test_manual_introspection(test_vtable_2);
test_manual_introspection(test_vtable_deprecated);
test_manual_introspection((const sd_bus_vtable *) vtable_format_221);
return 0;
}
+20 -112
View File
@@ -1,3 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include <stdbool.h>
#include <stddef.h>
@@ -5,120 +7,18 @@
#undef NDEBUG
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include "sd-bus-vtable.h"
#ifndef __cplusplus
# include "bus-objects.h"
#endif
#include "test-vtable-data.h"
#define DEFAULT_BUS_PATH "unix:path=/run/dbus/system_bus_socket"
struct context {
bool quit;
char *something;
char *automatic_string_property;
uint32_t automatic_integer_property;
};
static int handler(sd_bus_message *m, void *userdata, sd_bus_error *error) {
return 1;
}
static int value_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
return 1;
}
static int get_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
return 1;
}
static int set_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *value, void *userdata, sd_bus_error *error) {
return 1;
}
static const sd_bus_vtable vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_METHOD("AlterSomething", "s", "s", handler, 0),
SD_BUS_METHOD("Exit", "", "", handler, 0),
SD_BUS_METHOD_WITH_OFFSET("AlterSomething2", "s", "s", handler, 200, 0),
SD_BUS_METHOD_WITH_OFFSET("Exit2", "", "", handler, 200, 0),
SD_BUS_METHOD_WITH_NAMES_OFFSET("AlterSomething3", "so", SD_BUS_PARAM(string) SD_BUS_PARAM(path),
"s", SD_BUS_PARAM(returnstring), handler, 200, 0),
SD_BUS_METHOD_WITH_NAMES("Exit3", "bx", SD_BUS_PARAM(with_confirmation) SD_BUS_PARAM(after_msec),
"bb", SD_BUS_PARAM(accepted) SD_BUS_PARAM(scheduled), handler, 0),
SD_BUS_PROPERTY("Value", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("Value2", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
SD_BUS_PROPERTY("Value3", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Value4", "s", value_handler, 10, 0),
SD_BUS_PROPERTY("AnExplicitProperty", "s", NULL, offsetof(struct context, something),
SD_BUS_VTABLE_PROPERTY_EXPLICIT|SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
SD_BUS_WRITABLE_PROPERTY("Something", "s", get_handler, set_handler, 0, 0),
SD_BUS_WRITABLE_PROPERTY("AutomaticStringProperty", "s", NULL, NULL,
offsetof(struct context, automatic_string_property), 0),
SD_BUS_WRITABLE_PROPERTY("AutomaticIntegerProperty", "u", NULL, NULL,
offsetof(struct context, automatic_integer_property), 0),
SD_BUS_METHOD("NoOperation", NULL, NULL, NULL, 0),
SD_BUS_SIGNAL("DummySignal", "b", 0),
SD_BUS_SIGNAL("DummySignal2", "so", 0),
SD_BUS_SIGNAL_WITH_NAMES("DummySignal3", "so", SD_BUS_PARAM(string) SD_BUS_PARAM(path), 0),
SD_BUS_VTABLE_END
};
struct sd_bus_vtable_original {
uint8_t type:8;
uint64_t flags:56;
union {
struct {
size_t element_size;
} start;
struct {
const char *member;
const char *signature;
const char *result;
sd_bus_message_handler_t handler;
size_t offset;
} method;
struct {
const char *member;
const char *signature;
} signal;
struct {
const char *member;
const char *signature;
sd_bus_property_get_t get;
sd_bus_property_set_t set;
size_t offset;
} property;
} x;
};
static const struct sd_bus_vtable_original vtable_format_original[] = {
{
.type = _SD_BUS_VTABLE_START,
.flags = 0,
.x = {
.start = {
.element_size = sizeof(struct sd_bus_vtable_original)
},
},
},
{
.type = _SD_BUS_VTABLE_METHOD,
.flags = 0,
.x = {
.method = {
.member = "Exit",
.signature = "",
.result = "",
.handler = handler,
.offset = 0,
},
},
},
{
.type = _SD_BUS_VTABLE_END,
.flags = 0,
.x = { { 0 } },
}
};
static void test_vtable(void) {
sd_bus *bus = NULL;
struct context c = {};
@@ -126,16 +26,24 @@ static void test_vtable(void) {
assert(sd_bus_new(&bus) >= 0);
assert(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.testVtable", vtable, &c) >= 0);
assert(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.testVtable2", vtable, &c) >= 0);
assert(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.testVtable", test_vtable_2, &c) >= 0);
assert(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.testVtable2", test_vtable_2, &c) >= 0);
/* the cast on the line below is needed to test with the old version of the table */
assert(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.testVtableOriginal", (const sd_bus_vtable *)vtable_format_original, &c) >= 0);
assert(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.testVtable221",
(const sd_bus_vtable *)vtable_format_221, &c) >= 0);
assert(sd_bus_set_address(bus, DEFAULT_BUS_PATH) >= 0);
r = sd_bus_start(bus);
assert(r == 0 || /* success */
r == -ENOENT /* dbus is inactive */ );
#ifndef __cplusplus
_cleanup_free_ char *s = NULL;
assert_se(introspect_path(bus, "/foo", NULL, false, true, NULL, &s, NULL) == 1);
fputs(s, stdout);
#endif
sd_bus_unref(bus);
}
+132
View File
@@ -0,0 +1,132 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/* This is meant to be included in other files, hence no headers */
struct context {
bool quit;
char *something;
char *automatic_string_property;
uint32_t automatic_integer_property;
};
static int handler(sd_bus_message *m, void *userdata, sd_bus_error *error) {
return 1;
}
static int value_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
return 1;
}
static int get_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
return 1;
}
static int set_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *value, void *userdata, sd_bus_error *error) {
return 1;
}
static const sd_bus_vtable test_vtable_1[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_METHOD("Hello", "ssas", "a(uu)", NULL, 0),
SD_BUS_METHOD("DeprecatedHello", "", "", NULL, SD_BUS_VTABLE_DEPRECATED),
SD_BUS_METHOD("DeprecatedHelloNoReply", "", "", NULL, SD_BUS_VTABLE_DEPRECATED|SD_BUS_VTABLE_METHOD_NO_REPLY),
SD_BUS_SIGNAL("Wowza", "sss", 0),
SD_BUS_SIGNAL("DeprecatedWowza", "ut", SD_BUS_VTABLE_DEPRECATED),
SD_BUS_WRITABLE_PROPERTY("AProperty", "s", get_handler, set_handler, 0, 0),
SD_BUS_PROPERTY("AReadOnlyDeprecatedProperty", "(ut)", get_handler, 0, SD_BUS_VTABLE_DEPRECATED),
SD_BUS_PROPERTY("ChangingProperty", "t", get_handler, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("Invalidating", "t", get_handler, 0, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
SD_BUS_PROPERTY("Constant", "t", get_handler, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_PROPERTY_EXPLICIT),
SD_BUS_VTABLE_END
};
static const sd_bus_vtable test_vtable_2[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_METHOD("AlterSomething", "s", "s", handler, 0),
SD_BUS_METHOD("Exit", "", "", handler, 0),
SD_BUS_METHOD_WITH_OFFSET("AlterSomething2", "s", "s", handler, 200, 0),
SD_BUS_METHOD_WITH_OFFSET("Exit2", "", "", handler, 200, 0),
SD_BUS_METHOD_WITH_NAMES_OFFSET("AlterSomething3", "so", SD_BUS_PARAM(string) SD_BUS_PARAM(path),
"s", SD_BUS_PARAM(returnstring), handler, 200, 0),
SD_BUS_METHOD_WITH_NAMES("Exit3", "bx", SD_BUS_PARAM(with_confirmation) SD_BUS_PARAM(after_msec),
"bb", SD_BUS_PARAM(accepted) SD_BUS_PARAM(scheduled), handler, 0),
SD_BUS_PROPERTY("Value", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("Value2", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
SD_BUS_PROPERTY("Value3", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Value4", "s", value_handler, 10, 0),
SD_BUS_PROPERTY("AnExplicitProperty", "s", NULL, offsetof(struct context, something),
SD_BUS_VTABLE_PROPERTY_EXPLICIT|SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
SD_BUS_WRITABLE_PROPERTY("Something", "s", get_handler, set_handler, 0, 0),
SD_BUS_WRITABLE_PROPERTY("AutomaticStringProperty", "s", NULL, NULL,
offsetof(struct context, automatic_string_property), 0),
SD_BUS_WRITABLE_PROPERTY("AutomaticIntegerProperty", "u", NULL, NULL,
offsetof(struct context, automatic_integer_property), 0),
SD_BUS_METHOD("NoOperation", NULL, NULL, NULL, 0),
SD_BUS_SIGNAL("DummySignal", "b", 0),
SD_BUS_SIGNAL("DummySignal2", "so", 0),
SD_BUS_SIGNAL_WITH_NAMES("DummySignal3", "so", SD_BUS_PARAM(string) SD_BUS_PARAM(path), 0),
SD_BUS_VTABLE_END
};
static const sd_bus_vtable test_vtable_deprecated[] = {
SD_BUS_VTABLE_START(SD_BUS_VTABLE_DEPRECATED),
SD_BUS_VTABLE_END
};
struct sd_bus_vtable_221 {
uint8_t type:8;
uint64_t flags:56;
union {
struct {
size_t element_size;
} start;
struct {
const char *member;
const char *signature;
const char *result;
sd_bus_message_handler_t handler;
size_t offset;
} method;
struct {
const char *member;
const char *signature;
} signal;
struct {
const char *member;
const char *signature;
sd_bus_property_get_t get;
sd_bus_property_set_t set;
size_t offset;
} property;
} x;
};
static const struct sd_bus_vtable_221 vtable_format_221[] = {
{
.type = _SD_BUS_VTABLE_START,
.flags = 0,
.x = {
.start = {
.element_size = sizeof(struct sd_bus_vtable_221)
},
},
},
{
.type = _SD_BUS_VTABLE_METHOD,
.flags = 0,
.x = {
.method = {
.member = "Exit",
.signature = "",
.result = "",
.handler = handler,
.offset = 0,
},
},
},
{
.type = _SD_BUS_VTABLE_END,
.flags = 0,
.x = { { 0 } },
}
};
+12 -1
View File
@@ -52,6 +52,15 @@ enum {
_SD_BUS_VTABLE_PARAM_NAMES = 1 << 0,
};
extern const unsigned sd_bus_object_vtable_format;
/* Note: unused areas in the sd_bus_vtable[] array must be initalized to 0. The stucture contains an embedded
* union, and the compiler is NOT required to initalize the unused areas of the union when the rest of the
* structure is initalized. Normally the array is defined as read-only data, in which case the linker places
* it in the BSS section, which is always fully initalized, so this is not a concern. But if the array is
* created on the stack or on the heap, care must be taken to initalize the unused areas, for examply by
* first memsetting the whole region to zero before filling the data in. */
struct sd_bus_vtable {
/* Please do not initialize this structure directly, use the
* macros below instead */
@@ -62,6 +71,7 @@ struct sd_bus_vtable {
struct {
size_t element_size;
uint64_t features;
const unsigned *vtable_format_reference;
} start;
struct {
const char *member;
@@ -93,7 +103,8 @@ struct sd_bus_vtable {
.x = { \
.start = { \
.element_size = sizeof(sd_bus_vtable), \
.features = _SD_BUS_VTABLE_PARAM_NAMES \
.features = _SD_BUS_VTABLE_PARAM_NAMES, \
.vtable_format_reference = &sd_bus_object_vtable_format, \
}, \
}, \
}
+8 -4
View File
@@ -6,18 +6,22 @@ for header in sys.argv[2:]:
print('#include "{}"'.format(header.split('/')[-1]))
print('''
void* functions[] = {''')
const void* symbols[] = {''')
for line in open(sys.argv[1]):
match = re.search('^ +([a-zA-Z0-9_]+);', line)
if match:
print(' {},'.format(match.group(1)))
s = match.group(1)
if s == 'sd_bus_object_vtable_format':
print(' &{},'.format(s))
else:
print(' {},'.format(s))
print('''};
int main(void) {
unsigned i;
for (i = 0; i < sizeof(functions)/sizeof(void*); i++)
printf("%p\\n", functions[i]);
for (i = 0; i < sizeof(symbols)/sizeof(void*); i++)
printf("%p\\n", symbols[i]);
return 0;
}''')
+4 -2
View File
@@ -911,7 +911,8 @@ tests += [
[],
[threads]],
[['src/libsystemd/sd-bus/test-bus-vtable.c'],
[['src/libsystemd/sd-bus/test-bus-vtable.c',
'src/libsystemd/sd-bus/test-vtable-data.h'],
[],
[]],
@@ -934,7 +935,8 @@ tests += [
[threads],
'', 'manual'],
[['src/libsystemd/sd-bus/test-bus-introspect.c'],
[['src/libsystemd/sd-bus/test-bus-introspect.c',
'src/libsystemd/sd-bus/test-vtable-data.h'],
[],
[]],