]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/shared/dropin.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / shared / dropin.c
index 2c1cd84df5cdc70229b917ceeb63422d0ad404bf..a16f436bede7e41a1938510a23f6be2a3a6d0385 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
 /***
   This file is part of systemd.
 
@@ -17,7 +18,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dirent.h>
 #include <errno.h>
 #include <stdarg.h>
 #include <stdio.h>
 
 #include "alloc-util.h"
 #include "conf-files.h"
+#include "dirent-util.h"
 #include "dropin.h"
 #include "escape.h"
 #include "fd-util.h"
 #include "fileio-label.h"
+#include "fs-util.h"
 #include "hashmap.h"
 #include "log.h"
 #include "macro.h"
 int drop_in_file(const char *dir, const char *unit, unsigned level,
                  const char *name, char **_p, char **_q) {
 
+        char prefix[DECIMAL_STR_MAX(unsigned)];
         _cleanup_free_ char *b = NULL;
         char *p, *q;
 
-        char prefix[DECIMAL_STR_MAX(unsigned)];
-
         assert(unit);
         assert(name);
         assert(_p);
@@ -116,136 +117,96 @@ 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(
+static int unit_file_find_dir(
+                const char *original_root,
                 const char *path,
-                UnitDependency dependency,
-                dependency_consumer_t consumer,
-                void *arg,
-                char ***strv) {
+                char ***dirs) {
 
-        _cleanup_closedir_ DIR *d = NULL;
+        _cleanup_free_ char *chased = 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();
-
+        r = chase_symlinks(path, original_root, 0, &chased);
+        if (r == -ENOENT) /* Ignore -ENOENT, after all most units won't have a drop-in dir */
                 return 0;
-        }
-
-        assert(consumer);
-
-        d = opendir(path);
-        if (!d) {
-                if (errno == ENOENT)
-                        return 0;
-
-                return log_error_errno(errno, "Failed to open directory %s: %m", path);
-        }
-
-        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 (hidden_or_backup_file(de->d_name))
-                        continue;
-
-                f = strjoin(path, "/", de->d_name);
-                if (!f)
-                        return log_oom();
+        if (r < 0)
+                return log_full_errno(LOG_WARNING, r, "Failed to canonicalize path %s: %m", path);
 
-                r = consumer(dependency, de->d_name, f, arg);
-                if (r < 0)
-                        return r;
-        }
+        r = strv_push(dirs, chased);
+        if (r < 0)
+                return log_oom();
 
+        chased = NULL;
         return 0;
 }
 
-int unit_file_process_dir(
+static int unit_file_find_dirs(
+                const char *original_root,
                 Set *unit_path_cache,
                 const char *unit_path,
                 const char *name,
                 const char *suffix,
-                UnitDependency dependency,
-                dependency_consumer_t consumer,
-                void *arg,
-                char ***strv) {
+                char ***dirs) {
 
-        _cleanup_free_ char *path = NULL;
+        char *path;
         int r;
 
         assert(unit_path);
         assert(name);
         assert(suffix);
 
-        path = strjoin(unit_path, "/", name, suffix);
-        if (!path)
-                return log_oom();
+        path = strjoina(unit_path, "/", name, suffix);
 
-        if (!unit_path_cache || set_get(unit_path_cache, path))
-                (void) iterate_dir(path, dependency, consumer, arg, strv);
+        if (!unit_path_cache || set_get(unit_path_cache, path)) {
+                r = unit_file_find_dir(original_root, path, dirs);
+                if (r < 0)
+                        return r;
+        }
 
         if (unit_name_is_valid(name, UNIT_NAME_INSTANCE)) {
-                _cleanup_free_ char *template = NULL, *p = NULL;
                 /* Also try the template dir */
 
+                _cleanup_free_ char *template = NULL;
+
                 r = unit_name_template(name, &template);
                 if (r < 0)
                         return log_error_errno(r, "Failed to generate template from unit name: %m");
 
-                p = strjoin(unit_path, "/", template, suffix);
-                if (!p)
-                        return log_oom();
-
-                if (!unit_path_cache || set_get(unit_path_cache, p))
-                        (void) iterate_dir(p, dependency, consumer, arg, strv);
+                return unit_file_find_dirs(original_root, unit_path_cache, unit_path, template, suffix, dirs);
         }
 
         return 0;
 }
 
 int unit_file_find_dropin_paths(
+                const char *original_root,
                 char **lookup_path,
                 Set *unit_path_cache,
+                const char *dir_suffix,
+                const char *file_suffix,
                 Set *names,
-                char ***paths) {
+                char ***ret) {
 
-        _cleanup_strv_free_ char **strv = NULL, **ans = NULL;
+        _cleanup_strv_free_ char **dirs = NULL;
         Iterator i;
-        char *t;
+        char *t, **p;
         int r;
 
-        assert(paths);
-
-        SET_FOREACH(t, names, i) {
-                char **p;
+        assert(ret);
 
+        SET_FOREACH(t, names, i)
                 STRV_FOREACH(p, lookup_path)
-                        unit_file_process_dir(unit_path_cache, *p, t, ".d", _UNIT_DEPENDENCY_INVALID, NULL, NULL, &strv);
-        }
+                        unit_file_find_dirs(original_root, unit_path_cache, *p, t, dir_suffix, &dirs);
 
-        if (strv_isempty(strv))
+        if (strv_isempty(dirs)) {
+                *ret = NULL;
                 return 0;
+        }
 
-        r = conf_files_list_strv(&ans, ".conf", NULL, (const char**) strv);
+        r = conf_files_list_strv(ret, file_suffix, NULL, 0, (const char**) dirs);
         if (r < 0)
-                return log_warning_errno(r, "Failed to get list of configuration files: %m");
+                return log_warning_errno(r, "Failed to create the list of configuration files: %m");
 
-        *paths = ans;
-        ans = NULL;
         return 1;
 }