return c->vtable->method.handler(bus, m, u);
}
+static int invoke_property_get(
+ sd_bus *bus,
+ const sd_bus_vtable *v,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *m,
+ sd_bus_error *error,
+ void *userdata) {
+
+ int r;
+ void *p;
+
+ assert(bus);
+ assert(v);
+
+ if (v->property.get)
+ return v->property.get(bus, path, interface, property, m, error, userdata);
+
+ /* Automatic handling if no callback is defined. */
+
+ switch (v->property.signature[0]) {
+
+ case SD_BUS_TYPE_STRING:
+ case SD_BUS_TYPE_OBJECT_PATH:
+ case SD_BUS_TYPE_SIGNATURE:
+ p = *(char**) userdata;
+ break;
+
+ default:
+ p = userdata;
+ }
+
+ r = sd_bus_message_append_basic(m, v->property.signature[0], p);
+ if (r < 0)
+ return r;
+
+ return 1;
+}
+
static int property_get_set_callbacks_run(
sd_bus *bus,
sd_bus_message *m,
if (r < 0)
return r;
- if (c->vtable->property.get) {
- r = c->vtable->property.get(bus, m->path, c->interface, c->member, reply, &error, u);
- if (r < 0)
- return r;
- } else
- assert_not_reached("automatic properties not supported yet");
+ r = invoke_property_get(bus, c->vtable, m->path, c->interface, c->member, reply, &error, u);
+ if (r < 0)
+ return r;
if (sd_bus_error_is_set(&error)) {
r = sd_bus_reply_method_error(bus, m, &error);
if (r < 0)
return r;
- r = v->property.get(bus, path, c->interface, v->property.member, reply, error, vtable_property_convert_userdata(v, userdata));
+ r = invoke_property_get(bus, v, path, c->interface, v->property.member, reply, error, vtable_property_convert_userdata(v, userdata));
if (r < 0)
return r;
static int object_manager_serialize_path(
sd_bus *bus,
sd_bus_message *reply,
+ const char *prefix,
const char *path,
bool require_fallback,
sd_bus_error *error) {
assert(bus);
assert(reply);
+ assert(prefix);
assert(path);
assert(error);
- n = hashmap_get(bus->nodes, path);
+ n = hashmap_get(bus->nodes, prefix);
if (!n)
return 0;
assert(error);
/* First, add all vtables registered for this path */
- r = object_manager_serialize_path(bus, reply, path, false, error);
+ r = object_manager_serialize_path(bus, reply, path, path, false, error);
if (r < 0)
return r;
if (sd_bus_error_is_set(error))
*e = 0;
- r = object_manager_serialize_path(bus, reply, p, true, error);
+ r = object_manager_serialize_path(bus, reply, p, path, true, error);
if (r < 0)
return r;
return 1;
}
-static int object_find_and_run(sd_bus *bus, sd_bus_message *m, const char *p, bool require_fallback, bool *found_object) {
+static int object_find_and_run(
+ sd_bus *bus,
+ sd_bus_message *m,
+ const char *p,
+ bool require_fallback,
+ bool *found_object) {
+
struct node *n;
struct vtable_member vtable_key, *v;
int r;
const char *types, ...) {
_cleanup_bus_message_unref_ sd_bus_message *m = NULL;
- va_list ap;
int r;
if (!bus)
if (r < 0)
return r;
- va_start(ap, types);
- r = bus_message_append_ap(m, types, ap);
- va_end(ap);
- if (r < 0)
- return r;
+ if (!isempty(types)) {
+ va_list ap;
+
+ va_start(ap, types);
+ r = bus_message_append_ap(m, types, ap);
+ va_end(ap);
+ if (r < 0)
+ return r;
+ }
return sd_bus_send(bus, m, NULL);
}
const char *types, ...) {
_cleanup_bus_message_unref_ sd_bus_message *m = NULL;
- va_list ap;
int r;
if (!bus)
if (r < 0)
return r;
- va_start(ap, types);
- r = bus_message_append_ap(m, types, ap);
- va_end(ap);
- if (r < 0)
- return r;
+ if (!isempty(types)) {
+ va_list ap;
+
+ va_start(ap, types);
+ r = bus_message_append_ap(m, types, ap);
+ va_end(ap);
+ if (r < 0)
+ return r;
+ }
return sd_bus_send_with_reply_and_block(bus, m, 0, error, reply);
}
const char *types, ...) {
_cleanup_bus_message_unref_ sd_bus_message *m = NULL;
- va_list ap;
int r;
if (!bus)
if (r < 0)
return r;
- va_start(ap, types);
- r = bus_message_append_ap(m, types, ap);
- va_end(ap);
- if (r < 0)
- return r;
+ if (!isempty(types)) {
+ va_list ap;
+
+ va_start(ap, types);
+ r = bus_message_append_ap(m, types, ap);
+ va_end(ap);
+ if (r < 0)
+ return r;
+ }
return sd_bus_send(bus, m, NULL);
}
if (w->interface && w->node && w->vtable) {
const sd_bus_vtable *v;
- for (v = w->vtable; v->type != _SD_BUS_VTABLE_END; w++) {
+ for (v = w->vtable; v->type != _SD_BUS_VTABLE_END; v++) {
struct vtable_member *x = NULL;
switch (v->type) {
sd_bus_object_find_t find,
void *userdata) {
- struct node_vtable *c, *i;
+ struct node_vtable *c = NULL, *i;
const sd_bus_vtable *v;
struct node *n;
int r;
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])) ||
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;
free_node_vtable(bus, c);
bus_node_gc(bus, n);
- return 0;
+ return r;
}
static int remove_object_vtable_internal(
if (streq(c->interface, interface))
break;
-
- r = node_vtable_get_userdata(bus, path, c, &u);
- if (r < 0)
- return r;
- if (r > 0)
- break;
}
if (!c)
return 0;
- r = sd_bus_message_new_signal(bus, path, "org.freedesktop.DBus", "PropertiesChanged", &m);
+ r = node_vtable_get_userdata(bus, path, c, &u);
+ if (r <= 0)
+ return r;
+
+ r = sd_bus_message_new_signal(bus, path, "org.freedesktop.DBus.Properties", "PropertiesChanged", &m);
if (r < 0)
return r;
if (r < 0)
return r;
- r = sd_bus_message_append(m, "s", *n);
+ r = sd_bus_message_append(m, "s", *property);
if (r < 0)
return r;
if (r < 0)
return r;
- r = v->vtable->property.get(bus, m->path, interface, *property, m, &error, u);
+ r = invoke_property_get(bus, v->vtable, m->path, interface, *property, m, &error, vtable_property_convert_userdata(v->vtable, u));
if (r < 0)
return r;