summaryrefslogtreecommitdiff
path: root/src/shared/install.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2014-06-16 19:49:31 +0200
committerLennart Poettering <lennart@poettering.net>2014-06-17 02:43:17 +0200
commitd309c1c36426f9a355e28e3c35153281939aeea6 (patch)
tree74f4042dad40df25503f1b8c00e2cf3ce2f89cf6 /src/shared/install.c
parentbcafe923a74e702abbba3655b0270febe143499f (diff)
install: beef up preset logic to limit to only enable or only disable, and do all-unit preset operations
The new "systemctl preset-all" command may now be used to put all installed units back into the enable/disable state the vendor/admin encoded in preset files. Also, introduce "systemctl --preset-mode=enable-only" and "systemctl --preset-mode=disable-only" to only apply the enable or only the disable operations of a "systemctl preset" or "systemctl preset-all" operation. "systemctl preset-all" implements this RFE: https://bugzilla.redhat.com/show_bug.cgi?id=630174
Diffstat (limited to 'src/shared/install.c')
-rw-r--r--src/shared/install.c151
1 files changed, 138 insertions, 13 deletions
diff --git a/src/shared/install.c b/src/shared/install.c
index 40dc7bebe8..7e0e20c603 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -1831,12 +1831,12 @@ int unit_file_preset(
bool runtime,
const char *root_dir,
char **files,
+ UnitFilePresetMode mode,
bool force,
UnitFileChange **changes,
unsigned *n_changes) {
_cleanup_install_context_done_ InstallContext plus = {}, minus = {};
- _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
_cleanup_lookup_paths_free_ LookupPaths paths = {};
_cleanup_free_ char *config_path = NULL;
char **i;
@@ -1844,6 +1844,7 @@ int unit_file_preset(
assert(scope >= 0);
assert(scope < _UNIT_FILE_SCOPE_MAX);
+ assert(mode < _UNIT_FILE_PRESET_MODE_MAX);
r = lookup_paths_init_from_scope(&paths, scope, root_dir);
if (r < 0)
@@ -1862,25 +1863,141 @@ int unit_file_preset(
if (r < 0)
return r;
- if (r)
+ if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
r = install_info_add_auto(&plus, *i);
- else
+ else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
r = install_info_add_auto(&minus, *i);
+ else
+ r = 0;
if (r < 0)
return r;
}
- r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
+ r = 0;
- q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
- if (r == 0)
- r = q;
+ if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
+ _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
- /* Returns number of symlinks that where supposed to be installed. */
- q = install_context_apply(&plus, &paths, config_path, root_dir, force,
- changes, n_changes);
- if (r == 0)
- r = q;
+ r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
+
+ q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
+ if (r == 0)
+ r = q;
+ }
+
+ if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
+ /* Returns number of symlinks that where supposed to be installed. */
+ q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
+ if (r == 0)
+ r = q;
+ }
+
+ return r;
+}
+
+int unit_file_preset_all(
+ UnitFileScope scope,
+ bool runtime,
+ const char *root_dir,
+ UnitFilePresetMode mode,
+ bool force,
+ UnitFileChange **changes,
+ unsigned *n_changes) {
+
+ _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
+ _cleanup_lookup_paths_free_ LookupPaths paths = {};
+ _cleanup_free_ char *config_path = NULL;
+ char **i;
+ int r, q;
+
+ assert(scope >= 0);
+ assert(scope < _UNIT_FILE_SCOPE_MAX);
+ assert(mode < _UNIT_FILE_PRESET_MODE_MAX);
+
+ r = lookup_paths_init_from_scope(&paths, scope, root_dir);
+ if (r < 0)
+ return r;
+
+ r = get_config_path(scope, runtime, root_dir, &config_path);
+ if (r < 0)
+ return r;
+
+ STRV_FOREACH(i, paths.unit_path) {
+ _cleanup_closedir_ DIR *d = NULL;
+ _cleanup_free_ char *buf = NULL;
+ const char *units_dir;
+
+ if (!isempty(root_dir)) {
+ buf = strjoin(root_dir, "/", *i, NULL);
+ if (!buf)
+ return -ENOMEM;
+
+ units_dir = buf;
+ } else
+ units_dir = *i;
+
+ d = opendir(units_dir);
+ if (!d) {
+ if (errno == ENOENT)
+ continue;
+
+ return -errno;
+ }
+
+ for (;;) {
+ struct dirent *de;
+
+ errno = 0;
+ de = readdir(d);
+ if (!de && errno != 0)
+ return -errno;
+
+ if (!de)
+ break;
+
+ if (ignore_file(de->d_name))
+ continue;
+
+ if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
+ continue;
+
+ dirent_ensure_type(d, de);
+
+ if (de->d_type != DT_REG)
+ continue;
+
+ r = unit_file_query_preset(scope, de->d_name);
+ if (r < 0)
+ return r;
+
+ if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
+ r = install_info_add_auto(&plus, de->d_name);
+ else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
+ r = install_info_add_auto(&minus, de->d_name);
+ else
+ r = 0;
+ if (r < 0)
+ return r;
+ }
+ }
+
+ r = 0;
+
+ if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
+ _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
+
+ r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
+
+ q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, NULL);
+ if (r == 0)
+ r = q;
+ }
+
+ if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
+ q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
+ if (r == 0)
+ r = q;
+ }
return r;
}
@@ -1937,8 +2054,8 @@ int unit_file_get_list(
}
for (;;) {
- struct dirent *de;
_cleanup_unitfilelist_free_ UnitFileList *f = NULL;
+ struct dirent *de;
errno = 0;
de = readdir(d);
@@ -2031,3 +2148,11 @@ static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX]
};
DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);
+
+static const char* const unit_file_preset_mode_table[_UNIT_FILE_PRESET_MODE_MAX] = {
+ [UNIT_FILE_PRESET_FULL] = "full",
+ [UNIT_FILE_PRESET_ENABLE_ONLY] = "enable-only",
+ [UNIT_FILE_PRESET_DISABLE_ONLY] = "disable-only",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode, UnitFilePresetMode);