chiark / gitweb /
tree-wide: drop 'This file is part of systemd' blurb
[elogind.git] / src / libelogind / sd-bus / bus-objects.c
index 05a00f2178f63c530f1bb0b5388ab3c9d0941b8d..6713b6ba654bd7d2c5b251d6df6a9d533a9b15ac 100644 (file)
@@ -1,34 +1,20 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
+/* SPDX-License-Identifier: LGPL-2.1+ */
 /***
-  This file is part of systemd.
-
   Copyright 2013 Lennart Poettering
-
-  systemd is free software; you can redistribute it and/or modify it
-  under the terms of the GNU Lesser General Public License as published by
-  the Free Software Foundation; either version 2.1 of the License, or
-  (at your option) any later version.
-
-  systemd is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include "strv.h"
-#include "set.h"
+#include "alloc-util.h"
 #include "bus-internal.h"
+#include "bus-introspect.h"
 #include "bus-message.h"
-#include "bus-type.h"
+#include "bus-objects.h"
 #include "bus-signature.h"
-#include "bus-introspect.h"
-#include "bus-util.h"
 #include "bus-slot.h"
-#include "bus-objects.h"
+#include "bus-type.h"
+#include "bus-util.h"
+#include "set.h"
+#include "string-util.h"
+#include "strv.h"
 
 static int node_vtable_get_userdata(
                 sd_bus *bus,
@@ -38,7 +24,7 @@ static int node_vtable_get_userdata(
                 sd_bus_error *error) {
 
         sd_bus_slot *s;
-        void *u;
+        void *u, *found_u;
         int r;
 
         assert(bus);
@@ -50,7 +36,7 @@ static int node_vtable_get_userdata(
         if (c->find) {
                 bus->current_slot = sd_bus_slot_ref(s);
                 bus->current_userdata = u;
-                r = c->find(bus, path, c->interface, u, &u, error);
+                r = c->find(bus, path, c->interface, u, &found_u, error);
                 bus->current_userdata = NULL;
                 bus->current_slot = sd_bus_slot_unref(s);
 
@@ -60,10 +46,11 @@ static int node_vtable_get_userdata(
                         return -sd_bus_error_get_errno(error);
                 if (r == 0)
                         return r;
-        }
+        } else
+                found_u = u;
 
         if (userdata)
-                *userdata = u;
+                *userdata = found_u;
 
         return 1;
 }
@@ -145,7 +132,7 @@ static int add_enumerated_to_set(
                                 continue;
                         }
 
-                        if (!object_path_is_valid(*k)){
+                        if (!object_path_is_valid(*k)) {
                                 free(*k);
                                 r = -EINVAL;
                                 continue;
@@ -171,9 +158,9 @@ static int add_enumerated_to_set(
 
 enum {
         /* if set, add_subtree() works recursively */
-        CHILDREN_RECURSIVE              = (1U << 1),
+        CHILDREN_RECURSIVE      = 1 << 0,
         /* if set, add_subtree() scans object-manager hierarchies recursively */
