blob: a3459abb03a4ab371be3521fd923f26d203f0058 [file] [log] [blame]
Alexander Hansenaa9c24a2025-10-30 13:59:26 +01001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright 2016 IBM Corporation
3
Matt Spinlercc6ee9c2018-09-19 13:23:13 -05004#include "mapper.h"
5
George Liucf724032024-10-29 14:31:51 +08006#include "internal.h"
7
Matt Spinlercc6ee9c2018-09-19 13:23:13 -05008#include <errno.h>
William A. Kennington III20cbbfb2018-06-15 10:10:13 -07009#include <stdbool.h>
Brad Bishopa959f122021-08-03 11:21:01 -040010#include <stddef.h>
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050011#include <stdio.h>
Brad Bishop2afe7182016-08-13 14:08:17 -040012#include <stdlib.h>
Brad Bishop62ece2b2016-07-25 09:00:51 -040013#include <string.h>
Brad Bishop3d468792016-09-20 15:39:38 -040014#include <sys/timerfd.h>
Brad Bishop62ece2b2016-07-25 09:00:51 -040015#include <systemd/sd-bus.h>
Brad Bishop3d468792016-09-20 15:39:38 -040016#include <systemd/sd-event.h>
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050017#include <unistd.h>
Brad Bishop62ece2b2016-07-25 09:00:51 -040018
Brad Bishop75057c82021-08-03 15:22:02 -040019#define _public_ __attribute__((__visibility__("default")))
Brad Bishop2d41d6a2021-08-03 08:14:45 -040020#define _unused_ __attribute__((unused))
Brad Bishop75057c82021-08-03 15:22:02 -040021
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050022static const char* async_wait_introspection_match =
Ed Tanous167e2372018-05-07 11:59:10 -070023 "type='signal',"
24 "sender='xyz.openbmc_project.ObjectMapper',"
25 "interface='xyz.openbmc_project.ObjectMapper.Private',"
26 "member='IntrospectionComplete'";
Brad Bishop2afe7182016-08-13 14:08:17 -040027
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050028static const char* async_wait_interfaces_added_match =
Ed Tanous167e2372018-05-07 11:59:10 -070029 "type='signal',"
30 "interface='org.freedesktop.DBus.ObjectManager',"
31 "member='InterfacesAdded'";
Brad Bishop2afe7182016-08-13 14:08:17 -040032
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050033static const char* interfaces_removed_match =
Ed Tanous167e2372018-05-07 11:59:10 -070034 "type='signal',"
35 "interface='org.freedesktop.DBus.ObjectManager',"
36 "member='InterfacesRemoved'";
Adriana Kobylak78edbb62017-05-04 15:45:19 -050037
Brad Bishop3d468792016-09-20 15:39:38 -040038static const int mapper_busy_retries = 5;
39static const uint64_t mapper_busy_delay_interval_usec = 1000000;
40
Brad Bishop2afe7182016-08-13 14:08:17 -040041struct mapper_async_wait
42{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050043 char** objs;
44 void (*callback)(int, void*);
45 void* userdata;
46 sd_event* loop;
47 sd_bus* conn;
48 sd_bus_slot* introspection_slot;
49 sd_bus_slot* intf_slot;
50 int* status;
Brad Bishopa959f122021-08-03 11:21:01 -040051 size_t count;
Ed Tanous167e2372018-05-07 11:59:10 -070052 int finished;
53 int r;
Brad Bishop2afe7182016-08-13 14:08:17 -040054};
55
56struct async_wait_callback_data
57{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050058 mapper_async_wait* wait;
59 const char* path;
60 sd_event_source* event_source;
Ed Tanous167e2372018-05-07 11:59:10 -070061 int retry;
Brad Bishop2afe7182016-08-13 14:08:17 -040062};
63
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -050064struct mapper_async_subtree
65{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050066 char* namespace;
67 char* interface;
68 void (*callback)(int, void*);
69 void* userdata;
70 sd_event* loop;
71 sd_bus* conn;
72 sd_bus_slot* slot;
73 sd_event_source* event_source;
Ed Tanous167e2372018-05-07 11:59:10 -070074 int finished;
75 int op;
76 int retry;
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -050077};
78
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050079static int async_wait_match_introspection_complete(sd_bus_message*, void*,
80 sd_bus_error*);
81static int async_wait_check_done(mapper_async_wait*);
82static void async_wait_done(int r, mapper_async_wait*);
83static int async_wait_get_objects(mapper_async_wait*);
84static int async_wait_getobject_callback(sd_bus_message*, void*, sd_bus_error*);
Brad Bishop2afe7182016-08-13 14:08:17 -040085
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050086static int async_subtree_match_callback(sd_bus_message*, void*, sd_bus_error*);
87static void async_subtree_done(int r, mapper_async_subtree*);
88static int async_subtree_getpaths(mapper_async_subtree*);
89static int async_subtree_getpaths_callback(sd_bus_message*, void*,
90 sd_bus_error*);
Adriana Kobylak78edbb62017-05-04 15:45:19 -050091
Brad Bishopa959f122021-08-03 11:21:01 -040092size_t sarraylen(char* array[])
Brad Bishop2afe7182016-08-13 14:08:17 -040093{
Brad Bishopa959f122021-08-03 11:21:01 -040094 size_t count = 0;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050095 char** p = array;
Brad Bishop2afe7182016-08-13 14:08:17 -040096
Ed Tanous167e2372018-05-07 11:59:10 -070097 while (*p != NULL)
98 {
99 ++count;
100 ++p;
101 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400102
Ed Tanous167e2372018-05-07 11:59:10 -0700103 return count;
Brad Bishop2afe7182016-08-13 14:08:17 -0400104}
105
Brad Bishopa669a502021-08-03 16:01:43 -0400106void sarrayfree(char* array[])
Brad Bishop2afe7182016-08-13 14:08:17 -0400107{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500108 char** p = array;
Ed Tanous167e2372018-05-07 11:59:10 -0700109 while (*p != NULL)
110 {
111 free(*p);
112 ++p;
113 }
114 free(array);
Brad Bishop2afe7182016-08-13 14:08:17 -0400115}
116
Brad Bishopa669a502021-08-03 16:01:43 -0400117char** sarraydup(char* array[])
Brad Bishop2afe7182016-08-13 14:08:17 -0400118{
Brad Bishopa959f122021-08-03 11:21:01 -0400119 size_t count = sarraylen(array);
120 size_t i;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500121 char** ret = NULL;
Brad Bishop2afe7182016-08-13 14:08:17 -0400122
Brad Bishopa669a502021-08-03 16:01:43 -0400123 ret = calloc(count + 1, sizeof(*ret));
Ed Tanous167e2372018-05-07 11:59:10 -0700124 if (!ret)
George Liucf724032024-10-29 14:31:51 +0800125 {
Ed Tanous167e2372018-05-07 11:59:10 -0700126 return NULL;
George Liucf724032024-10-29 14:31:51 +0800127 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400128
Ed Tanous167e2372018-05-07 11:59:10 -0700129 for (i = 0; i < count; ++i)
130 {
131 ret[i] = strdup(array[i]);
132 if (!ret[i])
George Liucf724032024-10-29 14:31:51 +0800133 {
Ed Tanous167e2372018-05-07 11:59:10 -0700134 goto error;
George Liucf724032024-10-29 14:31:51 +0800135 }
Ed Tanous167e2372018-05-07 11:59:10 -0700136 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400137
Ed Tanous167e2372018-05-07 11:59:10 -0700138 return ret;
Brad Bishop2afe7182016-08-13 14:08:17 -0400139
140error:
Ed Tanous167e2372018-05-07 11:59:10 -0700141 sarrayfree(ret);
142 return NULL;
Brad Bishop2afe7182016-08-13 14:08:17 -0400143}
144
Brad Bishop2d41d6a2021-08-03 08:14:45 -0400145static int async_wait_timeout_callback(_unused_ sd_event_source* s,
146 _unused_ uint64_t usec, void* userdata)
Brad Bishop3d468792016-09-20 15:39:38 -0400147{
Ed Tanous167e2372018-05-07 11:59:10 -0700148 int r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500149 struct async_wait_callback_data* data = userdata;
150 mapper_async_wait* wait = data->wait;
Brad Bishop3d468792016-09-20 15:39:38 -0400151
Ed Tanous167e2372018-05-07 11:59:10 -0700152 sd_event_source_unref(data->event_source);
Brad Bishopa02cd542021-10-12 19:12:42 -0400153 r = sd_bus_call_method_async(
154 wait->conn, NULL, "xyz.openbmc_project.ObjectMapper",
155 "/xyz/openbmc_project/object_mapper",
156 "xyz.openbmc_project.ObjectMapper", "GetObject",
157 async_wait_getobject_callback, data, "sas", data->path, 0, NULL);
Ed Tanous167e2372018-05-07 11:59:10 -0700158 if (r < 0)
159 {
160 async_wait_done(r, wait);
161 free(data);
162 }
Brad Bishop3d468792016-09-20 15:39:38 -0400163
Ed Tanous167e2372018-05-07 11:59:10 -0700164 return 0;
Brad Bishop3d468792016-09-20 15:39:38 -0400165}
166
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500167static int async_wait_getobject_callback(sd_bus_message* m, void* userdata,
Brad Bishop2d41d6a2021-08-03 08:14:45 -0400168 _unused_ sd_bus_error* e)
Brad Bishop2afe7182016-08-13 14:08:17 -0400169{
Brad Bishopa959f122021-08-03 11:21:01 -0400170 size_t i;
171 int r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500172 struct async_wait_callback_data* data = userdata;
173 mapper_async_wait* wait = data->wait;
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700174 uint64_t next_retry;
Brad Bishop2afe7182016-08-13 14:08:17 -0400175
Ed Tanous167e2372018-05-07 11:59:10 -0700176 if (wait->finished)
George Liucf724032024-10-29 14:31:51 +0800177 {
Ed Tanous167e2372018-05-07 11:59:10 -0700178 goto exit;
George Liucf724032024-10-29 14:31:51 +0800179 }
Brad Bishop3d468792016-09-20 15:39:38 -0400180
Patrick Williamse82b0582020-11-16 16:25:20 -0600181 if (sd_bus_message_is_method_error(
182 m, "xyz.openbmc_project.Common.Error.ResourceNotFound"))
George Liucf724032024-10-29 14:31:51 +0800183 {
Ed Tanous167e2372018-05-07 11:59:10 -0700184 goto exit;
George Liucf724032024-10-29 14:31:51 +0800185 }
Brad Bishop8ccdaed2016-09-20 15:54:32 -0400186
Patrick Williamse82b0582020-11-16 16:25:20 -0600187 r = sd_bus_message_get_errno(m);
188
William A. Kennington III24829462018-06-15 10:10:25 -0700189 if ((r == EBUSY || r == ENOBUFS) && data->retry < mapper_busy_retries)
Ed Tanous167e2372018-05-07 11:59:10 -0700190 {
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700191 r = sd_event_now(wait->loop, CLOCK_MONOTONIC, &next_retry);
Ed Tanous167e2372018-05-07 11:59:10 -0700192 if (r < 0)
193 {
194 async_wait_done(r, wait);
195 goto exit;
196 }
Brad Bishop3d468792016-09-20 15:39:38 -0400197
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700198 next_retry += mapper_busy_delay_interval_usec * (1 << data->retry);
Ed Tanous167e2372018-05-07 11:59:10 -0700199 r = sd_event_add_time(wait->loop, &data->event_source, CLOCK_MONOTONIC,
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700200 next_retry, 0, async_wait_timeout_callback, data);
201 ++data->retry;
Ed Tanous167e2372018-05-07 11:59:10 -0700202 if (r < 0)
203 {
204 async_wait_done(r, wait);
205 goto exit;
206 }
Brad Bishop3d468792016-09-20 15:39:38 -0400207
Ed Tanous167e2372018-05-07 11:59:10 -0700208 return 0;
209 }
Brad Bishop3d468792016-09-20 15:39:38 -0400210
Ed Tanous167e2372018-05-07 11:59:10 -0700211 if (r)
212 {
213 async_wait_done(-r, wait);
214 goto exit;
215 }
Brad Bishop3d468792016-09-20 15:39:38 -0400216
Ed Tanous167e2372018-05-07 11:59:10 -0700217 for (i = 0; i < wait->count; ++i)
218 {
219 if (!strcmp(data->path, wait->objs[i]))
220 {
221 wait->status[i] = 1;
222 }
223 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400224
Ed Tanous167e2372018-05-07 11:59:10 -0700225 if (async_wait_check_done(wait))
George Liucf724032024-10-29 14:31:51 +0800226 {
Ed Tanous167e2372018-05-07 11:59:10 -0700227 async_wait_done(0, wait);
George Liucf724032024-10-29 14:31:51 +0800228 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400229
Brad Bishop3d468792016-09-20 15:39:38 -0400230exit:
Ed Tanous167e2372018-05-07 11:59:10 -0700231 free(data);
232 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400233}
234
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500235static int async_wait_get_objects(mapper_async_wait* wait)
Brad Bishop2afe7182016-08-13 14:08:17 -0400236{
Brad Bishopa959f122021-08-03 11:21:01 -0400237 size_t i;
238 int r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500239 struct async_wait_callback_data* data = NULL;
Brad Bishop2afe7182016-08-13 14:08:17 -0400240
Ed Tanous167e2372018-05-07 11:59:10 -0700241 for (i = 0; i < wait->count; ++i)
242 {
243 if (wait->status[i])
George Liucf724032024-10-29 14:31:51 +0800244 {
Ed Tanous167e2372018-05-07 11:59:10 -0700245 continue;
George Liucf724032024-10-29 14:31:51 +0800246 }
Ed Tanous167e2372018-05-07 11:59:10 -0700247 data = malloc(sizeof(*data));
248 data->wait = wait;
249 data->path = wait->objs[i];
250 data->retry = 0;
251 data->event_source = NULL;
Brad Bishopa02cd542021-10-12 19:12:42 -0400252 r = sd_bus_call_method_async(
253 wait->conn, NULL, "xyz.openbmc_project.ObjectMapper",
254 "/xyz/openbmc_project/object_mapper",
255 "xyz.openbmc_project.ObjectMapper", "GetObject",
256 async_wait_getobject_callback, data, "sas", wait->objs[i], 0, NULL);
Ed Tanous167e2372018-05-07 11:59:10 -0700257 if (r < 0)
258 {
259 free(data);
260 fprintf(stderr, "Error invoking method: %s\n", strerror(-r));
261 return r;
262 }
263 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400264
Ed Tanous167e2372018-05-07 11:59:10 -0700265 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400266}
267
George Liucf724032024-10-29 14:31:51 +0800268static int async_wait_match_introspection_complete(
269 _unused_ sd_bus_message* m, void* w, _unused_ sd_bus_error* e)
Brad Bishop2afe7182016-08-13 14:08:17 -0400270{
Ed Tanous167e2372018-05-07 11:59:10 -0700271 int r;
Brad Bishop2afe7182016-08-13 14:08:17 -0400272
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500273 mapper_async_wait* wait = w;
Ed Tanous167e2372018-05-07 11:59:10 -0700274 if (wait->finished)
George Liucf724032024-10-29 14:31:51 +0800275 {
Ed Tanous167e2372018-05-07 11:59:10 -0700276 return 0;
George Liucf724032024-10-29 14:31:51 +0800277 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400278
Ed Tanous167e2372018-05-07 11:59:10 -0700279 r = async_wait_get_objects(wait);
280 if (r < 0)
George Liucf724032024-10-29 14:31:51 +0800281 {
Ed Tanous167e2372018-05-07 11:59:10 -0700282 async_wait_done(r, wait);
George Liucf724032024-10-29 14:31:51 +0800283 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400284
Ed Tanous167e2372018-05-07 11:59:10 -0700285 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400286}
287
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500288static void async_wait_done(int r, mapper_async_wait* w)
Brad Bishop2afe7182016-08-13 14:08:17 -0400289{
Ed Tanous167e2372018-05-07 11:59:10 -0700290 if (w->finished)
George Liucf724032024-10-29 14:31:51 +0800291 {
Ed Tanous167e2372018-05-07 11:59:10 -0700292 return;
George Liucf724032024-10-29 14:31:51 +0800293 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400294
Ed Tanous167e2372018-05-07 11:59:10 -0700295 w->finished = 1;
296 sd_bus_slot_unref(w->introspection_slot);
297 sd_bus_slot_unref(w->intf_slot);
Brad Bishop2afe7182016-08-13 14:08:17 -0400298
Ed Tanous167e2372018-05-07 11:59:10 -0700299 if (w->callback)
George Liucf724032024-10-29 14:31:51 +0800300 {
Ed Tanous167e2372018-05-07 11:59:10 -0700301 w->callback(r, w->userdata);
George Liucf724032024-10-29 14:31:51 +0800302 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400303}
304
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500305static int async_wait_check_done(mapper_async_wait* w)
Brad Bishop2afe7182016-08-13 14:08:17 -0400306{
Brad Bishopa959f122021-08-03 11:21:01 -0400307 size_t i;
Brad Bishop2afe7182016-08-13 14:08:17 -0400308
Ed Tanous167e2372018-05-07 11:59:10 -0700309 if (w->finished)
George Liucf724032024-10-29 14:31:51 +0800310 {
Ed Tanous167e2372018-05-07 11:59:10 -0700311 return 1;
George Liucf724032024-10-29 14:31:51 +0800312 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400313
Ed Tanous167e2372018-05-07 11:59:10 -0700314 for (i = 0; i < w->count; ++i)
George Liucf724032024-10-29 14:31:51 +0800315 {
Ed Tanous167e2372018-05-07 11:59:10 -0700316 if (!w->status[i])
George Liucf724032024-10-29 14:31:51 +0800317 {
Ed Tanous167e2372018-05-07 11:59:10 -0700318 return 0;
George Liucf724032024-10-29 14:31:51 +0800319 }
320 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400321
Ed Tanous167e2372018-05-07 11:59:10 -0700322 return 1;
Brad Bishop2afe7182016-08-13 14:08:17 -0400323}
324
Brad Bishop75057c82021-08-03 15:22:02 -0400325_public_ void mapper_wait_async_free(mapper_async_wait* w)
Brad Bishop2afe7182016-08-13 14:08:17 -0400326{
Ed Tanous167e2372018-05-07 11:59:10 -0700327 free(w->status);
328 sarrayfree(w->objs);
329 free(w);
Brad Bishop2afe7182016-08-13 14:08:17 -0400330}
331
Brad Bishop75057c82021-08-03 15:22:02 -0400332_public_ int mapper_wait_async(sd_bus* conn, sd_event* loop, char* objs[],
333 void (*callback)(int, void*), void* userdata,
334 mapper_async_wait** w)
Brad Bishop2afe7182016-08-13 14:08:17 -0400335{
Ed Tanous167e2372018-05-07 11:59:10 -0700336 int r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500337 mapper_async_wait* wait = NULL;
Brad Bishop2afe7182016-08-13 14:08:17 -0400338
Ed Tanous167e2372018-05-07 11:59:10 -0700339 wait = malloc(sizeof(*wait));
340 if (!wait)
George Liucf724032024-10-29 14:31:51 +0800341 {
Ed Tanous167e2372018-05-07 11:59:10 -0700342 return -ENOMEM;
George Liucf724032024-10-29 14:31:51 +0800343 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400344
Ed Tanous167e2372018-05-07 11:59:10 -0700345 memset(wait, 0, sizeof(*wait));
346 wait->conn = conn;
347 wait->loop = loop;
348 wait->callback = callback;
349 wait->userdata = userdata;
350 wait->count = sarraylen(objs);
351 if (!wait->count)
Brad Bishop2ac32332021-08-03 14:06:52 -0400352 {
353 r = 0;
354 goto free_wait;
355 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400356
Ed Tanous167e2372018-05-07 11:59:10 -0700357 wait->objs = sarraydup(objs);
358 if (!wait->objs)
359 {
360 r = -ENOMEM;
361 goto free_wait;
362 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400363
Ed Tanous167e2372018-05-07 11:59:10 -0700364 wait->status = malloc(sizeof(*wait->status) * wait->count);
365 if (!wait->status)
366 {
367 r = -ENOMEM;
368 goto free_objs;
369 }
370 memset(wait->status, 0, sizeof(*wait->status) * wait->count);
Brad Bishop2afe7182016-08-13 14:08:17 -0400371
Ed Tanous167e2372018-05-07 11:59:10 -0700372 r = sd_bus_add_match(conn, &wait->introspection_slot,
373 async_wait_introspection_match,
374 async_wait_match_introspection_complete, wait);
375 if (r < 0)
376 {
377 fprintf(stderr, "Error adding match rule: %s\n", strerror(-r));
378 goto free_status;
379 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400380
Ed Tanous167e2372018-05-07 11:59:10 -0700381 r = sd_bus_add_match(conn, &wait->intf_slot,
382 async_wait_interfaces_added_match,
383 async_wait_match_introspection_complete, wait);
384 if (r < 0)
385 {
386 fprintf(stderr, "Error adding match rule: %s\n", strerror(-r));
387 goto unref_name_slot;
388 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400389
Ed Tanous167e2372018-05-07 11:59:10 -0700390 r = async_wait_get_objects(wait);
391 if (r < 0)
392 {
393 fprintf(stderr, "Error calling method: %s\n", strerror(-r));
394 goto unref_intf_slot;
395 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400396
Ed Tanous167e2372018-05-07 11:59:10 -0700397 *w = wait;
Brad Bishop2afe7182016-08-13 14:08:17 -0400398
Ed Tanous167e2372018-05-07 11:59:10 -0700399 return 0;
Brad Bishop2afe7182016-08-13 14:08:17 -0400400
401unref_intf_slot:
Ed Tanous167e2372018-05-07 11:59:10 -0700402 sd_bus_slot_unref(wait->intf_slot);
Brad Bishop2afe7182016-08-13 14:08:17 -0400403unref_name_slot:
Ed Tanous167e2372018-05-07 11:59:10 -0700404 sd_bus_slot_unref(wait->introspection_slot);
Brad Bishop2afe7182016-08-13 14:08:17 -0400405free_status:
Ed Tanous167e2372018-05-07 11:59:10 -0700406 free(wait->status);
Brad Bishop2afe7182016-08-13 14:08:17 -0400407free_objs:
Ed Tanous167e2372018-05-07 11:59:10 -0700408 sarrayfree(wait->objs);
Brad Bishop2afe7182016-08-13 14:08:17 -0400409free_wait:
Ed Tanous167e2372018-05-07 11:59:10 -0700410 free(wait);
Brad Bishop2afe7182016-08-13 14:08:17 -0400411
Ed Tanous167e2372018-05-07 11:59:10 -0700412 return r;
Brad Bishop2afe7182016-08-13 14:08:17 -0400413}
414
George Liucf724032024-10-29 14:31:51 +0800415static int async_subtree_timeout_callback(
416 _unused_ sd_event_source* s, _unused_ uint64_t usec, void* userdata)
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500417{
Ed Tanous167e2372018-05-07 11:59:10 -0700418 int r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500419 struct mapper_async_subtree* subtree = userdata;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500420
Ed Tanous167e2372018-05-07 11:59:10 -0700421 sd_event_source_unref(subtree->event_source);
422 r = sd_bus_call_method_async(
Brad Bishopa02cd542021-10-12 19:12:42 -0400423 subtree->conn, NULL, "xyz.openbmc_project.ObjectMapper",
424 "/xyz/openbmc_project/object_mapper",
425 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
426 async_subtree_getpaths_callback, subtree, "sias", subtree->namespace, 0,
427 1, subtree->interface);
Ed Tanous167e2372018-05-07 11:59:10 -0700428 if (r < 0)
George Liucf724032024-10-29 14:31:51 +0800429 {
Ed Tanous167e2372018-05-07 11:59:10 -0700430 async_subtree_done(r, subtree);
George Liucf724032024-10-29 14:31:51 +0800431 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500432
Ed Tanous167e2372018-05-07 11:59:10 -0700433 return 0;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500434}
435
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500436static int async_subtree_getpaths_callback(sd_bus_message* m, void* userdata,
Brad Bishop2d41d6a2021-08-03 08:14:45 -0400437 _unused_ sd_bus_error* e)
Adriana Kobylak025d7952017-05-08 13:30:45 -0500438{
Ed Tanous167e2372018-05-07 11:59:10 -0700439 int r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500440 struct mapper_async_subtree* subtree = userdata;
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700441 uint64_t next_retry;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500442
Ed Tanous167e2372018-05-07 11:59:10 -0700443 if (subtree->finished)
George Liucf724032024-10-29 14:31:51 +0800444 {
Ed Tanous167e2372018-05-07 11:59:10 -0700445 goto exit;
George Liucf724032024-10-29 14:31:51 +0800446 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500447
Ed Tanous167e2372018-05-07 11:59:10 -0700448 r = sd_bus_message_get_errno(m);
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500449
Patrick Williamse82b0582020-11-16 16:25:20 -0600450 if (sd_bus_message_is_method_error(
451 m, "xyz.openbmc_project.Common.Error.ResourceNotFound"))
Ed Tanous167e2372018-05-07 11:59:10 -0700452 {
453 if (subtree->op == MAPPER_OP_REMOVE)
George Liucf724032024-10-29 14:31:51 +0800454 {
Ed Tanous167e2372018-05-07 11:59:10 -0700455 r = 0;
George Liucf724032024-10-29 14:31:51 +0800456 }
Ed Tanous167e2372018-05-07 11:59:10 -0700457 else
George Liucf724032024-10-29 14:31:51 +0800458 {
Ed Tanous167e2372018-05-07 11:59:10 -0700459 goto exit;
George Liucf724032024-10-29 14:31:51 +0800460 }
Ed Tanous167e2372018-05-07 11:59:10 -0700461 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500462
William A. Kennington III24829462018-06-15 10:10:25 -0700463 if ((r == EBUSY || r == ENOBUFS) && subtree->retry < mapper_busy_retries)
Ed Tanous167e2372018-05-07 11:59:10 -0700464 {
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700465 r = sd_event_now(subtree->loop, CLOCK_MONOTONIC, &next_retry);
Ed Tanous167e2372018-05-07 11:59:10 -0700466 if (r < 0)
467 {
468 async_subtree_done(r, subtree);
469 goto exit;
470 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500471
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700472 next_retry += mapper_busy_delay_interval_usec * (1 << subtree->retry);
Ed Tanous167e2372018-05-07 11:59:10 -0700473 r = sd_event_add_time(subtree->loop, &subtree->event_source,
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700474 CLOCK_MONOTONIC, next_retry, 0,
Ed Tanous167e2372018-05-07 11:59:10 -0700475 async_subtree_timeout_callback, subtree);
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700476 ++subtree->retry;
Ed Tanous167e2372018-05-07 11:59:10 -0700477 if (r < 0)
478 {
479 async_subtree_done(r, subtree);
480 goto exit;
481 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500482
Ed Tanous167e2372018-05-07 11:59:10 -0700483 return 0;
484 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500485
Ed Tanous167e2372018-05-07 11:59:10 -0700486 if (r)
487 {
488 async_subtree_done(-r, subtree);
489 goto exit;
490 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500491
Ed Tanous167e2372018-05-07 11:59:10 -0700492 if (subtree->op == MAPPER_OP_REMOVE)
493 {
William A. Kennington III20cbbfb2018-06-15 10:10:13 -0700494 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "s");
495 if (r < 0)
496 {
497 async_subtree_done(r, subtree);
498 goto exit;
499 }
500
501 r = sd_bus_message_at_end(m, false);
502 if (r < 0)
503 {
504 async_subtree_done(r, subtree);
505 goto exit;
506 }
507
Ed Tanous167e2372018-05-07 11:59:10 -0700508 /* For remove, operation is complete when the interface is not present
William A. Kennington III20cbbfb2018-06-15 10:10:13 -0700509 * we know it is empty if the returned array is empty
Ed Tanous167e2372018-05-07 11:59:10 -0700510 */
William A. Kennington III20cbbfb2018-06-15 10:10:13 -0700511 if (r)
Ed Tanous167e2372018-05-07 11:59:10 -0700512 async_subtree_done(0, subtree);
513 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500514
515exit:
Ed Tanous167e2372018-05-07 11:59:10 -0700516 return 0;
Adriana Kobylak025d7952017-05-08 13:30:45 -0500517}
518
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500519static int async_subtree_getpaths(mapper_async_subtree* subtree)
Adriana Kobylak025d7952017-05-08 13:30:45 -0500520{
Ed Tanous167e2372018-05-07 11:59:10 -0700521 int r = 0;
Adriana Kobylak025d7952017-05-08 13:30:45 -0500522
Ed Tanous167e2372018-05-07 11:59:10 -0700523 subtree->retry = 0;
524 subtree->event_source = NULL;
525 r = sd_bus_call_method_async(
Brad Bishopa02cd542021-10-12 19:12:42 -0400526 subtree->conn, NULL, "xyz.openbmc_project.ObjectMapper",
527 "/xyz/openbmc_project/object_mapper",
528 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
529 async_subtree_getpaths_callback, subtree, "sias", subtree->namespace, 0,
530 1, subtree->interface);
Ed Tanous167e2372018-05-07 11:59:10 -0700531 if (r < 0)
532 {
533 fprintf(stderr, "Error invoking method: %s\n", strerror(-r));
534 return r;
535 }
Adriana Kobylak025d7952017-05-08 13:30:45 -0500536
Ed Tanous167e2372018-05-07 11:59:10 -0700537 return 0;
Adriana Kobylak025d7952017-05-08 13:30:45 -0500538}
539
Brad Bishop2d41d6a2021-08-03 08:14:45 -0400540static int async_subtree_match_callback(_unused_ sd_bus_message* m, void* t,
541 _unused_ sd_bus_error* e)
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500542{
Ed Tanous167e2372018-05-07 11:59:10 -0700543 int r;
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500544
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500545 mapper_async_subtree* subtree = t;
Ed Tanous167e2372018-05-07 11:59:10 -0700546 if (subtree->finished)
George Liucf724032024-10-29 14:31:51 +0800547 {
Ed Tanous167e2372018-05-07 11:59:10 -0700548 return 0;
George Liucf724032024-10-29 14:31:51 +0800549 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500550
Ed Tanous167e2372018-05-07 11:59:10 -0700551 r = async_subtree_getpaths(subtree);
552 if (r < 0)
George Liucf724032024-10-29 14:31:51 +0800553 {
Ed Tanous167e2372018-05-07 11:59:10 -0700554 async_subtree_done(r, subtree);
George Liucf724032024-10-29 14:31:51 +0800555 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500556
Ed Tanous167e2372018-05-07 11:59:10 -0700557 return 0;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500558}
559
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500560static void async_subtree_done(int r, mapper_async_subtree* t)
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500561{
Ed Tanous167e2372018-05-07 11:59:10 -0700562 if (t->finished)
George Liucf724032024-10-29 14:31:51 +0800563 {
Ed Tanous167e2372018-05-07 11:59:10 -0700564 return;
George Liucf724032024-10-29 14:31:51 +0800565 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500566
Ed Tanous167e2372018-05-07 11:59:10 -0700567 t->finished = 1;
568 sd_bus_slot_unref(t->slot);
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500569
Ed Tanous167e2372018-05-07 11:59:10 -0700570 if (t->callback)
George Liucf724032024-10-29 14:31:51 +0800571 {
Ed Tanous167e2372018-05-07 11:59:10 -0700572 t->callback(r, t->userdata);
George Liucf724032024-10-29 14:31:51 +0800573 }
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500574}
575
Brad Bishop75057c82021-08-03 15:22:02 -0400576_public_ int mapper_subtree_async(sd_bus* conn, sd_event* loop, char* namespace,
577 char* interface, void (*callback)(int, void*),
578 void* userdata, mapper_async_subtree** t,
579 int op)
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500580{
Ed Tanous167e2372018-05-07 11:59:10 -0700581 int r = 0;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500582 mapper_async_subtree* subtree = NULL;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500583
Ed Tanous167e2372018-05-07 11:59:10 -0700584 subtree = malloc(sizeof(*subtree));
585 if (!subtree)
George Liucf724032024-10-29 14:31:51 +0800586 {
Ed Tanous167e2372018-05-07 11:59:10 -0700587 return -ENOMEM;
George Liucf724032024-10-29 14:31:51 +0800588 }
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500589
Ed Tanous167e2372018-05-07 11:59:10 -0700590 memset(subtree, 0, sizeof(*subtree));
591 subtree->conn = conn;
592 subtree->loop = loop;
593 subtree->namespace = namespace;
594 subtree->interface = interface;
595 subtree->callback = callback;
596 subtree->userdata = userdata;
597 subtree->op = op;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500598
Ed Tanous167e2372018-05-07 11:59:10 -0700599 if (subtree->op == MAPPER_OP_REMOVE)
600 {
601 r = sd_bus_add_match(conn, &subtree->slot, interfaces_removed_match,
602 async_subtree_match_callback, subtree);
603 if (r < 0)
604 {
605 fprintf(stderr, "Error adding match rule: %s\n", strerror(-r));
606 goto unref_slot;
607 }
608 }
609 else
610 {
611 /* Operation not supported */
612 r = -EINVAL;
613 goto free_subtree;
614 }
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500615
Ed Tanous167e2372018-05-07 11:59:10 -0700616 r = async_subtree_getpaths(subtree);
617 if (r < 0)
618 {
619 fprintf(stderr, "Error calling method: %s\n", strerror(-r));
620 goto unref_slot;
621 }
Adriana Kobylak025d7952017-05-08 13:30:45 -0500622
Ed Tanous167e2372018-05-07 11:59:10 -0700623 *t = subtree;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500624
Ed Tanous167e2372018-05-07 11:59:10 -0700625 return 0;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500626
627unref_slot:
Ed Tanous167e2372018-05-07 11:59:10 -0700628 sd_bus_slot_unref(subtree->slot);
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500629free_subtree:
Ed Tanous167e2372018-05-07 11:59:10 -0700630 free(subtree);
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500631
Ed Tanous167e2372018-05-07 11:59:10 -0700632 return r;
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500633}
634
Brad Bishop75057c82021-08-03 15:22:02 -0400635_public_ int mapper_get_object(sd_bus* conn, const char* obj,
636 sd_bus_message** reply)
Brad Bishop62ece2b2016-07-25 09:00:51 -0400637{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500638 sd_bus_message* request = NULL;
Ed Tanous167e2372018-05-07 11:59:10 -0700639 int r, retry = 0;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400640
Brad Bishopa02cd542021-10-12 19:12:42 -0400641 r = sd_bus_message_new_method_call(
642 conn, &request, "xyz.openbmc_project.ObjectMapper",
643 "/xyz/openbmc_project/object_mapper",
644 "xyz.openbmc_project.ObjectMapper", "GetObject");
Ed Tanous167e2372018-05-07 11:59:10 -0700645 if (r < 0)
George Liucf724032024-10-29 14:31:51 +0800646 {
Ed Tanous167e2372018-05-07 11:59:10 -0700647 goto exit;
George Liucf724032024-10-29 14:31:51 +0800648 }
Brad Bishop62ece2b2016-07-25 09:00:51 -0400649
Ed Tanous167e2372018-05-07 11:59:10 -0700650 r = sd_bus_message_append(request, "s", obj);
651 if (r < 0)
George Liucf724032024-10-29 14:31:51 +0800652 {
Ed Tanous167e2372018-05-07 11:59:10 -0700653 goto exit;
George Liucf724032024-10-29 14:31:51 +0800654 }
Ed Tanous167e2372018-05-07 11:59:10 -0700655 r = sd_bus_message_append(request, "as", 0, NULL);
656 if (r < 0)
George Liucf724032024-10-29 14:31:51 +0800657 {
Ed Tanous167e2372018-05-07 11:59:10 -0700658 goto exit;
George Liucf724032024-10-29 14:31:51 +0800659 }
Brad Bishop62ece2b2016-07-25 09:00:51 -0400660
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700661 while (true)
Ed Tanous167e2372018-05-07 11:59:10 -0700662 {
William A. Kennington III24829462018-06-15 10:10:25 -0700663 r = sd_bus_call(conn, request, 0, NULL, reply);
664 if (r == -EBUSY || r == -ENOBUFS)
Ed Tanous167e2372018-05-07 11:59:10 -0700665 {
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700666 if (retry >= mapper_busy_retries)
667 break;
Brad Bishop3d468792016-09-20 15:39:38 -0400668
William A. Kennington III5e21ac02018-06-15 10:10:20 -0700669 usleep(mapper_busy_delay_interval_usec * (1 << retry));
670 ++retry;
Ed Tanous167e2372018-05-07 11:59:10 -0700671 continue;
672 }
673 break;
674 }
Brad Bishop3d468792016-09-20 15:39:38 -0400675
Ed Tanous167e2372018-05-07 11:59:10 -0700676 if (r < 0)
George Liucf724032024-10-29 14:31:51 +0800677 {
Ed Tanous167e2372018-05-07 11:59:10 -0700678 goto exit;
George Liucf724032024-10-29 14:31:51 +0800679 }
Brad Bishop3d468792016-09-20 15:39:38 -0400680
681exit:
Ed Tanous167e2372018-05-07 11:59:10 -0700682 sd_bus_message_unref(request);
Brad Bishop3d468792016-09-20 15:39:38 -0400683
Ed Tanous167e2372018-05-07 11:59:10 -0700684 return r;
Brad Bishop3d468792016-09-20 15:39:38 -0400685}
686
Brad Bishop75057c82021-08-03 15:22:02 -0400687_public_ int mapper_get_service(sd_bus* conn, const char* obj, char** service)
Brad Bishop3d468792016-09-20 15:39:38 -0400688{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500689 sd_bus_message* reply = NULL;
690 const char* tmp;
Ed Tanous167e2372018-05-07 11:59:10 -0700691 int r;
Brad Bishop3d468792016-09-20 15:39:38 -0400692
Ed Tanous167e2372018-05-07 11:59:10 -0700693 r = mapper_get_object(conn, obj, &reply);
694 if (r < 0)
George Liucf724032024-10-29 14:31:51 +0800695 {
Ed Tanous167e2372018-05-07 11:59:10 -0700696 goto exit;
George Liucf724032024-10-29 14:31:51 +0800697 }
Brad Bishop62ece2b2016-07-25 09:00:51 -0400698
Ed Tanous167e2372018-05-07 11:59:10 -0700699 r = sd_bus_message_enter_container(reply, 0, NULL);
700 if (r < 0)
George Liucf724032024-10-29 14:31:51 +0800701 {
Ed Tanous167e2372018-05-07 11:59:10 -0700702 goto exit;
George Liucf724032024-10-29 14:31:51 +0800703 }
Brad Bishop62ece2b2016-07-25 09:00:51 -0400704
Ed Tanous167e2372018-05-07 11:59:10 -0700705 r = sd_bus_message_enter_container(reply, 0, NULL);
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_read(reply, "s", &tmp);
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 *service = strdup(tmp);
Brad Bishop62ece2b2016-07-25 09:00:51 -0400718
719exit:
Ed Tanous167e2372018-05-07 11:59:10 -0700720 sd_bus_message_unref(reply);
Brad Bishop62ece2b2016-07-25 09:00:51 -0400721
Ed Tanous167e2372018-05-07 11:59:10 -0700722 return r;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400723}