chiark / gitweb /
tree-wide: drop 'This file is part of systemd' blurb
[elogind.git] / src / libelogind / sd-bus / bus-track.c
index 77a63a978c7e09d8b26cdf8a9bf49fd7664aafc1..846556cb36096666ef6e293b6e12fce15f103e27 100644 (file)
@@ -1,20 +1,6 @@
+/* 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 "sd-bus.h"
@@ -43,29 +29,18 @@ struct sd_bus_track {
         bool in_queue:1;   /* In bus->track_queue? */
         bool modified:1;
         bool recursive:1;
+        sd_bus_destroy_t destroy_callback;
 
         LIST_FIELDS(sd_bus_track, tracks);
 };
 
-#define MATCH_PREFIX                                        \
-        "type='signal',"                                    \
-        "sender='org.freedesktop.DBus',"                    \
-        "path='/org/freedesktop/DBus',"                     \
-        "interface='org.freedesktop.DBus',"                 \
-        "member='NameOwnerChanged',"                        \
-        "arg0='"
-
-#define MATCH_SUFFIX \
-        "'"
-
-#define MATCH_FOR_NAME(name)                                            \
-        ({                                                              \
-                char *_x;                                               \
-                size_t _l = strlen(name);                               \
-                _x = alloca(strlen(MATCH_PREFIX)+_l+strlen(MATCH_SUFFIX)+1); \
-                strcpy(stpcpy(stpcpy(_x, MATCH_PREFIX), name), MATCH_SUFFIX); \
-                _x;                                                     \
-        })
+#define MATCH_FOR_NAME(name)                            \
+        strjoina("type='signal',"                       \
+                 "sender='org.freedesktop.DBus',"       \
+                 "path='/org/freedesktop/DBus',"        \
+                 "interface='org.freedesktop.DBus',"    \
+                 "member='NameOwnerChanged',"           \
+                 "arg0='", name, "'")
 
 static struct track_item* track_item_free(struct track_item *i) {
 
@@ -74,9 +49,7 @@ static struct track_item* track_item_free(struct track_item *i) {
 
         sd_bus_slot_unref(i->slot);
         free(i->name);
-        free(i);
-
-        return NULL;
+        return mfree(i);
 }
 
 DEFINE_TRIVIAL_CLEANUP_FUNC(struct track_item*, track_item_free);
@@ -149,6 +122,7 @@ _public_ int sd_bus_track_new(
         sd_bus_track *t;
 
         assert_return(bus, -EINVAL);
+        assert_return(bus = bus_resolve(bus), -ENOPKG);
         assert_return(track, -EINVAL);
 
         if (!bus->bus_client)
@@ -185,30 +159,26 @@ _public_ sd_bus_track* sd_bus_track_ref(sd_bus_track *track) {
 }
 
 _public_ sd_bus_track* sd_bus_track_unref(sd_bus_track *track) {
-        struct track_item *i;
-
         if (!track)
                 return NULL;
 
         assert(track->n_ref > 0);
+        track->n_ref--;
 
-        if (track->n_ref > 1) {
-                track->n_ref--;
+        if (track->n_ref > 0)
                 return NULL;
-        }
-
-        while ((i = hashmap_steal_first(track->names)))
-                track_item_free(i);
 
         if (track->in_list)
                 LIST_REMOVE(tracks, track->bus->tracks, track);
 
         bus_track_remove_from_queue(track);
-        hashmap_free(track->names);
-        sd_bus_unref(track->bus);
-        free(track);
+        track->names = hashmap_free_with_destructor(track->names, track_item_free);
+        track->bus = sd_bus_unref(track->bus);
 
-        return NULL;
+        if (track->destroy_callback)
+                track->destroy_callback(track->userdata);
+
+        return mfree(track);
 }
 
 static int on_name_owner_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
@@ -267,9 +237,7 @@ _public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) {
 
         bus_track_remove_from_queue(track); /* don't dispatch this while we work in it */
 
-        track->n_adding++; /* make sure we aren't dispatched while we synchronously add this match */
-        r = sd_bus_add_match(track->bus, &n->slot, match, on_name_owner_changed, track);
-        track->n_adding--;
+        r = sd_bus_add_match_async(track->bus, &n->slot, match, on_name_owner_changed, NULL, track);
         if (r < 0) {
                 bus_track_add_to_queue(track);
                 return r;
@@ -431,10 +399,7 @@ void bus_track_dispatch(sd_bus_track *track) {
         sd_bus_track_unref(track);
 }
 
-#if 0 /// UNNEEDED by elogind
 void bus_track_close(sd_bus_track *track) {
-        struct track_item *i;
-
         assert(track);
 
         /* Called whenever our bus connected is closed. If so, and our track object is non-empty, dispatch it
@@ -452,8 +417,7 @@ void bus_track_close(sd_bus_track *track) {
                 return;
 
         /* Let's flush out all names */
-        while ((i = hashmap_steal_first(track->names)))
-                track_item_free(i);
+        hashmap_clear_with_destructor(track->names, track_item_free);
 
         /* Invoke handler */
         if (track->handler)
@@ -476,7 +440,22 @@ _public_ void *sd_bus_track_set_userdata(sd_bus_track *track, void *userdata) {
 
         return ret;
 }
-#endif // 0
+
+_public_ int sd_bus_track_set_destroy_callback(sd_bus_track *track, sd_bus_destroy_t callback) {
+        assert_return(track, -EINVAL);
+
+        track->destroy_callback = callback;
+        return 0;
+}
+
+_public_ int sd_bus_track_get_destroy_callback(sd_bus_track *track, sd_bus_destroy_t *ret) {
+        assert_return(track, -EINVAL);
+
+        if (ret)
+                *ret = track->destroy_callback;
+
+        return !!track->destroy_callback;
+}
 
 _public_ int sd_bus_track_set_recursive(sd_bus_track *track, int b) {
         assert_return(track, -EINVAL);