blob: 34c053c5cf991e1b636c9d2f9332f166e919741a [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 */
Brad Bishop36eb1e52016-11-01 15:18:36 -040016#include "config.h"
Brad Bishop2afe7182016-08-13 14:08:17 -040017#include <stdlib.h>
Brad Bishop62ece2b2016-07-25 09:00:51 -040018#include <string.h>
Brad Bishop2afe7182016-08-13 14:08:17 -040019#include <stdio.h>
20#include <errno.h>
Brad Bishop3d468792016-09-20 15:39:38 -040021#include <unistd.h>
22#include <sys/timerfd.h>
Brad Bishop62ece2b2016-07-25 09:00:51 -040023#include <systemd/sd-bus.h>
Brad Bishop3d468792016-09-20 15:39:38 -040024#include <systemd/sd-event.h>
Brad Bishop62ece2b2016-07-25 09:00:51 -040025#include "mapper.h"
26
Brad Bishop829181d2017-02-24 09:49:14 -050027static const char *async_wait_introspection_match =
Brad Bishop2afe7182016-08-13 14:08:17 -040028 "type='signal',"
Brad Bishop829181d2017-02-24 09:49:14 -050029 "sender='xyz.openbmc_project.ObjectMapper',"
30 "interface='xyz.openbmc_project.ObjectMapper.Private',"
31 "member='IntrospectionComplete'";
Brad Bishop2afe7182016-08-13 14:08:17 -040032
33static const char *async_wait_interfaces_added_match =
34 "type='signal',"
35 "interface='org.freedesktop.DBus.ObjectManager',"
36 "member='InterfacesAdded'";
37
Adriana Kobylak78edbb62017-05-04 15:45:19 -050038static const char *interfaces_removed_match =
39 "type='signal',"
40 "interface='org.freedesktop.DBus.ObjectManager',"
41 "member='InterfacesRemoved'";
42
Brad Bishop3d468792016-09-20 15:39:38 -040043static const int mapper_busy_retries = 5;
44static const uint64_t mapper_busy_delay_interval_usec = 1000000;
45
Brad Bishop2afe7182016-08-13 14:08:17 -040046struct mapper_async_wait
47{
48 char **objs;
49 void (*callback)(int, void *);
50 void *userdata;
Brad Bishop3d468792016-09-20 15:39:38 -040051 sd_event *loop;
Brad Bishop2afe7182016-08-13 14:08:17 -040052 sd_bus *conn;
Brad Bishop829181d2017-02-24 09:49:14 -050053 sd_bus_slot *introspection_slot;
Brad Bishop2afe7182016-08-13 14:08:17 -040054 sd_bus_slot *intf_slot;
55 int *status;
56 int count;
57 int finished;
58 int r;
59};
60
61struct async_wait_callback_data
62{
63 mapper_async_wait *wait;
64 const char *path;
Brad Bishop3d468792016-09-20 15:39:38 -040065 sd_event_source *event_source;
66 int retry;
Brad Bishop2afe7182016-08-13 14:08:17 -040067};
68
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -050069struct mapper_async_subtree
70{
Adriana Kobylak78edbb62017-05-04 15:45:19 -050071 char *namespace;
72 char *interface;
73 void (*callback)(int, void *);
74 void *userdata;
75 sd_event *loop;
76 sd_bus *conn;
77 sd_bus_slot *slot;
Adriana Kobylak025d7952017-05-08 13:30:45 -050078 sd_event_source *event_source;
Adriana Kobylakb2f26812017-05-08 13:58:02 -050079 int finished;
Adriana Kobylak78edbb62017-05-04 15:45:19 -050080 int op;
Adriana Kobylak025d7952017-05-08 13:30:45 -050081 int retry;
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -050082};
83
Brad Bishop829181d2017-02-24 09:49:14 -050084static int async_wait_match_introspection_complete(sd_bus_message *, void *,
Brad Bishop2afe7182016-08-13 14:08:17 -040085 sd_bus_error *);
86static int async_wait_check_done(mapper_async_wait *);
87static void async_wait_done(int r, mapper_async_wait *);
88static int async_wait_get_objects(mapper_async_wait *);
Brad Bishop3d468792016-09-20 15:39:38 -040089static int async_wait_getobject_callback(sd_bus_message *,
90 void *, sd_bus_error *);
Brad Bishop2afe7182016-08-13 14:08:17 -040091
Adriana Kobylak78edbb62017-05-04 15:45:19 -050092static int async_subtree_match_callback(sd_bus_message *, void *,
93 sd_bus_error *);
Adriana Kobylakb2f26812017-05-08 13:58:02 -050094static void async_subtree_done(int r, mapper_async_subtree *);
Adriana Kobylak025d7952017-05-08 13:30:45 -050095static int async_subtree_getpaths(mapper_async_subtree *);
96static int async_subtree_getpaths_callback(sd_bus_message *,
97 void *, sd_bus_error *);
Adriana Kobylak78edbb62017-05-04 15:45:19 -050098
Brad Bishop2afe7182016-08-13 14:08:17 -040099static int sarraylen(char *array[])
100{
101 int count = 0;
102 char **p = array;
103
104 while(*p != NULL) {
105 ++count;
106 ++p;
107 }
108
109 return count;
110}
111
112static void sarrayfree(char *array[])
113{
114 char **p = array;
115 while(*p != NULL) {
116 free(*p);
117 ++p;
118 }
119 free(array);
120}
121
122static char **sarraydup(char *array[])
123{
124 int count = sarraylen(array);
125 int i;
126 char **ret = NULL;
127
128 ret = malloc(sizeof(*ret) * count);
129 if(!ret)
130 return NULL;
131
132 for(i=0; i<count; ++i) {
133 ret[i] = strdup(array[i]);
134 if(!ret[i])
135 goto error;
136 }
137
138 return ret;
139
140error:
141 sarrayfree(ret);
142 return NULL;
143}
144
Brad Bishop3d468792016-09-20 15:39:38 -0400145static int async_wait_timeout_callback(sd_event_source *s,
146 uint64_t usec, void *userdata)
147{
148 int r;
149 struct async_wait_callback_data *data = userdata;
150 mapper_async_wait *wait = data->wait;
151
152 sd_event_source_unref(data->event_source);
153 r = sd_bus_call_method_async(
154 wait->conn,
155 NULL,
Brad Bishop36eb1e52016-11-01 15:18:36 -0400156 MAPPER_BUSNAME,
157 MAPPER_PATH,
158 MAPPER_INTERFACE,
Brad Bishop3d468792016-09-20 15:39:38 -0400159 "GetObject",
160 async_wait_getobject_callback,
161 data,
Brad Bishope1c7cf92016-11-02 10:20:35 -0400162 "sas",
163 data->path,
164 0,
165 NULL);
Brad Bishop3d468792016-09-20 15:39:38 -0400166 if(r < 0) {
167 async_wait_done(r, wait);
168 free(data);
169 }
170
171 return 0;
172}
173
Brad Bishop2afe7182016-08-13 14:08:17 -0400174static int async_wait_getobject_callback(sd_bus_message *m,
175 void *userdata,
176 sd_bus_error *e)
177{
Brad Bishop3d468792016-09-20 15:39:38 -0400178 int i, r;
Brad Bishop2afe7182016-08-13 14:08:17 -0400179 struct async_wait_callback_data *data = userdata;
180 mapper_async_wait *wait = data->wait;
Brad Bishop3d468792016-09-20 15:39:38 -0400181 uint64_t now;
Brad Bishop2afe7182016-08-13 14:08:17 -0400182
183 if(wait->finished)
Brad Bishop3d468792016-09-20 15:39:38 -0400184 goto exit;
185
186 r = sd_bus_message_get_errno(m);
Adriana Kobylakc7a7c452017-05-04 12:35:31 -0500187 if(r == ENOENT)
188 goto exit;
Brad Bishop8ccdaed2016-09-20 15:54:32 -0400189
Brad Bishop3d468792016-09-20 15:39:38 -0400190 if(r == EBUSY && data->retry < mapper_busy_retries) {
191 r = sd_event_now(wait->loop,
192 CLOCK_MONOTONIC,
193 &now);
194 if(r < 0) {
195 async_wait_done(r, wait);
196 goto exit;
197 }
198
199 ++data->retry;
200 r = sd_event_add_time(wait->loop,
201 &data->event_source,
202 CLOCK_MONOTONIC,
203 now + mapper_busy_delay_interval_usec,
204 0,
205 async_wait_timeout_callback,
206 data);
207 if(r < 0) {
208 async_wait_done(r, wait);
209 goto exit;
210 }
211
Brad Bishop2afe7182016-08-13 14:08:17 -0400212 return 0;
Brad Bishop3d468792016-09-20 15:39:38 -0400213 }
214
Brad Bishop8ccdaed2016-09-20 15:54:32 -0400215 if(r) {
Brad Bishop3d468792016-09-20 15:39:38 -0400216 async_wait_done(-r, wait);
217 goto exit;
218 }
219
Brad Bishop2afe7182016-08-13 14:08:17 -0400220 for(i=0; i<wait->count; ++i) {
221 if(!strcmp(data->path, wait->objs[i])) {
222 wait->status[i] = 1;
223 }
224 }
225
Brad Bishop2afe7182016-08-13 14:08:17 -0400226 if(async_wait_check_done(wait))
227 async_wait_done(0, wait);
228
Brad Bishop3d468792016-09-20 15:39:38 -0400229exit:
230 free(data);
Brad Bishop2afe7182016-08-13 14:08:17 -0400231 return 0;
232}
233
234static int async_wait_get_objects(mapper_async_wait *wait)
235{
236 int i, r;
237 struct async_wait_callback_data *data = NULL;
238
239 for(i=0; i<wait->count; ++i) {
240 if(wait->status[i])
241 continue;
242 data = malloc(sizeof(*data));
243 data->wait = wait;
244 data->path = wait->objs[i];
Brad Bishop3d468792016-09-20 15:39:38 -0400245 data->retry = 0;
246 data->event_source = NULL;
Brad Bishop2afe7182016-08-13 14:08:17 -0400247 r = sd_bus_call_method_async(
248 wait->conn,
249 NULL,
Brad Bishop36eb1e52016-11-01 15:18:36 -0400250 MAPPER_BUSNAME,
251 MAPPER_PATH,
252 MAPPER_INTERFACE,
Brad Bishop2afe7182016-08-13 14:08:17 -0400253 "GetObject",
254 async_wait_getobject_callback,
255 data,
Brad Bishope1c7cf92016-11-02 10:20:35 -0400256 "sas",
257 wait->objs[i],
258 0,
259 NULL);
Brad Bishop2afe7182016-08-13 14:08:17 -0400260 if(r < 0) {
261 free(data);
262 fprintf(stderr, "Error invoking method: %s\n",
263 strerror(-r));
264 return r;
265 }
266 }
267
268 return 0;
269}
270
Brad Bishop829181d2017-02-24 09:49:14 -0500271static int async_wait_match_introspection_complete(sd_bus_message *m, void *w,
Brad Bishop2afe7182016-08-13 14:08:17 -0400272 sd_bus_error *e)
273{
Brad Bishopa6797f82016-08-30 13:02:46 -0400274 int r;
Brad Bishop2afe7182016-08-13 14:08:17 -0400275
276 mapper_async_wait *wait = w;
277 if(wait->finished)
278 return 0;
279
280 r = async_wait_get_objects(wait);
281 if(r < 0)
282 async_wait_done(r, wait);
283
284 return 0;
285}
286
Brad Bishop2afe7182016-08-13 14:08:17 -0400287static void async_wait_done(int r, mapper_async_wait *w)
288{
289 if(w->finished)
290 return;
291
292 w->finished = 1;
Brad Bishop829181d2017-02-24 09:49:14 -0500293 sd_bus_slot_unref(w->introspection_slot);
Brad Bishop2afe7182016-08-13 14:08:17 -0400294 sd_bus_slot_unref(w->intf_slot);
295
296 if(w->callback)
297 w->callback(r, w->userdata);
298}
299
300static int async_wait_check_done(mapper_async_wait *w)
301{
302 int i;
303
304 if(w->finished)
305 return 1;
306
307 for(i=0; i<w->count; ++i)
308 if(!w->status[i])
309 return 0;
310
311 return 1;
312}
313
314void mapper_wait_async_free(mapper_async_wait *w)
315{
316 free(w->status);
317 sarrayfree(w->objs);
318 free(w);
319}
320
321int mapper_wait_async(sd_bus *conn,
Brad Bishop3d468792016-09-20 15:39:38 -0400322 sd_event *loop,
Brad Bishop2afe7182016-08-13 14:08:17 -0400323 char *objs[],
324 void (*callback)(int, void *),
325 void *userdata,
Adriana Kobylakc7a7c452017-05-04 12:35:31 -0500326 mapper_async_wait **w)
Brad Bishop2afe7182016-08-13 14:08:17 -0400327{
328 int r;
329 mapper_async_wait *wait = NULL;
330
331 wait = malloc(sizeof(*wait));
332 if(!wait)
333 return -ENOMEM;
334
335 memset(wait, 0, sizeof(*wait));
336 wait->conn = conn;
Brad Bishop3d468792016-09-20 15:39:38 -0400337 wait->loop = loop;
Brad Bishop2afe7182016-08-13 14:08:17 -0400338 wait->callback = callback;
339 wait->userdata = userdata;
340 wait->count = sarraylen(objs);
341 if(!wait->count)
342 return 0;
343
344 wait->objs = sarraydup(objs);
345 if(!wait->objs) {
346 r = -ENOMEM;
347 goto free_wait;
348 }
349
350 wait->status = malloc(sizeof(*wait->status) * wait->count);
351 if(!wait->status) {
352 r = -ENOMEM;
353 goto free_objs;
354 }
355 memset(wait->status, 0, sizeof(*wait->status) * wait->count);
356
Adriana Kobylakc7a7c452017-05-04 12:35:31 -0500357 r = sd_bus_add_match(conn,
358 &wait->introspection_slot,
359 async_wait_introspection_match,
360 async_wait_match_introspection_complete,
361 wait);
362 if(r < 0) {
363 fprintf(stderr, "Error adding match rule: %s\n",
364 strerror(-r));
365 goto free_status;
366 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400367
Adriana Kobylakc7a7c452017-05-04 12:35:31 -0500368 r = sd_bus_add_match(conn,
369 &wait->intf_slot,
370 async_wait_interfaces_added_match,
371 async_wait_match_introspection_complete,
372 wait);
373 if(r < 0) {
374 fprintf(stderr, "Error adding match rule: %s\n",
375 strerror(-r));
376 goto unref_name_slot;
Brad Bishop2afe7182016-08-13 14:08:17 -0400377 }
378
379 r = async_wait_get_objects(wait);
380 if(r < 0) {
381 fprintf(stderr, "Error calling method: %s\n",
382 strerror(-r));
383 goto unref_intf_slot;
384 }
385
386 *w = wait;
387
388 return 0;
389
390unref_intf_slot:
391 sd_bus_slot_unref(wait->intf_slot);
392unref_name_slot:
Brad Bishop829181d2017-02-24 09:49:14 -0500393 sd_bus_slot_unref(wait->introspection_slot);
Brad Bishop2afe7182016-08-13 14:08:17 -0400394free_status:
395 free(wait->status);
396free_objs:
397 sarrayfree(wait->objs);
398free_wait:
399 free(wait);
400
401 return r;
402}
403
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500404static int async_subtree_timeout_callback(sd_event_source *s,
405 uint64_t usec, void *userdata)
406{
407 int r;
408 struct mapper_async_subtree *subtree = userdata;
409
410 sd_event_source_unref(subtree->event_source);
411 r = sd_bus_call_method_async(
412 subtree->conn,
413 NULL,
414 MAPPER_BUSNAME,
415 MAPPER_PATH,
416 MAPPER_INTERFACE,
417 "GetSubTreePaths",
418 async_subtree_getpaths_callback,
419 subtree,
420 "sias",
421 subtree->namespace,
422 0, 1,
423 subtree->interface);
424 if(r < 0)
425 async_subtree_done(r, subtree);
426
427 return 0;
428}
429
Adriana Kobylak025d7952017-05-08 13:30:45 -0500430static int async_subtree_getpaths_callback(sd_bus_message *m,
431 void *userdata,
432 sd_bus_error *e)
433{
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500434 int r;
435 char *intf = NULL;
436 struct mapper_async_subtree *subtree = userdata;
437 uint64_t now;
438
439 if(subtree->finished)
440 goto exit;
441
442 r = sd_bus_message_get_errno(m);
443
444 if(r == ENOENT) {
445 if (subtree->op == MAPPER_OP_REMOVE)
446 r = 0;
447 else
448 goto exit;
449 }
450
451 if(r == EBUSY && subtree->retry < mapper_busy_retries) {
452 r = sd_event_now(subtree->loop,
453 CLOCK_MONOTONIC,
454 &now);
455 if(r < 0) {
456 async_subtree_done(r, subtree);
457 goto exit;
458 }
459
460 ++subtree->retry;
461 r = sd_event_add_time(subtree->loop,
462 &subtree->event_source,
463 CLOCK_MONOTONIC,
464 now + mapper_busy_delay_interval_usec,
465 0,
466 async_subtree_timeout_callback,
467 subtree);
468 if(r < 0) {
469 async_subtree_done(r, subtree);
470 goto exit;
471 }
472
473 return 0;
474 }
475
476 if(r) {
477 async_subtree_done(-r, subtree);
478 goto exit;
479 }
480
481 sd_bus_message_read(m, "as", 1, &intf);
482 if (subtree->op == MAPPER_OP_REMOVE) {
483 /* For remove, operation is complete when the interface is not present */
484 if (intf == NULL)
485 async_subtree_done(0, subtree);
486 }
487
488exit:
Adriana Kobylak025d7952017-05-08 13:30:45 -0500489 return 0;
490}
491
492static int async_subtree_getpaths(mapper_async_subtree *subtree)
493{
494 int r = 0;
495
496 subtree->retry = 0;
497 subtree->event_source = NULL;
498 r = sd_bus_call_method_async(
499 subtree->conn,
500 NULL,
501 MAPPER_BUSNAME,
502 MAPPER_PATH,
503 MAPPER_INTERFACE,
504 "GetSubTreePaths",
505 async_subtree_getpaths_callback,
506 subtree,
507 "sias",
508 subtree->namespace,
509 0, 1,
510 subtree->interface);
511 if (r < 0) {
512 fprintf(stderr, "Error invoking method: %s\n", strerror(-r));
513 return r;
514 }
515
516 return 0;
517}
518
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500519static int async_subtree_match_callback(sd_bus_message *m,
520 void *t,
521 sd_bus_error *e)
522{
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500523 int r;
524
525 mapper_async_subtree *subtree = t;
526 if(subtree->finished)
527 return 0;
528
529 r = async_subtree_getpaths(subtree);
530 if(r < 0)
531 async_subtree_done(r, subtree);
532
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500533 return 0;
534}
535
Adriana Kobylakb2f26812017-05-08 13:58:02 -0500536static void async_subtree_done(int r, mapper_async_subtree *t)
537{
538 if(t->finished)
539 return;
540
541 t->finished = 1;
542 sd_bus_slot_unref(t->slot);
543
544 if(t->callback)
545 t->callback(r, t->userdata);
546}
547
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500548int mapper_subtree_async(sd_bus *conn,
549 sd_event *loop,
550 char *namespace,
551 char *interface,
552 void (*callback)(int, void *),
553 void *userdata,
554 mapper_async_subtree **t,
555 int op)
556{
557 int r = 0;
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500558 mapper_async_subtree *subtree = NULL;
559
560 subtree = malloc(sizeof(*subtree));
561 if(!subtree)
562 return -ENOMEM;
563
564 memset(subtree, 0, sizeof(*subtree));
565 subtree->conn = conn;
566 subtree->loop = loop;
567 subtree->namespace = namespace;
568 subtree->interface = interface;
569 subtree->callback = callback;
570 subtree->userdata = userdata;
571 subtree->op = op;
572
573 if (subtree->op == MAPPER_OP_REMOVE) {
574 r = sd_bus_add_match(
575 conn,
576 &subtree->slot,
577 interfaces_removed_match,
578 async_subtree_match_callback,
579 subtree);
580 if(r < 0) {
581 fprintf(stderr, "Error adding match rule: %s\n",
582 strerror(-r));
583 goto unref_slot;
584 }
585 } else {
586 /* Operation not supported */
587 r = -EINVAL;
588 goto free_subtree;
589 }
590
Adriana Kobylak025d7952017-05-08 13:30:45 -0500591 r = async_subtree_getpaths(subtree);
592 if(r < 0) {
593 fprintf(stderr, "Error calling method: %s\n",
594 strerror(-r));
595 goto unref_slot;
596 }
597
Adriana Kobylak78edbb62017-05-04 15:45:19 -0500598 *t = subtree;
599
600 return 0;
601
602unref_slot:
603 sd_bus_slot_unref(subtree->slot);
604free_subtree:
605 free(subtree);
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500606
607 return r;
608}
609
Brad Bishop3d468792016-09-20 15:39:38 -0400610int mapper_get_object(sd_bus *conn, const char *obj, sd_bus_message **reply)
Brad Bishop62ece2b2016-07-25 09:00:51 -0400611{
612 sd_bus_error error = SD_BUS_ERROR_NULL;
Brad Bishop3d468792016-09-20 15:39:38 -0400613 sd_bus_message *request = NULL;
614 int r, retry = 0;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400615
616 r = sd_bus_message_new_method_call(
617 conn,
618 &request,
Brad Bishop36eb1e52016-11-01 15:18:36 -0400619 MAPPER_BUSNAME,
620 MAPPER_PATH,
621 MAPPER_INTERFACE,
Brad Bishop62ece2b2016-07-25 09:00:51 -0400622 "GetObject");
623 if (r < 0)
624 goto exit;
625
626 r = sd_bus_message_append(request, "s", obj);
627 if (r < 0)
628 goto exit;
Brad Bishope1c7cf92016-11-02 10:20:35 -0400629 r = sd_bus_message_append(request, "as", 0, NULL);
630 if (r < 0)
631 goto exit;
Brad Bishop62ece2b2016-07-25 09:00:51 -0400632
Brad Bishop3d468792016-09-20 15:39:38 -0400633 while(retry < mapper_busy_retries) {
634 sd_bus_error_free(&error);
635 r = sd_bus_call(conn, request, 0, &error, reply);
636 if (r < 0 && sd_bus_error_get_errno(&error) == EBUSY) {
637 ++retry;
638
639 if(retry != mapper_busy_retries)
640 usleep(mapper_busy_delay_interval_usec);
641 continue;
642 }
643 break;
644 }
645
646 if (r < 0)
647 goto exit;
648
649exit:
650 sd_bus_error_free(&error);
651 sd_bus_message_unref(request);
652
653 return r;
654}
655
656int mapper_get_service(sd_bus *conn, const char *obj, char **service)
657{
658 sd_bus_message *reply = NULL;
659 const char *tmp;
660 int r;
661
662 r = mapper_get_object(conn, obj, &reply);
Brad Bishop62ece2b2016-07-25 09:00:51 -0400663 if (r < 0)
664 goto exit;
665
666 r = sd_bus_message_enter_container(reply, 0, NULL);
667 if (r < 0)
668 goto exit;
669
670 r = sd_bus_message_enter_container(reply, 0, NULL);
671 if (r < 0)
672 goto exit;
673
674 r = sd_bus_message_read(reply, "s", &tmp);
675 if (r < 0)
676 goto exit;
677
678 *service = strdup(tmp);
679
680exit:
Brad Bishop62ece2b2016-07-25 09:00:51 -0400681 sd_bus_message_unref(reply);
682
683 return r;
684}