blob: 28ad3148f062a6bb1ba383719af53f26cd135e2b [file] [log] [blame]
Brad Bishop62ece2b2016-07-25 09:00:51 -04001/**
2 * Copyright © 2016 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050016#include "mapper.h"
17
George Liucf724032024-10-29 14:31:51 +080018#include "internal.h"
19
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050020#include <errno.h>
William A. Kennington III20cbbfb2018-06-15 10:10:13 -070021#include <stdbool.h>
Brad Bishopa959f122021-08-03 11:21:01 -040022#include <stddef.h>
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050023#include <stdio.h>
Brad Bishop2afe7182016-08-13 14:08:17 -040024#include <stdlib.h>
Brad Bishop62ece2b2016-07-25 09:00:51 -040025#include <string.h>
Brad Bishop3d468792016-09-20 15:39:38 -040026#include <sys/timerfd.h>
Brad Bishop62ece2b2016-07-25 09:00:51 -040027#include <systemd/sd-bus.h>
Brad Bishop3d468792016-09-20 15:39:38 -040028#include <systemd/sd-event.h>
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050029#include <unistd.h>
Brad Bishop62ece2b2016-07-25 09:00:51 -040030
Brad Bishop75057c82021-08-03 15:22:02 -040031#define _public_ __attribute__((__visibility__("default")))
Brad Bishop2d41d6a2021-08-03 08:14:45 -040032#define _unused_ __attribute__((unused))
Brad Bishop75057c82021-08-03 15:22:02 -040033
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050034static const char* async_wait_introspection_match =
Ed Tanous167e2372018-05-07 11:59:10 -070035 "type='signal',"
36 "sender='xyz.openbmc_project.ObjectMapper',"
37 "interface='xyz.openbmc_project.ObjectMapper.Private',"
38 "member='IntrospectionComplete'";
Brad Bishop2afe7182016-08-13 14:08:17 -040039
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050040static const char* async_wait_interfaces_added_match =
Ed Tanous167e2372018-05-07 11:59:10 -070041 "type='signal',"
42 "interface='org.freedesktop.DBus.ObjectManager',"
43 "member='InterfacesAdded'";
Brad Bishop2afe7182016-08-13 14:08:17 -040044
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050045static const char* interfaces_removed_match =
Ed Tanous167e2372018-05-07 11:59:10 -070046 "type='signal',"
47 "interface='org.freedesktop.DBus.ObjectManager',"
48 "member='InterfacesRemoved'";
Adriana Kobylak78edbb62017-05-04 15:45:19 -050049
Brad Bishop3d468792016-09-20 15:39:38 -040050static const int mapper_busy_retries = 5;
51static const uint64_t mapper_busy_delay_interval_usec = 1000000;
52
Brad Bishop2afe7182016-08-13 14:08:17 -040053struct mapper_async_wait
54{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050055 char** objs;
56 void (*callback)(int, void*);
57 void* userdata;
58 sd_event* loop;
59 sd_bus* conn;
60 sd_bus_slot* introspection_slot;
61 sd_bus_slot* intf_slot;
62 int* status;
Brad Bishopa959f122021-08-03 11:21:01 -040063 size_t count;
Ed Tanous167e2372018-05-07 11:59:10 -070064 int finished;
65 int r;
Brad Bishop2afe7182016-08-13 14:08:17 -040066};
67
68struct async_wait_callback_data
69{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050070 mapper_async_wait* wait;
71 const char* path;
72 sd_event_source* event_source;
Ed Tanous167e2372018-05-07 11:59:10 -070073 int retry;
Brad Bishop2afe7182016-08-13 14:08:17 -040074};
75
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -050076struct mapper_async_subtree
77{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050078 char* namespace;
79 char* interface;
80 void (*callback)(int, void*);
81 void* userdata;
82 sd_event* loop;
83 sd_bus* conn;
84 sd_bus_slot* slot;
85 sd_event_source* event_source;
Ed Tanous167e2372018-05-07 11:59:10 -070086 int finished;
87 int op;
88 int retry;
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -050089};
90
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050091static int async_wait_match_introspection_complete(sd_bus_message*, void*,
92 sd_bus_error*);
93static int async_wait_check_done(mapper_async_wait*);
94static void async_wait_done(int r, mapper_async_wait*);
95static int async_wait_get_objects(mapper_async_wait*);
96static int async_wait_getobject_callback(sd_bus_message*, void*, sd_bus_error*);
Brad Bishop2afe7182016-08-13 14:08:17 -040097
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050098static int async_subtree_match_callback(sd_bus_message*, void*, sd_bus_error*);
99static void async_subtree_done(int r, mapper_async_subtree*);
100static int async_subtree_getpaths(mapper_async_subtree*);
101static int async_subtree_getpaths_callback(sd_bus_message*, void*,
102 sd_bus_error*);
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500103
Brad Bishopa959f122021-08-03 11:21:01 -0400104size_t sarraylen(char* array[])
Brad Bishop2afe7182016-08-13 14:08:17 -0400105{
Brad Bishopa959f122021-08-03 11:21:01 -0400106 size_t count = 0;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500107 char** p = array;
Brad Bishop2afe7182016-08-13 14:08:17 -0400108
Ed Tanous167e2372018-05-07 11:59:10 -0700109 while (*p != NULL)
110 {
111 ++count;
112 ++p;
113 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400114
Ed Tanous167e2372018-05-07 11:59:10 -0700115 return count;
Brad Bishop2afe7182016-08-13 14:08:17 -0400116}
117
Brad Bishopa669a502021-08-03 16:01:43 -0400118void sarrayfree(char* array[])
Brad Bishop2afe7182016-08-13 14:08:17 -0400119{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500120 char** p = array;
Ed Tanous167e2372018-05-07 11:59:10 -0700121 while (*p != NULL)
122 {
123 free(*p);
124 ++p;
125 }
126 free(array);
Brad Bishop2afe7182016-08-13 14:08:17 -0400127}
128
Brad Bishopa669a502021-08-03 16:01:43 -0400129char** sarraydup(char* array[])
Brad Bishop2afe7182016-08-13 14:08:17 -0400130{
Brad Bishopa959f122021-08-03 11:21:01 -0400131 size_t count = sarraylen(array);
132 size_t i;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500133 char** ret = NULL;
Brad Bishop2afe7182016-08-13 14:08:17 -0400134
Brad Bishopa669a502021-08-03 16:01:43 -0400135 ret = calloc(count + 1, sizeof(*ret));
Ed Tanous167e2372018-05-07 11:59:10 -0700136 if (!ret)
George Liucf724032024-10-29 14:31:51 +0800137 {
Ed Tanous167e2372018-05-07 11:59:10 -0700138 return NULL;
George Liucf724032024-10-29 14:31:51 +0800139 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400140
Ed Tanous167e2372018-05-07 11:59:10 -0700141 for (i = 0; i < count; ++i)
142 {
143 ret[i] = strdup(array[i]);
144 if (!ret[i])
George Liucf724032024-10-29 14:31:51 +0800145 {
Ed Tanous167e2372018-05-07 11:59:10 -0700146 goto error;
George Liucf724032024-10-29 14:31:51 +0800147 }
Ed Tanous167e2372018-05-07 11:59:10 -0700148 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400149
Ed Tanous167e2372018-05-07 11:59:10 -0700150 return ret;
Brad Bishop2afe7182016-08-13 14:08:17 -0400151
152error:
Ed Tanous167e2372018-05-07 11:59:10 -0700153 sarrayfree(ret);
154 return NULL;
Brad Bishop2afe7182016-08-13 14:08:17 -0400155}
156
Brad Bishop2d41d6a2021-08-03 08:14:45 -0400157static int async_wait_timeout_callback(_unused_ sd_event_source* s,
158 _unused_ uint64_t usec, void* userdata)
Brad Bishop3d468792016-09-20 15:39:38 -0400159{
Ed Tanous167e2372018-05-07 11:59:10 -0700160 int r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500161 struct async_wait_callback_data* data = userdata;
162 mapper_async_wait* wait = data->wait;
Brad Bishop3d468792016-09-20 15:39:38 -0400163
Ed Tanous167e2372018-05-07 11:59:10 -0700164 sd_event_source_unref(data->event_source);
Brad Bishopa02cd542021-10-12 19:12:42 -0400165 r = sd_bus_call_method_async(
166 wait->conn, NULL, "xyz.openbmc_project.ObjectMapper",
167 "/xyz/openbmc_project/object_mapper",
168 "xyz.openbmc_project.ObjectMapper", "GetObject",
169 async_wait_getobject_callback, data, "sas", data->path, 0, NULL);
Ed Tanous167e2372018-05-07 11:59:10 -0700170 if (r < 0)
171 {
172 async_wait_done(r, wait);
173 free(data);
174 }
Brad Bishop3d468792016-09-20 15:39:38 -0400175
Ed Tanous167e2372018-05-07 11:59:10 -0700176 return 0;
Brad Bishop3d468792016-09-20 15:39:38 -0400177}
178
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500179static int async_wait_getobject_callback(sd_bus_message* m, void* userdata,
Brad Bishop2d41d6a2021-08-03 08:14:45 -0400180 _unused_ sd_bus_error* e)
Brad Bishop2afe7182016-08-13 14:08:17 -0400181{
Brad Bishopa959f122021-08-03 11:21:01 -0400182 size_t i;
183 int r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500184 struct async_wait_callback_data* data = userdata;
185 mapper_async_wait* wait = data->wait;
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700186 uint64_t next_retry;
Brad Bishop2afe7182016-08-13 14:08:17 -0400187
Ed Tanous167e2372018-05-07 11:59:10 -0700188 if (wait->finished)
George Liucf724032024-10-29 14:31:51 +0800189 {
Ed Tanous167e2372018-05-07 11:59:10 -0700190 goto exit;
George Liucf724032024-10-29 14:31:51 +0800191 }
Brad Bishop3d468792016-09-20 15:39:38 -0400192
Patrick Williamse82b0582020-11-16 16:25:20 -0600193 if (sd_bus_message_is_method_error(
194 m, "xyz.openbmc_project.Common.Error.ResourceNotFound"))
George Liucf724032024-10-29 14:31:51 +0800195 {
Ed Tanous167e2372018-05-07 11:59:10 -0700196 goto exit;
George Liucf724032024-10-29 14:31:51 +0800197 }
Brad Bishop8ccdaed2016-09-20 15:54:32 -0400198
Patrick Williamse82b0582020-11-16 16:25:20 -0600199 r = sd_bus_message_get_errno(m);
200
William A. Kennington III24829462018-06-15 10:10:25 -0700201 if ((r == EBUSY || r == ENOBUFS) && data->retry < mapper_busy_retries)
Ed Tanous167e2372018-05-07 11:59:10 -0700202 {
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700203 r = sd_event_now(wait->loop, CLOCK_MONOTONIC, &next_retry);
Ed Tanous167e2372018-05-07 11:59:10 -0700204 if (r < 0)
205 {
206 async_wait_done(r, wait);
207 goto exit;
208 }
Brad Bishop3d468792016-09-20 15:39:38 -0400209
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700210 next_retry += mapper_busy_delay_interval_usec * (1 << data->retry);
Ed Tanous167e2372018-05-07 11:59:10 -0700211 r = sd_event_add_time(wait->loop, &data->event_source, CLOCK_MONOTONIC,
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700212 next_retry, 0, async_wait_timeout_callback, data);
213 ++data->retry;
Ed Tanous167e2372018-05-07 11:59:10 -0700214 if (r < 0)
215 {
216 async_wait_done(r, wait);
217 goto exit;
218 }
Brad Bishop3d468792016-09-20 15:39:38 -0400219
Ed Tanous167e2372018-05-07 11:59:10 -0700220 return 0;
221 }
Brad Bishop3d468792016-09-20 15:39:38 -0400222
Ed Tanous167e2372018-05-07 11:59:10 -0700223 if (r)
224 {
225 async_wait_done(-r, wait);
226 goto exit;
227 }
Brad Bishop3d468792016-09-20 15:39:38 -0400228
Ed Tanous167e2372018-05-07 11:59:10 -0700229 for (i = 0; i < wait->count; ++i)
230 {
231 if (!strcmp(data->path, wait->objs[i]))
232 {
233 wait->status[i] = 1;
234 }
235 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400236
Ed Tanous167e2372018-05-07 11:59:10 -0700237 if (async_wait_check_done(wait))
George Liucf724032024-10-29 14:31:51 +0800238 {
Ed Tanous167e2372018-05-07 11:59:10 -0700239 async_wait_done(0, wait);
George Liucf724032024-10-29 14:31:51 +0800240 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400241
Brad Bishop3d468792016-09-20 15:39:38 -0400242exit:
Ed Tanous167e2372018-05-07 11:59:10 -0700243 free(data);
244 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400245}
246
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500247static int async_wait_get_objects(mapper_async_wait* wait)
Brad Bishop2afe7182016-08-13 14:08:17 -0400248{
Brad Bishopa959f122021-08-03 11:21:01 -0400249 size_t i;
250 int r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500251 struct async_wait_callback_data* data = NULL;
Brad Bishop2afe7182016-08-13 14:08:17 -0400252
Ed Tanous167e2372018-05-07 11:59:10 -0700253 for (i = 0; i < wait->count; ++i)
254 {
255 if (wait->status[i])
George Liucf724032024-10-29 14:31:51 +0800256 {
Ed Tanous167e2372018-05-07 11:59:10 -0700257 continue;
George Liucf724032024-10-29 14:31:51 +0800258 }
Ed Tanous167e2372018-05-07 11:59:10 -0700259 data = malloc(sizeof(*data));
260 data->wait = wait;
261 data->path = wait->objs[i];
262 data->retry = 0;
263 data->event_source = NULL;
Brad Bishopa02cd542021-10-12 19:12:42 -0400264 r = sd_bus_call_method_async(
265 wait->conn, NULL, "xyz.openbmc_project.ObjectMapper",
266 "/xyz/openbmc_project/object_mapper",
267 "xyz.openbmc_project.ObjectMapper", "GetObject",
268 async_wait_getobject_callback, data, "sas", wait->objs[i], 0, NULL);
Ed Tanous167e2372018-05-07 11:59:10 -0700269 if (r < 0)
270 {
271 free(data);
272 fprintf(stderr, "Error invoking method: %s\n", strerror(-r));
273 return r;
274 }
275 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400276
Ed Tanous167e2372018-05-07 11:59:10 -0700277 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400278}
279
George Liucf724032024-10-29 14:31:51 +0800280static int async_wait_match_introspection_complete(
281 _unused_ sd_bus_message* m, void* w, _unused_ sd_bus_error* e)
Brad Bishop2afe7182016-08-13 14:08:17 -0400282{
Ed Tanous167e2372018-05-07 11:59:10 -0700283 int r;
Brad Bishop2afe7182016-08-13 14:08:17 -0400284
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500285 mapper_async_wait* wait = w;
Ed Tanous167e2372018-05-07 11:59:10 -0700286 if (wait->finished)
George Liucf724032024-10-29 14:31:51 +0800287 {
Ed Tanous167e2372018-05-07 11:59:10 -0700288 return 0;
George Liucf724032024-10-29 14:31:51 +0800289 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400290
Ed Tanous167e2372018-05-07 11:59:10 -0700291 r = async_wait_get_objects(wait);
292 if (r < 0)
George Liucf724032024-10-29 14:31:51 +0800293 {
Ed Tanous167e2372018-05-07 11:59:10 -0700294 async_wait_done(r, wait);
George Liucf724032024-10-29 14:31:51 +0800295 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400296
Ed Tanous167e2372018-05-07 11:59:10 -0700297 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400298}
299
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500300static void async_wait_done(int r, mapper_async_wait* w)
Brad Bishop2afe7182016-08-13 14:08:17 -0400301{
Ed Tanous167e2372018-05-07 11:59:10 -0700302 if (w->finished)
George Liucf724032024-10-29 14:31:51 +0800303 {
Ed Tanous167e2372018-05-07 11:59:10 -0700304 return;
George Liucf724032024-10-29 14:31:51 +0800305 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400306
Ed Tanous167e2372018-05-07 11:59:10 -0700307 w->finished = 1;
308 sd_bus_slot_unref(w->introspection_slot);
309 sd_bus_slot_unref(w->intf_slot);
Brad Bishop2afe7182016-08-13 14:08:17 -0400310
Ed Tanous167e2372018-05-07 11:59:10 -0700311 if (w->callback)
George Liucf724032024-10-29 14:31:51 +0800312 {
Ed Tanous167e2372018-05-07 11:59:10 -0700313 w->callback(r, w->userdata);
George Liucf724032024-10-29 14:31:51 +0800314 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400315}
316
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500317static int async_wait_check_done(mapper_async_wait* w)
Brad Bishop2afe7182016-08-13 14:08:17 -0400318{
Brad Bishopa959f122021-08-03 11:21:01 -0400319 size_t i;
Brad Bishop2afe7182016-08-13 14:08:17 -0400320
Ed Tanous167e2372018-05-07 11:59:10 -0700321 if (w->finished)
George Liucf724032024-10-29 14:31:51 +0800322 {
Ed Tanous167e2372018-05-07 11:59:10 -0700323 return 1;
George Liucf724032024-10-29 14:31:51 +0800324 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400325
Ed Tanous167e2372018-05-07 11:59:10 -0700326 for (i = 0; i < w->count; ++i)
George Liucf724032024-10-29 14:31:51 +0800327 {
Ed Tanous167e2372018-05-07 11:59:10 -0700328 if (!w->status[i])
George Liucf724032024-10-29 14:31:51 +0800329 {
Ed Tanous167e2372018-05-07 11:59:10 -0700330 return 0;
George Liucf724032024-10-29 14:31:51 +0800331 }
332 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400333
Ed Tanous167e2372018-05-07 11:59:10 -0700334 return 1;
Brad Bishop2afe7182016-08-13 14:08:17 -0400335}
336
Brad Bishop75057c82021-08-03 15:22:02 -0400337_public_ void mapper_wait_async_free(mapper_async_wait* w)
Brad Bishop2afe7182016-08-13 14:08:17 -0400338{
Ed Tanous167e2372018-05-07 11:59:10 -0700339 free(w->status);
340 sarrayfree(w->objs);
341 free(w);
Brad Bishop2afe7182016-08-13 14:08:17 -0400342}
343
Brad Bishop75057c82021-08-03 15:22:02 -0400344_public_ int mapper_wait_async(sd_bus* conn, sd_event* loop, char* objs[],
345 void (*callback)(int, void*), void* userdata,
346 mapper_async_wait** w)
Brad Bishop2afe7182016-08-13 14:08:17 -0400347{
Ed Tanous167e2372018-05-07 11:59:10 -0700348 int r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500349 mapper_async_wait* wait = NULL;
Brad Bishop2afe7182016-08-13 14:08:17 -0400350
Ed Tanous167e2372018-05-07 11:59:10 -0700351 wait = malloc(sizeof(*wait));
352 if (!wait)
George Liucf724032024-10-29 14:31:51 +0800353 {
Ed Tanous167e2372018-05-07 11:59:10 -0700354 return -ENOMEM;
George Liucf724032024-10-29 14:31:51 +0800355 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400356
Ed Tanous167e2372018-05-07 11:59:10 -0700357 memset(wait, 0, sizeof(*wait));
358 wait->conn = conn;
359 wait->loop = loop;
360 wait->callback = callback;
361 wait->userdata = userdata;
362 wait->count = sarraylen(objs);
363 if (!wait->count)
Brad Bishop2ac32332021-08-03 14:06:52 -0400364 {
365 r = 0;
366 goto free_wait;
367 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400368
Ed Tanous167e2372018-05-07 11:59:10 -0700369 wait->objs = sarraydup(objs);
370 if (!wait->objs)
371 {
372 r = -ENOMEM;
373 goto free_wait;
374 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400375
Ed Tanous167e2372018-05-07 11:59:10 -0700376 wait->status = malloc(sizeof(*wait->status) * wait->count);
377 if (!wait->status)
378 {
379 r = -ENOMEM;
380 goto free_objs;
381 }
382 memset(wait->status, 0, sizeof(*wait->status) * wait->count);
Brad Bishop2afe7182016-08-13 14:08:17 -0400383
Ed Tanous167e2372018-05-07 11:59:10 -0700384 r = sd_bus_add_match(conn, &wait->introspection_slot,
385 async_wait_introspection_match,
386 async_wait_match_introspection_complete, wait);
387 if (r < 0)
388 {
389 fprintf(stderr, "Error adding match rule: %s\n", strerror(-r));
390 goto free_status;
391 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400392
Ed Tanous167e2372018-05-07 11:59:10 -0700393 r = sd_bus_add_match(conn, &wait->intf_slot,
394 async_wait_interfaces_added_match,
395 async_wait_match_introspection_complete, wait);
396 if (r < 0)
397 {
398 fprintf(stderr, "Error adding match rule: %s\n", strerror(-r));
399 goto unref_name_slot;
400 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400401
Ed Tanous167e2372018-05-07 11:59:10 -0700402 r = async_wait_get_objects(wait);
403 if (r < 0)
404 {
405 fprintf(stderr, "Error calling method: %s\n", strerror(-r));
406 goto unref_intf_slot;
407 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400408
Ed Tanous167e2372018-05-07 11:59:10 -0700409 *w = wait;
Brad Bishop2afe7182016-08-13 14:08:17 -0400410
Ed Tanous167e2372018-05-07 11:59:10 -0700411 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400412
413unref_intf_slot:
Ed Tanous167e2372018-05-07 11:59:10 -0700414 sd_bus_slot_unref(wait->intf_slot);
Brad Bishop2afe7182016-08-13 14:08:17 -0400415unref_name_slot:
Ed Tanous167e2372018-05-07 11:59:10 -0700416 sd_bus_slot_unref(wait->introspection_slot);
Brad Bishop2afe7182016-08-13 14:08:17 -0400417free_status:
Ed Tanous167e2372018-05-07 11:59:10 -0700418 free(wait->status);
Brad Bishop2afe7182016-08-13 14:08:17 -0400419free_objs:
Ed Tanous167e2372018-05-07 11:59:10 -0700420 sarrayfree(wait->objs);
Brad Bishop2afe7182016-08-13 14:08:17 -0400421free_wait:
Ed Tanous167e2372018-05-07 11:59:10 -0700422 free(wait);
Brad Bishop2afe7182016-08-13 14:08:17 -0400423
Ed Tanous167e2372018-05-07 11:59:10 -0700424 return r;
Brad Bishop2afe7182016-08-13 14:08:17 -0400425}
426
George Liucf724032024-10-29 14:31:51 +0800427static int async_subtree_timeout_callback(
428 _unused_ sd_event_source* s, _unused_ uint64_t usec, void* userdata)
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500429{
Ed Tanous167e2372018-05-07 11:59:10 -0700430 int r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500431 struct mapper_async_subtree* subtree = userdata;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500432
Ed Tanous167e2372018-05-07 11:59:10 -0700433 sd_event_source_unref(subtree->event_source);
434 r = sd_bus_call_method_async(
Brad Bishopa02cd542021-10-12 19:12:42 -0400435 subtree->conn, NULL, "xyz.openbmc_project.ObjectMapper",
436 "/xyz/openbmc_project/object_mapper",
437 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
438 async_subtree_getpaths_callback, subtree, "sias", subtree->namespace, 0,
439 1, subtree->interface);
Ed Tanous167e2372018-05-07 11:59:10 -0700440 if (r < 0)
George Liucf724032024-10-29 14:31:51 +0800441 {
Ed Tanous167e2372018-05-07 11:59:10 -0700442 async_subtree_done(r, subtree);
George Liucf724032024-10-29 14:31:51 +0800443 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500444
Ed Tanous167e2372018-05-07 11:59:10 -0700445 return 0;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500446}
447
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500448static int async_subtree_getpaths_callback(sd_bus_message* m, void* userdata,
Brad Bishop2d41d6a2021-08-03 08:14:45 -0400449 _unused_ sd_bus_error* e)
Adriana Kobylak025d7952017-05-08 13:30:45 -0500450{
Ed Tanous167e2372018-05-07 11:59:10 -0700451 int r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500452 struct mapper_async_subtree* subtree = userdata;
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700453 uint64_t next_retry;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500454
Ed Tanous167e2372018-05-07 11:59:10 -0700455 if (subtree->finished)
George Liucf724032024-10-29 14:31:51 +0800456 {
Ed Tanous167e2372018-05-07 11:59:10 -0700457 goto exit;
George Liucf724032024-10-29 14:31:51 +0800458 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500459
Ed Tanous167e2372018-05-07 11:59:10 -0700460 r = sd_bus_message_get_errno(m);
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500461
Patrick Williamse82b0582020-11-16 16:25:20 -0600462 if (sd_bus_message_is_method_error(
463 m, "xyz.openbmc_project.Common.Error.ResourceNotFound"))
Ed Tanous167e2372018-05-07 11:59:10 -0700464 {
465 if (subtree->op == MAPPER_OP_REMOVE)
George Liucf724032024-10-29 14:31:51 +0800466 {
Ed Tanous167e2372018-05-07 11:59:10 -0700467 r = 0;
George Liucf724032024-10-29 14:31:51 +0800468 }
Ed Tanous167e2372018-05-07 11:59:10 -0700469 else
George Liucf724032024-10-29 14:31:51 +0800470 {
Ed Tanous167e2372018-05-07 11:59:10 -0700471 goto exit;
George Liucf724032024-10-29 14:31:51 +0800472 }
Ed Tanous167e2372018-05-07 11:59:10 -0700473 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500474
William A. Kennington III24829462018-06-15 10:10:25 -0700475 if ((r == EBUSY || r == ENOBUFS) && subtree->retry < mapper_busy_retries)
Ed Tanous167e2372018-05-07 11:59:10 -0700476 {
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700477 r = sd_event_now(subtree->loop, CLOCK_MONOTONIC, &next_retry);
Ed Tanous167e2372018-05-07 11:59:10 -0700478 if (r < 0)
479 {
480 async_subtree_done(r, subtree);
481 goto exit;
482 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500483
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700484 next_retry += mapper_busy_delay_interval_usec * (1 << subtree->retry);
Ed Tanous167e2372018-05-07 11:59:10 -0700485 r = sd_event_add_time(subtree->loop, &subtree->event_source,
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700486 CLOCK_MONOTONIC, next_retry, 0,
Ed Tanous167e2372018-05-07 11:59:10 -0700487 async_subtree_timeout_callback, subtree);
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700488 ++subtree->retry;
Ed Tanous167e2372018-05-07 11:59:10 -0700489 if (r < 0)
490 {
491 async_subtree_done(r, subtree);
492 goto exit;
493 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500494
Ed Tanous167e2372018-05-07 11:59:10 -0700495 return 0;
496 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500497
Ed Tanous167e2372018-05-07 11:59:10 -0700498 if (r)
499 {
500 async_subtree_done(-r, subtree);
501 goto exit;
502 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500503
Ed Tanous167e2372018-05-07 11:59:10 -0700504 if (subtree->op == MAPPER_OP_REMOVE)
505 {
William A. Kennington III20cbbfb2018-06-15 10:10:13 -0700506 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "s");
507 if (r < 0)
508 {
509 async_subtree_done(r, subtree);
510 goto exit;
511 }
512
513 r = sd_bus_message_at_end(m, false);
514 if (r < 0)
515 {
516 async_subtree_done(r, subtree);
517 goto exit;
518 }
519
Ed Tanous167e2372018-05-07 11:59:10 -0700520 /* For remove, operation is complete when the interface is not present
William A. Kennington III20cbbfb2018-06-15 10:10:13 -0700521 * we know it is empty if the returned array is empty
Ed Tanous167e2372018-05-07 11:59:10 -0700522 */
William A. Kennington III20cbbfb2018-06-15 10:10:13 -0700523 if (r)
Ed Tanous167e2372018-05-07 11:59:10 -0700524 async_subtree_done(0, subtree);
525 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500526
527exit:
Ed Tanous167e2372018-05-07 11:59:10 -0700528 return 0;
Adriana Kobylak025d7952017-05-08 13:30:45 -0500529}
530
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500531static int async_subtree_getpaths(mapper_async_subtree* subtree)
Adriana Kobylak025d7952017-05-08 13:30:45 -0500532{
Ed Tanous167e2372018-05-07 11:59:10 -0700533 int r = 0;
Adriana Kobylak025d7952017-05-08 13:30:45 -0500534
Ed Tanous167e2372018-05-07 11:59:10 -0700535 subtree->retry = 0;
536 subtree->event_source = NULL;
537 r = sd_bus_call_method_async(
Brad Bishopa02cd542021-10-12 19:12:42 -0400538 subtree->conn, NULL, "xyz.openbmc_project.ObjectMapper",
539 "/xyz/openbmc_project/object_mapper",
540 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
541 async_subtree_getpaths_callback, subtree, "sias", subtree->namespace, 0,
542 1, subtree->interface);
Ed Tanous167e2372018-05-07 11:59:10 -0700543 if (r < 0)
544 {
545 fprintf(stderr, "Error invoking method: %s\n", strerror(-r));
546 return r;
547 }
Adriana Kobylak025d7952017-05-08 13:30:45 -0500548
Ed Tanous167e2372018-05-07 11:59:10 -0700549 return 0;
Adriana Kobylak025d7952017-05-08 13:30:45 -0500550}
551
Brad Bishop2d41d6a2021-08-03 08:14:45 -0400552static int async_subtree_match_callback(_unused_ sd_bus_message* m, void* t,
553 _unused_ sd_bus_error* e)
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500554{
Ed Tanous167e2372018-05-07 11:59:10 -0700555 int r;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500556
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500557 mapper_async_subtree* subtree = t;
Ed Tanous167e2372018-05-07 11:59:10 -0700558 if (subtree->finished)
George Liucf724032024-10-29 14:31:51 +0800559 {
Ed Tanous167e2372018-05-07 11:59:10 -0700560 return 0;
George Liucf724032024-10-29 14:31:51 +0800561 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500562
Ed Tanous167e2372018-05-07 11:59:10 -0700563 r = async_subtree_getpaths(subtree);
564 if (r < 0)
George Liucf724032024-10-29 14:31:51 +0800565 {
Ed Tanous167e2372018-05-07 11:59:10 -0700566 async_subtree_done(r, subtree);
George Liucf724032024-10-29 14:31:51 +0800567 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500568
Ed Tanous167e2372018-05-07 11:59:10 -0700569 return 0;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500570}
571
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500572static void async_subtree_done(int r, mapper_async_subtree* t)
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500573{
Ed Tanous167e2372018-05-07 11:59:10 -0700574 if (t->finished)
George Liucf724032024-10-29 14:31:51 +0800575 {
Ed Tanous167e2372018-05-07 11:59:10 -0700576 return;
George Liucf724032024-10-29 14:31:51 +0800577 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500578
Ed Tanous167e2372018-05-07 11:59:10 -0700579 t->finished = 1;
580 sd_bus_slot_unref(t->slot);
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500581
Ed Tanous167e2372018-05-07 11:59:10 -0700582 if (t->callback)
George Liucf724032024-10-29 14:31:51 +0800583 {
Ed Tanous167e2372018-05-07 11:59:10 -0700584 t->callback(r, t->userdata);
George Liucf724032024-10-29 14:31:51 +0800585 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500586}
587
Brad Bishop75057c82021-08-03 15:22:02 -0400588_public_ int mapper_subtree_async(sd_bus* conn, sd_event* loop, char* namespace,
589 char* interface, void (*callback)(int, void*),
590 void* userdata, mapper_async_subtree** t,
591 int op)
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500592{
Ed Tanous167e2372018-05-07 11:59:10 -0700593 int r = 0;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500594 mapper_async_subtree* subtree = NULL;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500595
Ed Tanous167e2372018-05-07 11:59:10 -0700596 subtree = malloc(sizeof(*subtree));
597 if (!subtree)
George Liucf724032024-10-29 14:31:51 +0800598 {
Ed Tanous167e2372018-05-07 11:59:10 -0700599 return -ENOMEM;
George Liucf724032024-10-29 14:31:51 +0800600 }
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500601
Ed Tanous167e2372018-05-07 11:59:10 -0700602 memset(subtree, 0, sizeof(*subtree));
603 subtree->conn = conn;
604 subtree->loop = loop;
605 subtree->namespace = namespace;
606 subtree->interface = interface;
607 subtree->callback = callback;
608 subtree->userdata = userdata;
609 subtree->op = op;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500610
Ed Tanous167e2372018-05-07 11:59:10 -0700611 if (subtree->op == MAPPER_OP_REMOVE)
612 {
613 r = sd_bus_add_match(conn, &subtree->slot, interfaces_removed_match,
614 async_subtree_match_callback, subtree);
615 if (r < 0)
616 {
617 fprintf(stderr, "Error adding match rule: %s\n", strerror(-r));
618 goto unref_slot;
619 }
620 }
621 else
622 {
623 /* Operation not supported */
624 r = -EINVAL;
625 goto free_subtree;
626 }
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500627
Ed Tanous167e2372018-05-07 11:59:10 -0700628 r = async_subtree_getpaths(subtree);
629 if (r < 0)
630 {
631 fprintf(stderr, "Error calling method: %s\n", strerror(-r));
632 goto unref_slot;
633 }
Adriana Kobylak025d7952017-05-08 13:30:45 -0500634
Ed Tanous167e2372018-05-07 11:59:10 -0700635 *t = subtree;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500636
Ed Tanous167e2372018-05-07 11:59:10 -0700637 return 0;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500638
639unref_slot:
Ed Tanous167e2372018-05-07 11:59:10 -0700640 sd_bus_slot_unref(subtree->slot);
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500641free_subtree:
Ed Tanous167e2372018-05-07 11:59:10 -0700642 free(subtree);
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500643
Ed Tanous167e2372018-05-07 11:59:10 -0700644 return r;
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500645}
646
Brad Bishop75057c82021-08-03 15:22:02 -0400647_public_ int mapper_get_object(sd_bus* conn, const char* obj,
648 sd_bus_message** reply)
Brad Bishop62ece2b2016-07-25 09:00:51 -0400649{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500650 sd_bus_message* request = NULL;
Ed Tanous167e2372018-05-07 11:59:10 -0700651 int r, retry = 0;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400652
Brad Bishopa02cd542021-10-12 19:12:42 -0400653 r = sd_bus_message_new_method_call(
654 conn, &request, "xyz.openbmc_project.ObjectMapper",
655 "/xyz/openbmc_project/object_mapper",
656 "xyz.openbmc_project.ObjectMapper", "GetObject");
Ed Tanous167e2372018-05-07 11:59:10 -0700657 if (r < 0)
George Liucf724032024-10-29 14:31:51 +0800658 {
Ed Tanous167e2372018-05-07 11:59:10 -0700659 goto exit;
George Liucf724032024-10-29 14:31:51 +0800660 }
Brad Bishop62ece2b2016-07-25 09:00:51 -0400661
Ed Tanous167e2372018-05-07 11:59:10 -0700662 r = sd_bus_message_append(request, "s", obj);
663 if (r < 0)
George Liucf724032024-10-29 14:31:51 +0800664 {
Ed Tanous167e2372018-05-07 11:59:10 -0700665 goto exit;
George Liucf724032024-10-29 14:31:51 +0800666 }
Ed Tanous167e2372018-05-07 11:59:10 -0700667 r = sd_bus_message_append(request, "as", 0, NULL);
668 if (r < 0)
George Liucf724032024-10-29 14:31:51 +0800669 {
Ed Tanous167e2372018-05-07 11:59:10 -0700670 goto exit;
George Liucf724032024-10-29 14:31:51 +0800671 }
Brad Bishop62ece2b2016-07-25 09:00:51 -0400672
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700673 while (true)
Ed Tanous167e2372018-05-07 11:59:10 -0700674 {
William A. Kennington III24829462018-06-15 10:10:25 -0700675 r = sd_bus_call(conn, request, 0, NULL, reply);
676 if (r == -EBUSY || r == -ENOBUFS)
Ed Tanous167e2372018-05-07 11:59:10 -0700677 {
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700678 if (retry >= mapper_busy_retries)
679 break;
Brad Bishop3d468792016-09-20 15:39:38 -0400680
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700681 usleep(mapper_busy_delay_interval_usec * (1 << retry));
682 ++retry;
Ed Tanous167e2372018-05-07 11:59:10 -0700683 continue;
684 }
685 break;
686 }
Brad Bishop3d468792016-09-20 15:39:38 -0400687
Ed Tanous167e2372018-05-07 11:59:10 -0700688 if (r < 0)
George Liucf724032024-10-29 14:31:51 +0800689 {
Ed Tanous167e2372018-05-07 11:59:10 -0700690 goto exit;
George Liucf724032024-10-29 14:31:51 +0800691 }
Brad Bishop3d468792016-09-20 15:39:38 -0400692
693exit:
Ed Tanous167e2372018-05-07 11:59:10 -0700694 sd_bus_message_unref(request);
Brad Bishop3d468792016-09-20 15:39:38 -0400695
Ed Tanous167e2372018-05-07 11:59:10 -0700696 return r;
Brad Bishop3d468792016-09-20 15:39:38 -0400697}
698
Brad Bishop75057c82021-08-03 15:22:02 -0400699_public_ int mapper_get_service(sd_bus* conn, const char* obj, char** service)
Brad Bishop3d468792016-09-20 15:39:38 -0400700{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500701 sd_bus_message* reply = NULL;
702 const char* tmp;
Ed Tanous167e2372018-05-07 11:59:10 -0700703 int r;
Brad Bishop3d468792016-09-20 15:39:38 -0400704
Ed Tanous167e2372018-05-07 11:59:10 -0700705 r = mapper_get_object(conn, obj, &reply);
706 if (r < 0)
George Liucf724032024-10-29 14:31:51 +0800707 {
Ed Tanous167e2372018-05-07 11:59:10 -0700708 goto exit;
George Liucf724032024-10-29 14:31:51 +0800709 }
Brad Bishop62ece2b2016-07-25 09:00:51 -0400710
Ed Tanous167e2372018-05-07 11:59:10 -0700711 r = sd_bus_message_enter_container(reply, 0, NULL);
712 if (r < 0)
George Liucf724032024-10-29 14:31:51 +0800713 {
Ed Tanous167e2372018-05-07 11:59:10 -0700714 goto exit;
George Liucf724032024-10-29 14:31:51 +0800715 }
Brad Bishop62ece2b2016-07-25 09:00:51 -0400716
Ed Tanous167e2372018-05-07 11:59:10 -0700717 r = sd_bus_message_enter_container(reply, 0, NULL);
718 if (r < 0)
George Liucf724032024-10-29 14:31:51 +0800719 {
Ed Tanous167e2372018-05-07 11:59:10 -0700720 goto exit;
George Liucf724032024-10-29 14:31:51 +0800721 }
Brad Bishop62ece2b2016-07-25 09:00:51 -0400722
Ed Tanous167e2372018-05-07 11:59:10 -0700723 r = sd_bus_message_read(reply, "s", &tmp);
724 if (r < 0)
George Liucf724032024-10-29 14:31:51 +0800725 {
Ed Tanous167e2372018-05-07 11:59:10 -0700726 goto exit;
George Liucf724032024-10-29 14:31:51 +0800727 }
Brad Bishop62ece2b2016-07-25 09:00:51 -0400728
Ed Tanous167e2372018-05-07 11:59:10 -0700729 *service = strdup(tmp);
Brad Bishop62ece2b2016-07-25 09:00:51 -0400730
731exit:
Ed Tanous167e2372018-05-07 11:59:10 -0700732 sd_bus_message_unref(reply);
Brad Bishop62ece2b2016-07-25 09:00:51 -0400733
Ed Tanous167e2372018-05-07 11:59:10 -0700734 return r;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400735}