static void *vtable_property_convert_userdata(const sd_bus_vtable *p, void *u) {
assert(p);
- return (uint8_t*) u + p->property.offset;
+ return (uint8_t*) u + p->x.property.offset;
}
static int vtable_property_get_userdata(
return 1;
}
-static int add_enumerated_to_set(sd_bus *bus, const char *prefix, struct node_enumerator *first, Set *s) {
+static int add_enumerated_to_set(
+ sd_bus *bus,
+ const char *prefix,
+ struct node_enumerator *first,
+ Set *s) {
+
struct node_enumerator *c;
int r;
return 0;
}
-static int add_subtree_to_set(sd_bus *bus, const char *prefix, struct node *n, Set *s) {
+static int add_subtree_to_set(
+ sd_bus *bus,
+ const char *prefix,
+ struct node *n,
+ Set *s) {
+
struct node *i;
int r;
return 0;
}
-static int get_child_nodes(sd_bus *bus, const char *prefix, struct node *n, Set **_s) {
+static int get_child_nodes(
+ sd_bus *bus,
+ const char *prefix,
+ struct node *n,
+ Set **_s) {
+
Set *s = NULL;
int r;
assert(bus);
+ assert(prefix);
assert(n);
assert(_s);
if (r < 0)
return r;
- if (!streq(strempty(c->vtable->method.signature), signature)) {
+ if (!streq(strempty(c->vtable->x.method.signature), signature)) {
r = sd_bus_reply_method_errorf(bus, m,
"org.freedesktop.DBus.Error.InvalidArgs",
"Invalid arguments '%s' to call %s:%s, expecting '%s'.",
- signature, c->interface, c->member, strempty(c->vtable->method.signature));
+ signature, c->interface, c->member, strempty(c->vtable->x.method.signature));
if (r < 0)
return r;
return 1;
}
- if (c->vtable->method.handler)
- return c->vtable->method.handler(bus, m, u);
+ if (c->vtable->x.method.handler)
+ return c->vtable->x.method.handler(bus, m, u);
/* If the method callback is NULL, make this a successful NOP */
r = sd_bus_reply_method_return(bus, m, NULL);
assert(bus);
assert(v);
+ assert(path);
+ assert(interface);
+ assert(property);
+ assert(m);
- if (v->property.get)
- return v->property.get(bus, path, interface, property, m, error, userdata);
+ if (v->x.property.get)
+ return v->x.property.get(bus, path, interface, property, m, error, userdata);
/* Automatic handling if no callback is defined. */
- assert(bus_type_is_basic(v->property.signature[0]));
+ assert(signature_is_single(v->x.property.signature, false));
+ assert(bus_type_is_basic(v->x.property.signature[0]));
- switch (v->property.signature[0]) {
+ switch (v->x.property.signature[0]) {
case SD_BUS_TYPE_STRING:
case SD_BUS_TYPE_OBJECT_PATH:
break;
}
- r = sd_bus_message_append_basic(m, v->property.signature[0], p);
+ r = sd_bus_message_append_basic(m, v->x.property.signature[0], p);
if (r < 0)
return r;
assert(bus);
assert(v);
+ assert(path);
+ assert(interface);
+ assert(property);
+ assert(value);
- if (v->property.set)
- return v->property.set(bus, path, interface, property, value, error, userdata);
+ if (v->x.property.set)
+ return v->x.property.set(bus, path, interface, property, value, error, userdata);
/* Automatic handling if no callback is defined. */
- assert(signature_is_single(v->property.signature, false));
- assert(bus_type_is_basic(v->property.signature[0]));
+ assert(signature_is_single(v->x.property.signature, false));
+ assert(bus_type_is_basic(v->x.property.signature[0]));
- switch (v->property.signature[0]) {
+ switch (v->x.property.signature[0]) {
case SD_BUS_TYPE_STRING:
case SD_BUS_TYPE_OBJECT_PATH:
const char *p;
char *n;
- r = sd_bus_message_read_basic(value, v->property.signature[0], &p);
+ r = sd_bus_message_read_basic(value, v->x.property.signature[0], &p);
if (r < 0)
return r;
}
default:
- r = sd_bus_message_read_basic(value, v->property.signature[0], userdata);
+ r = sd_bus_message_read_basic(value, v->x.property.signature[0], userdata);
if (r < 0)
return r;
assert(bus);
assert(m);
+ assert(c);
assert(found_object);
if (require_fallback && !c->parent->is_fallback)
c->last_iteration = bus->iteration_counter;
if (is_get) {
- r = sd_bus_message_open_container(reply, 'v', c->vtable->property.signature);
+ r = sd_bus_message_open_container(reply, 'v', c->vtable->x.property.signature);
if (r < 0)
return r;
if (c->vtable->type != _SD_BUS_VTABLE_WRITABLE_PROPERTY)
sd_bus_error_setf(&error, "org.freedesktop.DBus.Error.PropertyReadOnly", "Property '%s' is not writable.", c->member);
else {
- r = sd_bus_message_enter_container(m, 'v', c->vtable->property.signature);
+ r = sd_bus_message_enter_container(m, 'v', c->vtable->x.property.signature);
if (r < 0)
return r;
assert(bus);
assert(reply);
+ assert(path);
assert(c);
for (v = c->vtable+1; v->type != _SD_BUS_VTABLE_END; v++) {
if (r < 0)
return r;
- r = sd_bus_message_append(reply, "s", c->interface);
+ r = sd_bus_message_append(reply, "s", v->x.property.member);
if (r < 0)
return r;
- r = sd_bus_message_open_container(reply, 'v', v->property.signature);
+ r = sd_bus_message_open_container(reply, 'v', v->x.property.signature);
if (r < 0)
return r;
- r = invoke_property_get(bus, v, path, c->interface, v->property.member, reply, error, vtable_property_convert_userdata(v, userdata));
+ r = invoke_property_get(bus, v, path, c->interface, v->x.property.member, reply, error, vtable_property_convert_userdata(v, userdata));
if (r < 0)
return r;
static bool bus_node_with_object_manager(sd_bus *bus, struct node *n) {
assert(bus);
+ assert(n);
if (n->object_manager)
return true;
return false;
}
-static bool bus_node_exists(sd_bus *bus, struct node *n, const char *path, bool require_fallback) {
+static bool bus_node_exists(
+ sd_bus *bus,
+ struct node *n,
+ const char *path,
+ bool require_fallback) {
+
struct node_vtable *c;
struct node_callback *k;
assert(bus);
assert(n);
+ assert(path);
/* Tests if there's anything attached directly to this node
* for the specified path */
const char *path,
sd_bus_error *error) {
- size_t pl;
+ char *prefix;
int r;
assert(bus);
return 0;
/* Second, add fallback vtables registered for any of the prefixes */
- pl = strlen(path);
- if (pl > 1) {
- char p[pl + 1];
- strcpy(p, path);
-
- for (;;) {
- char *e;
-
- e = strrchr(p, '/');
- if (e == p || !e)
- break;
-
- *e = 0;
-
- r = object_manager_serialize_path(bus, reply, p, path, true, error);
- if (r < 0)
- return r;
+ prefix = alloca(strlen(path) + 1);
+ OBJECT_PATH_FOREACH_PREFIX(prefix, path) {
+ r = object_manager_serialize_path(bus, reply, prefix, path, true, error);
+ if (r < 0)
+ return r;
- if (sd_bus_error_is_set(error))
- return 0;
- }
+ if (sd_bus_error_is_set(error))
+ return 0;
}
return 0;
pl = strlen(m->path);
do {
- char p[pl+1];
+ char prefix[pl+1];
bus->nodes_modified = false;
return r;
/* Look for fallback prefixes */
- strcpy(p, m->path);
- for (;;) {
- char *e;
-
- if (streq(p, "/"))
- break;
+ OBJECT_PATH_FOREACH_PREFIX(prefix, m->path) {
if (bus->nodes_modified)
break;
- e = strrchr(p, '/');
- assert(e);
- if (e == p)
- *(e+1) = 0;
- else
- *e = 0;
-
- r = object_find_and_run(bus, m, p, true, &found_object);
+ r = object_find_and_run(bus, m, prefix, true, &found_object);
if (r != 0)
return r;
}
}
static int bus_add_object(
- sd_bus *b,
+ sd_bus *bus,
bool fallback,
const char *path,
sd_bus_message_handler_t callback,
struct node *n;
int r;
- if (!b)
- return -EINVAL;
- if (!object_path_is_valid(path))
- return -EINVAL;
- if (!callback)
- return -EINVAL;
- if (bus_pid_changed(b))
- return -ECHILD;
+ assert_return(bus, -EINVAL);
+ assert_return(object_path_is_valid(path), -EINVAL);
+ assert_return(callback, -EINVAL);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
- n = bus_node_allocate(b, path);
+ n = bus_node_allocate(bus, path);
if (!n)
return -ENOMEM;
fail:
free(c);
- bus_node_gc(b, n);
+ bus_node_gc(bus, n);
return r;
}
struct node_callback *c;
struct node *n;
- if (!bus)
- return -EINVAL;
- if (!object_path_is_valid(path))
- return -EINVAL;
- if (!callback)
- return -EINVAL;
- if (bus_pid_changed(bus))
- return -ECHILD;
+ assert_return(bus, -EINVAL);
+ assert_return(object_path_is_valid(path), -EINVAL);
+ assert_return(callback, -EINVAL);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
n = hashmap_get(bus->nodes, path);
if (!n)
key.path = w->node->path;
key.interface = w->interface;
- key.member = v->method.member;
+ key.member = v->x.method.member;
x = hashmap_remove(bus->vtable_methods, &key);
break;
key.path = w->node->path;
key.interface = w->interface;
- key.member = v->property.member;
+ key.member = v->x.property.member;
x = hashmap_remove(bus->vtable_properties, &key);
break;
}}
static unsigned vtable_member_hash_func(const void *a) {
const struct vtable_member *m = a;
+ assert(m);
+
return
string_hash_func(m->path) ^
string_hash_func(m->interface) ^
const struct vtable_member *x = a, *y = b;
int r;
+ assert(x);
+ assert(y);
+
r = strcmp(x->path, y->path);
if (r != 0)
return r;
struct node *n;
int r;
- if (!bus)
- return -EINVAL;
- if (!object_path_is_valid(path))
- return -EINVAL;
- if (!interface_name_is_valid(interface))
- return -EINVAL;
- if (!vtable || vtable[0].type != _SD_BUS_VTABLE_START || vtable[0].start.element_size != sizeof(struct sd_bus_vtable))
- return -EINVAL;
- if (bus_pid_changed(bus))
- return -ECHILD;
+ assert_return(bus, -EINVAL);
+ assert_return(object_path_is_valid(path), -EINVAL);
+ 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 == sizeof(struct sd_bus_vtable), -EINVAL);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
r = hashmap_ensure_allocated(&bus->vtable_methods, vtable_member_hash_func, vtable_member_compare_func);
if (r < 0)
case _SD_BUS_VTABLE_METHOD: {
struct vtable_member *m;
- if (!member_name_is_valid(v->method.member) ||
- !signature_is_valid(strempty(v->method.signature), false) ||
- !signature_is_valid(strempty(v->method.result), false) ||
- !(v->method.handler || (isempty(v->method.signature) && isempty(v->method.result))) ||
+ if (!member_name_is_valid(v->x.method.member) ||
+ !signature_is_valid(strempty(v->x.method.signature), false) ||
+ !signature_is_valid(strempty(v->x.method.result), false) ||
+ !(v->x.method.handler || (isempty(v->x.method.signature) && isempty(v->x.method.result))) ||
v->flags & (SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE|SD_BUS_VTABLE_PROPERTY_INVALIDATE_ONLY)) {
r = -EINVAL;
goto fail;
m->parent = c;
m->path = n->path;
m->interface = c->interface;
- m->member = v->method.member;
+ m->member = v->x.method.member;
m->vtable = v;
r = hashmap_put(bus->vtable_methods, m, m);
case _SD_BUS_VTABLE_WRITABLE_PROPERTY:
- if (!(v->property.set || bus_type_is_basic(v->property.signature[0]))) {
+ if (!(v->x.property.set || bus_type_is_basic(v->x.property.signature[0]))) {
r = -EINVAL;
goto fail;
}
case _SD_BUS_VTABLE_PROPERTY: {
struct vtable_member *m;
- if (!member_name_is_valid(v->property.member) ||
- !signature_is_single(v->property.signature, false) ||
- !(v->property.get || bus_type_is_basic(v->property.signature[0])) ||
+ if (!member_name_is_valid(v->x.property.member) ||
+ !signature_is_single(v->x.property.signature, false) ||
+ !(v->x.property.get || bus_type_is_basic(v->x.property.signature[0])) ||
v->flags & SD_BUS_VTABLE_METHOD_NO_REPLY ||
(v->flags & SD_BUS_VTABLE_PROPERTY_INVALIDATE_ONLY && !(v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE))) {
r = -EINVAL;
m->parent = c;
m->path = n->path;
m->interface = c->interface;
- m->member = v->property.member;
+ m->member = v->x.property.member;
m->vtable = v;
r = hashmap_put(bus->vtable_properties, m, m);
case _SD_BUS_VTABLE_SIGNAL:
- if (!member_name_is_valid(v->signal.member) ||
- !signature_is_single(strempty(v->signal.signature), false)) {
+ if (!member_name_is_valid(v->x.signal.member) ||
+ !signature_is_single(strempty(v->x.signal.signature), false)) {
r = -EINVAL;
goto fail;
}
struct node_vtable *c;
struct node *n;
- if (!bus)
- return -EINVAL;
- if (!object_path_is_valid(path))
- return -EINVAL;
- if (!interface_name_is_valid(interface))
- return -EINVAL;
- if (bus_pid_changed(bus))
- return -ECHILD;
+ assert_return(bus, -EINVAL);
+ assert_return(object_path_is_valid(path), -EINVAL);
+ assert_return(interface_name_is_valid(interface), -EINVAL);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
n = hashmap_get(bus->nodes, path);
if (!n)
LIST_REMOVE(struct node_vtable, vtables, n->vtables, c);
free_node_vtable(bus, c);
+ bus_node_gc(bus, n);
+
return 1;
}
struct node *n;
int r;
- if (!bus)
- return -EINVAL;
- if (!object_path_is_valid(path))
- return -EINVAL;
- if (!callback)
- return -EINVAL;
- if (bus_pid_changed(bus))
- return -ECHILD;
+ assert_return(bus, -EINVAL);
+ assert_return(object_path_is_valid(path), -EINVAL);
+ assert_return(callback, -EINVAL);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
n = bus_node_allocate(bus, path);
if (!n)
struct node_enumerator *c;
struct node *n;
- if (!bus)
- return -EINVAL;
- if (!object_path_is_valid(path))
- return -EINVAL;
- if (!callback)
- return -EINVAL;
- if (bus_pid_changed(bus))
- return -ECHILD;
+ assert_return(bus, -EINVAL);
+ assert_return(object_path_is_valid(path), -EINVAL);
+ assert_return(callback, -EINVAL);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
n = hashmap_get(bus->nodes, path);
if (!n)
int r;
assert(bus);
+ assert(prefix);
assert(path);
assert(interface);
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
struct vtable_member *v;
+ assert_return(member_name_is_valid(*property), -EINVAL);
+
key.member = *property;
v = hashmap_get(bus->vtable_properties, &key);
if (!v)
return -ENOENT;
assert(c == v->parent);
+ assert_return(v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE, -EDOM);
- if (!(v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE))
- return -EDOM;
if (v->vtable->flags & SD_BUS_VTABLE_PROPERTY_INVALIDATE_ONLY) {
has_invalidating = true;
continue;
if (r < 0)
return r;
- r = sd_bus_message_open_container(m, 'v', v->vtable->property.signature);
+ r = sd_bus_message_open_container(m, 'v', v->vtable->x.property.signature);
if (r < 0)
return r;
return 1;
}
-int sd_bus_emit_properties_changed_strv(sd_bus *bus, const char *path, const char *interface, char **names) {
- size_t pl;
+int sd_bus_emit_properties_changed_strv(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ char **names) {
+
+ char *prefix;
int r;
- if (!bus)
- return -EINVAL;
- if (!object_path_is_valid(path))
- return -EINVAL;
- if (!interface_name_is_valid(interface))
- return -EINVAL;
+ assert_return(bus, -EINVAL);
+ assert_return(object_path_is_valid(path), -EINVAL);
+ assert_return(interface_name_is_valid(interface), -EINVAL);
+ assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
+
+ if (strv_isempty(names))
+ return 0;
r = emit_properties_changed_on_interface(bus, path, path, interface, false, names);
if (r != 0)
return r;
- pl = strlen(path);
- if (pl > 1 ) {
- char p[pl+1];
-
- strcpy(p, path);
- for (;;) {
- char *e;
-
- if (streq(p, "/"))
- break;
-
- e = strrchr(p, '/');
- assert(e);
- if (e == p)
- *(e+1) = 0;
- else
- *e = 0;
-
- r = emit_properties_changed_on_interface(bus, p, path, interface, true, names);
- if (r != 0)
- return r;
- }
+ prefix = alloca(strlen(path) + 1);
+ OBJECT_PATH_FOREACH_PREFIX(prefix, path) {
+ r = emit_properties_changed_on_interface(bus, prefix, path, interface, true, names);
+ if (r != 0)
+ return r;
}
return -ENOENT;
}
-int sd_bus_emit_properties_changed(sd_bus *bus, const char *path, const char *interface, const char *name, ...) {
+int sd_bus_emit_properties_changed(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *name, ...) {
+
_cleanup_strv_free_ char **names = NULL;
va_list ap;
+ assert_return(bus, -EINVAL);
+ assert_return(object_path_is_valid(path), -EINVAL);
+ assert_return(interface_name_is_valid(interface), -EINVAL);
+ assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
+
+ if (!name)
+ return 0;
+
va_start(ap, name);
names = strv_new_ap(name, ap);
va_end(ap);
int sd_bus_add_object_manager(sd_bus *bus, const char *path) {
struct node *n;
- if (!bus)
- return -EINVAL;
- if (!object_path_is_valid(path))
- return -EINVAL;
- if (bus_pid_changed(bus))
- return -ECHILD;
+ assert_return(bus, -EINVAL);
+ assert_return(object_path_is_valid(path), -EINVAL);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
n = bus_node_allocate(bus, path);
if (!n)
int sd_bus_remove_object_manager(sd_bus *bus, const char *path) {
struct node *n;
- if (!bus)
- return -EINVAL;
- if (!object_path_is_valid(path))
- return -EINVAL;
- if (bus_pid_changed(bus))
- return -ECHILD;
+ assert_return(bus, -EINVAL);
+ assert_return(object_path_is_valid(path), -EINVAL);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
n = hashmap_get(bus->nodes, path);
if (!n)
n->object_manager = false;
bus_node_gc(bus, n);
+
return 1;
}