-        CHILDREN_SUBHIERARCHIES         = (1U << 0),
+        CHILDREN_SUBHIERARCHIES = 1 << 1,
 };
 
 static int add_subtree_to_set(
@@ -270,7 +257,7 @@ static int node_callbacks_run(
         assert(found_object);
 
         LIST_FOREACH(callbacks, c, first) {
-                _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
+                _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
                 sd_bus_slot *slot;
 
                 if (bus->nodes_modified)
@@ -337,7 +324,7 @@ static int check_access(sd_bus *bus, sd_bus_message *m, struct vtable_member *c,
         if (cap == 0)
                 cap = CAP_SYS_ADMIN;
         else
-                cap --;
+                cap--;
 
         r = sd_bus_query_sender_privilege(m, cap);
         if (r < 0)
@@ -355,7 +342,7 @@ static int method_callbacks_run(
                 bool require_fallback,
                 bool *found_object) {
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         const char *signature;
         void *u;
         int r;
@@ -578,8 +565,8 @@ static int property_get_set_callbacks_run(
                 bool is_get,
                 bool *found_object) {
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         sd_bus_slot *slot;
         void *u = NULL;
         int r;
@@ -752,7 +739,7 @@ static int vtable_append_all_properties(
                 return 1;
 
         for (v = c->vtable+1; v->type != _SD_BUS_VTABLE_END; v++) {
-                if (v->type != _SD_BUS_VTABLE_PROPERTY && v->type != _SD_BUS_VTABLE_WRITABLE_PROPERTY)
+                if (!IN_SET(v->type, _SD_BUS_VTABLE_PROPERTY, _SD_BUS_VTABLE_WRITABLE_PROPERTY))
                         continue;
 
                 if (v->flags & SD_BUS_VTABLE_HIDDEN)
@@ -779,7 +766,7 @@ static int property_get_all_callbacks_run(
                 const char *iface,
                 bool *found_object) {
 
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         struct node_vtable *c;
         bool found_interface;
         int r;
@@ -802,7 +789,7 @@ static int property_get_all_callbacks_run(
                 streq(iface, "org.freedesktop.DBus.Introspectable");
 
         LIST_FOREACH(vtables, c, first) {
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
                 void *u;
 
                 if (require_fallback && !c->is_fallback)
@@ -829,6 +816,9 @@ static int property_get_all_callbacks_run(
                         return 0;
         }
 
+        if (!*found_object)
+                return 0;
+
         if (!found_interface) {
                 r = sd_bus_reply_method_errorf(
                                 m,
@@ -879,7 +869,7 @@ static int bus_node_exists(
         }
 
         LIST_FOREACH(vtables, c, n->vtables) {
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
 
                 if (require_fallback && !c->is_fallback)
                         continue;
@@ -901,8 +891,8 @@ static int process_introspect(
                 bool require_fallback,
                 bool *found_object) {
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _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;
@@ -974,8 +964,10 @@ static int process_introspect(
                 /* 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)
+                if (r <= 0) {
+                        r = bus_maybe_reply_error(m, r, &error);
                         goto finish;
+                }
                 if (bus->nodes_modified) {
                         r = 0;
                         goto finish;
@@ -1057,6 +1049,22 @@ static int object_manager_serialize_path(
                         if (r < 0)
                                 return r;
 
+                        r = sd_bus_message_append(reply, "{sa{sv}}", "org.freedesktop.DBus.Peer", 0);
+                        if (r < 0)
+                                return r;
+
+                        r = sd_bus_message_append(reply, "{sa{sv}}", "org.freedesktop.DBus.Introspectable", 0);
+                        if (r < 0)
+                                return r;
+
+                        r = sd_bus_message_append(reply, "{sa{sv}}", "org.freedesktop.DBus.Properties", 0);
+                        if (r < 0)
+                                return r;
+
+                        r = sd_bus_message_append(reply, "{sa{sv}}", "org.freedesktop.DBus.ObjectManager", 0);
+                        if (r < 0)
+                                return r;
+
                         found_something = true;
                 }
 
@@ -1162,8 +1170,8 @@ static int process_get_managed_objects(
                 bool require_fallback,
                 bool *found_object) {
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _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;
         Iterator i;
         char *path;
@@ -1183,7 +1191,7 @@ static int process_get_managed_objects(
 
         r = get_child_nodes(bus, m->path, n, CHILDREN_RECURSIVE, &s, &error);
         if (r < 0)
-                return r;
+                return bus_maybe_reply_error(m, r, &error);
         if (bus->nodes_modified)
                 return 0;
 
@@ -1198,7 +1206,7 @@ static int process_get_managed_objects(
         SET_FOREACH(path, s, i) {
                 r = object_manager_serialize_path_and_fallbacks(bus, reply, path, &error);
                 if (r < 0)
-                        return r;
+                        return bus_maybe_reply_error(m, r, &error);
 
                 if (bus->nodes_modified)
                         return 0;
@@ -1328,7 +1336,7 @@ static int object_find_and_run(
         if (!*found_object) {
                 r = bus_node_exists(bus, n, m->path, require_fallback);
                 if (r < 0)
-                        return r;
+                        return bus_maybe_reply_error(m, r, NULL);
                 if (bus->nodes_modified)
                         return 0;
                 if (r > 0)
@@ -1346,7 +1354,7 @@ int bus_process_object(sd_bus *bus, sd_bus_message *m) {
         assert(bus);
         assert(m);
 
-        if (bus->hello_flags & KDBUS_HELLO_MONITOR)
+        if (bus->is_monitor)
                 return 0;
 
         if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
@@ -1447,14 +1455,12 @@ static struct node *bus_node_allocate(sd_bus *bus, const char *path) {
                 return NULL;
 
         n->parent = parent;
-        n->path = s;
-        s = NULL; /* do not free */
+        n->path = TAKE_PTR(s);
 
         r = hashmap_put(bus->nodes, n->path, n);
         if (r < 0) {
                 free(n->path);
-                free(n);
-                return NULL;
+                return mfree(n);
         }
 
         if (parent)
@@ -1476,7 +1482,7 @@ void bus_node_gc(sd_bus *b, struct node *n) {
             n->object_managers)
                 return;
 
-        assert(hashmap_remove(b->nodes, n->path) == n);
+        assert_se(hashmap_remove(b->nodes, n->path) == n);
 
         if (n->parent)
                 LIST_REMOVE(siblings, n->parent->child, n);
@@ -1525,6 +1531,7 @@ static int bus_add_object(
         int r;
 
         assert_return(bus, -EINVAL);
+        assert_return(bus = bus_resolve(bus), -ENOPKG);
         assert_return(object_path_is_valid(path), -EINVAL);
         assert_return(callback, -EINVAL);
         assert_return(!bus_pid_changed(bus), -ECHILD);
@@ -1578,25 +1585,14 @@ _public_ int sd_bus_add_fallback(
         return bus_add_object(bus, slot, true, prefix, callback, userdata);
 }
 
-static unsigned long vtable_member_hash_func(const void *a, const uint8_t hash_key[HASH_KEY_SIZE]) {
+static void vtable_member_hash_func(const void *a, struct siphash *state) {
         const struct vtable_member *m = a;
-        uint8_t hash_key2[HASH_KEY_SIZE];
-        unsigned long ret;
 
         assert(m);
 
-        ret = string_hash_func(m->path, hash_key);
-
-        /* Use a slightly different hash key for the interface */
-        memcpy(hash_key2, hash_key, HASH_KEY_SIZE);
-        hash_key2[0]++;
-        ret ^= string_hash_func(m->interface, hash_key2);
-
-        /* And an even different one for the  member */
-        hash_key2[0]++;
-        ret ^= string_hash_func(m->member, hash_key2);
-
-        return ret;
+        string_hash_func(m->path, state);
+        string_hash_func(m->interface, state);
+        string_hash_func(m->member, state);
 }
 
 static int vtable_member_compare_func(const void *a, const void *b) {
@@ -1639,6 +1635,7 @@ static int add_object_vtable_internal(
         int r;
 
         assert_return(bus, -EINVAL);
+        assert_return(bus = bus_resolve(bus), -ENOPKG);
         assert_return(object_path_is_valid(path), -EINVAL);
         assert_return(interface_name_is_valid(interface), -EINVAL);
         assert_return(vtable, -EINVAL);
@@ -1744,8 +1741,7 @@ static int add_object_vtable_internal(
                                 goto fail;
                         }
 
-                        /* Fall through */
-
+                        _fallthrough_;
                 case _SD_BUS_VTABLE_PROPERTY: {
                         struct vtable_member *m;
 
@@ -1849,6 +1845,7 @@ _public_ int sd_bus_add_node_enumerator(
         int r;
 
         assert_return(bus, -EINVAL);
+        assert_return(bus = bus_resolve(bus), -ENOPKG);
         assert_return(object_path_is_valid(path), -EINVAL);
         assert_return(callback, -EINVAL);
         assert_return(!bus_pid_changed(bus), -ECHILD);
@@ -1890,8 +1887,8 @@ static int emit_properties_changed_on_interface(
                 bool *found_interface,
                 char **names) {
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         bool has_invalidating = false, has_changing = false;
         struct vtable_member key = {};
         struct node_vtable *c;
@@ -1989,7 +1986,7 @@ static int emit_properties_changed_on_interface(
                          * as changing in the message. */
 
                         for (v = c->vtable+1; v->type != _SD_BUS_VTABLE_END; v++) {
-                                if (v->type != _SD_BUS_VTABLE_PROPERTY && v->type != _SD_BUS_VTABLE_WRITABLE_PROPERTY)
+                                if (!IN_SET(v->type, _SD_BUS_VTABLE_PROPERTY, _SD_BUS_VTABLE_WRITABLE_PROPERTY))
                                         continue;
 
                                 if (v->flags & SD_BUS_VTABLE_HIDDEN)
@@ -2060,7 +2057,7 @@ static int emit_properties_changed_on_interface(
                                 const sd_bus_vtable *v;
 
                                 for (v = c->vtable+1; v->type != _SD_BUS_VTABLE_END; v++) {
-                                        if (v->type != _SD_BUS_VTABLE_PROPERTY && v->type != _SD_BUS_VTABLE_WRITABLE_PROPERTY)
+                                        if (!IN_SET(v->type, _SD_BUS_VTABLE_PROPERTY, _SD_BUS_VTABLE_WRITABLE_PROPERTY))
                                                 continue;
 
                                         if (v->flags & SD_BUS_VTABLE_HIDDEN)
@@ -2100,6 +2097,7 @@ _public_ int sd_bus_emit_properties_changed_strv(
         int r;
 
         assert_return(bus, -EINVAL);
+        assert_return(bus = bus_resolve(bus), -ENOPKG);
         assert_return(object_path_is_valid(path), -EINVAL);
         assert_return(interface_name_is_valid(interface), -EINVAL);
         assert_return(!bus_pid_changed(bus), -ECHILD);
@@ -2146,6 +2144,7 @@ _public_ int sd_bus_emit_properties_changed(
         char **names;
 
         assert_return(bus, -EINVAL);
+        assert_return(bus = bus_resolve(bus), -ENOPKG);
         assert_return(object_path_is_valid(path), -EINVAL);
         assert_return(interface_name_is_valid(interface), -EINVAL);
         assert_return(!bus_pid_changed(bus), -ECHILD);
@@ -2185,7 +2184,7 @@ static int object_added_append_all_prefix(
                 return 0;
 
         LIST_FOREACH(vtables, c, n->vtables) {
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
                 void *u = NULL;
 
                 if (require_fallback && !c->is_fallback)
@@ -2314,7 +2313,7 @@ static int object_added_append_all(sd_bus *bus, sd_bus_message *m, const char *p
 _public_ int sd_bus_emit_object_added(sd_bus *bus, const char *path) {
         BUS_DONT_DESTROY(bus);
 
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         struct node *object_manager;
         int r;
 
@@ -2330,6 +2329,7 @@ _public_ int sd_bus_emit_object_added(sd_bus *bus, const char *path) {
          */
 
         assert_return(bus, -EINVAL);
+        assert_return(bus = bus_resolve(bus), -ENOPKG);
         assert_return(object_path_is_valid(path), -EINVAL);
         assert_return(!bus_pid_changed(bus), -ECHILD);
 
@@ -2374,8 +2374,6 @@ _public_ int sd_bus_emit_object_added(sd_bus *bus, const char *path) {
         return sd_bus_send(bus, m, NULL);
 }
 
-/// UNNEEDED by elogind
-#if 0
 static int object_removed_append_all_prefix(
                 sd_bus *bus,
                 sd_bus_message *m,
@@ -2400,7 +2398,7 @@ static int object_removed_append_all_prefix(
                 return 0;
 
         LIST_FOREACH(vtables, c, n->vtables) {
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
                 void *u = NULL;
 
                 if (require_fallback && !c->is_fallback)
@@ -2486,7 +2484,7 @@ static int object_removed_append_all(sd_bus *bus, sd_bus_message *m, const char
 _public_ int sd_bus_emit_object_removed(sd_bus *bus, const char *path) {
         BUS_DONT_DESTROY(bus);
 
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         struct node *object_manager;
         int r;
 
@@ -2502,6 +2500,7 @@ _public_ int sd_bus_emit_object_removed(sd_bus *bus, const char *path) {
          */
 
         assert_return(bus, -EINVAL);
+        assert_return(bus = bus_resolve(bus), -ENOPKG);
         assert_return(object_path_is_valid(path), -EINVAL);
         assert_return(!bus_pid_changed(bus), -ECHILD);
 
@@ -2545,7 +2544,6 @@ _public_ int sd_bus_emit_object_removed(sd_bus *bus, const char *path) {
 
         return sd_bus_send(bus, m, NULL);
 }
-#endif // 0
 
 static int interfaces_added_append_one_prefix(
                 sd_bus *bus,
@@ -2555,7 +2553,7 @@ static int interfaces_added_append_one_prefix(
                 const char *interface,
                 bool require_fallback) {
 
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         bool found_interface = false;
         struct node_vtable *c;
         struct node *n;
@@ -2650,12 +2648,13 @@ static int interfaces_added_append_one(
 _public_ int sd_bus_emit_interfaces_added_strv(sd_bus *bus, const char *path, char **interfaces) {
         BUS_DONT_DESTROY(bus);
 
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         struct node *object_manager;
         char **i;
         int r;
 
         assert_return(bus, -EINVAL);
+        assert_return(bus = bus_resolve(bus), -ENOPKG);
         assert_return(object_path_is_valid(path), -EINVAL);
         assert_return(!bus_pid_changed(bus), -ECHILD);
 
@@ -2722,6 +2721,7 @@ _public_ int sd_bus_emit_interfaces_added(sd_bus *bus, const char *path, const c
         char **interfaces;
 
         assert_return(bus, -EINVAL);
+        assert_return(bus = bus_resolve(bus), -ENOPKG);
         assert_return(object_path_is_valid(path), -EINVAL);
         assert_return(!bus_pid_changed(bus), -ECHILD);
 
@@ -2734,11 +2734,12 @@ _public_ int sd_bus_emit_interfaces_added(sd_bus *bus, const char *path, const c
 }
 
 _public_ int sd_bus_emit_interfaces_removed_strv(sd_bus *bus, const char *path, char **interfaces) {
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         struct node *object_manager;
         int r;
 
         assert_return(bus, -EINVAL);
+        assert_return(bus = bus_resolve(bus), -ENOPKG);
         assert_return(object_path_is_valid(path), -EINVAL);
         assert_return(!bus_pid_changed(bus), -ECHILD);
 
@@ -2773,6 +2774,7 @@ _public_ int sd_bus_emit_interfaces_removed(sd_bus *bus, const char *path, const
         char **interfaces;
 
         assert_return(bus, -EINVAL);
+        assert_return(bus = bus_resolve(bus), -ENOPKG);
         assert_return(object_path_is_valid(path), -EINVAL);
         assert_return(!bus_pid_changed(bus), -ECHILD);
 
@@ -2784,14 +2786,13 @@ _public_ int sd_bus_emit_interfaces_removed(sd_bus *bus, const char *path, const
         return sd_bus_emit_interfaces_removed_strv(bus, path, interfaces);
 }
 
-/// UNNEEDED by elogind
-#if 0
 _public_ int sd_bus_add_object_manager(sd_bus *bus, sd_bus_slot **slot, const char *path) {
         sd_bus_slot *s;
         struct node *n;
         int r;
 
         assert_return(bus, -EINVAL);
+        assert_return(bus = bus_resolve(bus), -ENOPKG);
         assert_return(object_path_is_valid(path), -EINVAL);
         assert_return(!bus_pid_changed(bus), -ECHILD);
 
@@ -2820,4 +2821,3 @@ fail:
 
         return r;
 }
-#endif // 0