blob: 485a507128f1aa10cd76288cbe31a853e6078120 [file] [log] [blame]
Brad Bishop2afe7182016-08-13 14:08:17 -04001/**
Andrew Geissler981f2662017-03-03 15:58:23 -06002 * Copyright 2016 IBM Corporation
Brad Bishop2afe7182016-08-13 14:08:17 -04003 *
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 */
George Liucf724032024-10-29 14:31:51 +080016#include "mapper.h"
17
Matt Spinler59cbf342018-09-24 09:46:00 -050018#include <errno.h>
Brad Bishop2afe7182016-08-13 14:08:17 -040019#include <stdio.h>
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050020#include <stdlib.h>
Brad Bishop2afe7182016-08-13 14:08:17 -040021#include <systemd/sd-bus.h>
22#include <systemd/sd-event.h>
Matt Spinler55922022020-04-27 13:45:14 -050023#include <unistd.h>
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050024
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050025static void quit(int r, void* loop)
Brad Bishop2afe7182016-08-13 14:08:17 -040026{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050027 sd_event_exit((sd_event*)loop, r);
Brad Bishop2afe7182016-08-13 14:08:17 -040028}
29
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050030static int wait_main(int argc, char* argv[])
Brad Bishop2afe7182016-08-13 14:08:17 -040031{
Ed Tanous167e2372018-05-07 11:59:10 -070032 int r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050033 sd_bus* conn = NULL;
34 sd_event* loop = NULL;
35 mapper_async_wait* wait = NULL;
Matt Spinler55922022020-04-27 13:45:14 -050036 size_t attempts = 0;
Patrick Williamsaf3d7972022-04-08 11:10:40 -050037 const size_t max_attempts = 20;
Brad Bishop2afe7182016-08-13 14:08:17 -040038
Ed Tanous167e2372018-05-07 11:59:10 -070039 if (argc < 3)
40 {
41 fprintf(stderr, "Usage: %s wait OBJECTPATH...\n", argv[0]);
42 exit(EXIT_FAILURE);
43 }
Brad Bishop2afe7182016-08-13 14:08:17 -040044
Matt Spinler55922022020-04-27 13:45:14 -050045 /* Mapper waits are typically run early in the boot process, and in some
46 * cases the CPU and/or object manager daemon are so busy that the
47 * GetObject call may fail with a timeout and cause the event loop to exit.
48 * If this happens, retry a few times. Don't retry on other failures.
49 */
50 while (1)
Ed Tanous167e2372018-05-07 11:59:10 -070051 {
Matt Spinler55922022020-04-27 13:45:14 -050052 attempts++;
Brad Bishop2afe7182016-08-13 14:08:17 -040053
Brad Bishopf15b06c2021-08-02 22:27:39 -040054 r = sd_bus_default(&conn);
Matt Spinler55922022020-04-27 13:45:14 -050055 if (r < 0)
56 {
57 fprintf(stderr, "Error connecting to system bus: %s\n",
58 strerror(-r));
59 goto finish;
60 }
Brad Bishop2afe7182016-08-13 14:08:17 -040061
Matt Spinler55922022020-04-27 13:45:14 -050062 r = sd_event_default(&loop);
63 if (r < 0)
64 {
65 fprintf(stderr, "Error obtaining event loop: %s\n", strerror(-r));
Brad Bishop2afe7182016-08-13 14:08:17 -040066
Matt Spinler55922022020-04-27 13:45:14 -050067 goto finish;
68 }
Brad Bishop2afe7182016-08-13 14:08:17 -040069
Matt Spinler55922022020-04-27 13:45:14 -050070 r = sd_bus_attach_event(conn, loop, SD_EVENT_PRIORITY_NORMAL);
71 if (r < 0)
72 {
73 fprintf(stderr,
74 "Failed to attach system "
75 "bus to event loop: %s\n",
76 strerror(-r));
77 goto finish;
78 }
Brad Bishop2afe7182016-08-13 14:08:17 -040079
Matt Spinler55922022020-04-27 13:45:14 -050080 r = mapper_wait_async(conn, loop, argv + 2, quit, loop, &wait);
81 if (r < 0)
82 {
83 fprintf(stderr, "Error configuring waitlist: %s\n", strerror(-r));
84 goto finish;
85 }
86
87 r = sd_event_loop(loop);
88 if (r < 0)
89 {
90 fprintf(stderr, "Event loop exited: %s\n", strerror(-r));
91
William A. Kennington III551fafb2020-05-08 02:43:01 -070092 if (-r == ETIMEDOUT || -r == EHOSTUNREACH)
Matt Spinler55922022020-04-27 13:45:14 -050093 {
94 if (attempts <= max_attempts)
95 {
Patrick Williamsaf3d7972022-04-08 11:10:40 -050096 fprintf(stderr, "Retrying in 1s\n");
97 sleep(1);
Matt Spinler55922022020-04-27 13:45:14 -050098 sd_event_unref(loop);
99 sd_bus_unref(conn);
100 continue;
101 }
102 else
103 {
104 fprintf(stderr, "Giving up\n");
105 }
106 }
107 else
108 {
109 goto finish;
110 }
111 }
112
113 break;
Ed Tanous167e2372018-05-07 11:59:10 -0700114 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400115
116finish:
Ed Tanous167e2372018-05-07 11:59:10 -0700117 exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
Brad Bishop2afe7182016-08-13 14:08:17 -0400118}
119
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500120static int subtree_main(int argc, char* argv[])
Adriana Kobylak04d7c7d2017-05-04 14:06:18 -0500121{
Ed Tanous167e2372018-05-07 11:59:10 -0700122 int r = 0;
123 int op = 0;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500124 static const char* token = ":";
125 char* tmp = NULL;
126 char* namespace = NULL;
127 char* interface = NULL;
128 sd_bus* conn = NULL;
129 sd_event* loop = NULL;
130 mapper_async_subtree* subtree = NULL;
Adriana Kobylak04d7c7d2017-05-04 14:06:18 -0500131
Ed Tanous167e2372018-05-07 11:59:10 -0700132 if (argc != 3)
133 {
134 fprintf(stderr,
135 "Usage: %s subtree-remove "
136 "NAMESPACE%sINTERFACE\n",
137 argv[0], token);
138 exit(EXIT_FAILURE);
139 }
Adriana Kobylak6a8688f2017-05-05 11:32:17 -0500140
Ed Tanous167e2372018-05-07 11:59:10 -0700141 op = MAPPER_OP_REMOVE;
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500142
Ed Tanous167e2372018-05-07 11:59:10 -0700143 namespace = strtok_r(argv[2], token, &tmp);
144 interface = strtok_r(NULL, token, &tmp);
145 if ((namespace == NULL) || (interface == NULL))
146 {
147 fprintf(stderr, "Token '%s' was not found in '%s'\n", token, argv[2]);
148 exit(EXIT_FAILURE);
149 }
Adriana Kobylak04d7c7d2017-05-04 14:06:18 -0500150
Brad Bishopf15b06c2021-08-02 22:27:39 -0400151 r = sd_bus_default(&conn);
Ed Tanous167e2372018-05-07 11:59:10 -0700152 if (r < 0)
153 {
154 fprintf(stderr, "Error connecting to system bus: %s\n", strerror(-r));
155 goto finish;
156 }
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500157
Ed Tanous167e2372018-05-07 11:59:10 -0700158 r = sd_event_default(&loop);
159 if (r < 0)
160 {
161 fprintf(stderr, "Error obtaining event loop: %s\n", strerror(-r));
162 goto finish;
163 }
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500164
Ed Tanous167e2372018-05-07 11:59:10 -0700165 r = sd_bus_attach_event(conn, loop, SD_EVENT_PRIORITY_NORMAL);
166 if (r < 0)
167 {
168 fprintf(stderr, "Failed to attach system bus to event loop: %s\n",
169 strerror(-r));
170 goto finish;
171 }
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500172
Ed Tanous167e2372018-05-07 11:59:10 -0700173 r = mapper_subtree_async(conn, loop, namespace, interface, quit, loop,
174 &subtree, op);
175 if (r < 0)
176 {
177 fprintf(stderr, "Error configuring subtree list: %s\n", strerror(-r));
178 goto finish;
179 }
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500180
Ed Tanous167e2372018-05-07 11:59:10 -0700181 r = sd_event_loop(loop);
182 if (r < 0)
183 {
Matt Spinler59cbf342018-09-24 09:46:00 -0500184 /* If this function has been called after the interface in */
185 /* question has already been removed, then GetSubTree will */
186 /* fail and it will show up here. Treat as success instead. */
187 if (r == -ENXIO)
188 {
189 r = 0;
190 }
191 else
192 {
193 fprintf(stderr, "Error starting event loop: %d(%s)\n", r,
194 strerror(-r));
195 goto finish;
196 }
Ed Tanous167e2372018-05-07 11:59:10 -0700197 }
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500198
199finish:
Ed Tanous167e2372018-05-07 11:59:10 -0700200 exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
Adriana Kobylak04d7c7d2017-05-04 14:06:18 -0500201}
202
Andrew Geissler981f2662017-03-03 15:58:23 -0600203/* print out the distinct dbus service name for the input dbus path */
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500204static int get_service_main(int argc, char* argv[])
Andrew Geissler981f2662017-03-03 15:58:23 -0600205{
Ed Tanous167e2372018-05-07 11:59:10 -0700206 int r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500207 sd_bus* conn = NULL;
208 char* service = NULL;
Andrew Geissler981f2662017-03-03 15:58:23 -0600209
Ed Tanous167e2372018-05-07 11:59:10 -0700210 if (argc != 3)
211 {
212 fprintf(stderr, "Usage: %s get-service OBJECTPATH\n", argv[0]);
213 exit(EXIT_FAILURE);
214 }
Andrew Geissler981f2662017-03-03 15:58:23 -0600215
Brad Bishopf15b06c2021-08-02 22:27:39 -0400216 r = sd_bus_default(&conn);
Ed Tanous167e2372018-05-07 11:59:10 -0700217 if (r < 0)
218 {
219 fprintf(stderr, "Error connecting to system bus: %s\n", strerror(-r));
220 goto finish;
221 }
Andrew Geissler981f2662017-03-03 15:58:23 -0600222
Ed Tanous167e2372018-05-07 11:59:10 -0700223 r = mapper_get_service(conn, argv[2], &service);
224 if (r < 0)
225 {
226 fprintf(stderr, "Error finding '%s' service: %s\n", argv[2],
227 strerror(-r));
228 goto finish;
229 }
Andrew Geissler981f2662017-03-03 15:58:23 -0600230
Ed Tanous167e2372018-05-07 11:59:10 -0700231 printf("%s\n", service);
Andrew Geissler981f2662017-03-03 15:58:23 -0600232
233finish:
Ed Tanous167e2372018-05-07 11:59:10 -0700234 exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
Andrew Geissler981f2662017-03-03 15:58:23 -0600235}
236
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500237int main(int argc, char* argv[])
Brad Bishop2afe7182016-08-13 14:08:17 -0400238{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500239 static const char* usage =
Ed Tanous167e2372018-05-07 11:59:10 -0700240 "Usage: %s {COMMAND} ...\n"
241 "\nCOMMANDS:\n"
Ed Tanous167e2372018-05-07 11:59:10 -0700242 " wait wait for the specified objects to appear on the "
243 "DBus\n"
244 " subtree-remove\n"
245 " wait until the specified interface is not present\n"
246 " in any of the subtrees of the specified namespace\n"
247 " get-service return the service identifier for input path\n";
Brad Bishop2afe7182016-08-13 14:08:17 -0400248
Ed Tanous167e2372018-05-07 11:59:10 -0700249 if (argc < 2)
250 {
251 fprintf(stderr, usage, argv[0]);
252 exit(EXIT_FAILURE);
253 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400254
Ed Tanous167e2372018-05-07 11:59:10 -0700255 if (!strcmp(argv[1], "wait"))
George Liucf724032024-10-29 14:31:51 +0800256 {
Ed Tanous167e2372018-05-07 11:59:10 -0700257 wait_main(argc, argv);
George Liucf724032024-10-29 14:31:51 +0800258 }
259
Ed Tanous167e2372018-05-07 11:59:10 -0700260 if (!strcmp(argv[1], "subtree-remove"))
George Liucf724032024-10-29 14:31:51 +0800261 {
Ed Tanous167e2372018-05-07 11:59:10 -0700262 subtree_main(argc, argv);
George Liucf724032024-10-29 14:31:51 +0800263 }
264
Ed Tanous167e2372018-05-07 11:59:10 -0700265 if (!strcmp(argv[1], "get-service"))
George Liucf724032024-10-29 14:31:51 +0800266 {
Ed Tanous167e2372018-05-07 11:59:10 -0700267 get_service_main(argc, argv);
George Liucf724032024-10-29 14:31:51 +0800268 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400269
Ed Tanous167e2372018-05-07 11:59:10 -0700270 fprintf(stderr, usage, argv[0]);
271 exit(EXIT_FAILURE);
Brad Bishop2afe7182016-08-13 14:08:17 -0400272}