1SD_BUS_ADD_OBJECT(3) sd_bus_add_object SD_BUS_ADD_OBJECT(3)
2
3
4
6 sd_bus_add_object, sd_bus_add_fallback, sd_bus_add_object_vtable,
7 sd_bus_add_fallback_vtable, sd_bus_add_filter,
8 SD_BUS_VTABLE_CAPABILITY, SD_BUS_VTABLE_START, SD_BUS_VTABLE_END,
9 SD_BUS_METHOD_WITH_NAMES_OFFSET, SD_BUS_METHOD_WITH_NAMES,
10 SD_BUS_METHOD_WITH_OFFSET, SD_BUS_METHOD, SD_BUS_SIGNAL_WITH_NAMES,
11 SD_BUS_SIGNAL, SD_BUS_WRITABLE_PROPERTY, SD_BUS_PROPERTY, SD_BUS_PARAM
12 - Declare properties and methods for a D-Bus path
13
15 #include <systemd/sd-bus-vtable.h>
16
17
18 typedef int (*sd_bus_message_handler_t)(sd_bus_message *m,
19 void *userdata,
20 sd_bus_error *ret_error);
21
22 typedef int (*sd_bus_property_get_t)(sd_bus *bus, const char *path,
23 const char *interface,
24 const char *property,
25 sd_bus_message *reply,
26 void *userdata,
27 sd_bus_error *ret_error);
28
29 typedef int (*sd_bus_property_set_t)(sd_bus *bus, const char *path,
30 const char *interface,
31 const char *property,
32 sd_bus_message *value,
33 void *userdata,
34 sd_bus_error *ret_error);
35
36 typedef int (*sd_bus_object_find_t)(const char *path,
37 const char *interface,
38 void *userdata, void **ret_found,
39 sd_bus_error *ret_error);
40
41 int sd_bus_add_object(sd_bus *bus, sd_bus_slot **slot,
42 const char *path,
43 sd_bus_message_handler_t callback,
44 void *userdata);
45
46 int sd_bus_add_fallback(sd_bus *bus, sd_bus_slot **slot,
47 const char *path,
48 sd_bus_message_handler_t callback,
49 void *userdata);
50
51 int sd_bus_add_object_vtable(sd_bus *bus, sd_bus_slot **slot,
52 const char *path, const char *interface,
53 const sd_bus_vtable *vtable,
54 void *userdata);
55
56 int sd_bus_add_fallback_vtable(sd_bus *bus, sd_bus_slot **slot,
57 const char *prefix,
58 const char *interface,
59 const sd_bus_vtable *vtable,
60 sd_bus_object_find_t find,
61 void *userdata);
62
63 int sd_bus_add_filter(sd_bus *bus, sd_bus_slot **slot,
64 sd_bus_message_handler_t callback,
65 void *userdata);
66
67 SD_BUS_VTABLE_CAPABILITY(capability)
68
69 SD_BUS_VTABLE_START(flags)
70
71 SD_BUS_VTABLE_END
72
73 SD_BUS_METHOD_WITH_ARGS_OFFSET(member, args, result, handler, offset,
74 flags)
75
76 SD_BUS_METHOD_WITH_ARGS(member, args, result, handler, flags)
77
78 SD_BUS_METHOD_WITH_NAMES_OFFSET(member, signature, in_names, result,
79 out_names, handler, offset, flags)
80
81 SD_BUS_METHOD_WITH_NAMES(member, signature, in_names, result,
82 out_names, handler, flags)
83
84 SD_BUS_METHOD_WITH_OFFSET(member, signature, result, handler, offset,
85 flags)
86
87 SD_BUS_METHOD(member, signature, result, handler, flags)
88
89 SD_BUS_SIGNAL_WITH_ARGS(member, args, flags)
90
91 SD_BUS_SIGNAL_WITH_NAMES(member, signature, names, flags)
92
93 SD_BUS_SIGNAL(member, signature, flags)
94
95 SD_BUS_WRITABLE_PROPERTY(member, signature, get, set, offset, flags)
96
97 SD_BUS_PROPERTY(member, signature, get, offset, flags)
98
99 SD_BUS_PARAM(name)
100
101 SD_BUS_ARGS(...)
102
103 SD_BUS_RESULT(...)
104
105 SD_BUS_NO_ARGS
106
107 SD_BUS_NO_RESULT
108
110 sd_bus_add_object_vtable() is used to declare attributes for the object
111 path path connected to the bus connection bus under the interface
112 interface. The table vtable may contain property declarations using
113 SD_BUS_PROPERTY() or SD_BUS_WRITABLE_PROPERTY(), method declarations
114 using SD_BUS_METHOD(), SD_BUS_METHOD_WITH_NAMES(),
115 SD_BUS_METHOD_WITH_OFFSET(), or SD_BUS_METHOD_WITH_NAMES_OFFSET(), and
116 signal declarations using SD_BUS_SIGNAL_WITH_NAMES() or
117 SD_BUS_SIGNAL(), see below. The userdata parameter contains a pointer
118 that will be passed to various callback functions. It may be specified
119 as NULL if no value is necessary. An interface can have any number of
120 vtables attached to it.
121
122 sd_bus_add_fallback_vtable() is similar to sd_bus_add_object_vtable(),
123 but is used to register "fallback" attributes. When looking for an
124 attribute declaration, bus object paths registered with
125 sd_bus_add_object_vtable() are checked first. If no match is found, the
126 fallback vtables are checked for each prefix of the bus object path,
127 i.e. with the last slash-separated components successively removed.
128 This allows the vtable to be used for an arbitrary number of
129 dynamically created objects.
130
131 Parameter find is a function which is used to locate the target object
132 based on the bus object path path. It must return 1 and set the
133 ret_found output parameter if the object is found, return 0 if the
134 object was not found, and return a negative errno-style error code or
135 initialize the error structure ret_error on error. The pointer passed
136 in ret_found will be used as the userdata parameter for the callback
137 functions (offset by the offset offsets as specified in the vtable
138 entries).
139
140 sd_bus_add_object() attaches a callback directly to the object path
141 path. An object path can have any number of callbacks attached to it.
142 Each callback is prepended to the list of callbacks which are always
143 called in order. sd_bus_add_fallback() is similar to
144 sd_bus_add_object() but applies to fallback paths instead.
145
146 sd_bus_add_filter() installs a callback that is invoked for each
147 incoming D-Bus message. Filters can be used to handle logic common to
148 all messages received by a service (e.g. authentication or
149 authorization).
150
151 When a request is received, any associated callbacks are called
152 sequentially until a callback returns a non-zero integer. Return zero
153 from a callback to give other callbacks the chance to process the
154 request. Callbacks are called in the following order: first, global
155 callbacks installed with sd_bus_add_filter() are called. Second,
156 callbacks attached directly to the request object path are called,
157 followed by any D-Bus method callbacks attached to the request object
158 path, interface and member. Finally, the property callbacks attached to
159 the request object path, interface and member are called. If the final
160 callback returns zero, an error reply is sent back to the caller
161 indicating no matching object for the request was found.
162
163 Note that you can return a positive integer from a method callback
164 without immediately sending a reply. This informs sd-bus this callback
165 will take responsibility for replying to the request without forcing
166 the callback to produce a reply immediately. This allows a callback to
167 perform any number of asynchronous operations required to construct a
168 reply. However, if producing a reply takes too long, the method call
169 will time out at the caller. This is only available to methods and not
170 properties.
171
172 If a callback was invoked to handle a request that expects a reply and
173 the callback returns a negative value, the value is interpreted as a
174 negative errno-style error code and sent back to the caller as a D-Bus
175 error as if sd_bus_reply_method_errno(3) was called. Additionally, all
176 callbacks take a sd_bus_error output parameter that can be used to
177 provide more detailed error information. If ret_error is set when the
178 callback finishes, the corresponding D-Bus error is sent back to the
179 caller as if sd_bus_reply_method_error(3) was called. Any error stored
180 in ret_error takes priority over any negative values returned by the
181 same callback when determining which error to send back to the caller.
182 Use sd_bus_error_set(3) or one of its variants to set ret_error and
183 return a negative integer from a callback with a single function call.
184 To send an error reply after a callback has already finished, use
185 sd_bus_reply_method_errno(3) or one of its variants.
186
187 For all functions, a match slot is created internally. If the output
188 parameter slot is NULL, a "floating" slot object is created, see
189 sd_bus_slot_set_floating(3). Otherwise, a pointer to the slot object is
190 returned. In that case, the reference to the slot object should be
191 dropped when the vtable is not needed anymore, see
192 sd_bus_slot_unref(3).
193
194 The sd_bus_vtable array
195 The array consists of the structures of type sd_bus_vtable, but it
196 should never be filled in manually, but through one of the following
197 macros:
198
199 SD_BUS_VTABLE_START(flags), SD_BUS_VTABLE_END
200 Those must always be the first and last element. The flags
201 parameter can be used to set attributes that apply to the whole
202 array; see the "Flags" section below.
203
204 SD_BUS_METHOD_WITH_ARGS_OFFSET(), SD_BUS_METHOD_WITH_ARGS()
205 Declare a D-Bus method with the name member, arguments args and
206 result result. args expects a sequence of argument type/name pairs
207 wrapped in the SD_BUS_ARGS() macro. The elements at even indices in
208 this list describe the types of the method's arguments. The
209 method's parameter signature is the concatenation of all the string
210 literals at even indices in args. If a method has no parameters,
211 pass SD_BUS_NO_ARGS to args. The elements at uneven indices
212 describe the names of the method's arguments. result expects a
213 sequence of type/name pairs wrapped in the SD_BUS_RESULT() macro in
214 the same format as SD_BUS_ARGS(). The method's result signature is
215 the concatenation of all the string literals at even indices in
216 result. If a method has no result, pass SD_BUS_NO_RESULT to result.
217 Note that argument types are expected to be quoted string literals
218 and argument names are expected to be unquoted string literals. See
219 below for a complete example.
220
221 The handler function handler must be of type
222 sd_bus_message_handler_t. It will be called to handle the incoming
223 messages that call this method. It receives a pointer that is the
224 userdata parameter passed to the registration function offset by
225 offset bytes. This may be used to pass pointers to different fields
226 in the same data structure to different methods in the same vtable.
227 To send a reply from handler, call sd_bus_reply_method_return(3)
228 with the message the callback was invoked with. Parameter flags is
229 a combination of flags, see below.
230
231 SD_BUS_METHOD_WITH_ARGS() is a shorthand for calling
232 SD_BUS_METHOD_WITH_ARGS_OFFSET() with an offset of zero.
233
234 SD_BUS_METHOD_WITH_NAMES_OFFSET(), SD_BUS_METHOD_WITH_NAMES(),
235 SD_BUS_METHOD_WITH_OFFSET(), SD_BUS_METHOD()
236 Declare a D-Bus method with the name member, parameter signature
237 signature, result signature result. Parameters in_names and
238 out_names specify the argument names of the input and output
239 arguments in the function signature. in_names and out_names should
240 be created using the SD_BUS_PARAM() macro, see below. In all other
241 regards, this macro behaves exactly the same as
242 SD_BUS_METHOD_WITH_ARGS_OFFSET().
243
244 SD_BUS_METHOD_WITH_NAMES(), SD_BUS_METHOD_WITH_OFFSET(), and
245 SD_BUS_METHOD() are variants which specify zero offset (userdata
246 parameter is passed with no change), leave the names unset (i.e. no
247 parameter names), or both.
248
249 Prefer using SD_BUS_METHOD_WITH_ARGS_OFFSET() and
250 SD_BUS_METHOD_WITH_ARGS() over these macros as they allow
251 specifying argument types and names next to each other which is
252 less error-prone than first specifying all argument types followed
253 by specifying all argument names.
254
255 SD_BUS_SIGNAL_WITH_ARGS()
256 Declare a D-Bus signal with the name member and arguments args.
257 args expects a sequence of argument type/name pairs wrapped in the
258 SD_BUS_ARGS() macro. The elements at even indices in this list
259 describe the types of the signal's arguments. The signal's
260 parameter signature is the concatenation of all the string literals
261 at even indices in args. If a signal has no parameters, pass
262 SD_BUS_NO_ARGS to args. The elements at uneven indices describe the
263 names of the signal's arguments. Parameter flags is a combination
264 of flags. See below for a complete example.
265
266 SD_BUS_SIGNAL_WITH_NAMES(), SD_BUS_SIGNAL()
267 Declare a D-Bus signal with the name member, parameter signature
268 signature, and argument names names. names should be created using
269 the SD_BUS_PARAM() macro, see below. Parameter flags is a
270 combination of flags, see below.
271
272 SD_BUS_SIGNAL() is equivalent to SD_BUS_SIGNAL_WITH_NAMES() with
273 the names parameter unset (i.e. no parameter names).
274
275 Prefer using SD_BUS_SIGNAL_WITH_ARGS() over these macros as it
276 allows specifying argument types and names next to each other which
277 is less error-prone than first specifying all argument types
278 followed by specifying all argument names.
279
280 SD_BUS_WRITABLE_PROPERTY(), SD_BUS_PROPERTY()
281 Declare a D-Bus property with the name member and value signature
282 signature. Parameters get and set are the getter and setter
283 methods. They are called with a pointer that is the userdata
284 parameter passed to the registration function offset by offset
285 bytes. This may be used pass pointers to different fields in the
286 same data structure to different setters and getters in the same
287 vtable. Parameter flags is a combination of flags, see below.
288
289 The setter and getter methods may be omitted (specified as NULL),
290 if the property is one of the basic types or "as" in case of
291 read-only properties. In those cases, the userdata and offset
292 parameters must together point to a valid variable of the
293 corresponding type. A default setter and getter will be provided,
294 which simply copy the argument between this variable and the
295 message.
296
297 SD_BUS_PROPERTY() is used to define a read-only property.
298
299 SD_BUS_PARAM()
300 Parameter names should be wrapped in this macro, see the example
301 below.
302
303 Flags
304 The flags parameter is used to specify a combination of D-Bus
305 annotations[1].
306
307 SD_BUS_VTABLE_DEPRECATED
308 Mark this vtable entry as deprecated using the
309 org.freedesktop.DBus.Deprecated annotation in introspection data.
310 If specified for SD_BUS_VTABLE_START(), the annotation is applied
311 to the enclosing interface.
312
313 SD_BUS_VTABLE_HIDDEN
314 Make this vtable entry hidden. It will not be shown in
315 introspection data. If specified for SD_BUS_VTABLE_START(), all
316 entries in the array are hidden.
317
318 SD_BUS_VTABLE_METHOD_NO_REPLY
319 Mark this vtable entry as a method that will not return a reply
320 using the org.freedesktop.DBus.Method.NoReply annotation in
321 introspection data.
322
323 SD_BUS_VTABLE_PROPERTY_CONST, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE,
324 SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION
325 Those three flags correspond to different values of the
326 org.freedesktop.DBus.Property.EmitsChangedSignal annotation, which
327 specifies whether the
328 org.freedesktop.DBus.Properties.PropertiesChanged signal is emitted
329 whenever the property changes. SD_BUS_VTABLE_PROPERTY_CONST
330 corresponds to const and means that the property never changes
331 during the lifetime of the object it belongs to, so no signal needs
332 to be emitted. SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE corresponds to
333 true and means that the signal is emitted.
334 SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION corresponds to
335 invalidates and means that the signal is emitted, but the value is
336 not included in the signal.
337
338 SD_BUS_VTABLE_PROPERTY_EXPLICIT
339 Mark this vtable property entry as requiring explicit request to
340 for the value to be shown (generally because the value is large or
341 slow to calculate). This entry cannot be combined with
342 SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE, and will not be shown in
343 property listings by default (e.g. busctl introspect). This
344 corresponds to the org.freedesktop.systemd1.Explicit annotation in
345 introspection data.
346
347 SD_BUS_VTABLE_SENSITIVE
348 Mark this vtable method entry as processing sensitive data. When
349 set, incoming method call messages and their outgoing reply
350 messages are marked as sensitive using sd_bus_message_sensitive(3),
351 so that they are erased from memory when freed.
352
353 SD_BUS_VTABLE_ABSOLUTE_OFFSET
354 Mark this vtable method or property entry so that the user data
355 pointer passed to its associated handler functions is determined
356 slightly differently: instead of adding the offset parameter of the
357 entry to the user data pointer specified during vtable
358 registration, the offset is passed directly, converted to a
359 pointer, without taking the user data pointer specified during
360 vtable registration into account.
361
362 SD_BUS_VTABLE_CAPABILITY(capability)
363 Access to this vtable entry will be allowed if the calling process
364 has the capability capability, as described in
365 sd_bus_query_sender_privilege(3). If used for
366 SD_BUS_VTABLE_START(), provides a default for all entries in the
367 array. If not specified, either for an individual entry or the
368 whole array, CAP_SYS_ADMIN is checked by default. See
369 capabilities(7) for information about capabilities.
370
371 Note that vtable entries may be marked as unprivileged and the
372 whole bus may be marked as trusted, see the discussion of
373 SD_BUS_VTABLE_UNPRIVILEGED below.
374
375 SD_BUS_VTABLE_UNPRIVILEGED
376 Mark this vtable entry as unprivileged. Access to privileged
377 entries is limited to users with appropriate capabilities as
378 described above. In practice many vtable entries are marked as
379 unprivileged, and either are open to everyone, or the decision
380 whether to allow access is taken later, e.g. by delegating to
381 polkit[2].
382
383 The whole bus may be marked as trusted, in which case annotations
384 at the entry level are ignored, see sd_bus_set_trusted(3).
385
386 When not specified, the org.freedesktop.systemd1.Privileged
387 annotation with value "true" will be shown in introspection data.
388
389 Note that this page describes checks implemented in the D-Bus
390 client. The D-Bus server has an additional policy that may permit
391 or deny connections, see "CONFIGURATION FILE" in dbus-daemon(1).
392
394 Example 1. Create a simple listener on the bus
395
396 /* SPDX-License-Identifier: CC0-1.0 */
397
398 #include <errno.h>
399 #include <stdbool.h>
400 #include <stddef.h>
401 #include <stdlib.h>
402 #include <stdio.h>
403 #include <systemd/sd-bus.h>
404
405 #define _cleanup_(f) __attribute__((cleanup(f)))
406
407 typedef struct object {
408 char *name;
409 uint32_t number;
410 } object;
411
412 static int method(sd_bus_message *m, void *userdata, sd_bus_error *error) {
413 printf("Got called with userdata=%p\n", userdata);
414 return 1;
415 }
416
417 static const sd_bus_vtable vtable[] = {
418 SD_BUS_VTABLE_START(0),
419 SD_BUS_METHOD(
420 "Method1", "s", "s", method, 0),
421 SD_BUS_METHOD_WITH_NAMES_OFFSET(
422 "Method2",
423 "so", SD_BUS_PARAM(string) SD_BUS_PARAM(path),
424 "s", SD_BUS_PARAM(returnstring),
425 method, offsetof(object, number),
426 SD_BUS_VTABLE_DEPRECATED),
427 SD_BUS_METHOD_WITH_ARGS_OFFSET(
428 "Method3",
429 SD_BUS_ARGS("s", string, "o", path),
430 SD_BUS_RESULT("s", returnstring),
431 method, offsetof(object, number),
432 SD_BUS_VTABLE_UNPRIVILEGED),
433 SD_BUS_METHOD_WITH_ARGS(
434 "Method4",
435 SD_BUS_NO_ARGS,
436 SD_BUS_NO_RESULT,
437 method,
438 SD_BUS_VTABLE_UNPRIVILEGED),
439 SD_BUS_SIGNAL(
440 "Signal1",
441 "so",
442 0),
443 SD_BUS_SIGNAL_WITH_NAMES(
444 "Signal2",
445 "so", SD_BUS_PARAM(string) SD_BUS_PARAM(path),
446 0),
447 SD_BUS_SIGNAL_WITH_ARGS(
448 "Signal3",
449 SD_BUS_ARGS("s", string, "o", path),
450 0),
451 SD_BUS_WRITABLE_PROPERTY(
452 "AutomaticStringProperty", "s", NULL, NULL,
453 offsetof(object, name),
454 SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
455 SD_BUS_WRITABLE_PROPERTY(
456 "AutomaticIntegerProperty", "u", NULL, NULL,
457 offsetof(object, number),
458 SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
459 SD_BUS_VTABLE_END
460 };
461
462 #define check(x) ({ \
463 int r = x; \
464 errno = r < 0 ? -r : 0; \
465 printf(#x ": %m\n"); \
466 if (r < 0) \
467 return EXIT_FAILURE; \
468 })
469
470 int main(int argc, char **argv) {
471 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
472
473 sd_bus_default(&bus);
474
475 object object = { .number = 666 };
476 check((object.name = strdup("name")) != NULL);
477
478 check(sd_bus_add_object_vtable(bus, NULL, "/object",
479 "org.freedesktop.systemd.VtableExample",
480 vtable,
481 &object));
482
483 for (;;) {
484 check(sd_bus_wait(bus, UINT64_MAX));
485 check(sd_bus_process(bus, NULL));
486 }
487
488 free(object.name);
489
490 return 0;
491 }
492
493 This creates a simple client on the bus (the user bus, when run as
494 normal user). We may use the D-Bus
495 org.freedesktop.DBus.Introspectable.Introspect call to acquire the XML
496 description of the interface:
497
498 <!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
499 "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
500 <!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
501 <node>
502 <interface name="org.freedesktop.DBus.Peer">
503 <method name="Ping"/>
504 <method name="GetMachineId">
505 <arg type="s" name="machine_uuid" direction="out"/>
506 </method>
507 </interface>
508 <interface name="org.freedesktop.DBus.Introspectable">
509 <method name="Introspect">
510 <arg name="xml_data" type="s" direction="out"/>
511 </method>
512 </interface>
513 <interface name="org.freedesktop.DBus.Properties">
514 <method name="Get">
515 <arg name="interface_name" direction="in" type="s"/>
516 <arg name="property_name" direction="in" type="s"/>
517 <arg name="value" direction="out" type="v"/>
518 </method>
519 <method name="GetAll">
520 <arg name="interface_name" direction="in" type="s"/>
521 <arg name="props" direction="out" type="a{sv}"/>
522 </method>
523 <method name="Set">
524 <arg name="interface_name" direction="in" type="s"/>
525 <arg name="property_name" direction="in" type="s"/>
526 <arg name="value" direction="in" type="v"/>
527 </method>
528 <signal name="PropertiesChanged">
529 <arg type="s" name="interface_name"/>
530 <arg type="a{sv}" name="changed_properties"/>
531 <arg type="as" name="invalidated_properties"/>
532 </signal>
533 </interface>
534 <interface name="org.freedesktop.systemd.VtableExample">
535 <method name="Method1">
536 <arg type="s" direction="in"/>
537 <arg type="s" direction="out"/>
538 </method>
539 <method name="Method2">
540 <arg type="s" name="string" direction="in"/>
541 <arg type="o" name="path" direction="in"/>
542 <arg type="s" name="returnstring" direction="out"/>
543 <annotation name="org.freedesktop.DBus.Deprecated" value="true"/>
544 </method>
545 <property name="AutomaticStringProperty" type="s" access="readwrite">
546 </property>
547 <property name="AutomaticIntegerProperty" type="u" access="readwrite">
548 <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="invalidates"/>
549 </property>
550 </interface>
551 </node>
552
553
555 On success, sd_bus_add_object_vtable() and sd_bus_add_fallback_vtable()
556 return a non-negative integer. On failure, they return a negative
557 errno-style error code.
558
559 Errors
560 Returned errors may indicate the following problems:
561
562 -EINVAL
563 One of the required parameters is NULL or invalid. A reserved D-Bus
564 interface was passed as the interface parameter.
565
566 -ENOPKG
567 The bus cannot be resolved.
568
569 -ECHILD
570 The bus was created in a different process.
571
572 -ENOMEM
573 Memory allocation failed.
574
575 -EPROTOTYPE
576 sd_bus_add_object_vtable() and sd_bus_add_fallback_vtable() have
577 been both called for the same bus object path, which is not
578 allowed.
579
580 -EEXIST
581 This vtable has already been registered for this interface and
582 path.
583
585 These APIs are implemented as a shared library, which can be compiled
586 and linked to with the libsystemd pkg-config(1) file.
587
589 sd-bus(3), busctl(1), sd_bus_emit_properties_changed(3),
590 sd_bus_emit_object_added(3)
591
593 1. D-Bus annotations
594 https://dbus.freedesktop.org/doc/dbus-specification.html#introspection-format
595
596 2. polkit
597 https://www.freedesktop.org/software/polkit/docs/latest/
598
599
600
601systemd 250 SD_BUS_ADD_OBJECT(3)