]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/shared/install.c
coccinelle: make use of SYNTHETIC_ERRNO
[thirdparty/systemd.git] / src / shared / install.c
index 46e07ebb98abb4432d6de4178c8a5ce639157b38..97c48afe5d8f54d0214b0ca38fe06a582334faee 100644 (file)
@@ -1,9 +1,4 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
-/***
-  This file is part of systemd.
-
-  Copyright 2011 Lennart Poettering
-***/
 
 #include <dirent.h>
 #include <errno.h>
@@ -46,9 +41,9 @@
 #define UNIT_FILE_FOLLOW_SYMLINK_MAX 64
 
 typedef enum SearchFlags {
-        SEARCH_LOAD                   = 1U << 0,
-        SEARCH_FOLLOW_CONFIG_SYMLINKS = 1U << 1,
-        SEARCH_DROPIN                 = 1U << 2,
+        SEARCH_LOAD                   = 1 << 0,
+        SEARCH_FOLLOW_CONFIG_SYMLINKS = 1 << 1,
+        SEARCH_DROPIN                 = 1 << 2,
 } SearchFlags;
 
 typedef struct {
@@ -65,6 +60,7 @@ typedef enum {
 typedef struct {
         char *pattern;
         PresetAction action;
+        char **instances;
 } PresetRule;
 
 typedef struct {
@@ -92,8 +88,10 @@ static inline void presets_freep(Presets *p) {
         if (!p)
                 return;
 
-        for (i = 0; i < p->n_rules; i++)
+        for (i = 0; i < p->n_rules; i++) {
                 free(p->rules[i].pattern);
+                strv_free(p->rules[i].instances);
+        }
 
         free(p->rules);
         p->n_rules = 0;
@@ -686,7 +684,7 @@ static int remove_marked_symlinks(
         return r;
 }
 
-static bool is_symlink_with_known_name(const UnitFileInstallInfo *i, const char *name) {
+static int is_symlink_with_known_name(const UnitFileInstallInfo *i, const char *name) {
         int r;
 
         if (streq(name, i->name))
@@ -894,16 +892,13 @@ static int find_symlinks_in_scope(
                 if (r > 0) {
                         /* We found symlinks in this dir? Yay! Let's see where precisely it is enabled. */
 
-                        r = path_is_config(paths, *p, false);
-                        if (r < 0)
-                                return r;
-                        if (r > 0) {
+                        if (path_equal_ptr(*p, paths->persistent_config)) {
                                 /* This is the best outcome, let's return it immediately. */
                                 *state = UNIT_FILE_ENABLED;
                                 return 1;
                         }
 
-                        /* look for globally enablement of user units */
+                        /* look for global enablement of user units */
                         if (scope == UNIT_FILE_USER && path_is_user_config_dir(*p)) {
                                 *state = UNIT_FILE_ENABLED;
                                 return 1;
@@ -918,11 +913,7 @@ static int find_symlinks_in_scope(
                                 enabled_at_all = true;
 
                 } else if (same_name_link) {
-
-                        r = path_is_config(paths, *p, false);
-                        if (r < 0)
-                                return r;
-                        if (r > 0)
+                        if (path_equal_ptr(*p, paths->persistent_config))
                                 same_name_link_config = true;
                         else {
                                 r = path_is_runtime(paths, *p, false);
@@ -1241,10 +1232,9 @@ static int unit_file_load(
                 type = unit_name_to_type(info->name);
                 if (type < 0)
                         return -EINVAL;
-                if (unit_name_is_valid(info->name, UNIT_NAME_TEMPLATE|UNIT_NAME_INSTANCE) && !unit_type_may_template(type)) {
-                        log_error("Unit type %s cannot be templated.", unit_type_to_string(type));
-                        return -EINVAL;
-                }
+                if (unit_name_is_valid(info->name, UNIT_NAME_TEMPLATE|UNIT_NAME_INSTANCE) && !unit_type_may_template(type))
+                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                               "Unit type %s cannot be templated.", unit_type_to_string(type));
 
                 if (!(flags & SEARCH_LOAD)) {
                         r = lstat(path, &st);
@@ -1457,10 +1447,10 @@ static int unit_file_search(
                 }
         }
 
-        if (!found_unit) {
-                log_debug("Cannot find unit %s%s%s.", info->name, template ? " or " : "", strempty(template));
-                return -ENOENT;
-        }
+        if (!found_unit)
+                return log_debug_errno(SYNTHETIC_ERRNO(ENOENT),
+                                       "Cannot find unit %s%s%s.",
+                                       info->name, template ? " or " : "", strempty(template));
 
         if (info->type == UNIT_FILE_TYPE_MASKED)
                 return result;
@@ -1685,6 +1675,25 @@ static int install_info_discover(
         return r;
 }
 
+static int install_info_discover_and_check(
+                        UnitFileScope scope,
+                        InstallContext *c,
+                        const LookupPaths *paths,
+                        const char *name,
+                        SearchFlags flags,
+                        UnitFileInstallInfo **ret,
+                        UnitFileChange **changes,
+                        size_t *n_changes) {
+
+        int r;
+
+        r = install_info_discover(scope, c, paths, name, flags, ret, changes, n_changes);
+        if (r < 0)
+                return r;
+
+        return install_info_may_process(ret ? *ret : NULL, paths, changes, n_changes);
+}
+
 static int install_info_symlink_alias(
                 UnitFileInstallInfo *i,
                 const LookupPaths *paths,
@@ -1886,10 +1895,10 @@ static int install_context_apply(
                 if (q < 0)
                         return q;
 
-                r = install_info_traverse(scope, c, paths, i, flags, NULL);
-                if (r < 0) {
+                q = install_info_traverse(scope, c, paths, i, flags, NULL);
+                if (q < 0) {
                         unit_file_changes_add(changes, n_changes, r, i->name, NULL);
-                        return r;
+                        return q;
                 }
 
                 /* We can attempt to process a masked unit when a different unit
@@ -1923,7 +1932,6 @@ static int install_context_mark_for_removal(
                 InstallContext *c,
                 const LookupPaths *paths,
                 Set **remove_symlinks_to,
-                const char *config_path,
                 UnitFileChange **changes,
                 size_t *n_changes) {
 
@@ -1932,7 +1940,6 @@ static int install_context_mark_for_removal(
 
         assert(c);
         assert(paths);
-        assert(config_path);
 
         /* Marks all items for removal */
 
@@ -2042,7 +2049,7 @@ int unit_file_unmask(
         size_t n_todo = 0, n_allocated = 0;
         const char *config_path;
         char **i;
-        bool dry_run;
+        bool dry_run = !!(flags & UNIT_FILE_DRY_RUN);
         int r, q;
 
         assert(scope >= 0);
@@ -2052,73 +2059,71 @@ int unit_file_unmask(
         if (r < 0)
                 return r;
 
-        config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config;
-        if (!config_path)
-                return -ENXIO;
-
-        dry_run = !!(flags & UNIT_FILE_DRY_RUN);
-
         STRV_FOREACH(i, files) {
-                _cleanup_free_ char *path = NULL;
-
                 if (!unit_name_is_valid(*i, UNIT_NAME_ANY))
                         return -EINVAL;
 
-                path = path_make_absolute(*i, config_path);
-                if (!path)
-                        return -ENOMEM;
+                FOREACH_STRING(config_path, paths.runtime_config, paths.persistent_config) {
+                        _cleanup_free_ char *path = NULL;
 
-                r = null_or_empty_path(path);
-                if (r == -ENOENT)
-                        continue;
-                if (r < 0)
-                        return r;
-                if (r == 0)
-                        continue;
+                        path = path_make_absolute(*i, config_path);
+                        if (!path)
+                                return -ENOMEM;
 
-                if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2))
-                        return -ENOMEM;
+                        r = null_or_empty_path(path);
+                        if (r == -ENOENT)
+                                continue;
+                        if (r < 0)
+                                return r;
+                        if (r == 0)
+                                continue;
 
-                todo[n_todo] = strdup(*i);
-                if (!todo[n_todo])
-                        return -ENOMEM;
+                        if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2))
+                                return -ENOMEM;
 
-                n_todo++;
+                        todo[n_todo] = strdup(*i);
+                        if (!todo[n_todo])
+                                return -ENOMEM;
+
+                        n_todo++;
+                }
         }
 
         strv_uniq(todo);
 
         r = 0;
-        STRV_FOREACH(i, todo) {
-                _cleanup_free_ char *path = NULL;
-                const char *rp;
+        FOREACH_STRING(config_path, paths.runtime_config, paths.persistent_config) {
+                STRV_FOREACH(i, todo) {
+                        _cleanup_free_ char *path = NULL;
+                        const char *rp;
 
-                path = path_make_absolute(*i, config_path);
-                if (!path)
-                        return -ENOMEM;
+                        path = path_make_absolute(*i, config_path);
+                        if (!path)
+                                return -ENOMEM;
 
-                if (!dry_run && unlink(path) < 0) {
-                        if (errno != ENOENT) {
-                                if (r >= 0)
-                                        r = -errno;
-                                unit_file_changes_add(changes, n_changes, -errno, path, NULL);
+                        if (!dry_run && unlink(path) < 0) {
+                                if (errno != ENOENT) {
+                                        if (r >= 0)
+                                                r = -errno;
+                                        unit_file_changes_add(changes, n_changes, -errno, path, NULL);
+                                }
+
+                                continue;
                         }
 
-                        continue;
-                }
+                        unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
 
-                unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
+                        rp = skip_root(&paths, path);
+                        q = mark_symlink_for_removal(&remove_symlinks_to, rp ?: path);
+                        if (q < 0)
+                                return q;
+                }
 
-                rp = skip_root(&paths, path);
-                q = mark_symlink_for_removal(&remove_symlinks_to, rp ?: path);
-                if (q < 0)
-                        return q;
+                q = remove_marked_symlinks(remove_symlinks_to, config_path, &paths, dry_run, changes, n_changes);
+                if (r >= 0)
+                        r = q;
         }
 
-        q = remove_marked_symlinks(remove_symlinks_to, config_path, &paths, dry_run, changes, n_changes);
-        if (r >= 0)
-                r = q;
-
         return r;
 }
 
@@ -2412,11 +2417,8 @@ int unit_file_add_dependency(
         if (!config_path)
                 return -ENXIO;
 
-        r = install_info_discover(scope, &c, &paths, target, SEARCH_FOLLOW_CONFIG_SYMLINKS,
-                                  &target_info, changes, n_changes);
-        if (r < 0)
-                return r;
-        r = install_info_may_process(target_info, &paths, changes, n_changes);
+        r = install_info_discover_and_check(scope, &c, &paths, target, SEARCH_FOLLOW_CONFIG_SYMLINKS,
+                                            &target_info, changes, n_changes);
         if (r < 0)
                 return r;
 
@@ -2425,11 +2427,8 @@ int unit_file_add_dependency(
         STRV_FOREACH(f, files) {
                 char ***l;
 
-                r = install_info_discover(scope, &c, &paths, *f, SEARCH_FOLLOW_CONFIG_SYMLINKS,
-                                          &i, changes, n_changes);
-                if (r < 0)
-                        return r;
-                r = install_info_may_process(i, &paths, changes, n_changes);
+                r = install_info_discover_and_check(scope, &c, &paths, *f, SEARCH_FOLLOW_CONFIG_SYMLINKS,
+                                                    &i, changes, n_changes);
                 if (r < 0)
                         return r;
 
@@ -2445,7 +2444,7 @@ int unit_file_add_dependency(
                         l = &i->required_by;
 
                 strv_free(*l);
-                *l = strv_new(target_info->name, NULL);
+                *l = strv_new(target_info->name);
                 if (!*l)
                         return -ENOMEM;
         }
@@ -2480,11 +2479,8 @@ int unit_file_enable(
                 return -ENXIO;
 
         STRV_FOREACH(f, files) {
-                r = install_info_discover(scope, &c, &paths, *f, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS,
-                                          &i, changes, n_changes);
-                if (r < 0)
-                        return r;
-                r = install_info_may_process(i, &paths, changes, n_changes);
+                r = install_info_discover_and_check(scope, &c, &paths, *f, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS,
+                                                    &i, changes, n_changes);
                 if (r < 0)
                         return r;
 
@@ -2510,6 +2506,7 @@ int unit_file_disable(
         _cleanup_(lookup_paths_free) LookupPaths paths = {};
         _cleanup_(install_context_done) InstallContext c = {};
         _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
+        bool dry_run = !!(flags & UNIT_FILE_DRY_RUN);
         const char *config_path;
         char **i;
         int r;
@@ -2521,10 +2518,6 @@ int unit_file_disable(
         if (r < 0)
                 return r;
 
-        config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config;
-        if (!config_path)
-                return -ENXIO;
-
         STRV_FOREACH(i, files) {
                 if (!unit_name_is_valid(*i, UNIT_NAME_ANY))
                         return -EINVAL;
@@ -2534,11 +2527,17 @@ int unit_file_disable(
                         return r;
         }
 
-        r = install_context_mark_for_removal(scope, &c, &paths, &remove_symlinks_to, config_path, changes, n_changes);
+        r = install_context_mark_for_removal(scope, &c, &paths, &remove_symlinks_to, changes, n_changes);
         if (r < 0)
                 return r;
 
-        return remove_marked_symlinks(remove_symlinks_to, config_path, &paths, !!(flags & UNIT_FILE_DRY_RUN), changes, n_changes);
+        FOREACH_STRING(config_path, paths.runtime_config, paths.persistent_config) {
+                r = remove_marked_symlinks(remove_symlinks_to, config_path, &paths, dry_run, changes, n_changes);
+                if (r < 0)
+                        return r;
+        }
+
+        return 0;
 }
 
 int unit_file_reenable(
@@ -2595,10 +2594,7 @@ int unit_file_set_default(
         if (r < 0)
                 return r;
 
-        r = install_info_discover(scope, &c, &paths, name, 0, &i, changes, n_changes);
-        if (r < 0)
-                return r;
-        r = install_info_may_process(i, &paths, changes, n_changes);
+        r = install_info_discover_and_check(scope, &c, &paths, name, 0, &i, changes, n_changes);
         if (r < 0)
                 return r;
 
@@ -2768,6 +2764,39 @@ int unit_file_exists(UnitFileScope scope, const LookupPaths *paths, const char *
         return 1;
 }
 
+static int split_pattern_into_name_and_instances(const char *pattern, char **out_unit_name, char ***out_instances) {
+        _cleanup_strv_free_ char **instances = NULL;
+        _cleanup_free_ char *unit_name = NULL;
+        int r;
+
+        assert(pattern);
+        assert(out_instances);
+        assert(out_unit_name);
+
+        r = extract_first_word(&pattern, &unit_name, NULL, 0);
+        if (r < 0)
+                return r;
+
+        /* We handle the instances logic when unit name is extracted */
+        if (pattern) {
+                /* We only create instances when a rule of templated unit
+                 * is seen. A rule like enable foo@.service a b c will
+                 * result in an array of (a, b, c) as instance names */
+                if (!unit_name_is_valid(unit_name, UNIT_NAME_TEMPLATE))
+                        return -EINVAL;
+
+                instances = strv_split(pattern, WHITESPACE);
+                if (!instances)
+                        return -ENOMEM;
+
+                *out_instances = TAKE_PTR(instances);
+        }
+
+        *out_unit_name = TAKE_PTR(unit_name);
+
+        return 0;
+}
+
 static int read_presets(UnitFileScope scope, const char *root_dir, Presets *presets) {
         _cleanup_(presets_freep) Presets ps = {};
         size_t n_allocated = 0;
@@ -2811,7 +2840,6 @@ static int read_presets(UnitFileScope scope, const char *root_dir, Presets *pres
 
         STRV_FOREACH(p, files) {
                 _cleanup_fclose_ FILE *f;
-                char line[LINE_MAX];
                 int n = 0;
 
                 f = fopen(*p, "re");
@@ -2822,11 +2850,18 @@ static int read_presets(UnitFileScope scope, const char *root_dir, Presets *pres
                         return -errno;
                 }
 
-                FOREACH_LINE(line, f, return -errno) {
+                for (;;) {
+                        _cleanup_free_ char *line = NULL;
                         PresetRule rule = {};
                         const char *parameter;
                         char *l;
 
+                        r = read_line(f, LONG_LINE_MAX, &line);
+                        if (r < 0)
+                                return r;
+                        if (r == 0)
+                                break;
+
                         l = strstrip(line);
                         n++;
 
@@ -2837,15 +2872,20 @@ static int read_presets(UnitFileScope scope, const char *root_dir, Presets *pres
 
                         parameter = first_word(l, "enable");
                         if (parameter) {
-                                char *pattern;
+                                char *unit_name;
+                                char **instances = NULL;
 
-                                pattern = strdup(parameter);
-                                if (!pattern)
-                                        return -ENOMEM;
+                                /* Unit_name will remain the same as parameter when no instances are specified */
+                                r = split_pattern_into_name_and_instances(parameter, &unit_name, &instances);
+                                if (r < 0) {
+                                        log_syntax(NULL, LOG_WARNING, *p, n, r, "Couldn't parse line '%s'. Ignoring.", line);
+                                        continue;
+                                }
 
                                 rule = (PresetRule) {
-                                        .pattern = pattern,
+                                        .pattern = unit_name,
                                         .action = PRESET_ENABLE,
+                                        .instances = instances,
                                 };
                         }
 
@@ -2881,15 +2921,71 @@ static int read_presets(UnitFileScope scope, const char *root_dir, Presets *pres
         return 0;
 }
 
-static int query_presets(const char *name, const Presets presets) {
+static int pattern_match_multiple_instances(
+                        const PresetRule rule,
+                        const char *unit_name,
+                        char ***ret) {
+
+        _cleanup_free_ char *templated_name = NULL;
+        int r;
+
+        /* If no ret is needed or the rule itself does not have instances
+         * initalized, we return not matching */
+        if (!ret || !rule.instances)
+                return 0;
+
+        r = unit_name_template(unit_name, &templated_name);
+        if (r < 0)
+                return r;
+        if (!streq(rule.pattern, templated_name))
+                return 0;
+
+        /* Compose a list of specified instances when unit name is a template  */
+        if (unit_name_is_valid(unit_name, UNIT_NAME_TEMPLATE)) {
+                _cleanup_free_ char *prefix = NULL;
+                _cleanup_strv_free_ char **out_strv = NULL;
+                char **iter;
+
+                r = unit_name_to_prefix(unit_name, &prefix);
+                if (r < 0)
+                        return r;
+
+                STRV_FOREACH(iter, rule.instances) {
+                        _cleanup_free_ char *name = NULL;
+                        r = unit_name_build(prefix, *iter, ".service", &name);
+                        if (r < 0)
+                                return r;
+                        r = strv_extend(&out_strv, name);
+                        if (r < 0)
+                                return r;
+                }
+
+                *ret = TAKE_PTR(out_strv);
+                return 1;
+        } else {
+                /* We now know the input unit name is an instance name */
+                _cleanup_free_ char *instance_name = NULL;
+
+                r = unit_name_to_instance(unit_name, &instance_name);
+                if (r < 0)
+                        return r;
+
+                if (strv_find(rule.instances, instance_name))
+                        return 1;
+        }
+        return 0;
+}
+
+static int query_presets(const char *name, const Presets presets, char ***instance_name_list) {
         PresetAction action = PRESET_UNKNOWN;
         size_t i;
-
+        char **s;
         if (!unit_name_is_valid(name, UNIT_NAME_ANY))
                 return -EINVAL;
 
         for (i = 0; i < presets.n_rules; i++)
-                if (fnmatch(presets.rules[i].pattern, name, FNM_NOESCAPE) == 0) {
+                if (pattern_match_multiple_instances(presets.rules[i], name, instance_name_list) > 0 ||
+                    fnmatch(presets.rules[i].pattern, name, FNM_NOESCAPE) == 0) {
                         action = presets.rules[i].action;
                         break;
                 }
@@ -2899,7 +2995,11 @@ static int query_presets(const char *name, const Presets presets) {
                 log_debug("Preset files don't specify rule for %s. Enabling.", name);
                 return 1;
         case PRESET_ENABLE:
-                log_debug("Preset files say enable %s.", name);
+                if (instance_name_list && *instance_name_list)
+                        STRV_FOREACH(s, *instance_name_list)
+                                log_debug("Preset files say enable %s.", *s);
+                else
+                        log_debug("Preset files say enable %s.", name);
                 return 1;
         case PRESET_DISABLE:
                 log_debug("Preset files say disable %s.", name);
@@ -2917,50 +3017,50 @@ int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char
         if (r < 0)
                 return r;
 
-        return query_presets(name, presets);
+        return query_presets(name, presets, NULL);
 }
 
 static int execute_preset(
                 UnitFileScope scope,
+                UnitFileFlags flags,
                 InstallContext *plus,
                 InstallContext *minus,
                 const LookupPaths *paths,
-                const char *config_path,
                 char **files,
                 UnitFilePresetMode mode,
-                bool force,
                 UnitFileChange **changes,
                 size_t *n_changes) {
 
-        int r;
+        const char *config_path;
+        bool force = !!(flags & UNIT_FILE_FORCE);
+        bool runtime = !!(flags & UNIT_FILE_RUNTIME);
+        int r = 0, q;
 
         assert(plus);
         assert(minus);
         assert(paths);
-        assert(config_path);
 
         if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
                 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
 
-                r = install_context_mark_for_removal(scope, minus, paths, &remove_symlinks_to, config_path, changes, n_changes);
-                if (r < 0)
-                        return r;
+                q = install_context_mark_for_removal(scope, minus, paths, &remove_symlinks_to, changes, n_changes);
+                if (q < 0)
+                        return q;
 
-                r = remove_marked_symlinks(remove_symlinks_to, config_path, paths, false, changes, n_changes);
-        } else
-                r = 0;
+                FOREACH_STRING(config_path, paths->runtime_config, paths->persistent_config) {
+                        q = remove_marked_symlinks(remove_symlinks_to, config_path, paths, false, changes, n_changes);
+                        if (r == 0)
+                                r = q;
+                }
+        }
 
         if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
-                int q;
-
                 /* Returns number of symlinks that where supposed to be installed. */
-                q = install_context_apply(scope, plus, paths, config_path, force, SEARCH_LOAD, changes, n_changes);
-                if (r >= 0) {
-                        if (q < 0)
-                                r = q;
-                        else
-                                r += q;
-                }
+                q = install_context_apply(scope, plus, paths,
+                                          runtime ? paths->runtime_config : paths->persistent_config,
+                                          force, SEARCH_LOAD, changes, n_changes);
+                if (r == 0)
+                        r = q;
         }
 
         return r;
@@ -2977,6 +3077,7 @@ static int preset_prepare_one(
                 size_t *n_changes) {
 
         _cleanup_(install_context_done) InstallContext tmp = {};
+        _cleanup_strv_free_ char **instance_name_list = NULL;
         UnitFileInstallInfo *i;
         int r;
 
@@ -2992,19 +3093,26 @@ static int preset_prepare_one(
                 return 0;
         }
 
-        r = query_presets(name, presets);
+        r = query_presets(name, presets, &instance_name_list);
         if (r < 0)
                 return r;
 
         if (r > 0) {
-                r = install_info_discover(scope, plus, paths, name, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS,
-                                          &i, changes, n_changes);
-                if (r < 0)
-                        return r;
+                if (instance_name_list) {
+                        char **s;
+                        STRV_FOREACH(s, instance_name_list) {
+                                r = install_info_discover_and_check(scope, plus, paths, *s, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS,
+                                                                    &i, changes, n_changes);
+                                if (r < 0)
+                                        return r;
+                        }
+                } else {
+                        r = install_info_discover_and_check(scope, plus, paths, name, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS,
+                                                            &i, changes, n_changes);
+                        if (r < 0)
+                                return r;
+                }
 
-                r = install_info_may_process(i, paths, changes, n_changes);
-                if (r < 0)
-                        return r;
         } else
                 r = install_info_discover(scope, minus, paths, name, SEARCH_FOLLOW_CONFIG_SYMLINKS,
                                           &i, changes, n_changes);
@@ -3024,7 +3132,6 @@ int unit_file_preset(
         _cleanup_(install_context_done) InstallContext plus = {}, minus = {};
         _cleanup_(lookup_paths_free) LookupPaths paths = {};
         _cleanup_(presets_freep) Presets presets = {};
-        const char *config_path;
         char **i;
         int r;
 
@@ -3036,10 +3143,6 @@ int unit_file_preset(
         if (r < 0)
                 return r;
 
-        config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config;
-        if (!config_path)
-                return -ENXIO;
-
         r = read_presets(scope, root_dir, &presets);
         if (r < 0)
                 return r;
@@ -3050,7 +3153,7 @@ int unit_file_preset(
                         return r;
         }
 
-        return execute_preset(scope, &plus, &minus, &paths, config_path, files, mode, !!(flags & UNIT_FILE_FORCE), changes, n_changes);
+        return execute_preset(scope, flags, &plus, &minus, &paths, files, mode, changes, n_changes);
 }
 
 int unit_file_preset_all(
@@ -3064,7 +3167,6 @@ int unit_file_preset_all(
         _cleanup_(install_context_done) InstallContext plus = {}, minus = {};
         _cleanup_(lookup_paths_free) LookupPaths paths = {};
         _cleanup_(presets_freep) Presets presets = {};
-        const char *config_path = NULL;
         char **i;
         int r;
 
@@ -3076,10 +3178,6 @@ int unit_file_preset_all(
         if (r < 0)
                 return r;
 
-        config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config;
-        if (!config_path)
-                return -ENXIO;
-
         r = read_presets(scope, root_dir, &presets);
         if (r < 0)
                 return r;
@@ -3097,7 +3195,6 @@ int unit_file_preset_all(
                 }
 
                 FOREACH_DIRENT(de, d, return -errno) {
-
                         if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
                                 continue;
 
@@ -3121,7 +3218,7 @@ int unit_file_preset_all(
                 }
         }
 
-        return execute_preset(scope, &plus, &minus, &paths, config_path, NULL, mode, !!(flags & UNIT_FILE_FORCE), changes, n_changes);
+        return execute_preset(scope, flags, &plus, &minus, &paths, NULL, mode, changes, n_changes);
 }
 
 static void unit_file_list_free_one(UnitFileList *f) {