/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-***/
#include <dirent.h>
#include <errno.h>
#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 {
typedef struct {
char *pattern;
PresetAction action;
+ char **instances;
} PresetRule;
typedef struct {
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;
}
-static int unit_file_lookup_state(UnitFileScope scope, const LookupPaths *paths, const char *name, UnitFileState *ret);
-
bool unit_type_may_alias(UnitType type) {
return IN_SET(type,
UNIT_SERVICE,
int unit_file_changes_add(
UnitFileChange **changes,
- unsigned *n_changes,
+ size_t *n_changes,
UnitFileChangeType type,
const char *path,
const char *source) {
if (!p || (source && !s))
return -ENOMEM;
- path_kill_slashes(p);
+ path_simplify(p, false);
if (s)
- path_kill_slashes(s);
+ path_simplify(s, false);
c[*n_changes] = (UnitFileChange) { type, p, s };
p = s = NULL;
return 0;
}
-void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
- unsigned i;
+void unit_file_changes_free(UnitFileChange *changes, size_t n_changes) {
+ size_t i;
assert(changes || n_changes == 0);
free(changes);
}
-void unit_file_dump_changes(int r, const char *verb, const UnitFileChange *changes, unsigned n_changes, bool quiet) {
- unsigned i;
+void unit_file_dump_changes(int r, const char *verb, const UnitFileChange *changes, size_t n_changes, bool quiet) {
+ size_t i;
bool logged = false;
assert(changes || n_changes == 0);
const char *new_path,
bool force,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
_cleanup_free_ char *dest = NULL, *dirname = NULL;
const char *rp;
if (!n)
return -ENOMEM;
- path_kill_slashes(n);
+ path_simplify(n, false);
r = set_consume(*remove_symlinks_to, n);
if (r == -EEXIST)
bool dry_run,
bool *restart,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
_cleanup_closedir_ DIR *d = NULL;
struct dirent *de;
p = path_make_absolute(de->d_name, path);
if (!p)
return -ENOMEM;
- path_kill_slashes(p);
+ path_simplify(p, false);
q = readlink_malloc(p, &dest);
if (q == -ENOENT)
const LookupPaths *lp,
bool dry_run,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
_cleanup_close_ int fd = -1;
bool restart;
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))
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;
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);
UnitFileInstallInfo *i,
const LookupPaths *paths,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
assert(i);
assert(paths);
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);
}
}
- 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;
SearchFlags flags,
UnitFileInstallInfo **ret,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
UnitFileInstallInfo *i;
int r;
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,
const char *config_path,
bool force,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
char **s;
int r = 0, q;
char **list,
const char *suffix,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
_cleanup_free_ char *buf = NULL;
const char *n;
const char *config_path,
bool force,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
_cleanup_free_ char *path = NULL;
int r;
const char *config_path,
bool force,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
int r, q;
bool force,
SearchFlags flags,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
UnitFileInstallInfo *i;
int r;
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
InstallContext *c,
const LookupPaths *paths,
Set **remove_symlinks_to,
- const char *config_path,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
UnitFileInstallInfo *i;
int r;
assert(c);
assert(paths);
- assert(config_path);
/* Marks all items for removal */
const char *root_dir,
char **files,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
_cleanup_(lookup_paths_free) LookupPaths paths = {};
const char *config_path;
const char *root_dir,
char **files,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
_cleanup_(lookup_paths_free) LookupPaths paths = {};
_cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
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);
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;
}
const char *root_dir,
char **files,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
_cleanup_(lookup_paths_free) LookupPaths paths = {};
_cleanup_strv_free_ char **todo = NULL;
const char *root_dir,
char **files,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
_cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
_cleanup_(lookup_paths_free) LookupPaths paths = {};
const char *target,
UnitDependency dep,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
_cleanup_(lookup_paths_free) LookupPaths paths = {};
_cleanup_(install_context_done) InstallContext c = {};
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;
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;
l = &i->required_by;
strv_free(*l);
- *l = strv_new(target_info->name, NULL);
+ *l = strv_new(target_info->name);
if (!*l)
return -ENOMEM;
}
const char *root_dir,
char **files,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
_cleanup_(lookup_paths_free) LookupPaths paths = {};
_cleanup_(install_context_done) InstallContext c = {};
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;
const char *root_dir,
char **files,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
_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;
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;
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(
const char *root_dir,
char **files,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
char **n;
int r;
const char *root_dir,
const char *name,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
_cleanup_(lookup_paths_free) LookupPaths paths = {};
_cleanup_(install_context_done) InstallContext c = {};
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;
return 0;
}
-static int unit_file_lookup_state(
+int unit_file_lookup_state(
UnitFileScope scope,
const LookupPaths *paths,
const char *name,
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;
assert(scope < _UNIT_FILE_SCOPE_MAX);
assert(presets);
- if (scope == UNIT_FILE_SYSTEM)
+ switch (scope) {
+ case UNIT_FILE_SYSTEM:
r = conf_files_list(&files, ".preset", root_dir, 0,
"/etc/systemd/system-preset",
"/run/systemd/system-preset",
"/lib/systemd/system-preset",
#endif
NULL);
- else if (scope == UNIT_FILE_GLOBAL)
+ break;
+
+ case UNIT_FILE_GLOBAL:
+ case UNIT_FILE_USER:
r = conf_files_list(&files, ".preset", root_dir, 0,
"/etc/systemd/user-preset",
"/run/systemd/user-preset",
"/usr/local/lib/systemd/user-preset",
"/usr/lib/systemd/user-preset",
NULL);
- else {
- *presets = (Presets){};
+ break;
- return 0;
+ default:
+ assert_not_reached("Invalid unit file scope");
}
if (r < 0)
STRV_FOREACH(p, files) {
_cleanup_fclose_ FILE *f;
- char line[LINE_MAX];
int n = 0;
f = fopen(*p, "re");
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++;
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,
};
}
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;
}
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);
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,
- unsigned *n_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;
const char *name,
Presets presets,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
_cleanup_(install_context_done) InstallContext tmp = {};
+ _cleanup_strv_free_ char **instance_name_list = NULL;
UnitFileInstallInfo *i;
int r;
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);
char **files,
UnitFilePresetMode mode,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
_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;
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;
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(
const char *root_dir,
UnitFilePresetMode mode,
UnitFileChange **changes,
- unsigned *n_changes) {
+ size_t *n_changes) {
_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;
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;
}
FOREACH_DIRENT(de, d, return -errno) {
-
if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
continue;
}
}
- 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) {