From 9fdb2a33f5f19a71f5d1785bbab1e5e94ee81cc7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 26 Aug 2011 23:11:47 +0200 Subject: [PATCH 3/3] activation: if systemd activation is enabled look directly in systemd unit directories for services Previously when systemd bus activation was to be used by a service it had to ship two .service files: one systemd unit file, and one D-Bus activation file. Both files carry the same suffix but contain very different contents. This patch makes it unnecessary to ship the D-Bus activation file, and -- if systemd activation is enabled -- teaches D-Bus to watch the systemd unit files directly. Enumeration of bus-activatable systemd units is very easy: if a unit file (usually symlink) is named "dbus-org.freedesktop.Foobar.service" then it can be bus activated. Hence, all D-Bus needs to do is iterate through the systemd unit directories and look for all files/symlinks whose name starts with "dbus-" and ends in ".service". Opening the files is not necessary. This patch makes the search path for systemd unit files configurable closely following the semantics how native D-Bus activation file search paths are configured. The default search paths is initialized from the information of the systemd pkg-config file. This also hooks up inotify change notification with this scheme. If other init systems want a similar kind of activation this patch lays the ground work for it, in that that the search path structure gains a type enumerator which could be extended for other init systems. This currently only covers systemd integration on the system bus. (session support is out of focus since in systemd we're aiming more for the user bus than the session bus, but the user bus doesn't exist yet). --- bus/activation.c | 412 ++++++++++++++++++++++++++++++++++++++------ bus/activation.h | 4 +- bus/bus.c | 15 ++- bus/config-parser-common.c | 12 ++ bus/config-parser-common.h | 2 + bus/config-parser.c | 88 +++++++++- bus/config-parser.h | 1 + configure.ac | 5 +- dbus/dbus-sysdeps-unix.c | 20 ++ dbus/dbus-sysdeps-win.c | 14 ++ dbus/dbus-sysdeps.h | 1 + 11 files changed, 512 insertions(+), 62 deletions(-) diff --git a/bus/activation.c b/bus/activation.c index 4d0a469..90b54c4 100644 --- a/bus/activation.c +++ b/bus/activation.c @@ -57,8 +57,15 @@ struct BusActivation DBusHashTable *environment; }; +typedef enum +{ + NATIVE_SERVICE_DIRECTORY, + SYSTEMD_SERVICE_DIRECTORY +} DBusServiceDirectoryType; + typedef struct { + DBusServiceDirectoryType type; int refcount; char *dir_c; DBusHashTable *entries; @@ -256,6 +263,7 @@ update_desktop_file_entry (BusActivation *activation, dbus_bool_t retval; _DBUS_ASSERT_ERROR_IS_CLEAR (error); + _dbus_assert (s_dir->type == NATIVE_SERVICE_DIRECTORY); name = NULL; exec = NULL; @@ -470,6 +478,137 @@ out: } static dbus_bool_t +load_systemd_file_entry (BusActivation *activation, + BusServiceDirectory *s_dir, + DBusString *filename, + DBusError *error) +{ + BusActivationEntry *entry; + DBusStat stat_buf; + DBusString file_path; + dbus_bool_t retval; + + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + _dbus_assert (s_dir->type == SYSTEMD_SERVICE_DIRECTORY); + + entry = NULL; + retval = FALSE; + + if (!_dbus_string_init (&file_path)) + { + BUS_SET_OOM (error); + return FALSE; + } + + if (!_dbus_string_append (&file_path, s_dir->dir_c) || + !_dbus_concat_dir_and_file (&file_path, filename)) + { + BUS_SET_OOM (error); + goto out; + } + + if (!_dbus_stat (&file_path, &stat_buf, NULL)) + { + dbus_set_error (error, DBUS_ERROR_FAILED, + "Can't stat the service file\n"); + goto out; + } + + if (!_dbus_stat_is_file (&stat_buf)) + { + dbus_set_error (error, DBUS_ERROR_FAILED, + "Service file is not a regular file\n"); + goto out; + } + + entry = _dbus_hash_table_lookup_string (s_dir->entries, + _dbus_string_get_const_data (filename)); + + if (entry == NULL) /* New file */ + { + int len; + char *name; + + /* Strip prefix and suffix of the file name. The caller will + have verified them for us, so we just blindly cut them off + here to get the bus name. This turns + "dbus-org.foobar.Waldo.service into org.foobar.Waldo. */ + len = _dbus_string_get_length (filename); + name = _dbus_memdup (_dbus_string_get_const_data (filename) + 5, len - 5 - 8 + 1); + if (!name) + { + BUS_SET_OOM (error); + goto out; + } + name[len - 5 - 8] = 0; + + if (_dbus_hash_table_lookup_string (activation->entries, name)) + { + dbus_set_error (error, DBUS_ERROR_FAILED, + "Service %s already exists in activation entry list\n", name); + dbus_free(name); + goto out; + } + + entry = dbus_new0 (BusActivationEntry, 1); + if (entry == NULL) + { + BUS_SET_OOM (error); + dbus_free(name); + goto out; + } + + entry->refcount = 1; + entry->s_dir = s_dir; + entry->name = name; + + /* The filename and systemd service name in this case are the + same */ + entry->systemd_service = _dbus_strdup (_dbus_string_get_const_data (filename)); + if (!entry->systemd_service) + { + BUS_SET_OOM (error); + goto out; + } + + entry->filename = _dbus_strdup (_dbus_string_get_const_data (filename)); + if (!entry->filename) + { + BUS_SET_OOM (error); + goto out; + } + + if (!_dbus_hash_table_insert_string (activation->entries, entry->name, bus_activation_entry_ref (entry))) + { + BUS_SET_OOM (error); + goto out; + } + + if (!_dbus_hash_table_insert_string (s_dir->entries, entry->filename, bus_activation_entry_ref (entry))) + { + /* Revert the insertion in the entries table */ + _dbus_hash_table_remove_string (activation->entries, entry->name); + BUS_SET_OOM (error); + goto out; + } + + _dbus_verbose ("Added \"%s\" to list of services\n", entry->name); + } + + entry->mtime = stat_buf.mtime; + retval = TRUE; + +out: + /* if these have been transferred into entry, the variables will be NULL */ + _dbus_string_free (&file_path); + + if (entry) + bus_activation_entry_unref (entry); + + return retval; +} + +static dbus_bool_t check_service_file (BusActivation *activation, BusActivationEntry *entry, BusActivationEntry **updated_entry, @@ -573,9 +712,9 @@ out: * hash entries it already added. */ static dbus_bool_t -update_directory (BusActivation *activation, - BusServiceDirectory *s_dir, - DBusError *error) +update_native_directory (BusActivation *activation, + BusServiceDirectory *s_dir, + DBusError *error) { DBusDirIter *iter; DBusString dir, filename; @@ -586,6 +725,7 @@ update_directory (BusActivation *activation, DBusString full_path; _DBUS_ASSERT_ERROR_IS_CLEAR (error); + _dbus_assert (s_dir->type == NATIVE_SERVICE_DIRECTORY); iter = NULL; desktop_file = NULL; @@ -718,6 +858,129 @@ update_directory (BusActivation *activation, } static dbus_bool_t +update_systemd_directory (BusActivation *activation, + BusServiceDirectory *s_dir, + DBusError *error) +{ + DBusDirIter *iter; + DBusString dir, filename; + DBusError tmp_error; + dbus_bool_t retval; + BusActivationEntry *entry; + DBusString full_path; + + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + _dbus_assert (s_dir->type == SYSTEMD_SERVICE_DIRECTORY); + + iter = NULL; + + _dbus_string_init_const (&dir, s_dir->dir_c); + + if (!_dbus_string_init (&filename)) + { + BUS_SET_OOM (error); + return FALSE; + } + + if (!_dbus_string_init (&full_path)) + { + BUS_SET_OOM (error); + _dbus_string_free (&filename); + return FALSE; + } + + retval = FALSE; + + /* from this point it's safe to "goto out" */ + + iter = _dbus_directory_open (&dir, error); + if (iter == NULL) + { + _dbus_verbose ("Failed to open directory %s: %s\n", + s_dir->dir_c, + error ? error->message : "unknown"); + goto out; + } + + /* Now read the files */ + dbus_error_init (&tmp_error); + while (_dbus_directory_get_next_file (iter, &filename, &tmp_error)) + { + _dbus_assert (!dbus_error_is_set (&tmp_error)); + + _dbus_string_set_length (&full_path, 0); + + if (!_dbus_string_ends_with_c_str (&filename, ".service") || + !_dbus_string_starts_with_c_str (&filename, "dbus-")) + { + _dbus_verbose ("Skipping non-activation file %s\n", + _dbus_string_get_const_data (&filename)); + continue; + } + + entry = _dbus_hash_table_lookup_string (s_dir->entries, _dbus_string_get_const_data (&filename)); + if (entry) /* Already has this service file in the cache */ + continue; + + if (!_dbus_string_append (&full_path, s_dir->dir_c) || + !_dbus_concat_dir_and_file (&full_path, &filename)) + { + BUS_SET_OOM (error); + goto out; + } + + if (!load_systemd_file_entry (activation, s_dir, &filename, &tmp_error)) + { + _dbus_verbose ("Could not add %s to activation entry list: %s\n", + _dbus_string_get_const_data (&full_path), tmp_error.message); + + if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY)) + { + dbus_move_error (&tmp_error, error); + goto out; + } + + dbus_error_free (&tmp_error); + continue; + } + else + continue; + } + + if (dbus_error_is_set (&tmp_error)) + { + dbus_move_error (&tmp_error, error); + goto out; + } + + retval = TRUE; + + out: + if (!retval) + _DBUS_ASSERT_ERROR_IS_SET (error); + else + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + + if (iter != NULL) + _dbus_directory_close (iter); + _dbus_string_free (&filename); + _dbus_string_free (&full_path); + + return retval; +} + +static dbus_bool_t +update_directory (BusActivation *activation, + BusServiceDirectory *s_dir, + DBusError *error) +{ + if (s_dir->type == SYSTEMD_SERVICE_DIRECTORY) + return update_systemd_directory (activation, s_dir, error); + else + return update_native_directory (activation, s_dir, error); +} + +static dbus_bool_t populate_environment (BusActivation *activation) { DBusString key; @@ -780,14 +1043,71 @@ out: return retval; } +static dbus_bool_t +bus_activation_reload_one (BusActivation *activation, + const char *directory, + DBusServiceDirectoryType type, + DBusError *error) +{ + char *dir; + BusServiceDirectory *s_dir; + + dir = _dbus_strdup (directory); + if (!dir) + { + BUS_SET_OOM (error); + return FALSE; + } + + s_dir = dbus_new0 (BusServiceDirectory, 1); + if (!s_dir) + { + dbus_free (dir); + BUS_SET_OOM (error); + return FALSE; + } + + s_dir->refcount = 1; + s_dir->dir_c = dir; + s_dir->type = type; + + s_dir->entries = _dbus_hash_table_new (DBUS_HASH_STRING, NULL, + (DBusFreeFunction)bus_activation_entry_unref); + + if (!s_dir->entries) + { + bus_service_directory_unref (s_dir); + BUS_SET_OOM (error); + return FALSE; + } + + if (!_dbus_hash_table_insert_string (activation->directories, s_dir->dir_c, s_dir)) + { + bus_service_directory_unref (s_dir); + BUS_SET_OOM (error); + return FALSE; + } + + /* only fail on OOM, it is ok if we can't read the directory */ + if (!update_directory (activation, s_dir, error)) + { + if (dbus_error_has_name (error, DBUS_ERROR_NO_MEMORY)) + return FALSE; + + dbus_error_free (error); + } + + return TRUE; +} + dbus_bool_t bus_activation_reload (BusActivation *activation, const DBusString *address, DBusList **directories, + DBusList **systemd_directories, DBusError *error) { DBusList *link; - char *dir; if (activation->server_address != NULL) dbus_free (activation->server_address); @@ -821,53 +1141,31 @@ bus_activation_reload (BusActivation *activation, link = _dbus_list_get_first_link (directories); while (link != NULL) { - BusServiceDirectory *s_dir; - - dir = _dbus_strdup ((const char *) link->data); - if (!dir) - { - BUS_SET_OOM (error); - goto failed; - } - - s_dir = dbus_new0 (BusServiceDirectory, 1); - if (!s_dir) - { - dbus_free (dir); - BUS_SET_OOM (error); - goto failed; - } + if (!bus_activation_reload_one (activation, + link->data, + NATIVE_SERVICE_DIRECTORY, + error)) + goto failed; - s_dir->refcount = 1; - s_dir->dir_c = dir; - - s_dir->entries = _dbus_hash_table_new (DBUS_HASH_STRING, NULL, - (DBusFreeFunction)bus_activation_entry_unref); - - if (!s_dir->entries) - { - bus_service_directory_unref (s_dir); - BUS_SET_OOM (error); - goto failed; - } + link = _dbus_list_get_next_link (directories, link); + } - if (!_dbus_hash_table_insert_string (activation->directories, s_dir->dir_c, s_dir)) - { - bus_service_directory_unref (s_dir); - BUS_SET_OOM (error); - goto failed; - } + if (bus_context_get_systemd_activation (activation->context)) + { + /* Only enumerate systemd service files when systemd activation + is enabled */ - /* only fail on OOM, it is ok if we can't read the directory */ - if (!update_directory (activation, s_dir, error)) + link = _dbus_list_get_first_link (systemd_directories); + while (link != NULL) { - if (dbus_error_has_name (error, DBUS_ERROR_NO_MEMORY)) + if (!bus_activation_reload_one (activation, + link->data, + SYSTEMD_SERVICE_DIRECTORY, + error)) goto failed; - else - dbus_error_free (error); - } - link = _dbus_list_get_next_link (directories, link); + link = _dbus_list_get_next_link (systemd_directories, link); + } } return TRUE; @@ -879,6 +1177,7 @@ BusActivation* bus_activation_new (BusContext *context, const DBusString *address, DBusList **directories, + DBusList **systemd_directories, DBusError *error) { BusActivation *activation; @@ -898,7 +1197,7 @@ bus_activation_new (BusContext *context, activation->context = context; activation->n_pending_activations = 0; - if (!bus_activation_reload (activation, address, directories, error)) + if (!bus_activation_reload (activation, address, directories, systemd_directories, error)) goto failed; /* Initialize this hash table once, we don't want to lose pending @@ -1795,14 +2094,17 @@ bus_activation_activate_service (BusActivation *activation, return FALSE; } - pending_activation->exec = _dbus_strdup (entry->exec); - if (!pending_activation->exec) + if (entry->exec) { - _dbus_verbose ("Failed to copy service exec for pending activation\n"); - BUS_SET_OOM (error); - bus_pending_activation_unref (pending_activation); - bus_pending_activation_entry_free (pending_activation_entry); - return FALSE; + pending_activation->exec = _dbus_strdup (entry->exec); + if (!pending_activation->exec) + { + _dbus_verbose ("Failed to copy service exec for pending activation\n"); + BUS_SET_OOM (error); + bus_pending_activation_unref (pending_activation); + bus_pending_activation_entry_free (pending_activation_entry); + return FALSE; + } } if (entry->systemd_service) @@ -2444,15 +2746,17 @@ do_service_reload_test (DBusString *dir, dbus_bool_t oom_test) BusActivation *activation; DBusString address; DBusList *directories; + DBusList *systemd_directories; CheckData d; directories = NULL; + systemd_directories = NULL; _dbus_string_init_const (&address, ""); if (!_dbus_list_append (&directories, _dbus_string_get_data (dir))) return FALSE; - activation = bus_activation_new (NULL, &address, &directories, NULL); + activation = bus_activation_new (NULL, &address, &directories, &systemd_directories, NULL); if (!activation) return FALSE; diff --git a/bus/activation.h b/bus/activation.h index 97f25b1..c56facd 100644 --- a/bus/activation.h +++ b/bus/activation.h @@ -31,10 +31,12 @@ BusActivation* bus_activation_new (BusContext *context, const DBusString *address, DBusList **directories, + DBusList **systemd_directories, DBusError *error); -dbus_bool_t bus_activation_reload (BusActivation *activation, +dbus_bool_t bus_activation_reload (BusActivation *activation, const DBusString *address, DBusList **directories, + DBusList **systemd_directories, DBusError *error); BusActivation* bus_activation_ref (BusActivation *activation); void bus_activation_unref (BusActivation *activation); diff --git a/bus/bus.c b/bus/bus.c index 04b1286..826fdbc 100644 --- a/bus/bus.c +++ b/bus/bus.c @@ -480,7 +480,7 @@ process_config_every_time (BusContext *context, { DBusString full_address; DBusList *link; - DBusList **dirs; + DBusList **dirs, **systemd_dirs; BusActivation *new_activation; char *addr; const char *servicehelper; @@ -552,6 +552,7 @@ process_config_every_time (BusContext *context, /* get the service directories */ dirs = bus_config_parser_get_service_dirs (parser); + systemd_dirs = bus_config_parser_get_systemd_service_dirs (parser); /* and the service helper */ servicehelper = bus_config_parser_get_servicehelper (parser); @@ -571,12 +572,12 @@ process_config_every_time (BusContext *context, /* Create activation subsystem */ if (context->activation) { - if (!bus_activation_reload (context->activation, &full_address, dirs, error)) + if (!bus_activation_reload (context->activation, &full_address, dirs, systemd_dirs, error)) goto failed; } else { - context->activation = bus_activation_new (context, &full_address, dirs, error); + context->activation = bus_activation_new (context, &full_address, dirs, systemd_dirs, error); } if (context->activation == NULL) @@ -600,6 +601,7 @@ process_config_every_time (BusContext *context, static dbus_bool_t list_concat_new (DBusList **a, DBusList **b, + DBusList **c, DBusList **result) { DBusList *link; @@ -616,6 +618,12 @@ list_concat_new (DBusList **a, if (!_dbus_list_append (result, link->data)) goto oom; } + if (c != NULL) + for (link = _dbus_list_get_first_link (c); link; link = _dbus_list_get_next_link (c, link)) + { + if (!_dbus_list_append (result, link->data)) + goto oom; + } return TRUE; oom: @@ -666,6 +674,7 @@ process_config_postinit (BusContext *context, */ if (!list_concat_new (bus_config_parser_get_conf_dirs (parser), bus_config_parser_get_service_dirs (parser), + bus_config_parser_get_systemd_service_dirs (parser), &watched_dirs)) { BUS_SET_OOM (error); diff --git a/bus/config-parser-common.c b/bus/config-parser-common.c index c522ff4..ac5f891 100644 --- a/bus/config-parser-common.c +++ b/bus/config-parser-common.c @@ -91,10 +91,18 @@ bus_config_parser_element_name_to_type (const char *name) { return ELEMENT_STANDARD_SYSTEM_SERVICEDIRS; } + else if (strcmp (name, "standard_system_systemd_servicedirs") == 0) + { + return ELEMENT_STANDARD_SYSTEM_SYSTEMD_SERVICEDIRS; + } else if (strcmp (name, "servicedir") == 0) { return ELEMENT_SERVICEDIR; } + else if (strcmp (name, "systemd_servicedir") == 0) + { + return ELEMENT_SYSTEMD_SERVICEDIR; + } else if (strcmp (name, "include") == 0) { return ELEMENT_INCLUDE; @@ -163,8 +171,12 @@ bus_config_parser_element_type_to_name (ElementType type) return "standard_session_servicedirs"; case ELEMENT_STANDARD_SYSTEM_SERVICEDIRS: return "standard_system_servicedirs"; + case ELEMENT_STANDARD_SYSTEM_SYSTEMD_SERVICEDIRS: + return "standard_system_systemd_servicedirs"; case ELEMENT_SERVICEDIR: return "servicedir"; + case ELEMENT_SYSTEMD_SERVICEDIR: + return "systemd_servicedir"; case ELEMENT_SERVICEHELPER: return "servicehelper"; case ELEMENT_INCLUDEDIR: diff --git a/bus/config-parser-common.h b/bus/config-parser-common.h index 186bf4c..a7c1536 100644 --- a/bus/config-parser-common.h +++ b/bus/config-parser-common.h @@ -39,6 +39,7 @@ typedef enum ELEMENT_FORK, ELEMENT_PIDFILE, ELEMENT_SERVICEDIR, + ELEMENT_SYSTEMD_SERVICEDIR, ELEMENT_SERVICEHELPER, ELEMENT_INCLUDEDIR, /* this is really , but winioctl.h defines ELEMENT_TYPE */ @@ -47,6 +48,7 @@ typedef enum ELEMENT_ASSOCIATE, ELEMENT_STANDARD_SESSION_SERVICEDIRS, ELEMENT_STANDARD_SYSTEM_SERVICEDIRS, + ELEMENT_STANDARD_SYSTEM_SYSTEMD_SERVICEDIRS, ELEMENT_KEEP_UMASK, ELEMENT_SYSLOG, ELEMENT_ALLOW_ANONYMOUS diff --git a/bus/config-parser.c b/bus/config-parser.c index 21c41c3..7408724 100644 --- a/bus/config-parser.c +++ b/bus/config-parser.c @@ -99,6 +99,7 @@ struct BusConfigParser DBusList *mechanisms; /**< Auth mechanisms */ DBusList *service_dirs; /**< Directories to look for session services in */ + DBusList *systemd_service_dirs; /**< Same for systemd services */ DBusList *conf_dirs; /**< Directories to look for policy configuration in */ @@ -333,6 +334,9 @@ merge_included (BusConfigParser *parser, while ((link = _dbus_list_pop_first_link (&included->service_dirs))) service_dirs_append_link_unique_or_free (&parser->service_dirs, link); + while ((link = _dbus_list_pop_first_link (&included->systemd_service_dirs))) + service_dirs_append_link_unique_or_free (&parser->systemd_service_dirs, link); + while ((link = _dbus_list_pop_first_link (&included->conf_dirs))) _dbus_list_append_link (&parser->conf_dirs, link); @@ -503,6 +507,12 @@ bus_config_parser_unref (BusConfigParser *parser) _dbus_list_clear (&parser->service_dirs); + _dbus_list_foreach (&parser->systemd_service_dirs, + (DBusForeachFunction) dbus_free, + NULL); + + _dbus_list_clear (&parser->systemd_service_dirs); + _dbus_list_foreach (&parser->conf_dirs, (DBusForeachFunction) dbus_free, NULL); @@ -865,6 +875,32 @@ start_busconfig_child (BusConfigParser *parser, return TRUE; } + else if (element_type == ELEMENT_STANDARD_SYSTEM_SYSTEMD_SERVICEDIRS) + { + DBusList *link; + DBusList *dirs; + dirs = NULL; + + if (!check_no_attributes (parser, "standard_system_systemd_servicedirs", attribute_names, attribute_values, error)) + return FALSE; + + if (push_element (parser, ELEMENT_STANDARD_SYSTEM_SYSTEMD_SERVICEDIRS) == NULL) + { + BUS_SET_OOM (error); + return FALSE; + } + + if (!_dbus_get_standard_system_systemd_servicedirs (&dirs)) + { + BUS_SET_OOM (error); + return FALSE; + } + + while ((link = _dbus_list_pop_first_link (&dirs))) + service_dirs_append_link_unique_or_free (&parser->systemd_service_dirs, link); + + return TRUE; + } else if (element_type == ELEMENT_ALLOW_ANONYMOUS) { if (!check_no_attributes (parser, "allow_anonymous", attribute_names, attribute_values, error)) @@ -2010,6 +2046,7 @@ bus_config_parser_end_element (BusConfigParser *parser, case ELEMENT_PIDFILE: case ELEMENT_AUTH: case ELEMENT_SERVICEDIR: + case ELEMENT_SYSTEMD_SERVICEDIR: case ELEMENT_SERVICEHELPER: case ELEMENT_INCLUDEDIR: case ELEMENT_LIMIT: @@ -2040,6 +2077,7 @@ bus_config_parser_end_element (BusConfigParser *parser, case ELEMENT_ASSOCIATE: case ELEMENT_STANDARD_SESSION_SERVICEDIRS: case ELEMENT_STANDARD_SYSTEM_SERVICEDIRS: + case ELEMENT_STANDARD_SYSTEM_SYSTEMD_SERVICEDIRS: case ELEMENT_ALLOW_ANONYMOUS: break; } @@ -2335,8 +2373,9 @@ bus_config_parser_content (BusConfigParser *parser, case ELEMENT_FORK: case ELEMENT_SYSLOG: case ELEMENT_KEEP_UMASK: - case ELEMENT_STANDARD_SESSION_SERVICEDIRS: - case ELEMENT_STANDARD_SYSTEM_SERVICEDIRS: + case ELEMENT_STANDARD_SESSION_SERVICEDIRS: + case ELEMENT_STANDARD_SYSTEM_SERVICEDIRS: + case ELEMENT_STANDARD_SYSTEM_SYSTEMD_SERVICEDIRS: case ELEMENT_ALLOW_ANONYMOUS: case ELEMENT_SELINUX: case ELEMENT_ASSOCIATE: @@ -2559,6 +2598,40 @@ bus_config_parser_content (BusConfigParser *parser, } break; + case ELEMENT_SYSTEMD_SERVICEDIR: + { + char *s; + DBusString full_path; + + e->had_content = TRUE; + + if (!_dbus_string_init (&full_path)) + goto nomem; + + if (!make_full_path (&parser->basedir, content, &full_path)) + { + _dbus_string_free (&full_path); + goto nomem; + } + + if (!_dbus_string_copy_data (&full_path, &s)) + { + _dbus_string_free (&full_path); + goto nomem; + } + + /* _only_ extra session directories can be specified */ + if (!service_dirs_append_unique_or_free (&parser->systemd_service_dirs, s)) + { + _dbus_string_free (&full_path); + dbus_free (s); + goto nomem; + } + + _dbus_string_free (&full_path); + } + break; + case ELEMENT_LIMIT: { long val; @@ -2647,6 +2720,12 @@ bus_config_parser_get_service_dirs (BusConfigParser *parser) } DBusList** +bus_config_parser_get_systemd_service_dirs (BusConfigParser *parser) +{ + return &parser->systemd_service_dirs; +} + +DBusList** bus_config_parser_get_conf_dirs (BusConfigParser *parser) { return &parser->conf_dirs; @@ -3058,7 +3137,10 @@ config_parsers_equal (const BusConfigParser *a, if (!lists_of_c_strings_equal (a->service_dirs, b->service_dirs)) return FALSE; - + + if (!lists_of_c_strings_equal (a->systemd_service_dirs, b->systemd_service_dirs)) + return FALSE; + /* FIXME: compare policy */ /* FIXME: compare service selinux ID table */ diff --git a/bus/config-parser.h b/bus/config-parser.h index ba5bf74..455a121 100644 --- a/bus/config-parser.h +++ b/bus/config-parser.h @@ -69,6 +69,7 @@ dbus_bool_t bus_config_parser_get_keep_umask (BusConfigParser *parser); const char* bus_config_parser_get_pidfile (BusConfigParser *parser); const char* bus_config_parser_get_servicehelper (BusConfigParser *parser); DBusList** bus_config_parser_get_service_dirs (BusConfigParser *parser); +DBusList** bus_config_parser_get_systemd_service_dirs (BusConfigParser *parser); DBusList** bus_config_parser_get_conf_dirs (BusConfigParser *parser); BusPolicy* bus_config_parser_steal_policy (BusConfigParser *parser); void bus_config_parser_get_limits (BusConfigParser *parser, diff --git a/configure.ac b/configure.ac index b60e417..d1a5978 100644 --- a/configure.ac +++ b/configure.ac @@ -1396,12 +1396,15 @@ AM_CONDITIONAL(DBUS_INIT_SCRIPTS_CYGWIN, test x$with_init_scripts = xcygwin) ##### systemd unit files AC_ARG_WITH([systemdsystemunitdir], AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]), - [], [with_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)]) + [], [with_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd) ; + systemdsystemunitpath=$($PKG_CONFIG --variable=systemdsystemunitpath systemd)]) if test "x$with_systemdsystemunitdir" != xno; then AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir]) fi AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$with_systemdsystemunitdir" -a "x$with_systemdsystemunitdir" != xno ]) +AC_DEFINE_UNQUOTED(SYSTEMD_SYSTEM_UNIT_PATH, "$systemdsystemunitpath", [systemd unit search path]) + ##### Set up location for system bus socket if ! test -z "$with_system_socket"; then DBUS_SYSTEM_SOCKET=$with_system_socket diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c index 1c7c7aa..046b13d 100644 --- a/dbus/dbus-sysdeps-unix.c +++ b/dbus/dbus-sysdeps-unix.c @@ -3729,6 +3729,26 @@ _dbus_get_standard_system_servicedirs (DBusList **dirs) } /** + * Returns the standard directories for a system bus to look for systemd service + * activation files in + * + * @param dirs the directory list we are returning + * @returns #FALSE on OOM + */ +dbus_bool_t +_dbus_get_standard_system_systemd_servicedirs (DBusList **dirs) +{ + DBusString path; + dbus_bool_t retval; + + _dbus_string_init_const (&path, SYSTEMD_SYSTEM_UNIT_PATH); + retval = _dbus_split_paths_and_append (&path, "", dirs); + _dbus_string_free (&path); + + return retval; +} + +/** * Append the absolute path of the system.conf file * (there is no system bus on Windows so this can just * return FALSE and print a warning or something) diff --git a/dbus/dbus-sysdeps-win.c b/dbus/dbus-sysdeps-win.c index f9afada..140f548 100644 --- a/dbus/dbus-sysdeps-win.c +++ b/dbus/dbus-sysdeps-win.c @@ -3049,6 +3049,20 @@ _dbus_get_standard_system_servicedirs (DBusList **dirs) return TRUE; } +/** + * Returns the standard directories for a system bus to look for systemd service + * activation files in + * + * @param dirs the directory list we are returning + * @returns #FALSE on OOM + */ +dbus_bool_t +_dbus_get_standard_system_systemd_servicedirs (DBusList **dirs) +{ + *dirs = NULL; + return TRUE; +} + _DBUS_DEFINE_GLOBAL_LOCK (atomic); /** diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h index 65434f2..747c77b 100644 --- a/dbus/dbus-sysdeps.h +++ b/dbus/dbus-sysdeps.h @@ -323,6 +323,7 @@ dbus_bool_t _dbus_path_is_absolute (const DBusString *filename); dbus_bool_t _dbus_get_standard_session_servicedirs (DBusList **dirs); dbus_bool_t _dbus_get_standard_system_servicedirs (DBusList **dirs); +dbus_bool_t _dbus_get_standard_system_systemd_servicedirs (DBusList **dirs); dbus_bool_t _dbus_append_system_config_file (DBusString *str); dbus_bool_t _dbus_append_session_config_file (DBusString *str); -- 1.7.6