2017-11-18 17:09:20 +01:00
/* SPDX-License-Identifier: LGPL-2.1+ */
2010-02-03 13:03:47 +01:00
2010-02-01 03:33:24 +01:00
# include <errno.h>
2015-10-24 22:58:24 +02:00
# include <sys/epoll.h>
2010-02-01 03:33:24 +01:00
# include <unistd.h>
2013-11-19 21:12:59 +01:00
# include "sd-bus.h"
2015-10-24 22:58:24 +02:00
2015-10-27 03:01:06 +01:00
# include "alloc-util.h"
2015-10-24 22:58:24 +02:00
# include "bus-common-errors.h"
# include "bus-error.h"
# include "bus-internal.h"
2020-01-22 11:39:22 +01:00
# include "bus-polkit.h"
2018-05-28 11:13:19 +02:00
# include "dbus-automount.h"
2015-10-24 22:58:24 +02:00
# include "dbus-cgroup.h"
2018-05-28 11:13:19 +02:00
# include "dbus-device.h"
2013-11-19 21:12:59 +01:00
# include "dbus-execute.h"
2015-10-24 22:58:24 +02:00
# include "dbus-job.h"
2013-11-19 21:12:59 +01:00
# include "dbus-kill.h"
2015-10-24 22:58:24 +02:00
# include "dbus-manager.h"
2018-05-28 11:13:19 +02:00
# include "dbus-mount.h"
# include "dbus-path.h"
# include "dbus-scope.h"
# include "dbus-service.h"
# include "dbus-slice.h"
# include "dbus-socket.h"
# include "dbus-swap.h"
# include "dbus-target.h"
# include "dbus-timer.h"
2015-10-24 22:58:24 +02:00
# include "dbus-unit.h"
2015-10-25 13:14:12 +01:00
# include "dbus.h"
# include "fd-util.h"
2017-12-27 18:22:31 +01:00
# include "fs-util.h"
2015-10-24 22:58:24 +02:00
# include "log.h"
# include "mkdir.h"
2018-01-11 00:39:12 +01:00
# include "process-util.h"
2015-10-24 22:58:24 +02:00
# include "selinux-access.h"
2018-10-17 20:40:09 +02:00
# include "serialize.h"
2018-05-15 20:17:34 +02:00
# include "service.h"
2010-09-01 03:30:59 +02:00
# include "special.h"
2015-10-24 22:58:24 +02:00
# include "string-util.h"
# include "strv.h"
2013-11-19 21:12:59 +01:00
# include "strxcpyx.h"
2015-10-27 00:42:07 +01:00
# include "user-util.h"
2010-05-23 03:45:33 +02:00
2015-03-04 16:32:17 +01:00
# define CONNECTIONS_MAX 4096
2010-06-19 03:04:04 +02:00
2013-11-19 21:12:59 +01:00
static void destroy_bus ( Manager * m , sd_bus * * bus ) ;
2018-11-13 11:59:06 +01:00
int bus_send_pending_reload_message ( Manager * m ) {
2013-11-19 21:12:59 +01:00
int r ;
2010-03-31 16:29:55 +02:00
assert ( m ) ;
2010-04-08 04:58:30 +02:00
2018-11-13 11:59:06 +01:00
if ( ! m - > pending_reload_message )
2013-11-19 21:12:59 +01:00
return 0 ;
2010-03-31 16:29:55 +02:00
2018-11-13 12:00:42 +01:00
/* If we cannot get rid of this message we won't dispatch any D-Bus messages, so that we won't end up wanting
* to queue another message . */
2010-02-01 03:33:24 +01:00
2018-11-13 11:59:06 +01:00
r = sd_bus_send ( NULL , m - > pending_reload_message , NULL ) ;
2013-11-19 21:12:59 +01:00
if ( r < 0 )
2018-11-13 12:00:42 +01:00
log_warning_errno ( r , " Failed to send queued message, ignoring: %m " ) ;
2010-02-01 03:33:24 +01:00
2018-11-13 11:59:06 +01:00
m - > pending_reload_message = sd_bus_message_unref ( m - > pending_reload_message ) ;
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
return 0 ;
2010-02-01 03:33:24 +01:00
}
2016-05-04 20:43:23 +02:00
int bus_forward_agent_released ( Manager * m , const char * path ) {
int r ;
assert ( m ) ;
assert ( path ) ;
if ( ! MANAGER_IS_SYSTEM ( m ) )
return 0 ;
if ( ! m - > system_bus )
return 0 ;
/* If we are running a system instance we forward the agent message on the system bus, so that the user
* instances get notified about this , too */
r = sd_bus_emit_signal ( m - > system_bus ,
" /org/freedesktop/systemd1/agent " ,
" org.freedesktop.systemd1.Agent " ,
" Released " ,
" s " , path ) ;
if ( r < 0 )
2017-09-08 17:24:57 +02:00
return log_debug_errno ( r , " Failed to propagate agent release message: %m " ) ;
2016-05-04 20:43:23 +02:00
return 1 ;
}
2015-04-29 18:35:10 +02:00
static int signal_agent_released ( sd_bus_message * message , void * userdata , sd_bus_error * error ) {
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
_cleanup_ ( sd_bus_creds_unrefp ) sd_bus_creds * creds = NULL ;
2013-11-19 21:12:59 +01:00
Manager * m = userdata ;
2016-05-04 20:43:23 +02:00
const char * cgroup ;
2015-07-04 12:14:45 +02:00
uid_t sender_uid ;
2013-11-19 21:12:59 +01:00
int r ;
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
assert ( message ) ;
2010-02-01 03:33:24 +01:00
assert ( m ) ;
2015-07-04 12:14:45 +02:00
/* only accept org.freedesktop.systemd1.Agent from UID=0 */
r = sd_bus_query_sender_creds ( message , SD_BUS_CREDS_EUID , & creds ) ;
if ( r < 0 )
return r ;
r = sd_bus_creds_get_euid ( creds , & sender_uid ) ;
if ( r < 0 | | sender_uid ! = 0 )
return 0 ;
/* parse 'cgroup-empty' notification */
2013-11-19 21:12:59 +01:00
r = sd_bus_message_read ( message , " s " , & cgroup ) ;
if ( r < 0 ) {
bus_log_parse_error ( r ) ;
return 0 ;
}
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
manager_notify_cgroup_empty ( m , cgroup ) ;
return 0 ;
}
2010-02-01 03:33:24 +01:00
2015-04-29 18:35:10 +02:00
static int signal_disconnected ( sd_bus_message * message , void * userdata , sd_bus_error * error ) {
2013-11-19 21:12:59 +01:00
Manager * m = userdata ;
2015-04-29 18:35:10 +02:00
sd_bus * bus ;
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
assert ( message ) ;
assert ( m ) ;
2015-04-29 18:35:10 +02:00
assert_se ( bus = sd_bus_message_get_bus ( message ) ) ;
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
if ( bus = = m - > api_bus )
2018-02-07 15:00:32 +01:00
bus_done_api ( m ) ;
2013-11-19 21:12:59 +01:00
if ( bus = = m - > system_bus )
2018-02-07 15:00:32 +01:00
bus_done_system ( m ) ;
2013-11-19 21:12:59 +01:00
if ( set_remove ( m - > private_buses , bus ) ) {
log_debug ( " Got disconnect on private connection. " ) ;
destroy_bus ( m , & bus ) ;
2010-02-01 03:33:24 +01:00
}
2013-11-19 21:12:59 +01:00
return 0 ;
2010-02-01 03:33:24 +01:00
}
2015-04-29 18:35:10 +02:00
static int signal_activation_request ( sd_bus_message * message , void * userdata , sd_bus_error * ret_error ) {
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
_cleanup_ ( sd_bus_error_free ) sd_bus_error error = SD_BUS_ERROR_NULL ;
_cleanup_ ( sd_bus_message_unrefp ) sd_bus_message * reply = NULL ;
2013-11-19 21:12:59 +01:00
Manager * m = userdata ;
const char * name ;
Unit * u ;
int r ;
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
assert ( message ) ;
2010-02-01 03:33:24 +01:00
assert ( m ) ;
2013-11-19 21:12:59 +01:00
r = sd_bus_message_read ( message , " s " , & name ) ;
if ( r < 0 ) {
bus_log_parse_error ( r ) ;
return 0 ;
}
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
if ( manager_unit_inactive_or_pending ( m , SPECIAL_DBUS_SERVICE ) | |
manager_unit_inactive_or_pending ( m , SPECIAL_DBUS_SOCKET ) ) {
r = sd_bus_error_setf ( & error , BUS_ERROR_SHUTTING_DOWN , " Refusing activation, D-Bus is shutting down. " ) ;
goto failed ;
}
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
r = manager_load_unit ( m , name , NULL , & error , & u ) ;
if ( r < 0 )
goto failed ;
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
if ( u - > refuse_manual_start ) {
2017-01-24 04:06:05 +01:00
r = sd_bus_error_setf ( & error , BUS_ERROR_ONLY_BY_DEPENDENCY , " Operation refused, %s may be requested by dependency only (it is configured to refuse manual start/stop). " , u - > id ) ;
2013-11-19 21:12:59 +01:00
goto failed ;
2010-02-01 03:33:24 +01:00
}
2019-03-22 20:57:30 +01:00
r = manager_add_job ( m , JOB_START , u , JOB_REPLACE , NULL , & error , NULL ) ;
2013-11-19 21:12:59 +01:00
if ( r < 0 )
goto failed ;
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
/* Successfully queued, that's it for us */
2010-02-01 03:33:24 +01:00
return 0 ;
2013-11-19 21:12:59 +01:00
failed :
if ( ! sd_bus_error_is_set ( & error ) )
sd_bus_error_set_errno ( & error , r ) ;
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
log_debug ( " D-Bus activation failed for %s: %s " , name , bus_error_message ( & error , r ) ) ;
2010-02-01 03:33:24 +01:00
2015-04-29 19:10:09 +02:00
r = sd_bus_message_new_signal ( sd_bus_message_get_bus ( message ) , & reply , " /org/freedesktop/systemd1 " , " org.freedesktop.systemd1.Activator " , " ActivationFailure " ) ;
2013-11-19 21:12:59 +01:00
if ( r < 0 ) {
bus_log_create_error ( r ) ;
return 0 ;
}
2013-11-21 02:14:05 +01:00
r = sd_bus_message_append ( reply , " sss " , name , error . name , error . message ) ;
2013-11-19 21:12:59 +01:00
if ( r < 0 ) {
bus_log_create_error ( r ) ;
return 0 ;
}
2015-04-29 19:10:09 +02:00
r = sd_bus_send_to ( NULL , reply , " org.freedesktop.DBus " , NULL ) ;
2014-11-28 18:23:20 +01:00
if ( r < 0 )
return log_error_errno ( r , " Failed to respond with to bus activation request: %m " ) ;
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
return 0 ;
2010-02-01 03:33:24 +01:00
}
2017-10-03 10:41:51 +02:00
# if HAVE_SELINUX
2015-04-29 18:35:10 +02:00
static int mac_selinux_filter ( sd_bus_message * message , void * userdata , sd_bus_error * error ) {
2013-11-21 23:36:51 +01:00
Manager * m = userdata ;
const char * verb , * path ;
Unit * u = NULL ;
Job * j ;
int r ;
assert ( message ) ;
/* Our own method calls are all protected individually with
* selinux checks , but the built - in interfaces need to be
* protected too . */
if ( sd_bus_message_is_method_call ( message , " org.freedesktop.DBus.Properties " , " Set " ) )
verb = " reload " ;
else if ( sd_bus_message_is_method_call ( message , " org.freedesktop.DBus.Introspectable " , NULL ) | |
sd_bus_message_is_method_call ( message , " org.freedesktop.DBus.Properties " , NULL ) | |
sd_bus_message_is_method_call ( message , " org.freedesktop.DBus.ObjectManager " , NULL ) | |
sd_bus_message_is_method_call ( message , " org.freedesktop.DBus.Peer " , NULL ) )
verb = " status " ;
else
return 0 ;
path = sd_bus_message_get_path ( message ) ;
if ( object_path_startswith ( " /org/freedesktop/systemd1 " , path ) ) {
2014-10-24 14:15:25 +02:00
r = mac_selinux_access_check ( message , verb , error ) ;
2013-11-21 23:36:51 +01:00
if ( r < 0 )
return r ;
return 0 ;
}
if ( streq_ptr ( path , " /org/freedesktop/systemd1/unit/self " ) ) {
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
_cleanup_ ( sd_bus_creds_unrefp ) sd_bus_creds * creds = NULL ;
2013-11-21 23:36:51 +01:00
pid_t pid ;
2013-11-28 17:50:02 +01:00
r = sd_bus_query_sender_creds ( message , SD_BUS_CREDS_PID , & creds ) ;
if ( r < 0 )
return 0 ;
r = sd_bus_creds_get_pid ( creds , & pid ) ;
2013-11-21 23:36:51 +01:00
if ( r < 0 )
return 0 ;
u = manager_get_unit_by_pid ( m , pid ) ;
} else {
r = manager_get_job_from_dbus_path ( m , path , & j ) ;
if ( r > = 0 )
u = j - > unit ;
else
manager_load_unit_from_dbus_path ( m , path , NULL , & u ) ;
}
if ( ! u )
return 0 ;
2014-10-24 14:15:25 +02:00
r = mac_selinux_unit_access_check ( u , message , verb , error ) ;
2013-11-21 23:36:51 +01:00
if ( r < 0 )
return r ;
return 0 ;
}
2013-12-12 15:58:31 +01:00
# endif
2013-11-21 23:36:51 +01:00
2013-11-22 01:14:57 +01:00
static int bus_job_find ( sd_bus * bus , const char * path , const char * interface , void * userdata , void * * found , sd_bus_error * error ) {
2013-11-19 21:12:59 +01:00
Manager * m = userdata ;
Job * j ;
int r ;
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
assert ( bus ) ;
assert ( path ) ;
assert ( interface ) ;
assert ( found ) ;
2010-02-01 03:33:24 +01:00
assert ( m ) ;
2013-11-19 21:12:59 +01:00
r = manager_get_job_from_dbus_path ( m , path , & j ) ;
if ( r < 0 )
return 0 ;
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
* found = j ;
return 1 ;
}
2010-02-01 03:33:24 +01:00
2013-11-22 01:14:57 +01:00
static int find_unit ( Manager * m , sd_bus * bus , const char * path , Unit * * unit , sd_bus_error * error ) {
2017-02-12 19:22:18 +01:00
Unit * u = NULL ; /* just to appease gcc, initialization is not really necessary */
2013-11-19 21:12:59 +01:00
int r ;
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
assert ( m ) ;
assert ( bus ) ;
assert ( path ) ;
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
if ( streq_ptr ( path , " /org/freedesktop/systemd1/unit/self " ) ) {
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
_cleanup_ ( sd_bus_creds_unrefp ) sd_bus_creds * creds = NULL ;
2013-11-19 21:12:59 +01:00
sd_bus_message * message ;
pid_t pid ;
2010-02-01 03:33:24 +01:00
2014-05-15 01:15:30 +02:00
message = sd_bus_get_current_message ( bus ) ;
2013-11-19 21:12:59 +01:00
if ( ! message )
2013-11-22 01:14:57 +01:00
return 0 ;
2010-02-01 03:33:24 +01:00
2013-11-28 17:50:02 +01:00
r = sd_bus_query_sender_creds ( message , SD_BUS_CREDS_PID , & creds ) ;
2013-11-19 21:12:59 +01:00
if ( r < 0 )
2013-11-28 17:50:02 +01:00
return r ;
r = sd_bus_creds_get_pid ( creds , & pid ) ;
if ( r < 0 )
return r ;
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
u = manager_get_unit_by_pid ( m , pid ) ;
2017-02-12 19:22:18 +01:00
if ( ! u )
return 0 ;
2013-11-19 21:12:59 +01:00
} else {
2013-11-22 01:14:57 +01:00
r = manager_load_unit_from_dbus_path ( m , path , error , & u ) ;
2013-11-19 21:12:59 +01:00
if ( r < 0 )
2013-11-22 01:14:57 +01:00
return 0 ;
2017-02-12 19:22:18 +01:00
assert ( u ) ;
2013-11-19 21:12:59 +01:00
}
2010-02-01 03:33:24 +01:00
2013-11-22 01:14:57 +01:00
* unit = u ;
return 1 ;
2010-02-01 03:33:24 +01:00
}
2013-11-22 01:14:57 +01:00
static int bus_unit_find ( sd_bus * bus , const char * path , const char * interface , void * userdata , void * * found , sd_bus_error * error ) {
2013-11-19 21:12:59 +01:00
Manager * m = userdata ;
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
assert ( bus ) ;
assert ( path ) ;
assert ( interface ) ;
assert ( found ) ;
2010-02-01 03:33:24 +01:00
assert ( m ) ;
2013-11-22 01:14:57 +01:00
return find_unit ( m , bus , path , ( Unit * * ) found , error ) ;
2010-02-01 03:33:24 +01:00
}
2013-11-22 01:14:57 +01:00
static int bus_unit_interface_find ( sd_bus * bus , const char * path , const char * interface , void * userdata , void * * found , sd_bus_error * error ) {
2013-11-19 21:12:59 +01:00
Manager * m = userdata ;
Unit * u ;
2013-11-22 01:14:57 +01:00
int r ;
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
assert ( bus ) ;
assert ( path ) ;
assert ( interface ) ;
assert ( found ) ;
2010-02-01 03:33:24 +01:00
assert ( m ) ;
2013-11-22 01:14:57 +01:00
r = find_unit ( m , bus , path , & u , error ) ;
if ( r < = 0 )
return r ;
2011-05-23 21:36:52 +02:00
2015-08-27 22:30:43 +02:00
if ( ! streq_ptr ( interface , unit_dbus_interface_from_type ( u - > type ) ) )
2013-11-19 21:12:59 +01:00
return 0 ;
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
* found = u ;
return 1 ;
2010-02-01 03:33:24 +01:00
}
2013-11-22 01:14:57 +01:00
static int bus_unit_cgroup_find ( sd_bus * bus , const char * path , const char * interface , void * userdata , void * * found , sd_bus_error * error ) {
2013-11-19 21:12:59 +01:00
Manager * m = userdata ;
Unit * u ;
2013-11-22 01:14:57 +01:00
int r ;
2010-02-05 00:38:41 +01:00
2013-11-19 21:12:59 +01:00
assert ( bus ) ;
assert ( path ) ;
assert ( interface ) ;
assert ( found ) ;
2010-02-05 00:38:41 +01:00
assert ( m ) ;
2013-11-22 01:14:57 +01:00
r = find_unit ( m , bus , path , & u , error ) ;
if ( r < = 0 )
return r ;
2010-04-15 23:16:16 +02:00
2015-08-27 22:30:43 +02:00
if ( ! streq_ptr ( interface , unit_dbus_interface_from_type ( u - > type ) ) )
2013-11-19 21:12:59 +01:00
return 0 ;
2010-04-15 23:16:16 +02:00
2015-08-28 17:14:59 +02:00
if ( ! UNIT_HAS_CGROUP_CONTEXT ( u ) )
2013-11-19 21:12:59 +01:00
return 0 ;
2010-06-02 04:24:16 +02:00
2013-11-19 21:12:59 +01:00
* found = u ;
return 1 ;
}
2010-06-02 04:24:16 +02:00
2013-11-22 01:14:57 +01:00
static int bus_cgroup_context_find ( sd_bus * bus , const char * path , const char * interface , void * userdata , void * * found , sd_bus_error * error ) {
2013-11-19 21:12:59 +01:00
Manager * m = userdata ;
CGroupContext * c ;
Unit * u ;
2013-11-22 01:14:57 +01:00
int r ;
2010-06-07 04:15:37 +02:00
2013-11-19 21:12:59 +01:00
assert ( bus ) ;
assert ( path ) ;
assert ( interface ) ;
assert ( found ) ;
assert ( m ) ;
2010-06-02 04:24:16 +02:00
2013-11-22 01:14:57 +01:00
r = find_unit ( m , bus , path , & u , error ) ;
if ( r < = 0 )
return r ;
2010-06-02 04:24:16 +02:00
2015-08-27 22:30:43 +02:00
if ( ! streq_ptr ( interface , unit_dbus_interface_from_type ( u - > type ) ) )
2013-11-19 21:12:59 +01:00
return 0 ;
2010-06-02 04:24:16 +02:00
2013-11-19 21:12:59 +01:00
c = unit_get_cgroup_context ( u ) ;
if ( ! c )
return 0 ;
2010-02-05 00:38:41 +01:00
2013-11-19 21:12:59 +01:00
* found = c ;
return 1 ;
}
2010-06-02 04:24:16 +02:00
2013-11-22 01:14:57 +01:00
static int bus_exec_context_find ( sd_bus * bus , const char * path , const char * interface , void * userdata , void * * found , sd_bus_error * error ) {
2013-11-19 21:12:59 +01:00
Manager * m = userdata ;
ExecContext * c ;
Unit * u ;
2013-11-22 01:14:57 +01:00
int r ;
2010-06-02 04:24:16 +02:00
2013-11-19 21:12:59 +01:00
assert ( bus ) ;
assert ( path ) ;
assert ( interface ) ;
assert ( found ) ;
assert ( m ) ;
2010-06-02 04:24:16 +02:00
2013-11-22 01:14:57 +01:00
r = find_unit ( m , bus , path , & u , error ) ;
if ( r < = 0 )
return r ;
2010-06-02 04:24:16 +02:00
2015-08-27 22:30:43 +02:00
if ( ! streq_ptr ( interface , unit_dbus_interface_from_type ( u - > type ) ) )
2013-11-19 21:12:59 +01:00
return 0 ;
2010-06-02 04:24:16 +02:00
2013-11-19 21:12:59 +01:00
c = unit_get_exec_context ( u ) ;
if ( ! c )
return 0 ;
2010-06-02 04:24:16 +02:00
2013-11-19 21:12:59 +01:00
* found = c ;
return 1 ;
2010-02-05 00:38:41 +01:00
}
2013-11-22 01:14:57 +01:00
static int bus_kill_context_find ( sd_bus * bus , const char * path , const char * interface , void * userdata , void * * found , sd_bus_error * error ) {
2013-11-19 21:12:59 +01:00
Manager * m = userdata ;
KillContext * c ;
Unit * u ;
2013-11-22 01:14:57 +01:00
int r ;
2010-03-31 16:29:55 +02:00
2013-11-19 21:12:59 +01:00
assert ( bus ) ;
assert ( path ) ;
assert ( interface ) ;
assert ( found ) ;
2010-03-31 16:29:55 +02:00
assert ( m ) ;
2013-11-22 01:14:57 +01:00
r = find_unit ( m , bus , path , & u , error ) ;
if ( r < = 0 )
return r ;
2010-03-31 16:29:55 +02:00
2015-08-27 22:30:43 +02:00
if ( ! streq_ptr ( interface , unit_dbus_interface_from_type ( u - > type ) ) )
2013-11-19 21:12:59 +01:00
return 0 ;
2010-03-31 16:29:55 +02:00
2013-11-19 21:12:59 +01:00
c = unit_get_kill_context ( u ) ;
if ( ! c )
return 0 ;
2010-09-03 01:45:14 +02:00
2013-11-19 21:12:59 +01:00
* found = c ;
return 1 ;
}
2010-03-31 16:29:55 +02:00
2013-11-22 01:14:57 +01:00
static int bus_job_enumerate ( sd_bus * bus , const char * path , void * userdata , char * * * nodes , sd_bus_error * error ) {
2017-01-25 04:21:16 +01:00
_cleanup_strv_free_ char * * l = NULL ;
2013-11-19 21:12:59 +01:00
Manager * m = userdata ;
unsigned k = 0 ;
Iterator i ;
Job * j ;
2010-03-31 16:29:55 +02:00
2013-11-19 21:12:59 +01:00
l = new0 ( char * , hashmap_size ( m - > jobs ) + 1 ) ;
if ( ! l )
return - ENOMEM ;
2010-03-31 16:29:55 +02:00
2013-11-19 21:12:59 +01:00
HASHMAP_FOREACH ( j , m - > jobs , i ) {
l [ k ] = job_dbus_path ( j ) ;
if ( ! l [ k ] )
return - ENOMEM ;
2010-06-19 03:04:04 +02:00
2013-11-19 21:12:59 +01:00
k + + ;
}
2010-06-19 03:04:04 +02:00
2013-11-19 21:12:59 +01:00
assert ( hashmap_size ( m - > jobs ) = = k ) ;
2010-08-06 03:21:50 +02:00
2018-03-22 16:53:26 +01:00
* nodes = TAKE_PTR ( l ) ;
2010-06-19 03:04:04 +02:00
2013-11-19 21:12:59 +01:00
return k ;
}
2010-09-03 01:45:14 +02:00
2013-11-22 01:14:57 +01:00
static int bus_unit_enumerate ( sd_bus * bus , const char * path , void * userdata , char * * * nodes , sd_bus_error * error ) {
2017-01-25 04:21:16 +01:00
_cleanup_strv_free_ char * * l = NULL ;
2013-11-19 21:12:59 +01:00
Manager * m = userdata ;
unsigned k = 0 ;
Iterator i ;
Unit * u ;
2010-08-06 03:21:50 +02:00
2013-11-19 21:12:59 +01:00
l = new0 ( char * , hashmap_size ( m - > units ) + 1 ) ;
if ( ! l )
return - ENOMEM ;
2010-09-03 01:45:14 +02:00
2013-11-19 21:12:59 +01:00
HASHMAP_FOREACH ( u , m - > units , i ) {
l [ k ] = unit_dbus_path ( u ) ;
if ( ! l [ k ] )
return - ENOMEM ;
2010-09-03 01:45:14 +02:00
2013-11-19 21:12:59 +01:00
k + + ;
2010-08-06 03:21:50 +02:00
}
2018-03-22 16:53:26 +01:00
* nodes = TAKE_PTR ( l ) ;
2010-06-19 03:04:04 +02:00
2013-11-19 21:12:59 +01:00
return k ;
2010-06-19 03:04:04 +02:00
}
2013-11-19 21:12:59 +01:00
static int bus_setup_api_vtables ( Manager * m , sd_bus * bus ) {
UnitType t ;
int r ;
2010-06-19 03:04:04 +02:00
2010-02-01 03:33:24 +01:00
assert ( m ) ;
2013-11-19 21:12:59 +01:00
assert ( bus ) ;
2010-02-01 03:33:24 +01:00
2017-10-03 10:41:51 +02:00
# if HAVE_SELINUX
2014-10-24 14:15:25 +02:00
r = sd_bus_add_filter ( bus , NULL , mac_selinux_filter , m ) ;
2014-11-28 18:23:20 +01:00
if ( r < 0 )
return log_error_errno ( r , " Failed to add SELinux access filter: %m " ) ;
2013-12-12 15:58:31 +01:00
# endif
2013-11-21 23:36:51 +01:00
2014-05-15 01:15:30 +02:00
r = sd_bus_add_object_vtable ( bus , NULL , " /org/freedesktop/systemd1 " , " org.freedesktop.systemd1.Manager " , bus_manager_vtable , m ) ;
2014-11-28 18:23:20 +01:00
if ( r < 0 )
return log_error_errno ( r , " Failed to register Manager vtable: %m " ) ;
2010-04-21 03:27:44 +02:00
2014-05-15 01:15:30 +02:00
r = sd_bus_add_fallback_vtable ( bus , NULL , " /org/freedesktop/systemd1/job " , " org.freedesktop.systemd1.Job " , bus_job_vtable , bus_job_find , m ) ;
2014-11-28 18:23:20 +01:00
if ( r < 0 )
return log_error_errno ( r , " Failed to register Job vtable: %m " ) ;
2010-02-05 00:38:41 +01:00
2014-05-15 01:15:30 +02:00
r = sd_bus_add_node_enumerator ( bus , NULL , " /org/freedesktop/systemd1/job " , bus_job_enumerate , m ) ;
2014-11-28 18:23:20 +01:00
if ( r < 0 )
return log_error_errno ( r , " Failed to add job enumerator: %m " ) ;
2010-04-04 22:48:47 +02:00
2014-05-15 01:15:30 +02:00
r = sd_bus_add_fallback_vtable ( bus , NULL , " /org/freedesktop/systemd1/unit " , " org.freedesktop.systemd1.Unit " , bus_unit_vtable , bus_unit_find , m ) ;
2014-11-28 18:23:20 +01:00
if ( r < 0 )
return log_error_errno ( r , " Failed to register Unit vtable: %m " ) ;
2010-04-04 22:48:47 +02:00
2014-05-15 01:15:30 +02:00
r = sd_bus_add_node_enumerator ( bus , NULL , " /org/freedesktop/systemd1/unit " , bus_unit_enumerate , m ) ;
2014-11-28 18:23:20 +01:00
if ( r < 0 )
return log_error_errno ( r , " Failed to add job enumerator: %m " ) ;
2010-04-04 22:48:47 +02:00
2013-11-19 21:12:59 +01:00
for ( t = 0 ; t < _UNIT_TYPE_MAX ; t + + ) {
2015-08-27 22:30:43 +02:00
const char * interface ;
assert_se ( interface = unit_dbus_interface_from_type ( t ) ) ;
r = sd_bus_add_fallback_vtable ( bus , NULL , " /org/freedesktop/systemd1/unit " , interface , unit_vtable [ t ] - > bus_vtable , bus_unit_interface_find , m ) ;
2014-11-28 18:23:20 +01:00
if ( r < 0 )
2015-08-27 22:30:43 +02:00
return log_error_errno ( r , " Failed to register type specific vtable for %s: %m " , interface ) ;
2010-04-04 22:48:47 +02:00
2013-11-19 21:12:59 +01:00
if ( unit_vtable [ t ] - > cgroup_context_offset > 0 ) {
2015-08-27 22:30:43 +02:00
r = sd_bus_add_fallback_vtable ( bus , NULL , " /org/freedesktop/systemd1/unit " , interface , bus_unit_cgroup_vtable , bus_unit_cgroup_find , m ) ;
2014-11-28 18:23:20 +01:00
if ( r < 0 )
2015-08-27 22:30:43 +02:00
return log_error_errno ( r , " Failed to register control group unit vtable for %s: %m " , interface ) ;
2010-04-04 22:48:47 +02:00
2015-08-27 22:30:43 +02:00
r = sd_bus_add_fallback_vtable ( bus , NULL , " /org/freedesktop/systemd1/unit " , interface , bus_cgroup_vtable , bus_cgroup_context_find , m ) ;
2014-11-28 18:23:20 +01:00
if ( r < 0 )
2015-08-27 22:30:43 +02:00
return log_error_errno ( r , " Failed to register control group vtable for %s: %m " , interface ) ;
2010-04-04 22:48:47 +02:00
}
2013-11-19 21:12:59 +01:00
if ( unit_vtable [ t ] - > exec_context_offset > 0 ) {
2015-08-27 22:30:43 +02:00
r = sd_bus_add_fallback_vtable ( bus , NULL , " /org/freedesktop/systemd1/unit " , interface , bus_exec_vtable , bus_exec_context_find , m ) ;
2014-11-28 18:23:20 +01:00
if ( r < 0 )
2015-08-27 22:30:43 +02:00
return log_error_errno ( r , " Failed to register execute vtable for %s: %m " , interface ) ;
2013-11-19 21:12:59 +01:00
}
2010-04-04 22:48:47 +02:00
2013-11-19 21:12:59 +01:00
if ( unit_vtable [ t ] - > kill_context_offset > 0 ) {
2015-08-27 22:30:43 +02:00
r = sd_bus_add_fallback_vtable ( bus , NULL , " /org/freedesktop/systemd1/unit " , interface , bus_kill_vtable , bus_kill_context_find , m ) ;
2014-11-28 18:23:20 +01:00
if ( r < 0 )
2015-08-27 22:30:43 +02:00
return log_error_errno ( r , " Failed to register kill vtable for %s: %m " , interface ) ;
2013-11-19 21:12:59 +01:00
}
2010-04-04 22:48:47 +02:00
}
2013-11-19 21:12:59 +01:00
return 0 ;
2010-04-04 22:48:47 +02:00
}
2013-11-19 21:12:59 +01:00
static int bus_setup_disconnected_match ( Manager * m , sd_bus * bus ) {
int r ;
2010-04-04 22:48:47 +02:00
2013-11-19 21:12:59 +01:00
assert ( m ) ;
assert ( bus ) ;
2010-04-04 22:48:47 +02:00
2017-12-19 12:29:04 +01:00
r = sd_bus_match_signal_async (
2013-11-19 21:12:59 +01:00
bus ,
2014-05-15 01:15:30 +02:00
NULL ,
2017-12-19 12:29:04 +01:00
" org.freedesktop.DBus.Local " ,
" /org/freedesktop/DBus/Local " ,
" org.freedesktop.DBus.Local " ,
" Disconnected " ,
signal_disconnected , NULL , m ) ;
2014-11-28 18:23:20 +01:00
if ( r < 0 )
2017-12-19 12:29:04 +01:00
return log_error_errno ( r , " Failed to request match for Disconnected message: %m " ) ;
2010-04-15 23:16:16 +02:00
2013-11-19 21:12:59 +01:00
return 0 ;
2010-02-01 03:33:24 +01:00
}
2013-11-19 21:12:59 +01:00
static int bus_on_connection ( sd_event_source * s , int fd , uint32_t revents , void * userdata ) {
2019-01-17 15:51:08 +01:00
_cleanup_ ( sd_bus_close_unrefp ) sd_bus * bus = NULL ;
2013-11-19 21:12:59 +01:00
_cleanup_close_ int nfd = - 1 ;
2010-06-04 22:03:22 +02:00
Manager * m = userdata ;
2013-11-19 21:12:59 +01:00
sd_id128_t id ;
int r ;
2010-06-04 22:03:22 +02:00
2013-11-19 21:12:59 +01:00
assert ( s ) ;
2010-06-04 22:03:22 +02:00
assert ( m ) ;
2013-11-19 21:12:59 +01:00
nfd = accept4 ( fd , NULL , NULL , SOCK_NONBLOCK | SOCK_CLOEXEC ) ;
if ( nfd < 0 ) {
2019-04-10 19:50:53 +02:00
if ( ERRNO_IS_ACCEPT_AGAIN ( errno ) )
return 0 ;
2014-11-28 19:29:59 +01:00
log_warning_errno ( errno , " Failed to accept private connection, ignoring: %m " ) ;
2013-11-19 21:12:59 +01:00
return 0 ;
}
2010-06-04 22:03:22 +02:00
2013-11-19 21:12:59 +01:00
if ( set_size ( m - > private_buses ) > = CONNECTIONS_MAX ) {
log_warning ( " Too many concurrent connections, refusing " ) ;
return 0 ;
}
2010-06-04 22:03:22 +02:00
2014-08-13 01:00:18 +02:00
r = set_ensure_allocated ( & m - > private_buses , NULL ) ;
2013-11-19 21:12:59 +01:00
if ( r < 0 ) {
log_oom ( ) ;
return 0 ;
}
2010-06-04 22:03:22 +02:00
2013-11-19 21:12:59 +01:00
r = sd_bus_new ( & bus ) ;
if ( r < 0 ) {
2014-11-28 13:19:16 +01:00
log_warning_errno ( r , " Failed to allocate new private connection bus: %m " ) ;
2013-11-19 21:12:59 +01:00
return 0 ;
}
2010-06-04 22:03:22 +02:00
2018-02-07 22:30:17 +01:00
( void ) sd_bus_set_description ( bus , " private-bus-connection " ) ;
2013-11-19 21:12:59 +01:00
r = sd_bus_set_fd ( bus , nfd , nfd ) ;
if ( r < 0 ) {
2014-11-28 13:19:16 +01:00
log_warning_errno ( r , " Failed to set fd on new connection bus: %m " ) ;
2013-11-19 21:12:59 +01:00
return 0 ;
}
2010-06-04 22:03:22 +02:00
2013-11-19 21:12:59 +01:00
nfd = - 1 ;
2010-06-04 22:03:22 +02:00
2013-11-19 21:12:59 +01:00
r = bus_check_peercred ( bus ) ;
if ( r < 0 ) {
2014-11-28 13:19:16 +01:00
log_warning_errno ( r , " Incoming private connection from unprivileged client, refusing: %m " ) ;
2013-11-19 21:12:59 +01:00
return 0 ;
}
2010-06-04 22:03:22 +02:00
2013-11-19 21:12:59 +01:00
assert_se ( sd_id128_randomize ( & id ) > = 0 ) ;
2010-06-04 22:03:22 +02:00
2013-11-19 21:12:59 +01:00
r = sd_bus_set_server ( bus , 1 , id ) ;
if ( r < 0 ) {
2014-11-28 13:19:16 +01:00
log_warning_errno ( r , " Failed to enable server support for new connection bus: %m " ) ;
2013-11-19 21:12:59 +01:00
return 0 ;
}
2010-06-04 22:03:22 +02:00
2015-04-23 00:37:47 +02:00
r = sd_bus_negotiate_creds ( bus , 1 ,
SD_BUS_CREDS_PID | SD_BUS_CREDS_UID |
SD_BUS_CREDS_EUID | SD_BUS_CREDS_EFFECTIVE_CAPS |
SD_BUS_CREDS_SELINUX_CONTEXT ) ;
if ( r < 0 ) {
log_warning_errno ( r , " Failed to enable credentials for new connection: %m " ) ;
return 0 ;
}
2017-12-20 19:43:05 +01:00
r = sd_bus_set_sender ( bus , " org.freedesktop.systemd1 " ) ;
if ( r < 0 ) {
log_warning_errno ( r , " Failed to set direct connection sender: %m " ) ;
return 0 ;
}
2013-11-19 21:12:59 +01:00
r = sd_bus_start ( bus ) ;
if ( r < 0 ) {
2014-11-28 13:19:16 +01:00
log_warning_errno ( r , " Failed to start new connection bus: %m " ) ;
2013-11-19 21:12:59 +01:00
return 0 ;
2010-06-04 22:03:22 +02:00
}
2013-11-19 21:12:59 +01:00
r = sd_bus_attach_event ( bus , m - > event , SD_EVENT_PRIORITY_NORMAL ) ;
if ( r < 0 ) {
2014-11-28 13:19:16 +01:00
log_warning_errno ( r , " Failed to attach new connection bus to event loop: %m " ) ;
2013-11-19 21:12:59 +01:00
return 0 ;
2010-06-04 22:03:22 +02:00
}
2013-11-19 21:12:59 +01:00
r = bus_setup_disconnected_match ( m , bus ) ;
if ( r < 0 )
return 0 ;
2010-06-04 22:03:22 +02:00
2013-11-19 21:12:59 +01:00
r = bus_setup_api_vtables ( m , bus ) ;
if ( r < 0 ) {
2014-11-28 13:19:16 +01:00
log_warning_errno ( r , " Failed to set up API vtables on new connection bus: %m " ) ;
2013-11-19 21:12:59 +01:00
return 0 ;
}
2010-06-04 22:03:22 +02:00
2013-11-19 21:12:59 +01:00
r = set_put ( m - > private_buses , bus ) ;
if ( r < 0 ) {
2015-04-10 23:39:13 +02:00
log_warning_errno ( r , " Failed to add new connection bus to set: %m " ) ;
2013-11-19 21:12:59 +01:00
return 0 ;
2010-06-04 22:03:22 +02:00
}
2013-11-19 21:12:59 +01:00
bus = NULL ;
2010-06-04 22:03:22 +02:00
2013-11-19 21:12:59 +01:00
log_debug ( " Accepted new private connection. " ) ;
2010-06-04 22:03:22 +02:00
2010-03-31 16:29:55 +02:00
return 0 ;
}
2013-11-19 21:12:59 +01:00
static int bus_setup_api ( Manager * m , sd_bus * bus ) {
2015-08-05 17:47:45 +02:00
Iterator i ;
char * name ;
Unit * u ;
2013-11-19 21:12:59 +01:00
int r ;
2010-04-06 16:32:07 +02:00
2013-11-19 21:12:59 +01:00
assert ( m ) ;
assert ( bus ) ;
2010-02-05 00:38:41 +01:00
2014-11-26 18:57:37 +01:00
/* Let's make sure we have enough credential bits so that we can make security and selinux decisions */
r = sd_bus_negotiate_creds ( bus , 1 ,
SD_BUS_CREDS_PID | SD_BUS_CREDS_UID |
SD_BUS_CREDS_EUID | SD_BUS_CREDS_EFFECTIVE_CAPS |
SD_BUS_CREDS_SELINUX_CONTEXT ) ;
if ( r < 0 )
2014-11-28 13:19:16 +01:00
log_warning_errno ( r , " Failed to enable credential passing, ignoring: %m " ) ;
2014-11-26 18:57:37 +01:00
2013-11-19 21:12:59 +01:00
r = bus_setup_api_vtables ( m , bus ) ;
if ( r < 0 )
return r ;
2011-12-18 14:58:10 +01:00
2015-08-05 17:47:45 +02:00
HASHMAP_FOREACH_KEY ( u , name , m - > watch_bus , i ) {
2015-10-17 16:25:10 +02:00
r = unit_install_bus_match ( u , bus , name ) ;
2015-08-05 17:47:45 +02:00
if ( r < 0 )
2015-10-15 17:39:14 +02:00
log_error_errno ( r , " Failed to subscribe to NameOwnerChanged signal for '%s': %m " , name ) ;
2015-08-05 17:47:45 +02:00
}
2013-11-19 21:12:59 +01:00
2017-12-19 12:29:04 +01:00
r = sd_bus_match_signal_async (
2013-11-19 21:12:59 +01:00
bus ,
2014-05-15 01:15:30 +02:00
NULL ,
2017-12-19 12:29:04 +01:00
" org.freedesktop.DBus " ,
" /org/freedesktop/DBus " ,
" org.freedesktop.systemd1.Activator " ,
" ActivationRequest " ,
signal_activation_request , NULL , m ) ;
2013-11-19 21:12:59 +01:00
if ( r < 0 )
2014-11-28 13:19:16 +01:00
log_warning_errno ( r , " Failed to subscribe to activation signal: %m " ) ;
2011-12-18 14:58:10 +01:00
2017-12-18 22:10:11 +01:00
/* Allow replacing of our name, to ease implementation of reexecution, where we keep the old connection open
* until after the new connection is set up and the name installed to allow clients to synchronously wait for
* reexecution to finish */
r = sd_bus_request_name_async ( bus , NULL , " org.freedesktop.systemd1 " , SD_BUS_NAME_REPLACE_EXISTING | SD_BUS_NAME_ALLOW_REPLACEMENT , NULL , NULL ) ;
2014-11-28 18:23:20 +01:00
if ( r < 0 )
2017-12-18 22:10:11 +01:00
return log_error_errno ( r , " Failed to request name: %m " ) ;
2010-09-03 01:45:14 +02:00
2013-11-19 21:12:59 +01:00
log_debug ( " Successfully connected to API bus. " ) ;
2018-02-07 22:36:51 +01:00
2010-04-06 16:32:07 +02:00
return 0 ;
}
core: rework how we connect to the bus
This removes the current bus_init() call, as it had multiple problems:
it munged handling of the three bus connections we care about (private,
"api" and system) into one, even though the conditions when which was
ready are very different. It also added redundant logging, as the
individual calls it called all logged on their own anyway.
The three calls bus_init_api(), bus_init_private() and bus_init_system()
are now made public. A new call manager_dbus_is_running() is added that
works much like manager_journal_is_running() and is a lot more careful
when checking whether dbus is around. Optionally it checks the unit's
deserialized_state rather than state, in order to accomodate for cases
where we cant to connect to the bus before deserializing the
"subscribed" list, before coldplugging the units.
manager_recheck_dbus() is added, that works a lot like
manager_recheck_journal() and is invoked in unit_notify(), i.e. when
units change state.
All in all this should make handling a bit more alike to journal
handling, and it also fixes one major bug: when running in user mode
we'll now connect to the system bus early on, without conditionalizing
this in anyway.
2018-02-07 14:52:22 +01:00
int bus_init_api ( Manager * m ) {
2019-01-17 16:07:22 +01:00
_cleanup_ ( sd_bus_close_unrefp ) sd_bus * bus = NULL ;
2010-04-06 16:32:07 +02:00
int r ;
2013-11-19 21:12:59 +01:00
if ( m - > api_bus )
return 0 ;
2011-12-18 14:58:10 +01:00
2013-11-19 21:12:59 +01:00
/* The API and system bus is the same if we are running in system mode */
2016-02-24 21:24:23 +01:00
if ( MANAGER_IS_SYSTEM ( m ) & & m - > system_bus )
2013-11-19 21:12:59 +01:00
bus = sd_bus_ref ( m - > system_bus ) ;
else {
2016-02-24 21:24:23 +01:00
if ( MANAGER_IS_SYSTEM ( m ) )
2018-03-29 16:14:11 +02:00
r = sd_bus_open_system_with_description ( & bus , " bus-api-system " ) ;
2013-11-19 21:12:59 +01:00
else
2018-03-29 16:14:11 +02:00
r = sd_bus_open_user_with_description ( & bus , " bus-api-user " ) ;
2018-01-10 17:22:12 +01:00
if ( r < 0 )
return log_error_errno ( r , " Failed to connect to API bus: %m " ) ;
2011-12-18 14:58:10 +01:00
2013-11-19 21:12:59 +01:00
r = sd_bus_attach_event ( bus , m - > event , SD_EVENT_PRIORITY_NORMAL ) ;
2018-01-10 17:22:12 +01:00
if ( r < 0 )
return log_error_errno ( r , " Failed to attach API bus to event loop: %m " ) ;
2011-12-18 14:58:10 +01:00
2013-11-19 21:12:59 +01:00
r = bus_setup_disconnected_match ( m , bus ) ;
if ( r < 0 )
2018-01-10 17:22:12 +01:00
return r ;
2011-12-18 14:58:10 +01:00
}
2013-11-19 21:12:59 +01:00
r = bus_setup_api ( m , bus ) ;
2018-01-10 17:22:12 +01:00
if ( r < 0 )
return log_error_errno ( r , " Failed to set up API bus: %m " ) ;
2011-12-18 14:58:10 +01:00
2018-04-05 07:26:26 +02:00
m - > api_bus = TAKE_PTR ( bus ) ;
2011-12-18 14:58:10 +01:00
return 0 ;
}
2013-11-19 21:12:59 +01:00
static int bus_setup_system ( Manager * m , sd_bus * bus ) {
int r ;
2011-12-18 14:58:10 +01:00
2013-11-19 21:12:59 +01:00
assert ( m ) ;
assert ( bus ) ;
2011-12-18 14:58:10 +01:00
2016-05-04 20:43:23 +02:00
/* if we are a user instance we get the Released message via the system bus */
if ( MANAGER_IS_USER ( m ) ) {
2017-12-19 12:29:04 +01:00
r = sd_bus_match_signal_async (
2015-03-11 16:35:21 +01:00
bus ,
NULL ,
2017-12-19 12:29:04 +01:00
NULL ,
" /org/freedesktop/systemd1/agent " ,
" org.freedesktop.systemd1.Agent " ,
" Released " ,
signal_agent_released , NULL , m ) ;
2015-03-11 16:35:21 +01:00
if ( r < 0 )
2017-12-19 12:29:04 +01:00
log_warning_errno ( r , " Failed to request Released match on system bus: %m " ) ;
2015-03-11 16:35:21 +01:00
}
2013-11-19 21:12:59 +01:00
log_debug ( " Successfully connected to system bus. " ) ;
return 0 ;
2011-12-18 14:58:10 +01:00
}
core: rework how we connect to the bus
This removes the current bus_init() call, as it had multiple problems:
it munged handling of the three bus connections we care about (private,
"api" and system) into one, even though the conditions when which was
ready are very different. It also added redundant logging, as the
individual calls it called all logged on their own anyway.
The three calls bus_init_api(), bus_init_private() and bus_init_system()
are now made public. A new call manager_dbus_is_running() is added that
works much like manager_journal_is_running() and is a lot more careful
when checking whether dbus is around. Optionally it checks the unit's
deserialized_state rather than state, in order to accomodate for cases
where we cant to connect to the bus before deserializing the
"subscribed" list, before coldplugging the units.
manager_recheck_dbus() is added, that works a lot like
manager_recheck_journal() and is invoked in unit_notify(), i.e. when
units change state.
All in all this should make handling a bit more alike to journal
handling, and it also fixes one major bug: when running in user mode
we'll now connect to the system bus early on, without conditionalizing
this in anyway.
2018-02-07 14:52:22 +01:00
int bus_init_system ( Manager * m ) {
2019-01-17 16:07:22 +01:00
_cleanup_ ( sd_bus_close_unrefp ) sd_bus * bus = NULL ;
2011-12-18 14:58:10 +01:00
int r ;
if ( m - > system_bus )
return 0 ;
2013-11-19 21:12:59 +01:00
/* The API and system bus is the same if we are running in system mode */
2018-02-07 22:47:26 +01:00
if ( MANAGER_IS_SYSTEM ( m ) & & m - > api_bus )
bus = sd_bus_ref ( m - > api_bus ) ;
else {
2018-03-29 16:14:11 +02:00
r = sd_bus_open_system_with_description ( & bus , " bus-system " ) ;
2018-02-07 22:47:26 +01:00
if ( r < 0 )
return log_error_errno ( r , " Failed to connect to system bus: %m " ) ;
2011-12-18 14:58:10 +01:00
2018-02-07 22:47:26 +01:00
r = sd_bus_attach_event ( bus , m - > event , SD_EVENT_PRIORITY_NORMAL ) ;
if ( r < 0 )
return log_error_errno ( r , " Failed to attach system bus to event loop: %m " ) ;
2011-12-18 14:58:10 +01:00
2018-02-07 22:47:26 +01:00
r = bus_setup_disconnected_match ( m , bus ) ;
if ( r < 0 )
return r ;
}
2011-12-18 14:58:10 +01:00
2013-11-19 21:12:59 +01:00
r = bus_setup_system ( m , bus ) ;
2018-01-10 17:22:12 +01:00
if ( r < 0 )
return log_error_errno ( r , " Failed to set up system bus: %m " ) ;
2011-12-18 14:58:10 +01:00
2018-04-05 07:26:26 +02:00
m - > system_bus = TAKE_PTR ( bus ) ;
2011-12-18 14:58:10 +01:00
return 0 ;
2010-06-19 03:04:04 +02:00
}
core: rework how we connect to the bus
This removes the current bus_init() call, as it had multiple problems:
it munged handling of the three bus connections we care about (private,
"api" and system) into one, even though the conditions when which was
ready are very different. It also added redundant logging, as the
individual calls it called all logged on their own anyway.
The three calls bus_init_api(), bus_init_private() and bus_init_system()
are now made public. A new call manager_dbus_is_running() is added that
works much like manager_journal_is_running() and is a lot more careful
when checking whether dbus is around. Optionally it checks the unit's
deserialized_state rather than state, in order to accomodate for cases
where we cant to connect to the bus before deserializing the
"subscribed" list, before coldplugging the units.
manager_recheck_dbus() is added, that works a lot like
manager_recheck_journal() and is invoked in unit_notify(), i.e. when
units change state.
All in all this should make handling a bit more alike to journal
handling, and it also fixes one major bug: when running in user mode
we'll now connect to the system bus early on, without conditionalizing
this in anyway.
2018-02-07 14:52:22 +01:00
int bus_init_private ( Manager * m ) {
2013-11-19 21:12:59 +01:00
_cleanup_close_ int fd = - 1 ;
2018-10-15 13:58:31 +02:00
union sockaddr_union sa = { } ;
2013-11-19 21:12:59 +01:00
sd_event_source * s ;
2018-10-15 13:58:31 +02:00
int r , salen ;
2010-06-19 03:04:04 +02:00
assert ( m ) ;
2013-11-19 21:12:59 +01:00
if ( m - > private_listen_fd > = 0 )
2010-06-19 03:04:04 +02:00
return 0 ;
2016-02-24 21:24:23 +01:00
if ( MANAGER_IS_SYSTEM ( m ) ) {
2011-07-01 22:34:37 +02:00
/* We want the private bus only when running as init */
2017-07-20 16:19:18 +02:00
if ( getpid_cached ( ) ! = 1 )
2011-07-01 22:34:37 +02:00
return 0 ;
2018-10-15 13:58:31 +02:00
salen = sockaddr_un_set_path ( & sa . un , " /run/systemd/private " ) ;
2011-07-01 22:34:37 +02:00
} else {
2018-10-15 13:58:31 +02:00
const char * e , * joined ;
2011-07-01 22:34:37 +02:00
2012-09-17 00:21:25 +02:00
e = secure_getenv ( " XDG_RUNTIME_DIR " ) ;
2018-11-20 23:40:44 +01:00
if ( ! e )
return log_error_errno ( SYNTHETIC_ERRNO ( EHOSTDOWN ) ,
" XDG_RUNTIME_DIR is not set, refusing. " ) ;
2011-07-01 22:34:37 +02:00
2018-10-15 13:58:31 +02:00
joined = strjoina ( e , " /systemd/private " ) ;
salen = sockaddr_un_set_path ( & sa . un , joined ) ;
2011-07-01 22:34:37 +02:00
}
2018-10-15 13:58:31 +02:00
if ( salen < 0 )
return log_error_errno ( salen , " Can't set path for AF_UNIX socket to bind to: %m " ) ;
2010-06-19 03:04:04 +02:00
2014-11-07 16:32:06 +01:00
( void ) mkdir_parents_label ( sa . un . sun_path , 0755 ) ;
2018-10-15 12:08:30 +02:00
( void ) sockaddr_un_unlink ( & sa . un ) ;
2013-11-19 21:12:59 +01:00
fd = socket ( AF_UNIX , SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK , 0 ) ;
2014-11-28 19:57:32 +01:00
if ( fd < 0 )
return log_error_errno ( errno , " Failed to allocate private socket: %m " ) ;
2010-06-19 03:04:04 +02:00
2013-11-19 21:12:59 +01:00
r = bind ( fd , & sa . sa , salen ) ;
2014-11-28 19:57:32 +01:00
if ( r < 0 )
return log_error_errno ( errno , " Failed to bind private socket: %m " ) ;
2010-06-19 03:04:04 +02:00
2013-11-19 21:12:59 +01:00
r = listen ( fd , SOMAXCONN ) ;
2014-11-28 19:57:32 +01:00
if ( r < 0 )
return log_error_errno ( errno , " Failed to make private socket listening: %m " ) ;
2010-06-19 03:04:04 +02:00
2017-12-27 18:22:31 +01:00
/* Generate an inotify event in case somebody waits for this socket to appear using inotify() */
( void ) touch ( sa . un . sun_path ) ;
2014-02-19 23:54:58 +01:00
r = sd_event_add_io ( m - > event , & s , fd , EPOLLIN , bus_on_connection , m ) ;
2014-11-28 18:23:20 +01:00
if ( r < 0 )
return log_error_errno ( r , " Failed to allocate event source: %m " ) ;
2010-06-19 03:04:04 +02:00
2015-04-29 16:05:32 +02:00
( void ) sd_event_source_set_description ( s , " bus-connection " ) ;
2018-10-15 12:09:17 +02:00
m - > private_listen_fd = TAKE_FD ( fd ) ;
2013-11-19 21:12:59 +01:00
m - > private_listen_event_source = s ;
2010-06-19 03:04:04 +02:00
2013-11-19 21:12:59 +01:00
log_debug ( " Successfully created private D-Bus server. " ) ;
2010-06-19 03:04:04 +02:00
2013-11-19 21:12:59 +01:00
return 0 ;
2010-06-19 03:04:04 +02:00
}
2013-11-19 21:12:59 +01:00
static void destroy_bus ( Manager * m , sd_bus * * bus ) {
2010-07-05 00:58:07 +02:00
Iterator i ;
2017-02-10 03:54:48 +01:00
Unit * u ;
2013-11-19 21:12:59 +01:00
Job * j ;
2010-07-05 00:58:07 +02:00
2013-11-19 21:12:59 +01:00
assert ( m ) ;
assert ( bus ) ;
2010-06-19 03:04:04 +02:00
2013-11-19 21:12:59 +01:00
if ( ! * bus )
2011-12-18 14:58:10 +01:00
return ;
2010-04-06 16:32:07 +02:00
2017-02-10 03:54:48 +01:00
/* Make sure all bus slots watching names are released. */
HASHMAP_FOREACH ( u , m - > watch_bus , i ) {
2019-12-23 16:48:18 +01:00
if ( u - > match_bus_slot & & sd_bus_slot_get_bus ( u - > match_bus_slot ) = = * bus )
u - > match_bus_slot = sd_bus_slot_unref ( u - > match_bus_slot ) ;
if ( u - > get_name_owner_slot & & sd_bus_slot_get_bus ( u - > get_name_owner_slot ) = = * bus )
u - > get_name_owner_slot = sd_bus_slot_unref ( u - > get_name_owner_slot ) ;
2017-02-10 03:54:48 +01:00
}
2013-11-19 21:12:59 +01:00
/* Get rid of tracked clients on this bus */
2014-03-03 01:33:45 +01:00
if ( m - > subscribed & & sd_bus_track_get_bus ( m - > subscribed ) = = * bus )
m - > subscribed = sd_bus_track_unref ( m - > subscribed ) ;
2013-11-19 21:12:59 +01:00
HASHMAP_FOREACH ( j , m - > jobs , i )
2016-11-15 19:29:50 +01:00
if ( j - > bus_track & & sd_bus_track_get_bus ( j - > bus_track ) = = * bus )
j - > bus_track = sd_bus_track_unref ( j - > bus_track ) ;
2010-02-05 00:38:41 +01:00
2018-02-07 22:40:41 +01:00
HASHMAP_FOREACH ( u , m - > units , i )
if ( u - > bus_track & & sd_bus_track_get_bus ( u - > bus_track ) = = * bus )
u - > bus_track = sd_bus_track_unref ( u - > bus_track ) ;
2013-11-19 21:12:59 +01:00
/* Get rid of queued message on this bus */
2018-11-13 11:59:06 +01:00
if ( m - > pending_reload_message & & sd_bus_message_get_bus ( m - > pending_reload_message ) = = * bus )
m - > pending_reload_message = sd_bus_message_unref ( m - > pending_reload_message ) ;
2010-04-06 16:32:07 +02:00
2013-11-19 21:12:59 +01:00
/* Possibly flush unwritten data, but only if we are
* unprivileged , since we don ' t want to sync here */
2016-02-24 21:24:23 +01:00
if ( ! MANAGER_IS_SYSTEM ( m ) )
2013-11-19 21:12:59 +01:00
sd_bus_flush ( * bus ) ;
2010-06-19 03:04:04 +02:00
2013-11-19 21:12:59 +01:00
/* And destroy the object */
2019-01-17 16:10:58 +01:00
* bus = sd_bus_close_unref ( * bus ) ;
2010-06-19 03:04:04 +02:00
}
2018-02-07 15:00:32 +01:00
void bus_done_api ( Manager * m ) {
2018-05-30 13:22:18 +02:00
destroy_bus ( m , & m - > api_bus ) ;
2018-02-07 15:00:32 +01:00
}
void bus_done_system ( Manager * m ) {
2018-05-30 13:22:18 +02:00
destroy_bus ( m , & m - > system_bus ) ;
2018-02-07 15:00:32 +01:00
}
void bus_done_private ( Manager * m ) {
sd_bus * b ;
assert ( m ) ;
2013-11-19 21:12:59 +01:00
while ( ( b = set_steal_first ( m - > private_buses ) ) )
destroy_bus ( m , & b ) ;
2010-04-15 23:16:16 +02:00
2015-09-09 23:12:07 +02:00
m - > private_buses = set_free ( m - > private_buses ) ;
2014-03-03 01:33:45 +01:00
2018-02-07 15:00:32 +01:00
m - > private_listen_event_source = sd_event_source_unref ( m - > private_listen_event_source ) ;
m - > private_listen_fd = safe_close ( m - > private_listen_fd ) ;
}
void bus_done ( Manager * m ) {
assert ( m ) ;
2010-04-15 23:16:16 +02:00
2018-02-07 15:00:32 +01:00
bus_done_api ( m ) ;
bus_done_system ( m ) ;
bus_done_private ( m ) ;
2010-04-15 23:16:16 +02:00
2018-02-07 15:00:32 +01:00
assert ( ! m - > subscribed ) ;
2014-08-06 11:45:36 +02:00
2018-02-07 15:00:32 +01:00
m - > deserialized_subscribed = strv_free ( m - > deserialized_subscribed ) ;
2014-08-06 11:45:36 +02:00
bus_verify_polkit_async_registry_free ( m - > polkit_registry ) ;
2010-07-05 00:58:07 +02:00
}
2011-04-28 22:07:01 +02:00
int bus_fdset_add_all ( Manager * m , FDSet * fds ) {
Iterator i ;
2013-11-19 21:12:59 +01:00
sd_bus * b ;
int fd ;
2011-04-28 22:07:01 +02:00
assert ( m ) ;
assert ( fds ) ;
/* When we are about to reexecute we add all D-Bus fds to the
* set to pass over to the newly executed systemd . They won ' t
2013-11-19 21:12:59 +01:00
* be used there however , except thatt they are closed at the
2011-04-28 22:07:01 +02:00
* very end of deserialization , those making it possible for
2011-04-28 23:51:24 +02:00
* clients to synchronously wait for systemd to reexec by
2011-04-28 22:07:01 +02:00
* simply waiting for disconnection */
2013-11-19 21:12:59 +01:00
if ( m - > api_bus ) {
fd = sd_bus_get_fd ( m - > api_bus ) ;
if ( fd > = 0 ) {
2011-04-28 22:07:01 +02:00
fd = fdset_put_dup ( fds , fd ) ;
if ( fd < 0 )
return fd ;
}
}
2013-11-19 21:12:59 +01:00
SET_FOREACH ( b , m - > private_buses , i ) {
fd = sd_bus_get_fd ( b ) ;
if ( fd > = 0 ) {
2011-04-28 22:07:01 +02:00
fd = fdset_put_dup ( fds , fd ) ;
if ( fd < 0 )
return fd ;
}
}
2013-11-19 21:12:59 +01:00
/* We don't offer any APIs on the system bus (well, unless it
* is the same as the API bus ) hence we don ' t bother with it
* here */
2013-07-10 19:24:03 +02:00
2013-11-19 21:12:59 +01:00
return 0 ;
2013-07-10 19:24:03 +02:00
}
2014-03-03 01:33:45 +01:00
int bus_foreach_bus (
Manager * m ,
sd_bus_track * subscribed2 ,
int ( * send_message ) ( sd_bus * bus , void * userdata ) ,
void * userdata ) {
Iterator i ;
sd_bus * b ;
int r , ret = 0 ;
2015-05-11 13:49:29 +02:00
/* Send to all direct buses, unconditionally */
2014-03-03 01:33:45 +01:00
SET_FOREACH ( b , m - > private_buses , i ) {
2018-02-13 18:27:47 +01:00
/* Don't bother with enqueing these messages to clients that haven't started yet */
if ( sd_bus_is_ready ( b ) < = 0 )
continue ;
2014-03-03 01:33:45 +01:00
r = send_message ( b , userdata ) ;
if ( r < 0 )
ret = r ;
}
/* Send to API bus, but only if somebody is subscribed */
2018-02-07 22:44:18 +01:00
if ( m - > api_bus & &
( sd_bus_track_count ( m - > subscribed ) > 0 | |
sd_bus_track_count ( subscribed2 ) > 0 ) ) {
2014-03-03 01:33:45 +01:00
r = send_message ( m - > api_bus , userdata ) ;
if ( r < 0 )
ret = r ;
}
return ret ;
}
2016-08-15 18:12:01 +02:00
void bus_track_serialize ( sd_bus_track * t , FILE * f , const char * prefix ) {
2014-03-03 01:33:45 +01:00
const char * n ;
2013-07-10 19:24:03 +02:00
assert ( f ) ;
2016-08-15 18:12:01 +02:00
assert ( prefix ) ;
2013-07-10 19:24:03 +02:00
2016-08-15 18:12:01 +02:00
for ( n = sd_bus_track_first ( t ) ; n ; n = sd_bus_track_next ( t ) ) {
int c , j ;
2014-12-02 00:15:13 +01:00
2016-08-15 18:12:01 +02:00
c = sd_bus_track_count_name ( t , n ) ;
2018-10-17 20:40:09 +02:00
for ( j = 0 ; j < c ; j + + )
( void ) serialize_item ( f , prefix , n ) ;
2016-08-15 18:12:01 +02:00
}
2014-03-03 01:33:45 +01:00
}
2016-08-15 18:12:01 +02:00
int bus_track_coldplug ( Manager * m , sd_bus_track * * t , bool recursive , char * * l ) {
2014-03-03 01:33:45 +01:00
int r = 0 ;
assert ( m ) ;
assert ( t ) ;
2016-08-15 18:12:01 +02:00
if ( strv_isempty ( l ) )
return 0 ;
2014-03-03 01:33:45 +01:00
2016-08-15 18:12:01 +02:00
if ( ! m - > api_bus )
return 0 ;
2014-03-03 01:33:45 +01:00
2016-08-15 18:12:01 +02:00
if ( ! * t ) {
r = sd_bus_track_new ( m - > api_bus , t , NULL , NULL ) ;
if ( r < 0 )
return r ;
2014-03-03 01:33:45 +01:00
}
2016-08-15 18:12:01 +02:00
r = sd_bus_track_set_recursive ( * t , recursive ) ;
if ( r < 0 )
return r ;
2016-11-15 19:18:36 +01:00
return bus_track_add_name_many ( * t , l ) ;
2013-07-10 19:24:03 +02:00
}
2014-08-06 11:45:36 +02:00
2015-02-18 17:40:57 +01:00
int bus_verify_manage_units_async ( Manager * m , sd_bus_message * call , sd_bus_error * error ) {
2015-09-05 16:07:16 +02:00
return bus_verify_polkit_async ( call , CAP_SYS_ADMIN , " org.freedesktop.systemd1.manage-units " , NULL , false , UID_INVALID , & m - > polkit_registry , error ) ;
2014-08-06 11:45:36 +02:00
}
int bus_verify_manage_unit_files_async ( Manager * m , sd_bus_message * call , sd_bus_error * error ) {
2015-09-05 16:07:16 +02:00
return bus_verify_polkit_async ( call , CAP_SYS_ADMIN , " org.freedesktop.systemd1.manage-unit-files " , NULL , false , UID_INVALID , & m - > polkit_registry , error ) ;
2014-08-06 11:45:36 +02:00
}
int bus_verify_reload_daemon_async ( Manager * m , sd_bus_message * call , sd_bus_error * error ) {
2015-09-05 16:07:16 +02:00
return bus_verify_polkit_async ( call , CAP_SYS_ADMIN , " org.freedesktop.systemd1.reload-daemon " , NULL , false , UID_INVALID , & m - > polkit_registry , error ) ;
2014-08-06 11:45:36 +02:00
}
2015-02-18 17:40:57 +01:00
int bus_verify_set_environment_async ( Manager * m , sd_bus_message * call , sd_bus_error * error ) {
2015-09-05 16:07:16 +02:00
return bus_verify_polkit_async ( call , CAP_SYS_ADMIN , " org.freedesktop.systemd1.set-environment " , NULL , false , UID_INVALID , & m - > polkit_registry , error ) ;
2015-02-18 17:40:57 +01:00
}
2018-02-13 18:30:34 +01:00
uint64_t manager_bus_n_queued_write ( Manager * m ) {
uint64_t c = 0 ;
Iterator i ;
sd_bus * b ;
int r ;
2019-04-27 02:22:40 +02:00
/* Returns the total number of messages queued for writing on all our direct and API buses. */
2018-02-13 18:30:34 +01:00
SET_FOREACH ( b , m - > private_buses , i ) {
uint64_t k ;
r = sd_bus_get_n_queued_write ( b , & k ) ;
if ( r < 0 )
log_debug_errno ( r , " Failed to query queued messages for private bus: %m " ) ;
else
c + = k ;
}
if ( m - > api_bus ) {
uint64_t k ;
r = sd_bus_get_n_queued_write ( m - > api_bus , & k ) ;
if ( r < 0 )
log_debug_errno ( r , " Failed to query queued messages for API bus: %m " ) ;
else
c + = k ;
}
return c ;
}
2018-05-28 11:13:19 +02:00
static void vtable_dump_bus_properties ( FILE * f , const sd_bus_vtable * table ) {
const sd_bus_vtable * i ;
for ( i = table ; i - > type ! = _SD_BUS_VTABLE_END ; i + + ) {
if ( ! IN_SET ( i - > type , _SD_BUS_VTABLE_PROPERTY , _SD_BUS_VTABLE_WRITABLE_PROPERTY ) | |
( i - > flags & ( SD_BUS_VTABLE_DEPRECATED | SD_BUS_VTABLE_HIDDEN ) ) ! = 0 )
continue ;
fprintf ( f , " %s \n " , i - > x . property . member ) ;
}
}
void dump_bus_properties ( FILE * f ) {
assert ( f ) ;
vtable_dump_bus_properties ( f , bus_automount_vtable ) ;
vtable_dump_bus_properties ( f , bus_cgroup_vtable ) ;
vtable_dump_bus_properties ( f , bus_device_vtable ) ;
vtable_dump_bus_properties ( f , bus_exec_vtable ) ;
vtable_dump_bus_properties ( f , bus_job_vtable ) ;
vtable_dump_bus_properties ( f , bus_kill_vtable ) ;
vtable_dump_bus_properties ( f , bus_manager_vtable ) ;
vtable_dump_bus_properties ( f , bus_mount_vtable ) ;
vtable_dump_bus_properties ( f , bus_path_vtable ) ;
vtable_dump_bus_properties ( f , bus_scope_vtable ) ;
vtable_dump_bus_properties ( f , bus_service_vtable ) ;
vtable_dump_bus_properties ( f , bus_slice_vtable ) ;
vtable_dump_bus_properties ( f , bus_socket_vtable ) ;
vtable_dump_bus_properties ( f , bus_swap_vtable ) ;
vtable_dump_bus_properties ( f , bus_target_vtable ) ;
vtable_dump_bus_properties ( f , bus_timer_vtable ) ;
vtable_dump_bus_properties ( f , bus_unit_vtable ) ;
vtable_dump_bus_properties ( f , bus_unit_cgroup_vtable ) ;
}