blob: 7b72a5ea04d420f0dc4bea27e821ce723c8c4c0f [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
George Liucf724032024-10-29 14:31:51 +08004#include "mapper.h"
5
Matt Spinler59cbf342018-09-24 09:46:00 -05006#include <errno.h>
Brad Bishop2afe7182016-08-13 14:08:17 -04007#include <stdio.h>
Matt Spinlercc6ee9c2018-09-19 13:23:13 -05008#include <stdlib.h>
Brad Bishop2afe7182016-08-13 14:08:17 -04009#include <systemd/sd-bus.h>
10#include <systemd/sd-event.h>
Matt Spinler55922022020-04-27 13:45:14 -050011#include <unistd.h>
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050012
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050013static void quit(int r, void* loop)
Brad Bishop2afe7182016-08-13 14:08:17 -040014{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050015 sd_event_exit((sd_event*)loop, r);
Brad Bishop2afe7182016-08-13 14:08:17 -040016}
17
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050018static int wait_main(int argc, char* argv[])
Brad Bishop2afe7182016-08-13 14:08:17 -040019{
Ed Tanous167e2372018-05-07 11:59:10 -070020 int r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050021 sd_bus* conn = NULL;
22 sd_event* loop = NULL;
23 mapper_async_wait* wait = NULL;
Matt Spinler55922022020-04-27 13:45:14 -050024 size_t attempts = 0;
Patrick Williamsaf3d7972022-04-08 11:10:40 -050025 const size_t max_attempts = 20;
Brad Bishop2afe7182016-08-13 14:08:17 -040026
Ed Tanous167e2372018-05-07 11:59:10 -070027 if (argc < 3)
28 {
29 fprintf(stderr, "Usage: %s wait OBJECTPATH...\n", argv[0]);
30 exit(EXIT_FAILURE);
31 }
Brad Bishop2afe7182016-08-13 14:08:17 -040032
Matt Spinler55922022020-04-27 13:45:14 -050033 /* Mapper waits are typically run early in the boot process, and in some
34 * cases the CPU and/or object manager daemon are so busy that the
35 * GetObject call may fail with a timeout and cause the event loop to exit.
36 * If this happens, retry a few times. Don't retry on other failures.
37 */
38 while (1)
Ed Tanous167e2372018-05-07 11:59:10 -070039 {
Matt Spinler55922022020-04-27 13:45:14 -050040 attempts++;
Brad Bishop2afe7182016-08-13 14:08:17 -040041
Brad Bishopf15b06c2021-08-02 22:27:39 -040042 r = sd_bus_default(&conn);
Matt Spinler55922022020-04-27 13:45:14 -050043 if (r < 0)
44 {
45 fprintf(stderr, "Error connecting to system bus: %s\n",
46 strerror(-r));
47 goto finish;
48 }
Brad Bishop2afe7182016-08-13 14:08:17 -040049
Matt Spinler55922022020-04-27 13:45:14 -050050 r = sd_event_default(&loop);
51 if (r < 0)
52 {
53 fprintf(stderr, "Error obtaining event loop: %s\n", strerror(-r));
Brad Bishop2afe7182016-08-13 14:08:17 -040054
Matt Spinler55922022020-04-27 13:45:14 -050055 goto finish;
56 }
Brad Bishop2afe7182016-08-13 14:08:17 -040057
Matt Spinler55922022020-04-27 13:45:14 -050058 r = sd_bus_attach_event(conn, loop, SD_EVENT_PRIORITY_NORMAL);
59 if (r < 0)
60 {
61 fprintf(stderr,
62 "Failed to attach system "
63 "bus to event loop: %s\n",
64 strerror(-r));
65 goto finish;
66 }
Brad Bishop2afe7182016-08-13 14:08:17 -040067
Matt Spinler55922022020-04-27 13:45:14 -050068 r = mapper_wait_async(conn, loop, argv + 2, quit, loop, &wait);
69 if (r < 0)
70 {
71 fprintf(stderr, "Error configuring waitlist: %s\n", strerror(-r));
72 goto finish;
73 }
74
75 r = sd_event_loop(loop);
76 if (r < 0)
77 {
78 fprintf(stderr, "Event loop exited: %s\n", strerror(-r));
79
William A. Kennington III551fafb2020-05-08 02:43:01 -070080 if (-r == ETIMEDOUT || -r == EHOSTUNREACH)
Matt Spinler55922022020-04-27 13:45:14 -050081 {
82 if (attempts <= max_attempts)
83 {
Patrick Williamsaf3d7972022-04-08 11:10:40 -050084 fprintf(stderr, "Retrying in 1s\n");
85 sleep(1);
Matt Spinler55922022020-04-27 13:45:14 -050086 sd_event_unref(loop);
87 sd_bus_unref(conn);
88 continue;
89 }
90 else
91 {
92 fprintf(stderr, "Giving up\n");
93 }
94 }
95 else
96 {
97 goto finish;
98 }
99 }
100
101 break;
Ed Tanous167e2372018-05-07 11:59:10 -0700102 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400103
104finish:
Ed Tanous167e2372018-05-07 11:59:10 -0700105 exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
Brad Bishop2afe7182016-08-13 14:08:17 -0400106}
107
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500108static int subtree_main(int argc, char* argv[])
Adriana Kobylak04d7c7d2017-05-04 14:06:18 -0500109{
Ed Tanous167e2372018-05-07 11:59:10 -0700110 int r = 0;
111 int op = 0;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500112 static const char* token = ":";
113 char* tmp = NULL;
114 char* namespace = NULL;
115 char* interface = NULL;
116 sd_bus* conn = NULL;
117 sd_event* loop = NULL;
118 mapper_async_subtree* subtree = NULL;
Adriana Kobylak04d7c7d2017-05-04 14:06:18 -0500119
Ed Tanous167e2372018-05-07 11:59:10 -0700120 if (argc != 3)
121 {
122 fprintf(stderr,
123 "Usage: %s subtree-remove "
124 "NAMESPACE%sINTERFACE\n",
125 argv[0], token);
126 exit(EXIT_FAILURE);
127 }
Adriana Kobylak6a8688f2017-05-05 11:32:17 -0500128
Ed Tanous167e2372018-05-07 11:59:10 -0700129 op = MAPPER_OP_REMOVE;
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500130
Ed Tanous167e2372018-05-07 11:59:10 -0700131 namespace = strtok_r(argv[2], token, &tmp);
132 interface = strtok_r(NULL, token, &tmp);
133 if ((namespace == NULL) || (interface == NULL))
134 {
135 fprintf(stderr, "Token '%s' was not found in '%s'\n", token, argv[2]);
136 exit(EXIT_FAILURE);
137 }
Adriana Kobylak04d7c7d2017-05-04 14:06:18 -0500138
Brad Bishopf15b06c2021-08-02 22:27:39 -0400139 r = sd_bus_default(&conn);
Ed Tanous167e2372018-05-07 11:59:10 -0700140 if (r < 0)
141 {
142 fprintf(stderr, "Error connecting to system bus: %s\n", strerror(-r));
143 goto finish;
144 }
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500145
Ed Tanous167e2372018-05-07 11:59:10 -0700146 r = sd_event_default(&loop);
147 if (r < 0)
148 {
149 fprintf(stderr, "Error obtaining event loop: %s\n", strerror(-r));
150 goto finish;
151 }
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500152
Ed Tanous167e2372018-05-07 11:59:10 -0700153 r = sd_bus_attach_event(conn, loop, SD_EVENT_PRIORITY_NORMAL);
154 if (r < 0)
155 {
156 fprintf(stderr, "Failed to attach system bus to event loop: %s\n",
157 strerror(-r));
158 goto finish;
159 }
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500160
Ed Tanous167e2372018-05-07 11:59:10 -0700161 r = mapper_subtree_async(conn, loop, namespace, interface, quit, loop,
162 &subtree, op);
163 if (r < 0)
164 {
165 fprintf(stderr, "Error configuring subtree list: %s\n", strerror(-r));
166 goto finish;
167 }
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500168
Ed Tanous167e2372018-05-07 11:59:10 -0700169 r = sd_event_loop(loop);
170 if (r < 0)
171 {
Matt Spinler59cbf342018-09-24 09:46:00 -0500172 /* If this function has been called after the interface in */
173 /* question has already been removed, then GetSubTree will */
174 /* fail and it will show up here. Treat as success instead. */
175 if (r == -ENXIO)
176 {
177 r = 0;
178 }
179 else
180 {
181 fprintf(stderr, "Error starting event loop: %d(%s)\n", r,
182 strerror(-r));
183 goto finish;
184 }
Ed Tanous167e2372018-05-07 11:59:10 -0700185 }
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500186
187finish:
Ed Tanous167e2372018-05-07 11:59:10 -0700188 exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
Adriana Kobylak04d7c7d2017-05-04 14:06:18 -0500189}
190
Andrew Geissler981f2662017-03-03 15:58:23 -0600191/* print out the distinct dbus service name for the input dbus path */
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500192static int get_service_main(int argc, char* argv[])
Andrew Geissler981f2662017-03-03 15:58:23 -0600193{
Ed Tanous167e2372018-05-07 11:59:10 -0700194 int r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500195 sd_bus* conn = NULL;
196 char* service = NULL;
Andrew Geissler981f2662017-03-03 15:58:23 -0600197
Ed Tanous167e2372018-05-07 11:59:10 -0700198 if (argc != 3)
199 {
200 fprintf(stderr, "Usage: %s get-service OBJECTPATH\n", argv[0]);
201 exit(EXIT_FAILURE);
202 }
Andrew Geissler981f2662017-03-03 15:58:23 -0600203
Brad Bishopf15b06c2021-08-02 22:27:39 -0400204 r = sd_bus_default(&conn);
Ed Tanous167e2372018-05-07 11:59:10 -0700205 if (r < 0)
206 {
207 fprintf(stderr, "Error connecting to system bus: %s\n", strerror(-r));
208 goto finish;
209 }
Andrew Geissler981f2662017-03-03 15:58:23 -0600210
Ed Tanous167e2372018-05-07 11:59:10 -0700211 r = mapper_get_service(conn, argv[2], &service);
212 if (r < 0)
213 {
214 fprintf(stderr, "Error finding '%s' service: %s\n", argv[2],
215 strerror(-r));
216 goto finish;
217 }
Andrew Geissler981f2662017-03-03 15:58:23 -0600218
Ed Tanous167e2372018-05-07 11:59:10 -0700219 printf("%s\n", service);
Andrew Geissler981f2662017-03-03 15:58:23 -0600220
221finish:
Ed Tanous167e2372018-05-07 11:59:10 -0700222 exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
Andrew Geissler981f2662017-03-03 15:58:23 -0600223}
224
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500225int main(int argc, char* argv[])
Brad Bishop2afe7182016-08-13 14:08:17 -0400226{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500227 static const char* usage =
Ed Tanous167e2372018-05-07 11:59:10 -0700228 "Usage: %s {COMMAND} ...\n"
229 "\nCOMMANDS:\n"
Ed Tanous167e2372018-05-07 11:59:10 -0700230 " wait wait for the specified objects to appear on the "
231 "DBus\n"
232 " subtree-remove\n"
233 " wait until the specified interface is not present\n"
234 " in any of the subtrees of the specified namespace\n"
235 " get-service return the service identifier for input path\n";
Brad Bishop2afe7182016-08-13 14:08:17 -0400236
Ed Tanous167e2372018-05-07 11:59:10 -0700237 if (argc < 2)
238 {
239 fprintf(stderr, usage, argv[0]);
240 exit(EXIT_FAILURE);
241 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400242
Ed Tanous167e2372018-05-07 11:59:10 -0700243 if (!strcmp(argv[1], "wait"))
George Liucf724032024-10-29 14:31:51 +0800244 {
Ed Tanous167e2372018-05-07 11:59:10 -0700245 wait_main(argc, argv);
George Liucf724032024-10-29 14:31:51 +0800246 }
247
Ed Tanous167e2372018-05-07 11:59:10 -0700248 if (!strcmp(argv[1], "subtree-remove"))
George Liucf724032024-10-29 14:31:51 +0800249 {
Ed Tanous167e2372018-05-07 11:59:10 -0700250 subtree_main(argc, argv);
George Liucf724032024-10-29 14:31:51 +0800251 }
252
Ed Tanous167e2372018-05-07 11:59:10 -0700253 if (!strcmp(argv[1], "get-service"))
George Liucf724032024-10-29 14:31:51 +0800254 {
Ed Tanous167e2372018-05-07 11:59:10 -0700255 get_service_main(argc, argv);
George Liucf724032024-10-29 14:31:51 +0800256 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400257
Ed Tanous167e2372018-05-07 11:59:10 -0700258 fprintf(stderr, usage, argv[0]);
259 exit(EXIT_FAILURE);
Brad Bishop2afe7182016-08-13 14:08:17 -0400260}