File: | build-scan/../src/libsystemd/sd-bus/bus-track.c |
Warning: | line 232, column 25 Potential leak of memory pointed to by 'n' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* SPDX-License-Identifier: LGPL-2.1+ */ | |||
2 | /*** | |||
3 | ***/ | |||
4 | ||||
5 | #include "sd-bus.h" | |||
6 | ||||
7 | #include "alloc-util.h" | |||
8 | #include "bus-internal.h" | |||
9 | #include "bus-track.h" | |||
10 | #include "bus-util.h" | |||
11 | ||||
12 | struct track_item { | |||
13 | unsigned n_ref; | |||
14 | char *name; | |||
15 | sd_bus_slot *slot; | |||
16 | }; | |||
17 | ||||
18 | struct sd_bus_track { | |||
19 | unsigned n_ref; | |||
20 | unsigned n_adding; /* are we in the process of adding a new name? */ | |||
21 | sd_bus *bus; | |||
22 | sd_bus_track_handler_t handler; | |||
23 | void *userdata; | |||
24 | Hashmap *names; | |||
25 | LIST_FIELDS(sd_bus_track, queue)sd_bus_track *queue_next, *queue_prev; | |||
26 | Iterator iterator; | |||
27 | bool_Bool in_list:1; /* In bus->tracks? */ | |||
28 | bool_Bool in_queue:1; /* In bus->track_queue? */ | |||
29 | bool_Bool modified:1; | |||
30 | bool_Bool recursive:1; | |||
31 | sd_bus_destroy_t destroy_callback; | |||
32 | ||||
33 | LIST_FIELDS(sd_bus_track, tracks)sd_bus_track *tracks_next, *tracks_prev; | |||
34 | }; | |||
35 | ||||
36 | #define MATCH_FOR_NAME(name)({ const char *_appendees_[] = { "type='signal'," "sender='org.freedesktop.DBus'," "path='/org/freedesktop/DBus'," "interface='org.freedesktop.DBus'," "member='NameOwnerChanged'," "arg0='", name, "'" }; char *_d_ , *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_ )/sizeof((_appendees_)[0]), ((void)0))) && _appendees_ [_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca (_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(_appendees_), typeof(& *(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0] ), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy (_p_, _appendees_[_i_]); *_p_ = 0; _d_; }) \ | |||
37 | strjoina("type='signal'," \({ const char *_appendees_[] = { "type='signal'," "sender='org.freedesktop.DBus'," "path='/org/freedesktop/DBus'," "interface='org.freedesktop.DBus'," "member='NameOwnerChanged'," "arg0='", name, "'" }; char *_d_ , *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_ )/sizeof((_appendees_)[0]), ((void)0))) && _appendees_ [_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca (_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(_appendees_), typeof(& *(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0] ), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy (_p_, _appendees_[_i_]); *_p_ = 0; _d_; }) | |||
38 | "sender='org.freedesktop.DBus'," \({ const char *_appendees_[] = { "type='signal'," "sender='org.freedesktop.DBus'," "path='/org/freedesktop/DBus'," "interface='org.freedesktop.DBus'," "member='NameOwnerChanged'," "arg0='", name, "'" }; char *_d_ , *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_ )/sizeof((_appendees_)[0]), ((void)0))) && _appendees_ [_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca (_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(_appendees_), typeof(& *(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0] ), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy (_p_, _appendees_[_i_]); *_p_ = 0; _d_; }) | |||
39 | "path='/org/freedesktop/DBus'," \({ const char *_appendees_[] = { "type='signal'," "sender='org.freedesktop.DBus'," "path='/org/freedesktop/DBus'," "interface='org.freedesktop.DBus'," "member='NameOwnerChanged'," "arg0='", name, "'" }; char *_d_ , *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_ )/sizeof((_appendees_)[0]), ((void)0))) && _appendees_ [_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca (_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(_appendees_), typeof(& *(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0] ), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy (_p_, _appendees_[_i_]); *_p_ = 0; _d_; }) | |||
40 | "interface='org.freedesktop.DBus'," \({ const char *_appendees_[] = { "type='signal'," "sender='org.freedesktop.DBus'," "path='/org/freedesktop/DBus'," "interface='org.freedesktop.DBus'," "member='NameOwnerChanged'," "arg0='", name, "'" }; char *_d_ , *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_ )/sizeof((_appendees_)[0]), ((void)0))) && _appendees_ [_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca (_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(_appendees_), typeof(& *(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0] ), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy (_p_, _appendees_[_i_]); *_p_ = 0; _d_; }) | |||
41 | "member='NameOwnerChanged'," \({ const char *_appendees_[] = { "type='signal'," "sender='org.freedesktop.DBus'," "path='/org/freedesktop/DBus'," "interface='org.freedesktop.DBus'," "member='NameOwnerChanged'," "arg0='", name, "'" }; char *_d_ , *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_ )/sizeof((_appendees_)[0]), ((void)0))) && _appendees_ [_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca (_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(_appendees_), typeof(& *(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0] ), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy (_p_, _appendees_[_i_]); *_p_ = 0; _d_; }) | |||
42 | "arg0='", name, "'")({ const char *_appendees_[] = { "type='signal'," "sender='org.freedesktop.DBus'," "path='/org/freedesktop/DBus'," "interface='org.freedesktop.DBus'," "member='NameOwnerChanged'," "arg0='", name, "'" }; char *_d_ , *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_ )/sizeof((_appendees_)[0]), ((void)0))) && _appendees_ [_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca (_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(_appendees_), typeof(& *(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0] ), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy (_p_, _appendees_[_i_]); *_p_ = 0; _d_; }) | |||
43 | ||||
44 | static struct track_item* track_item_free(struct track_item *i) { | |||
45 | ||||
46 | if (!i) | |||
47 | return NULL((void*)0); | |||
48 | ||||
49 | sd_bus_slot_unref(i->slot); | |||
50 | free(i->name); | |||
51 | return mfree(i); | |||
52 | } | |||
53 | ||||
54 | DEFINE_TRIVIAL_CLEANUP_FUNC(struct track_item*, track_item_free)static inline void track_item_freep(struct track_item* *p) { if (*p) track_item_free(*p); }; | |||
55 | ||||
56 | static void bus_track_add_to_queue(sd_bus_track *track) { | |||
57 | assert(track)do { if ((__builtin_expect(!!(!(track)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("track"), "../src/libsystemd/sd-bus/bus-track.c" , 57, __PRETTY_FUNCTION__); } while (0); | |||
58 | ||||
59 | /* Adds the bus track object to the queue of objects we should dispatch next, subject to a number of | |||
60 | * conditions. */ | |||
61 | ||||
62 | /* Already in the queue? */ | |||
63 | if (track->in_queue) | |||
64 | return; | |||
65 | ||||
66 | /* if we are currently in the process of adding a new name, then let's not enqueue this just yet, let's wait | |||
67 | * until the addition is complete. */ | |||
68 | if (track->n_adding > 0) | |||
69 | return; | |||
70 | ||||
71 | /* still referenced? */ | |||
72 | if (hashmap_size(track->names) > 0) | |||
73 | return; | |||
74 | ||||
75 | /* Nothing to call? */ | |||
76 | if (!track->handler) | |||
77 | return; | |||
78 | ||||
79 | /* Already closed? */ | |||
80 | if (!track->in_list) | |||
81 | return; | |||
82 | ||||
83 | LIST_PREPEND(queue, track->bus->track_queue, track)do { typeof(*(track->bus->track_queue)) **_head = & (track->bus->track_queue), *_item = (track); do { if (( __builtin_expect(!!(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("_item"), "../src/libsystemd/sd-bus/bus-track.c", 83, __PRETTY_FUNCTION__ ); } while (0); if ((_item->queue_next = *_head)) _item-> queue_next->queue_prev = _item; _item->queue_prev = ((void *)0); *_head = _item; } while (0); | |||
84 | track->in_queue = true1; | |||
85 | } | |||
86 | ||||
87 | static void bus_track_remove_from_queue(sd_bus_track *track) { | |||
88 | assert(track)do { if ((__builtin_expect(!!(!(track)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("track"), "../src/libsystemd/sd-bus/bus-track.c" , 88, __PRETTY_FUNCTION__); } while (0); | |||
89 | ||||
90 | if (!track->in_queue) | |||
91 | return; | |||
92 | ||||
93 | LIST_REMOVE(queue, track->bus->track_queue, track)do { typeof(*(track->bus->track_queue)) **_head = & (track->bus->track_queue), *_item = (track); do { if (( __builtin_expect(!!(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("_item"), "../src/libsystemd/sd-bus/bus-track.c", 93, __PRETTY_FUNCTION__ ); } while (0); if (_item->queue_next) _item->queue_next ->queue_prev = _item->queue_prev; if (_item->queue_prev ) _item->queue_prev->queue_next = _item->queue_next; else { do { if ((__builtin_expect(!!(!(*_head == _item)),0)) ) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("*_head == _item" ), "../src/libsystemd/sd-bus/bus-track.c", 93, __PRETTY_FUNCTION__ ); } while (0); *_head = _item->queue_next; } _item->queue_next = _item->queue_prev = ((void*)0); } while (0); | |||
94 | track->in_queue = false0; | |||
95 | } | |||
96 | ||||
97 | static int bus_track_remove_name_fully(sd_bus_track *track, const char *name) { | |||
98 | struct track_item *i; | |||
99 | ||||
100 | assert(track)do { if ((__builtin_expect(!!(!(track)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("track"), "../src/libsystemd/sd-bus/bus-track.c" , 100, __PRETTY_FUNCTION__); } while (0); | |||
101 | assert(name)do { if ((__builtin_expect(!!(!(name)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("name"), "../src/libsystemd/sd-bus/bus-track.c" , 101, __PRETTY_FUNCTION__); } while (0); | |||
102 | ||||
103 | i = hashmap_remove(track->names, name); | |||
104 | if (!i) | |||
105 | return 0; | |||
106 | ||||
107 | track_item_free(i); | |||
108 | ||||
109 | bus_track_add_to_queue(track); | |||
110 | ||||
111 | track->modified = true1; | |||
112 | return 1; | |||
113 | } | |||
114 | ||||
115 | _public___attribute__ ((visibility("default"))) int sd_bus_track_new( | |||
116 | sd_bus *bus, | |||
117 | sd_bus_track **track, | |||
118 | sd_bus_track_handler_t handler, | |||
119 | void *userdata) { | |||
120 | ||||
121 | sd_bus_track *t; | |||
122 | ||||
123 | assert_return(bus, -EINVAL)do { if (!(((__builtin_expect(!!(bus),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("bus"), "../src/libsystemd/sd-bus/bus-track.c" , 123, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
124 | assert_return(bus = bus_resolve(bus), -ENOPKG)do { if (!(((__builtin_expect(!!(bus = bus_resolve(bus)),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ( "bus = bus_resolve(bus)"), "../src/libsystemd/sd-bus/bus-track.c" , 124, __PRETTY_FUNCTION__), 0))) return (-65); } while (0); | |||
125 | assert_return(track, -EINVAL)do { if (!(((__builtin_expect(!!(track),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("track"), "../src/libsystemd/sd-bus/bus-track.c" , 125, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
126 | ||||
127 | if (!bus->bus_client) | |||
128 | return -EINVAL22; | |||
129 | ||||
130 | t = new0(sd_bus_track, 1)((sd_bus_track*) calloc((1), sizeof(sd_bus_track))); | |||
131 | if (!t) | |||
132 | return -ENOMEM12; | |||
133 | ||||
134 | t->n_ref = 1; | |||
135 | t->handler = handler; | |||
136 | t->userdata = userdata; | |||
137 | t->bus = sd_bus_ref(bus); | |||
138 | ||||
139 | LIST_PREPEND(tracks, bus->tracks, t)do { typeof(*(bus->tracks)) **_head = &(bus->tracks ), *_item = (t); do { if ((__builtin_expect(!!(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("_item"), "../src/libsystemd/sd-bus/bus-track.c" , 139, __PRETTY_FUNCTION__); } while (0); if ((_item->tracks_next = *_head)) _item->tracks_next->tracks_prev = _item; _item ->tracks_prev = ((void*)0); *_head = _item; } while (0); | |||
140 | t->in_list = true1; | |||
141 | ||||
142 | bus_track_add_to_queue(t); | |||
143 | ||||
144 | *track = t; | |||
145 | return 0; | |||
146 | } | |||
147 | ||||
148 | _public___attribute__ ((visibility("default"))) sd_bus_track* sd_bus_track_ref(sd_bus_track *track) { | |||
149 | ||||
150 | if (!track) | |||
151 | return NULL((void*)0); | |||
152 | ||||
153 | assert(track->n_ref > 0)do { if ((__builtin_expect(!!(!(track->n_ref > 0)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("track->n_ref > 0" ), "../src/libsystemd/sd-bus/bus-track.c", 153, __PRETTY_FUNCTION__ ); } while (0); | |||
154 | ||||
155 | track->n_ref++; | |||
156 | ||||
157 | return track; | |||
158 | } | |||
159 | ||||
160 | _public___attribute__ ((visibility("default"))) sd_bus_track* sd_bus_track_unref(sd_bus_track *track) { | |||
161 | if (!track) | |||
162 | return NULL((void*)0); | |||
163 | ||||
164 | assert(track->n_ref > 0)do { if ((__builtin_expect(!!(!(track->n_ref > 0)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("track->n_ref > 0" ), "../src/libsystemd/sd-bus/bus-track.c", 164, __PRETTY_FUNCTION__ ); } while (0); | |||
165 | track->n_ref--; | |||
166 | ||||
167 | if (track->n_ref > 0) | |||
168 | return NULL((void*)0); | |||
169 | ||||
170 | if (track->in_list) | |||
171 | LIST_REMOVE(tracks, track->bus->tracks, track)do { typeof(*(track->bus->tracks)) **_head = &(track ->bus->tracks), *_item = (track); do { if ((__builtin_expect (!!(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("_item"), "../src/libsystemd/sd-bus/bus-track.c", 171, __PRETTY_FUNCTION__ ); } while (0); if (_item->tracks_next) _item->tracks_next ->tracks_prev = _item->tracks_prev; if (_item->tracks_prev ) _item->tracks_prev->tracks_next = _item->tracks_next ; else { do { if ((__builtin_expect(!!(!(*_head == _item)),0) )) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("*_head == _item" ), "../src/libsystemd/sd-bus/bus-track.c", 171, __PRETTY_FUNCTION__ ); } while (0); *_head = _item->tracks_next; } _item->tracks_next = _item->tracks_prev = ((void*)0); } while (0); | |||
172 | ||||
173 | bus_track_remove_from_queue(track); | |||
174 | track->names = hashmap_free_with_destructor(track->names, track_item_free)({ ({ void *_item; while ((_item = hashmap_steal_first(track-> names))) track_item_free(_item); }); hashmap_free(track->names ); }); | |||
175 | track->bus = sd_bus_unref(track->bus); | |||
176 | ||||
177 | if (track->destroy_callback) | |||
178 | track->destroy_callback(track->userdata); | |||
179 | ||||
180 | return mfree(track); | |||
181 | } | |||
182 | ||||
183 | static int on_name_owner_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) { | |||
184 | sd_bus_track *track = userdata; | |||
185 | const char *name, *old, *new; | |||
186 | int r; | |||
187 | ||||
188 | assert(message)do { if ((__builtin_expect(!!(!(message)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("message"), "../src/libsystemd/sd-bus/bus-track.c" , 188, __PRETTY_FUNCTION__); } while (0); | |||
189 | assert(track)do { if ((__builtin_expect(!!(!(track)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("track"), "../src/libsystemd/sd-bus/bus-track.c" , 189, __PRETTY_FUNCTION__); } while (0); | |||
190 | ||||
191 | r = sd_bus_message_read(message, "sss", &name, &old, &new); | |||
192 | if (r < 0) | |||
193 | return 0; | |||
194 | ||||
195 | bus_track_remove_name_fully(track, name); | |||
196 | return 0; | |||
197 | } | |||
198 | ||||
199 | _public___attribute__ ((visibility("default"))) int sd_bus_track_add_name(sd_bus_track *track, const char *name) { | |||
200 | _cleanup_(track_item_freep)__attribute__((cleanup(track_item_freep))) struct track_item *n = NULL((void*)0); | |||
201 | struct track_item *i; | |||
202 | const char *match; | |||
203 | int r; | |||
204 | ||||
205 | assert_return(track, -EINVAL)do { if (!(((__builtin_expect(!!(track),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("track"), "../src/libsystemd/sd-bus/bus-track.c" , 205, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
206 | assert_return(service_name_is_valid(name), -EINVAL)do { if (!(((__builtin_expect(!!(service_name_is_valid(name)) ,1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD , ("service_name_is_valid(name)"), "../src/libsystemd/sd-bus/bus-track.c" , 206, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
207 | ||||
208 | i = hashmap_get(track->names, name); | |||
209 | if (i) { | |||
210 | if (track->recursive) { | |||
211 | unsigned k = track->n_ref + 1; | |||
212 | ||||
213 | if (k < track->n_ref) /* Check for overflow */ | |||
214 | return -EOVERFLOW75; | |||
215 | ||||
216 | track->n_ref = k; | |||
217 | } | |||
218 | ||||
219 | bus_track_remove_from_queue(track); | |||
220 | return 0; | |||
221 | } | |||
222 | ||||
223 | r = hashmap_ensure_allocated(&track->names, &string_hash_ops)internal_hashmap_ensure_allocated(&track->names, & string_hash_ops ); | |||
224 | if (r < 0) | |||
225 | return r; | |||
226 | ||||
227 | n = new0(struct track_item, 1)((struct track_item*) calloc((1), sizeof(struct track_item))); | |||
228 | if (!n) | |||
229 | return -ENOMEM12; | |||
230 | n->name = strdup(name); | |||
231 | if (!n->name) | |||
232 | return -ENOMEM12; | |||
| ||||
233 | ||||
234 | /* First, subscribe to this name */ | |||
235 | match = MATCH_FOR_NAME(name)({ const char *_appendees_[] = { "type='signal'," "sender='org.freedesktop.DBus'," "path='/org/freedesktop/DBus'," "interface='org.freedesktop.DBus'," "member='NameOwnerChanged'," "arg0='", name, "'" }; char *_d_ , *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_ )/sizeof((_appendees_)[0]), ((void)0))) && _appendees_ [_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca (_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(_appendees_), typeof(& *(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0] ), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy (_p_, _appendees_[_i_]); *_p_ = 0; _d_; }); | |||
236 | ||||
237 | bus_track_remove_from_queue(track); /* don't dispatch this while we work in it */ | |||
238 | ||||
239 | r = sd_bus_add_match_async(track->bus, &n->slot, match, on_name_owner_changed, NULL((void*)0), track); | |||
240 | if (r < 0) { | |||
241 | bus_track_add_to_queue(track); | |||
242 | return r; | |||
243 | } | |||
244 | ||||
245 | r = hashmap_put(track->names, n->name, n); | |||
246 | if (r < 0) { | |||
247 | bus_track_add_to_queue(track); | |||
248 | return r; | |||
249 | } | |||
250 | ||||
251 | /* Second, check if it is currently existing, or maybe doesn't, or maybe disappeared already. */ | |||
252 | track->n_adding++; /* again, make sure this isn't dispatch while we are working in it */ | |||
253 | r = sd_bus_get_name_creds(track->bus, name, 0, NULL((void*)0)); | |||
254 | track->n_adding--; | |||
255 | if (r < 0) { | |||
256 | hashmap_remove(track->names, name); | |||
257 | bus_track_add_to_queue(track); | |||
258 | return r; | |||
259 | } | |||
260 | ||||
261 | n->n_ref = 1; | |||
262 | n = NULL((void*)0); | |||
263 | ||||
264 | bus_track_remove_from_queue(track); | |||
265 | track->modified = true1; | |||
266 | ||||
267 | return 1; | |||
268 | } | |||
269 | ||||
270 | _public___attribute__ ((visibility("default"))) int sd_bus_track_remove_name(sd_bus_track *track, const char *name) { | |||
271 | struct track_item *i; | |||
272 | ||||
273 | assert_return(name, -EINVAL)do { if (!(((__builtin_expect(!!(name),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("name"), "../src/libsystemd/sd-bus/bus-track.c" , 273, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
274 | ||||
275 | if (!track) /* Treat a NULL track object as an empty track object */ | |||
276 | return 0; | |||
277 | ||||
278 | if (!track->recursive) | |||
279 | return bus_track_remove_name_fully(track, name); | |||
280 | ||||
281 | i = hashmap_get(track->names, name); | |||
282 | if (!i) | |||
283 | return -EUNATCH49; | |||
284 | if (i->n_ref <= 0) | |||
285 | return -EUNATCH49; | |||
286 | ||||
287 | i->n_ref--; | |||
288 | ||||
289 | if (i->n_ref <= 0) | |||
290 | return bus_track_remove_name_fully(track, name); | |||
291 | ||||
292 | return 1; | |||
293 | } | |||
294 | ||||
295 | _public___attribute__ ((visibility("default"))) unsigned sd_bus_track_count(sd_bus_track *track) { | |||
296 | ||||
297 | if (!track) /* Let's consider a NULL object equivalent to an empty object */ | |||
298 | return 0; | |||
299 | ||||
300 | /* This signature really should have returned an int, so that we can propagate errors. But well, ... Also, note | |||
301 | * that this returns the number of names being watched, and multiple references to the same name are not | |||
302 | * counted. */ | |||
303 | ||||
304 | return hashmap_size(track->names); | |||
305 | } | |||
306 | ||||
307 | _public___attribute__ ((visibility("default"))) const char* sd_bus_track_contains(sd_bus_track *track, const char *name) { | |||
308 | assert_return(name, NULL)do { if (!(((__builtin_expect(!!(name),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("name"), "../src/libsystemd/sd-bus/bus-track.c" , 308, __PRETTY_FUNCTION__), 0))) return (((void*)0)); } while (0); | |||
309 | ||||
310 | if (!track) /* Let's consider a NULL object equivalent to an empty object */ | |||
311 | return NULL((void*)0); | |||
312 | ||||
313 | return hashmap_get(track->names, (void*) name) ? name : NULL((void*)0); | |||
314 | } | |||
315 | ||||
316 | _public___attribute__ ((visibility("default"))) const char* sd_bus_track_first(sd_bus_track *track) { | |||
317 | const char *n = NULL((void*)0); | |||
318 | ||||
319 | if (!track) | |||
320 | return NULL((void*)0); | |||
321 | ||||
322 | track->modified = false0; | |||
323 | track->iterator = ITERATOR_FIRST((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .next_key = ( (void*)0) }); | |||
324 | ||||
325 | hashmap_iterate(track->names, &track->iterator, NULL((void*)0), (const void**) &n); | |||
326 | return n; | |||
327 | } | |||
328 | ||||
329 | _public___attribute__ ((visibility("default"))) const char* sd_bus_track_next(sd_bus_track *track) { | |||
330 | const char *n = NULL((void*)0); | |||
331 | ||||
332 | if (!track) | |||
333 | return NULL((void*)0); | |||
334 | ||||
335 | if (track->modified) | |||
336 | return NULL((void*)0); | |||
337 | ||||
338 | hashmap_iterate(track->names, &track->iterator, NULL((void*)0), (const void**) &n); | |||
339 | return n; | |||
340 | } | |||
341 | ||||
342 | _public___attribute__ ((visibility("default"))) int sd_bus_track_add_sender(sd_bus_track *track, sd_bus_message *m) { | |||
343 | const char *sender; | |||
344 | ||||
345 | assert_return(track, -EINVAL)do { if (!(((__builtin_expect(!!(track),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("track"), "../src/libsystemd/sd-bus/bus-track.c" , 345, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
| ||||
346 | assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-track.c" , 346, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
347 | ||||
348 | if (sd_bus_message_get_bus(m) != track->bus) | |||
349 | return -EINVAL22; | |||
350 | ||||
351 | sender = sd_bus_message_get_sender(m); | |||
352 | if (!sender) | |||
353 | return -EINVAL22; | |||
354 | ||||
355 | return sd_bus_track_add_name(track, sender); | |||
356 | } | |||
357 | ||||
358 | _public___attribute__ ((visibility("default"))) int sd_bus_track_remove_sender(sd_bus_track *track, sd_bus_message *m) { | |||
359 | const char *sender; | |||
360 | ||||
361 | assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-track.c" , 361, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
362 | ||||
363 | if (!track) /* Treat a NULL track object as an empty track object */ | |||
364 | return 0; | |||
365 | ||||
366 | if (sd_bus_message_get_bus(m) != track->bus) | |||
367 | return -EINVAL22; | |||
368 | ||||
369 | sender = sd_bus_message_get_sender(m); | |||
370 | if (!sender) | |||
371 | return -EINVAL22; | |||
372 | ||||
373 | return sd_bus_track_remove_name(track, sender); | |||
374 | } | |||
375 | ||||
376 | _public___attribute__ ((visibility("default"))) sd_bus* sd_bus_track_get_bus(sd_bus_track *track) { | |||
377 | assert_return(track, NULL)do { if (!(((__builtin_expect(!!(track),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("track"), "../src/libsystemd/sd-bus/bus-track.c" , 377, __PRETTY_FUNCTION__), 0))) return (((void*)0)); } while (0); | |||
378 | ||||
379 | return track->bus; | |||
380 | } | |||
381 | ||||
382 | void bus_track_dispatch(sd_bus_track *track) { | |||
383 | int r; | |||
384 | ||||
385 | assert(track)do { if ((__builtin_expect(!!(!(track)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("track"), "../src/libsystemd/sd-bus/bus-track.c" , 385, __PRETTY_FUNCTION__); } while (0); | |||
386 | assert(track->handler)do { if ((__builtin_expect(!!(!(track->handler)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("track->handler"), "../src/libsystemd/sd-bus/bus-track.c" , 386, __PRETTY_FUNCTION__); } while (0); | |||
387 | ||||
388 | bus_track_remove_from_queue(track); | |||
389 | ||||
390 | sd_bus_track_ref(track); | |||
391 | ||||
392 | r = track->handler(track, track->userdata); | |||
393 | if (r < 0) | |||
394 | log_debug_errno(r, "Failed to process track handler: %m")({ int _level = ((7)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/libsystemd/sd-bus/bus-track.c", 394, __func__, "Failed to process track handler: %m" ) : -abs(_e); }); | |||
395 | else if (r == 0) | |||
396 | bus_track_add_to_queue(track); | |||
397 | ||||
398 | sd_bus_track_unref(track); | |||
399 | } | |||
400 | ||||
401 | void bus_track_close(sd_bus_track *track) { | |||
402 | assert(track)do { if ((__builtin_expect(!!(!(track)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("track"), "../src/libsystemd/sd-bus/bus-track.c" , 402, __PRETTY_FUNCTION__); } while (0); | |||
403 | ||||
404 | /* Called whenever our bus connected is closed. If so, and our track object is non-empty, dispatch it | |||
405 | * immediately, as we are closing now, but first flush out all names. */ | |||
406 | ||||
407 | if (!track->in_list) | |||
408 | return; /* We already closed this one, don't close it again. */ | |||
409 | ||||
410 | /* Remember that this one is closed now */ | |||
411 | LIST_REMOVE(tracks, track->bus->tracks, track)do { typeof(*(track->bus->tracks)) **_head = &(track ->bus->tracks), *_item = (track); do { if ((__builtin_expect (!!(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("_item"), "../src/libsystemd/sd-bus/bus-track.c", 411, __PRETTY_FUNCTION__ ); } while (0); if (_item->tracks_next) _item->tracks_next ->tracks_prev = _item->tracks_prev; if (_item->tracks_prev ) _item->tracks_prev->tracks_next = _item->tracks_next ; else { do { if ((__builtin_expect(!!(!(*_head == _item)),0) )) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("*_head == _item" ), "../src/libsystemd/sd-bus/bus-track.c", 411, __PRETTY_FUNCTION__ ); } while (0); *_head = _item->tracks_next; } _item->tracks_next = _item->tracks_prev = ((void*)0); } while (0); | |||
412 | track->in_list = false0; | |||
413 | ||||
414 | /* If there's no name in this one anyway, we don't have to dispatch */ | |||
415 | if (hashmap_isempty(track->names)) | |||
416 | return; | |||
417 | ||||
418 | /* Let's flush out all names */ | |||
419 | hashmap_clear_with_destructor(track->names, track_item_free)({ void *_item; while ((_item = hashmap_steal_first(track-> names))) track_item_free(_item); }); | |||
420 | ||||
421 | /* Invoke handler */ | |||
422 | if (track->handler) | |||
423 | bus_track_dispatch(track); | |||
424 | } | |||
425 | ||||
426 | _public___attribute__ ((visibility("default"))) void *sd_bus_track_get_userdata(sd_bus_track *track) { | |||
427 | assert_return(track, NULL)do { if (!(((__builtin_expect(!!(track),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("track"), "../src/libsystemd/sd-bus/bus-track.c" , 427, __PRETTY_FUNCTION__), 0))) return (((void*)0)); } while (0); | |||
428 | ||||
429 | return track->userdata; | |||
430 | } | |||
431 | ||||
432 | _public___attribute__ ((visibility("default"))) void *sd_bus_track_set_userdata(sd_bus_track *track, void *userdata) { | |||
433 | void *ret; | |||
434 | ||||
435 | assert_return(track, NULL)do { if (!(((__builtin_expect(!!(track),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("track"), "../src/libsystemd/sd-bus/bus-track.c" , 435, __PRETTY_FUNCTION__), 0))) return (((void*)0)); } while (0); | |||
436 | ||||
437 | ret = track->userdata; | |||
438 | track->userdata = userdata; | |||
439 | ||||
440 | return ret; | |||
441 | } | |||
442 | ||||
443 | _public___attribute__ ((visibility("default"))) int sd_bus_track_set_destroy_callback(sd_bus_track *track, sd_bus_destroy_t callback) { | |||
444 | assert_return(track, -EINVAL)do { if (!(((__builtin_expect(!!(track),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("track"), "../src/libsystemd/sd-bus/bus-track.c" , 444, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
445 | ||||
446 | track->destroy_callback = callback; | |||
447 | return 0; | |||
448 | } | |||
449 | ||||
450 | _public___attribute__ ((visibility("default"))) int sd_bus_track_get_destroy_callback(sd_bus_track *track, sd_bus_destroy_t *ret) { | |||
451 | assert_return(track, -EINVAL)do { if (!(((__builtin_expect(!!(track),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("track"), "../src/libsystemd/sd-bus/bus-track.c" , 451, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
452 | ||||
453 | if (ret) | |||
454 | *ret = track->destroy_callback; | |||
455 | ||||
456 | return !!track->destroy_callback; | |||
457 | } | |||
458 | ||||
459 | _public___attribute__ ((visibility("default"))) int sd_bus_track_set_recursive(sd_bus_track *track, int b) { | |||
460 | assert_return(track, -EINVAL)do { if (!(((__builtin_expect(!!(track),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("track"), "../src/libsystemd/sd-bus/bus-track.c" , 460, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
461 | ||||
462 | if (track->recursive == !!b) | |||
463 | return 0; | |||
464 | ||||
465 | if (!hashmap_isempty(track->names)) | |||
466 | return -EBUSY16; | |||
467 | ||||
468 | track->recursive = b; | |||
469 | return 0; | |||
470 | } | |||
471 | ||||
472 | _public___attribute__ ((visibility("default"))) int sd_bus_track_get_recursive(sd_bus_track *track) { | |||
473 | assert_return(track, -EINVAL)do { if (!(((__builtin_expect(!!(track),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("track"), "../src/libsystemd/sd-bus/bus-track.c" , 473, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
474 | ||||
475 | return track->recursive; | |||
476 | } | |||
477 | ||||
478 | _public___attribute__ ((visibility("default"))) int sd_bus_track_count_sender(sd_bus_track *track, sd_bus_message *m) { | |||
479 | const char *sender; | |||
480 | ||||
481 | assert_return(m, -EINVAL)do { if (!(((__builtin_expect(!!(m),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("m"), "../src/libsystemd/sd-bus/bus-track.c" , 481, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
482 | ||||
483 | if (!track) /* Let's consider a NULL object equivalent to an empty object */ | |||
484 | return 0; | |||
485 | ||||
486 | if (sd_bus_message_get_bus(m) != track->bus) | |||
487 | return -EINVAL22; | |||
488 | ||||
489 | sender = sd_bus_message_get_sender(m); | |||
490 | if (!sender) | |||
491 | return -EINVAL22; | |||
492 | ||||
493 | return sd_bus_track_count_name(track, sender); | |||
494 | } | |||
495 | ||||
496 | _public___attribute__ ((visibility("default"))) int sd_bus_track_count_name(sd_bus_track *track, const char *name) { | |||
497 | struct track_item *i; | |||
498 | ||||
499 | assert_return(service_name_is_valid(name), -EINVAL)do { if (!(((__builtin_expect(!!(service_name_is_valid(name)) ,1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD , ("service_name_is_valid(name)"), "../src/libsystemd/sd-bus/bus-track.c" , 499, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
500 | ||||
501 | if (!track) /* Let's consider a NULL object equivalent to an empty object */ | |||
502 | return 0; | |||
503 | ||||
504 | i = hashmap_get(track->names, name); | |||
505 | if (!i) | |||
506 | return 0; | |||
507 | ||||
508 | return i->n_ref; | |||
509 | } |