bus-objects.c revision 4afd3348c7506dd1d36305b7bcb9feb8952b9d6b
1559N/A along with systemd; If not, see <http://www.gnu.org/licenses/>.
1559N/A#include "alloc-util.h"
1559N/A#include "bus-internal.h"
1559N/A#include "bus-introspect.h"
1559N/A#include "bus-message.h"
1559N/A#include "bus-objects.h"
1559N/A#include "bus-signature.h"
1559N/A#include "bus-slot.h"
1559N/A#include "bus-type.h"
1559N/A#include "bus-util.h"
1559N/A#include "string-util.h"
1570N/Astatic int node_vtable_get_userdata(
1559N/A struct node_vtable *c,
1559N/A sd_bus_slot *s;
if (userdata)
*userdata = u;
assert(p);
assert(p);
static int vtable_property_get_userdata(
const char *path,
struct vtable_member *p,
void **userdata,
assert(p);
static int add_enumerated_to_set(
const char *prefix,
Set *s,
struct node_enumerator *c;
assert(s);
free(*k);
if (!object_path_is_valid(*k)){
free(*k);
r = -EINVAL;
free(*k);
r = set_consume(s, *k);
if (r == -EEXIST)
static int add_subtree_to_set(
const char *prefix,
struct node *n,
unsigned int flags,
Set *s,
struct node *i;
assert(n);
assert(s);
return -ENOMEM;
r = set_consume(s, t);
if (r < 0 && r != -EEXIST)
static int get_child_nodes(
const char *prefix,
struct node *n,
unsigned int flags,
assert(n);
return -ENOMEM;
set_free_free(s);
*_s = s;
static int node_callbacks_run(
sd_bus_message *m,
bool require_fallback,
bool *found_object) {
struct node_callback *c;
assert(m);
*found_object = true;
r = sd_bus_message_rewind(m, true);
static int check_access(sd_bus *bus, sd_bus_message *m, struct vtable_member *c, sd_bus_error *error) {
assert(m);
assert(c);
if (cap == 0)
if (cap == 0)
cap --;
return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Access to %s.%s() not permitted.", c->interface, c->member);
static int method_callbacks_run(
sd_bus_message *m,
struct vtable_member *c,
bool require_fallback,
bool *found_object) {
const char *signature;
assert(m);
assert(c);
*found_object = true;
r = sd_bus_message_rewind(m, true);
if (!signature)
return -EINVAL;
return sd_bus_reply_method_errorf(
static int invoke_property_get(
const sd_bus_vtable *v,
const char *path,
const char *interface,
const char *property,
void *userdata,
assert(v);
case SD_BUS_TYPE_STRING:
case SD_BUS_TYPE_SIGNATURE:
case SD_BUS_TYPE_OBJECT_PATH:
p = *(char**) userdata;
assert(p);
p = userdata;
static int invoke_property_set(
const sd_bus_vtable *v,
const char *path,
const char *interface,
const char *property,
void *userdata,
assert(v);
case SD_BUS_TYPE_STRING:
case SD_BUS_TYPE_OBJECT_PATH:
case SD_BUS_TYPE_SIGNATURE: {
n = strdup(p);
return -ENOMEM;
*(char**) userdata = n;
static int property_get_set_callbacks_run(
sd_bus_message *m,
struct vtable_member *c,
bool require_fallback,
bool is_get,
bool *found_object) {
void *u = NULL;
assert(m);
assert(c);
*found_object = true;
if (is_get) {
char type = 0;
return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_PROPERTY_READ_ONLY, "Property '%s' is not writable.", c->member);
return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INVALID_ARGS, "Incorrect parameters for property '%s', expected '%s', got '%s'.", c->member, strempty(c->vtable->x.property.signature), strempty(signature));
r = sd_bus_message_exit_container(m);
static int vtable_append_one_property(
const char *path,
struct node_vtable *c,
const sd_bus_vtable *v,
void *userdata,
assert(c);
assert(v);
r = invoke_property_get(bus, slot, v, path, c->interface, v->x.property.member, reply, vtable_property_convert_userdata(v, userdata), error);
static int vtable_append_all_properties(
const char *path,
struct node_vtable *c,
void *userdata,
const sd_bus_vtable *v;
assert(c);
static int property_get_all_callbacks_run(
sd_bus_message *m,
bool require_fallback,
const char *iface,
bool *found_object) {
struct node_vtable *c;
bool found_interface;
assert(m);
*found_object = true;
found_interface = true;
if (!found_interface) {
static int bus_node_exists(
struct node *n,
const char *path,
bool require_fallback) {
struct node_vtable *c;
struct node_callback *k;
assert(n);
static int process_introspect(
sd_bus_message *m,
struct node *n,
bool require_fallback,
bool *found_object) {
struct node_vtable *c;
bool empty;
assert(m);
assert(n);
goto finish;
goto finish;
empty = false;
if (previous_interface)
goto finish;
if (previous_interface)
if (empty) {
goto finish;
goto finish;
*found_object = true;
goto finish;
goto finish;
goto finish;
static int object_manager_serialize_path(
const char *prefix,
const char *path,
bool require_fallback,
bool found_something = false;
struct node_vtable *i;
struct node *n;
if (!found_something) {
found_something = true;
if (previous_interface) {
if (previous_interface) {
if (found_something) {
static int object_manager_serialize_path_and_fallbacks(
const char *path,
char *prefix;
static int process_get_managed_objects(
sd_bus_message *m,
struct node *n,
bool require_fallback,
bool *found_object) {
Iterator i;
char *path;
assert(m);
assert(n);
static int object_find_and_run(
sd_bus_message *m,
bool require_fallback,
bool *found_object) {
struct node *n;
assert(m);
assert(p);
bool get = false;
r = sd_bus_message_rewind(m, true);
return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INVALID_ARGS, "Expected interface and member parameters");
const char *iface;
r = sd_bus_message_rewind(m, true);
if (iface[0] == 0)
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.ObjectManager", "GetManagedObjects")) {
if (!*found_object) {
*found_object = true;
bool found_object = false;
assert(m);
if (!found_object)
return NULL;
return NULL;
assert(e);
if (!parent)
return NULL;
return NULL;
n->path = s;
free(n);
return NULL;
if (parent)
assert(b);
if (n->child ||
n->callbacks ||
n->vtables ||
n->enumerators ||
n->object_managers)
if (n->parent)
free(n);
struct node *n;
char *prefix;
while (n && !n->object_managers)
n = n->parent;
if (out)
*out = n;
static int bus_add_object(
bool fallback,
const char *path,
void *userdata) {
sd_bus_slot *s;
struct node *n;
return -ENOMEM;
r = -ENOMEM;
goto fail;
if (slot)
*slot = s;
fail:
const char *path,
void *userdata) {
const char *prefix,
void *userdata) {
const struct vtable_member *m = a;
assert(m);
static int vtable_member_compare_func(const void *a, const void *b) {
const struct vtable_member *x = a, *y = b;
assert(x);
assert(y);
static int add_object_vtable_internal(
const char *path,
const char *interface,
bool fallback,
void *userdata) {
const sd_bus_vtable *v;
struct node *n;
return -ENOMEM;
r = -EPROTOTYPE;
goto fail;
r = -EEXIST;
goto fail;
existing = i;
r = -ENOMEM;
goto fail;
r = -ENOMEM;
goto fail;
switch (v->type) {
case _SD_BUS_VTABLE_METHOD: {
struct vtable_member *m;
v->flags & (SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE|SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION)) {
r = -EINVAL;
goto fail;
r = -ENOMEM;
goto fail;
m->vtable = v;
free(m);
goto fail;
r = -EINVAL;
goto fail;
r = -EINVAL;
goto fail;
case _SD_BUS_VTABLE_PROPERTY: {
struct vtable_member *m;
!(v->x.property.get || bus_type_is_basic(v->x.property.signature[0]) || streq(v->x.property.signature, "as")) ||
(!!(v->flags & SD_BUS_VTABLE_PROPERTY_CONST) + !!(v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE) + !!(v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION)) > 1 ||
((v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE) && (v->flags & SD_BUS_VTABLE_PROPERTY_EXPLICIT)) ||
r = -EINVAL;
goto fail;
r = -ENOMEM;
goto fail;
m->vtable = v;
free(m);
goto fail;
case _SD_BUS_VTABLE_SIGNAL:
r = -EINVAL;
goto fail;
r = -EINVAL;
goto fail;
if (slot)
*slot = s;
fail:
const char *path,
const char *interface,
void *userdata) {
const char *prefix,
const char *interface,
void *userdata) {
const char *path,
void *userdata) {
sd_bus_slot *s;
struct node *n;
return -ENOMEM;
r = -ENOMEM;
goto fail;
if (slot)
*slot = s;
fail:
static int emit_properties_changed_on_interface(
const char *prefix,
const char *path,
const char *interface,
bool require_fallback,
bool *found_interface,
char **names) {
struct node_vtable *c;
struct node *n;
char **property;
void *u = NULL;
r = sd_bus_message_new_signal(bus, &m, path, "org.freedesktop.DBus.Properties", "PropertiesChanged");
*found_interface = true;
if (names) {
struct vtable_member *v;
return -ENOENT;
if (c != v->parent)
has_invalidating = true;
has_changing = true;
const sd_bus_vtable *v;
has_invalidating = true;
has_changing = true;
r = sd_bus_message_close_container(m);
if (has_invalidating) {
if (names) {
struct vtable_member *v;
const sd_bus_vtable *v;
r = sd_bus_message_close_container(m);
const char *path,
const char *interface,
char **names) {
bool found_interface = false;
char *prefix;
return -ENOTCONN;
r = emit_properties_changed_on_interface(bus, path, path, interface, false, &found_interface, names);
r = emit_properties_changed_on_interface(bus, prefix, path, interface, true, &found_interface, names);
const char *path,
const char *interface,
const char *name, ...) {
char **names;
return -ENOTCONN;
if (!name)
static int object_added_append_all_prefix(
sd_bus_message *m,
Set *s,
const char *prefix,
const char *path,
bool require_fallback) {
struct node_vtable *c;
struct node *n;
assert(m);
assert(s);
void *u = NULL;
if (previous_interface) {
r = sd_bus_message_close_container(m);
r = sd_bus_message_close_container(m);
if (previous_interface) {
r = sd_bus_message_close_container(m);
r = sd_bus_message_close_container(m);
char *prefix;
assert(m);
return -ENOMEM;
return -ENOTCONN;
return -ESRCH;
m = sd_bus_message_unref(m);
r = sd_bus_message_new_signal(bus, &m, object_manager->path, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded");
r = sd_bus_message_close_container(m);
static int object_removed_append_all_prefix(
sd_bus_message *m,
Set *s,
const char *prefix,
const char *path,
bool require_fallback) {
struct node_vtable *c;
struct node *n;
assert(m);
assert(s);
void *u = NULL;
char *prefix;
assert(m);
return -ENOMEM;
* you must call this function before destroying/unlinking your object.
return -ENOTCONN;
return -ESRCH;
m = sd_bus_message_unref(m);
r = sd_bus_message_new_signal(bus, &m, object_manager->path, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved");
r = sd_bus_message_close_container(m);
static int interfaces_added_append_one_prefix(
sd_bus_message *m,
const char *prefix,
const char *path,
const char *interface,
bool require_fallback) {
bool found_interface = false;
struct node_vtable *c;
struct node *n;
void *u = NULL;
assert(m);
if (!found_interface) {
found_interface = true;
if (found_interface) {
r = sd_bus_message_close_container(m);
return found_interface;
static int interfaces_added_append_one(
sd_bus_message *m,
const char *path,
const char *interface) {
char *prefix;
assert(m);
return -ENOENT;
return -ENOTCONN;
return -ESRCH;
m = sd_bus_message_unref(m);
r = sd_bus_message_new_signal(bus, &m, object_manager->path, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded");
r = sd_bus_message_close_container(m);
r = sd_bus_message_close_container(m);
_public_ int sd_bus_emit_interfaces_added(sd_bus *bus, const char *path, const char *interface, ...) {
char **interfaces;
return -ENOTCONN;
_public_ int sd_bus_emit_interfaces_removed_strv(sd_bus *bus, const char *path, char **interfaces) {
return -ENOTCONN;
return -ESRCH;
r = sd_bus_message_new_signal(bus, &m, object_manager->path, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved");
_public_ int sd_bus_emit_interfaces_removed(sd_bus *bus, const char *path, const char *interface, ...) {
char **interfaces;
return -ENOTCONN;
sd_bus_slot *s;
struct node *n;
return -ENOMEM;
s = bus_slot_allocate(bus, !slot, BUS_NODE_OBJECT_MANAGER, sizeof(struct node_object_manager), NULL);
r = -ENOMEM;
goto fail;
if (slot)
*slot = s;
fail: