Coverage Report

Created: 2022-04-19 08:24

/src/systemd/src/libsystemd/sd-bus/bus-slot.c
Line
Count
Source (jump to first uncovered line)
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3
#include "sd-bus.h"
4
5
#include "alloc-util.h"
6
#include "bus-control.h"
7
#include "bus-objects.h"
8
#include "bus-slot.h"
9
#include "string-util.h"
10
11
sd_bus_slot *bus_slot_allocate(
12
                sd_bus *bus,
13
                bool floating,
14
                BusSlotType type,
15
                size_t extra,
16
527
                void *userdata) {
17
18
527
        sd_bus_slot *slot;
19
20
527
        assert(bus);
21
22
527
        slot = malloc0(offsetof(sd_bus_slot, reply_callback) + extra);
23
527
        if (!slot)
24
0
                return NULL;
25
26
527
        slot->n_ref = 1;
27
527
        slot->type = type;
28
527
        slot->bus = bus;
29
527
        slot->floating = floating;
30
527
        slot->userdata = userdata;
31
32
527
        if (!floating)
33
0
                sd_bus_ref(bus);
34
35
527
        LIST_PREPEND(slots, bus->slots, slot);
36
37
527
        return slot;
38
527
}
39
40
1.05k
void bus_slot_disconnect(sd_bus_slot *slot, bool unref) {
41
1.05k
        sd_bus *bus;
42
43
1.05k
        assert(slot);
44
45
1.05k
        if (!slot->bus)
46
527
                return;
47
48
527
        switch (slot->type) {
49
50
527
        case BUS_REPLY_CALLBACK:
51
52
527
                if (slot->reply_callback.cookie != 0)
53
527
                        ordered_hashmap_remove(slot->bus->reply_callbacks, &slot->reply_callback.cookie);
54
55
527
                if (slot->reply_callback.timeout_usec != 0)
56
527
                        prioq_remove(slot->bus->reply_callbacks_prioq, &slot->reply_callback, &slot->reply_callback.prioq_idx);
57
58
527
                break;
59
60
0
        case BUS_FILTER_CALLBACK:
61
0
                slot->bus->filter_callbacks_modified = true;
62
0
                LIST_REMOVE(callbacks, slot->bus->filter_callbacks, &slot->filter_callback);
63
0
                break;
64
65
0
        case BUS_MATCH_CALLBACK:
66
67
0
                if (slot->match_added)
68
0
                        (void) bus_remove_match_internal(slot->bus, slot->match_callback.match_string);
69
70
0
                if (slot->match_callback.install_slot) {
71
0
                        bus_slot_disconnect(slot->match_callback.install_slot, true);
72
0
                        slot->match_callback.install_slot = sd_bus_slot_unref(slot->match_callback.install_slot);
73
0
                }
74
75
0
                slot->bus->match_callbacks_modified = true;
76
0
                bus_match_remove(&slot->bus->match_callbacks, &slot->match_callback);
77
78
0
                slot->match_callback.match_string = mfree(slot->match_callback.match_string);
79
80
0
                break;
81
82
0
        case BUS_NODE_CALLBACK:
83
84
0
                if (slot->node_callback.node) {
85
0
                        LIST_REMOVE(callbacks, slot->node_callback.node->callbacks, &slot->node_callback);
86
0
                        slot->bus->nodes_modified = true;
87
88
0
                        bus_node_gc(slot->bus, slot->node_callback.node);
89
0
                }
90
91
0
                break;
92
93
0
        case BUS_NODE_ENUMERATOR:
94
95
0
                if (slot->node_enumerator.node) {
96
0
                        LIST_REMOVE(enumerators, slot->node_enumerator.node->enumerators, &slot->node_enumerator);
97
0
                        slot->bus->nodes_modified = true;
98
99
0
                        bus_node_gc(slot->bus, slot->node_enumerator.node);
100
0
                }
101
102
0
                break;
103
104
0
        case BUS_NODE_OBJECT_MANAGER:
105
106
0
                if (slot->node_object_manager.node) {
107
0
                        LIST_REMOVE(object_managers, slot->node_object_manager.node->object_managers, &slot->node_object_manager);
108
0
                        slot->bus->nodes_modified = true;
109
110
0
                        bus_node_gc(slot->bus, slot->node_object_manager.node);
111
0
                }
112
113
0
                break;
114
115
0
        case BUS_NODE_VTABLE:
116
117
0
                if (slot->node_vtable.node && slot->node_vtable.interface && slot->node_vtable.vtable) {
118
0
                        const sd_bus_vtable *v;
119
120
0
                        for (v = slot->node_vtable.vtable; v->type != _SD_BUS_VTABLE_END; v = bus_vtable_next(slot->node_vtable.vtable, v)) {
121
0
                                struct vtable_member *x = NULL;
122
123
0
                                switch (v->type) {
124
125
0
                                case _SD_BUS_VTABLE_METHOD: {
126
0
                                        struct vtable_member key;
127
128
0
                                        key.path = slot->node_vtable.node->path;
129
0
                                        key.interface = slot->node_vtable.interface;
130
0
                                        key.member = v->x.method.member;
131
132
0
                                        x = hashmap_remove(slot->bus->vtable_methods, &key);
133
0
                                        break;
134
0
                                }
135
136
0
                                case _SD_BUS_VTABLE_PROPERTY:
137
0
                                case _SD_BUS_VTABLE_WRITABLE_PROPERTY: {
138
0
                                        struct vtable_member key;
139
140
0
                                        key.path = slot->node_vtable.node->path;
141
0
                                        key.interface = slot->node_vtable.interface;
142
0
                                        key.member = v->x.method.member;
143
144
0
                                        x = hashmap_remove(slot->bus->vtable_properties, &key);
145
0
                                        break;
146
0
                                }}
147
148
0
                                free(x);
149
0
                        }
150
0
                }
151
152
0
                slot->node_vtable.interface = mfree(slot->node_vtable.interface);
153
154
0
                if (slot->node_vtable.node) {
155
0
                        LIST_REMOVE(vtables, slot->node_vtable.node->vtables, &slot->node_vtable);
156
0
                        slot->bus->nodes_modified = true;
157
158
0
                        bus_node_gc(slot->bus, slot->node_vtable.node);
159
0
                }
160
161
0
                break;
162
163
0
        default:
164
0
                assert_not_reached();
165
527
        }
166
167
527
        bus = slot->bus;
168
169
527
        slot->type = _BUS_SLOT_INVALID;
170
527
        slot->bus = NULL;
171
527
        LIST_REMOVE(slots, bus->slots, slot);
172
173
527
        if (!slot->floating)
174
0
                sd_bus_unref(bus);
175
527
        else if (unref)
176
527
                sd_bus_slot_unref(slot);
177
527
}
178
179
527
static sd_bus_slot* bus_slot_free(sd_bus_slot *slot) {
180
527
        assert(slot);
181
182
527
        bus_slot_disconnect(slot, false);
183
184
527
        if (slot->destroy_callback)
185
0
                slot->destroy_callback(slot->userdata);
186
187
527
        free(slot->description);
188
527
        return mfree(slot);
189
527
}
190
191
DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_bus_slot, sd_bus_slot, bus_slot_free);
192
193
0
_public_ sd_bus* sd_bus_slot_get_bus(sd_bus_slot *slot) {
194
0
        assert_return(slot, NULL);
195
196
0
        return slot->bus;
197
0
}
198
199
0
_public_ void *sd_bus_slot_get_userdata(sd_bus_slot *slot) {
200
0
        assert_return(slot, NULL);
201
202
0
        return slot->userdata;
203
0
}
204
205
0
_public_ void *sd_bus_slot_set_userdata(sd_bus_slot *slot, void *userdata) {
206
0
        void *ret;
207
208
0
        assert_return(slot, NULL);
209
210
0
        ret = slot->userdata;
211
0
        slot->userdata = userdata;
212
213
0
        return ret;
214
0
}
215
216
0
_public_ int sd_bus_slot_set_destroy_callback(sd_bus_slot *slot, sd_bus_destroy_t callback) {
217
0
        assert_return(slot, -EINVAL);
218
219
0
        slot->destroy_callback = callback;
220
0
        return 0;
221
0
}
222
223
0
_public_ int sd_bus_slot_get_destroy_callback(sd_bus_slot *slot, sd_bus_destroy_t *callback) {
224
0
        assert_return(slot, -EINVAL);
225
226
0
        if (callback)
227
0
                *callback = slot->destroy_callback;
228
229
0
        return !!slot->destroy_callback;
230
0
}
231
232
0
_public_ sd_bus_message *sd_bus_slot_get_current_message(sd_bus_slot *slot) {
233
0
        assert_return(slot, NULL);
234
0
        assert_return(slot->type >= 0, NULL);
235
236
0
        if (slot->bus->current_slot != slot)
237
0
                return NULL;
238
239
0
        return slot->bus->current_message;
240
0
}
241
242
0
_public_ sd_bus_message_handler_t sd_bus_slot_get_current_handler(sd_bus_slot *slot) {
243
0
        assert_return(slot, NULL);
244
0
        assert_return(slot->type >= 0, NULL);
245
246
0
        if (slot->bus->current_slot != slot)
247
0
                return NULL;
248
249
0
        return slot->bus->current_handler;
250
0
}
251
252
0
_public_ void* sd_bus_slot_get_current_userdata(sd_bus_slot *slot) {
253
0
        assert_return(slot, NULL);
254
0
        assert_return(slot->type >= 0, NULL);
255
256
0
        if (slot->bus->current_slot != slot)
257
0
                return NULL;
258
259
0
        return slot->bus->current_userdata;
260
0
}
261
262
0
_public_ int sd_bus_slot_get_floating(sd_bus_slot *slot) {
263
0
        assert_return(slot, -EINVAL);
264
265
0
        return slot->floating;
266
0
}
267
268
0
_public_ int sd_bus_slot_set_floating(sd_bus_slot *slot, int b) {
269
0
        assert_return(slot, -EINVAL);
270
271
0
        if (slot->floating == !!b)
272
0
                return 0;
273
274
0
        if (!slot->bus) /* already disconnected slots can't be reconnected */
275
0
                return -ESTALE;
276
277
0
        slot->floating = b;
278
279
        /* When a slot is "floating" then the bus references the slot. Otherwise the slot references the bus. Hence,
280
         * when we move from one to the other, let's increase one reference and decrease the other. */
281
282
0
        if (b) {
283
0
                sd_bus_slot_ref(slot);
284
0
                sd_bus_unref(slot->bus);
285
0
        } else {
286
0
                sd_bus_ref(slot->bus);
287
0
                sd_bus_slot_unref(slot);
288
0
        }
289
290
0
        return 1;
291
0
}
292
293
0
_public_ int sd_bus_slot_set_description(sd_bus_slot *slot, const char *description) {
294
0
        assert_return(slot, -EINVAL);
295
296
0
        return free_and_strdup(&slot->description, description);
297
0
}
298
299
0
_public_ int sd_bus_slot_get_description(sd_bus_slot *slot, const char **description) {
300
0
        assert_return(slot, -EINVAL);
301
0
        assert_return(description, -EINVAL);
302
303
0
        if (slot->description)
304
0
                *description = slot->description;
305
0
        else if (slot->type == BUS_MATCH_CALLBACK)
306
0
                *description = slot->match_callback.match_string;
307
0
        else
308
0
                return -ENXIO;
309
310
0
        return 0;
311
0
}