You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
146 lines
5.9 KiB
146 lines
5.9 KiB
From f88f7c68264f9cfef78f4a4e2f68e45de8f1f055 Mon Sep 17 00:00:00 2001 |
|
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl> |
|
Date: Tue, 15 Mar 2022 09:44:39 +0100 |
|
Subject: [PATCH] shared/install: fix reenable on linked unit files |
|
|
|
(cherry picked from commit 29a7c59abbe594422f1ed7602263420745339a3e) |
|
|
|
Related: #2082131 |
|
--- |
|
src/shared/install.c | 73 ++++++++++++++++++++++++++++++----- |
|
src/shared/install.h | 2 +- |
|
test/test-systemctl-enable.sh | 8 ++-- |
|
3 files changed, 68 insertions(+), 15 deletions(-) |
|
|
|
diff --git a/src/shared/install.c b/src/shared/install.c |
|
index 1018e4fbf3..bf11e5bdce 100644 |
|
--- a/src/shared/install.c |
|
+++ b/src/shared/install.c |
|
@@ -2707,17 +2707,74 @@ int unit_file_disable( |
|
return do_unit_file_disable(&lp, scope, flags, config_path, files, changes, n_changes); |
|
} |
|
|
|
+static int normalize_linked_files( |
|
+ UnitFileScope scope, |
|
+ const LookupPaths *lp, |
|
+ char **names_or_paths, |
|
+ char ***ret_names, |
|
+ char ***ret_files) { |
|
+ |
|
+ /* This is similar to normalize_filenames()/normalize_names() in src/systemctl/, |
|
+ * but operates on real unit names. For each argument we we look up the actual path |
|
+ * where the unit is found. This way linked units can be reenabled successfully. */ |
|
+ |
|
+ _cleanup_free_ char **files = NULL, **names = NULL; |
|
+ int r; |
|
+ |
|
+ STRV_FOREACH(a, names_or_paths) { |
|
+ _cleanup_(install_context_done) InstallContext ctx = { .scope = scope }; |
|
+ UnitFileInstallInfo *i = NULL; |
|
+ _cleanup_free_ char *n = NULL; |
|
+ |
|
+ r = path_extract_filename(*a, &n); |
|
+ if (r < 0) |
|
+ return r; |
|
+ if (r == O_DIRECTORY) |
|
+ return log_debug_errno(SYNTHETIC_ERRNO(EISDIR), |
|
+ "Unexpected path to a directory \"%s\", refusing.", *a); |
|
+ |
|
+ if (!is_path(*a)) { |
|
+ r = install_info_discover(&ctx, lp, n, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, &i, NULL, NULL); |
|
+ if (r < 0) |
|
+ log_debug_errno(r, "Failed to discover unit \"%s\", operating on name: %m", n); |
|
+ } |
|
+ |
|
+ r = strv_consume(&names, TAKE_PTR(n)); |
|
+ if (r < 0) |
|
+ return r; |
|
+ |
|
+ const char *p = NULL; |
|
+ if (i && i->path) |
|
+ /* Use startswith here, because we know that paths are normalized, and |
|
+ * path_startswith() would give us a relative path, but we need an absolute path |
|
+ * relative to i->root. |
|
+ * |
|
+ * In other words: /var/tmp/instroot.1234/etc/systemd/system/frobnicator.service |
|
+ * is replaced by /etc/systemd/system/frobnicator.service, which is "absolute" |
|
+ * in a sense, but only makes sense "relative" to /var/tmp/instroot.1234/. |
|
+ */ |
|
+ p = startswith(i->path, i->root); |
|
+ |
|
+ r = strv_extend(&files, p ?: *a); |
|
+ if (r < 0) |
|
+ return r; |
|
+ } |
|
+ |
|
+ *ret_names = TAKE_PTR(names); |
|
+ *ret_files = TAKE_PTR(files); |
|
+ return 0; |
|
+} |
|
+ |
|
int unit_file_reenable( |
|
UnitFileScope scope, |
|
UnitFileFlags flags, |
|
const char *root_dir, |
|
- char **files, |
|
+ char **names_or_paths, |
|
UnitFileChange **changes, |
|
size_t *n_changes) { |
|
|
|
_cleanup_(lookup_paths_free) LookupPaths lp = {}; |
|
- size_t l, i; |
|
- char **names; |
|
+ _cleanup_strv_free_ char **names = NULL, **files = NULL; |
|
int r; |
|
|
|
assert(scope >= 0); |
|
@@ -2731,13 +2788,11 @@ int unit_file_reenable( |
|
if (!config_path) |
|
return -ENXIO; |
|
|
|
- /* First, we invoke the disable command with only the basename... */ |
|
- l = strv_length(files); |
|
- names = newa(char*, l+1); |
|
- for (i = 0; i < l; i++) |
|
- names[i] = basename(files[i]); |
|
- names[i] = NULL; |
|
+ r = normalize_linked_files(scope, &lp, names_or_paths, &names, &files); |
|
+ if (r < 0) |
|
+ return r; |
|
|
|
+ /* First, we invoke the disable command with only the basename... */ |
|
r = do_unit_file_disable(&lp, scope, flags, config_path, names, changes, n_changes); |
|
if (r < 0) |
|
return r; |
|
diff --git a/src/shared/install.h b/src/shared/install.h |
|
index d21e2aaa45..dba6987406 100644 |
|
--- a/src/shared/install.h |
|
+++ b/src/shared/install.h |
|
@@ -111,7 +111,7 @@ int unit_file_reenable( |
|
UnitFileScope scope, |
|
UnitFileFlags flags, |
|
const char *root_dir, |
|
- char **files, |
|
+ char **names_or_paths, |
|
UnitFileChange **changes, |
|
size_t *n_changes); |
|
int unit_file_preset( |
|
diff --git a/test/test-systemctl-enable.sh b/test/test-systemctl-enable.sh |
|
index c1fb9626ab..0ed08a9da3 100644 |
|
--- a/test/test-systemctl-enable.sh |
|
+++ b/test/test-systemctl-enable.sh |
|
@@ -206,11 +206,9 @@ test ! -h "$root/etc/systemd/system/paths.target.wants/link1.path" |
|
islink "$root/etc/systemd/system/link1.path" "/link1.path" |
|
islink "$root/etc/systemd/system/paths.target.wants/link1.path" "/link1.path" |
|
|
|
-# FIXME |
|
-# "$systemctl" --root="$root" reenable 'link1.path' |
|
-# islink "$root/etc/systemd/system/link1.path" "/link1.path" |
|
-# islink "$root/etc/systemd/system/paths.target.wants/link1.path" "/link1.path" |
|
- |
|
+"$systemctl" --root="$root" reenable 'link1.path' |
|
+islink "$root/etc/systemd/system/link1.path" "/link1.path" |
|
+islink "$root/etc/systemd/system/paths.target.wants/link1.path" "/link1.path" |
|
|
|
: -------manual link------------------------------------------ |
|
cat >"$root/link3.suffix" <<EOF
|
|
|