diff options
-rw-r--r-- | src/core/load-dropin.c | 138 | ||||
-rw-r--r-- | src/core/load-dropin.h | 9 | ||||
-rw-r--r-- | src/core/unit.c | 2 | ||||
-rw-r--r-- | src/shared/dropin.c | 136 | ||||
-rw-r--r-- | src/shared/dropin.h | 29 |
5 files changed, 189 insertions, 125 deletions
diff --git a/src/core/load-dropin.c b/src/core/load-dropin.c index 8afaf45fe6..8be190040e 100644 --- a/src/core/load-dropin.c +++ b/src/core/load-dropin.c @@ -31,137 +31,27 @@ #include "load-fragment.h" #include "conf-files.h" -static int iterate_dir( - Unit *u, - const char *path, +static int add_dependency_consumer( UnitDependency dependency, - char ***strv) { - - _cleanup_closedir_ DIR *d = NULL; + const char *entry, + const char* filepath, + void *arg) { + Unit *u = arg; int r; assert(u); - assert(path); - - /* The config directories are special, since the order of the - * drop-ins matters */ - if (dependency < 0) { - r = strv_extend(strv, path); - if (r < 0) - return log_oom(); - - return 0; - } - - d = opendir(path); - if (!d) { - if (errno == ENOENT) - return 0; - - log_error_errno(errno, "Failed to open directory %s: %m", path); - return -errno; - } - - for (;;) { - struct dirent *de; - _cleanup_free_ char *f = NULL; - - errno = 0; - de = readdir(d); - if (!de && errno != 0) - return log_error_errno(errno, "Failed to read directory %s: %m", path); - - if (!de) - break; - - if (ignore_file(de->d_name)) - continue; - f = strjoin(path, "/", de->d_name, NULL); - if (!f) - return log_oom(); - - r = unit_add_dependency_by_name(u, dependency, de->d_name, f, true); - if (r < 0) - log_error_errno(r, "Cannot add dependency %s to %s, ignoring: %m", de->d_name, u->id); - } + r = unit_add_dependency_by_name(u, dependency, entry, filepath, true); + if (r < 0) + log_error_errno(r, "Cannot add dependency %s to %s, ignoring: %m", entry, u->id); return 0; } -static int process_dir( - Unit *u, - const char *unit_path, - const char *name, - const char *suffix, - UnitDependency dependency, - char ***strv) { - - _cleanup_free_ char *path = NULL; - - assert(u); - assert(unit_path); - assert(name); - assert(suffix); - - path = strjoin(unit_path, "/", name, suffix, NULL); - if (!path) - return log_oom(); - - if (!u->manager->unit_path_cache || set_get(u->manager->unit_path_cache, path)) - iterate_dir(u, path, dependency, strv); - - if (u->instance) { - _cleanup_free_ char *template = NULL, *p = NULL; - /* Also try the template dir */ - - template = unit_name_template(name); - if (!template) - return log_oom(); - - p = strjoin(unit_path, "/", template, suffix, NULL); - if (!p) - return log_oom(); - - if (!u->manager->unit_path_cache || set_get(u->manager->unit_path_cache, p)) - iterate_dir(u, p, dependency, strv); - } - - return 0; -} - -char **unit_find_dropin_paths(Unit *u) { - _cleanup_strv_free_ char **strv = NULL; - char **configs = NULL; - Iterator i; - char *t; - int r; - - assert(u); - - SET_FOREACH(t, u->names, i) { - char **p; - - STRV_FOREACH(p, u->manager->lookup_paths.unit_path) - process_dir(u, *p, t, ".d", _UNIT_DEPENDENCY_INVALID, &strv); - } - - if (strv_isempty(strv)) - return NULL; - - r = conf_files_list_strv(&configs, ".conf", NULL, (const char**) strv); - if (r < 0) { - log_error_errno(r, "Failed to get list of configuration files: %m"); - strv_free(configs); - return NULL; - } - - return configs; -} - int unit_load_dropin(Unit *u) { Iterator i; char *t, **f; + int r; assert(u); @@ -171,13 +61,15 @@ int unit_load_dropin(Unit *u) { char **p; STRV_FOREACH(p, u->manager->lookup_paths.unit_path) { - process_dir(u, *p, t, ".wants", UNIT_WANTS, NULL); - process_dir(u, *p, t, ".requires", UNIT_REQUIRES, NULL); + unit_file_process_dir(u->manager->unit_path_cache, *p, t, ".wants", UNIT_WANTS, + add_dependency_consumer, u, NULL); + unit_file_process_dir(u->manager->unit_path_cache, *p, t, ".requires", UNIT_REQUIRES, + add_dependency_consumer, u, NULL); } } - u->dropin_paths = unit_find_dropin_paths(u); - if (!u->dropin_paths) + r = unit_find_dropin_paths(u, &u->dropin_paths); + if (r <= 0) return 0; STRV_FOREACH(f, u->dropin_paths) { diff --git a/src/core/load-dropin.h b/src/core/load-dropin.h index fd551179e2..1e018c4525 100644 --- a/src/core/load-dropin.h +++ b/src/core/load-dropin.h @@ -22,8 +22,15 @@ ***/ #include "unit.h" +#include "dropin.h" /* Read service data supplementary drop-in directories */ -char **unit_find_dropin_paths(Unit *u); +static inline int unit_find_dropin_paths(Unit *u, char ***paths) { + return unit_file_find_dropin_paths(u->manager->lookup_paths.unit_path, + u->manager->unit_path_cache, + u->names, + paths); +} + int unit_load_dropin(Unit *u); diff --git a/src/core/unit.c b/src/core/unit.c index 8cec0e7e7f..a2f37282db 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -2894,7 +2894,7 @@ bool unit_need_daemon_reload(Unit *u) { return true; } - t = unit_find_dropin_paths(u); + (void) unit_find_dropin_paths(u, &t); loaded_cnt = strv_length(t); current_cnt = strv_length(u->dropin_paths); diff --git a/src/shared/dropin.c b/src/shared/dropin.c index c5c4f95719..40e6fee1c4 100644 --- a/src/shared/dropin.c +++ b/src/shared/dropin.c @@ -21,8 +21,10 @@ #include "dropin.h" #include "util.h" +#include "strv.h" #include "mkdir.h" #include "fileio-label.h" +#include "conf-files.h" int drop_in_file(const char *dir, const char *unit, unsigned level, const char *name, char **_p, char **_q) { @@ -100,3 +102,137 @@ int write_drop_in_format(const char *dir, const char *unit, unsigned level, return write_drop_in(dir, unit, level, name, p); } + +static int iterate_dir( + const char *path, + UnitDependency dependency, + dependency_consumer_t consumer, + void *arg, + char ***strv) { + + _cleanup_closedir_ DIR *d = NULL; + int r; + + assert(path); + + /* The config directories are special, since the order of the + * drop-ins matters */ + if (dependency < 0) { + r = strv_extend(strv, path); + if (r < 0) + return log_oom(); + + return 0; + } + + assert(consumer); + + d = opendir(path); + if (!d) { + if (errno == ENOENT) + return 0; + + log_error_errno(errno, "Failed to open directory %s: %m", path); + return -errno; + } + + for (;;) { + struct dirent *de; + _cleanup_free_ char *f = NULL; + + errno = 0; + de = readdir(d); + if (!de && errno != 0) + return log_error_errno(errno, "Failed to read directory %s: %m", path); + + if (!de) + break; + + if (ignore_file(de->d_name)) + continue; + + f = strjoin(path, "/", de->d_name, NULL); + if (!f) + return log_oom(); + + r = consumer(dependency, de->d_name, f, arg); + if (r < 0) + return r; + } + + return 0; +} + +int unit_file_process_dir( + Set * unit_path_cache, + const char *unit_path, + const char *name, + const char *suffix, + UnitDependency dependency, + dependency_consumer_t consumer, + void *arg, + char ***strv) { + + _cleanup_free_ char *path = NULL; + + assert(unit_path); + assert(name); + assert(suffix); + + path = strjoin(unit_path, "/", name, suffix, NULL); + if (!path) + return log_oom(); + + if (!unit_path_cache || set_get(unit_path_cache, path)) + iterate_dir(path, dependency, consumer, arg, strv); + + if (unit_name_is_instance(name)) { + _cleanup_free_ char *template = NULL, *p = NULL; + /* Also try the template dir */ + + template = unit_name_template(name); + if (!template) + return log_oom(); + + p = strjoin(unit_path, "/", template, suffix, NULL); + if (!p) + return log_oom(); + + if (!unit_path_cache || set_get(unit_path_cache, p)) + iterate_dir(p, dependency, consumer, arg, strv); + } + + return 0; +} + +int unit_file_find_dropin_paths( + char **lookup_path, + Set *unit_path_cache, + Set *names, + char ***paths) { + + _cleanup_strv_free_ char **strv = NULL, **ans = NULL; + Iterator i; + char *t; + int r; + + assert(paths); + + SET_FOREACH(t, names, i) { + char **p; + + STRV_FOREACH(p, lookup_path) + unit_file_process_dir(unit_path_cache, *p, t, ".d", _UNIT_DEPENDENCY_INVALID, NULL, NULL, &strv); + } + + if (strv_isempty(strv)) + return 0; + + r = conf_files_list_strv(&ans, ".conf", NULL, (const char**) strv); + if (r < 0) + return log_warning_errno(r, "Failed to get list of configuration files: %m"); + + *paths = ans; + ans = NULL; + return 1; +} diff --git a/src/shared/dropin.h b/src/shared/dropin.h index 9c9742d0e4..d4531fca2d 100644 --- a/src/shared/dropin.h +++ b/src/shared/dropin.h @@ -22,6 +22,8 @@ ***/ #include "macro.h" +#include "set.h" +#include "unit-name.h" int drop_in_file(const char *dir, const char *unit, unsigned level, const char *name, char **_p, char **_q); @@ -31,3 +33,30 @@ int write_drop_in(const char *dir, const char *unit, unsigned level, int write_drop_in_format(const char *dir, const char *unit, unsigned level, const char *name, const char *format, ...) _printf_(5, 6); + +/** + * This callback will be called for each directory entry @entry, + * with @filepath being the full path to the entry. + * + * If return value is negative, loop will be aborted. + */ +typedef int (*dependency_consumer_t)(UnitDependency dependency, + const char *entry, + const char* filepath, + void *arg); + +int unit_file_process_dir( + Set * unit_path_cache, + const char *unit_path, + const char *name, + const char *suffix, + UnitDependency dependency, + dependency_consumer_t consumer, + void *arg, + char ***strv); + +int unit_file_find_dropin_paths( + char **lookup_path, + Set *unit_path_cache, + Set *names, + char ***paths); |