summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2014-12-15 23:01:05 -0500
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2014-12-16 00:30:34 -0500
commitbc854dc7cd051e1e5a6ebcca8084b07168051c6c (patch)
tree6281cc6f6a9adf4e6f67b1f8660031156ddf6fe4
parentad2a035820e0fca29e49816f735bec1fcdabf82a (diff)
systemctl: refuse to edit runtime dropins when they already exist in /etc
The check for existing unit files and dropins is unified. path_join() is updated to not insert duplicate separators.
-rw-r--r--src/shared/path-util.c6
-rw-r--r--src/systemctl/systemctl.c139
-rw-r--r--src/test/test-path-util.c4
3 files changed, 41 insertions, 108 deletions
diff --git a/src/shared/path-util.c b/src/shared/path-util.c
index b3fe0b8179..dcc8321f50 100644
--- a/src/shared/path-util.c
+++ b/src/shared/path-util.c
@@ -439,14 +439,14 @@ char* path_join(const char *root, const char *path, const char *rest) {
assert(path);
if (!isempty(root))
- return strjoin(root, "/",
+ return strjoin(root, endswith(root, "/") ? "" : "/",
path[0] == '/' ? path+1 : path,
- rest ? "/" : NULL,
+ rest ? (endswith(path, "/") ? "" : "/") : NULL,
rest && rest[0] == '/' ? rest+1 : rest,
NULL);
else
return strjoin(path,
- rest ? "/" : NULL,
+ rest ? (endswith(path, "/") ? "" : "/") : NULL,
rest && rest[0] == '/' ? rest+1 : rest,
NULL);
}
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 51ba33079d..649fb5cde5 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -5902,41 +5902,58 @@ static int create_edit_temp_file(const char *new_path, const char *original_path
return 0;
}
-static int get_drop_in_to_edit(const char *unit_name, const char *user_home, const char *user_runtime, char **ret_path) {
- char *tmp_new_path;
- char *tmp;
-
- assert(unit_name);
- assert(ret_path);
+static int get_file_to_edit(const char *name, const char *user_home, const char *user_runtime, char **ret_path) {
+ _cleanup_free_ char *path = NULL, *path2 = NULL, *run = NULL;
switch (arg_scope) {
case UNIT_FILE_SYSTEM:
- tmp = strappenda(arg_runtime ? "/run/systemd/system/" : SYSTEM_CONFIG_UNIT_PATH "/", unit_name, ".d/override.conf");
+ path = path_join(arg_root, SYSTEM_CONFIG_UNIT_PATH, name);
+ if (arg_runtime)
+ run = path_join(arg_root, "/run/systemd/system/", name);
break;
case UNIT_FILE_GLOBAL:
- tmp = strappenda(arg_runtime ? "/run/systemd/user/" : USER_CONFIG_UNIT_PATH "/", unit_name, ".d/override.conf");
+ path = path_join(arg_root, USER_CONFIG_UNIT_PATH, name);
+ if (arg_runtime)
+ run = path_join(arg_root, "/run/systemd/user/", name);
break;
case UNIT_FILE_USER:
assert(user_home);
assert(user_runtime);
- tmp = strappenda(arg_runtime ? user_runtime : user_home, "/", unit_name, ".d/override.conf");
+ path = path_join(arg_root, user_home, name);
+ if (arg_runtime) {
+ path2 = path_join(arg_root, USER_CONFIG_UNIT_PATH, name);
+ if (!path2)
+ return log_oom();
+ run = path_join(arg_root, user_runtime, name);
+ }
break;
default:
assert_not_reached("Invalid scope");
}
-
- tmp_new_path = path_join(arg_root, tmp, NULL);
- if (!tmp_new_path)
+ if (!path || (arg_runtime && !run))
return log_oom();
- *ret_path = tmp_new_path;
+ if (arg_runtime) {
+ if (access(path, F_OK) >= 0)
+ return log_error_errno(EEXIST, "Refusing to create \"%s\" because it would be overriden by \"%s\" anyway.",
+ run, path);
+ if (path2 && access(path2, F_OK) >= 0)
+ return log_error_errno(EEXIST, "Refusing to create \"%s\" because it would be overriden by \"%s\" anyway.",
+ run, path2);
+ *ret_path = run;
+ run = NULL;
+ } else {
+ *ret_path = path;
+ path = NULL;
+ }
return 0;
}
-static int unit_file_create_drop_in(const char *unit_name, const char *user_home, const char *user_runtime, char **ret_new_path, char **ret_tmp_path) {
- char *tmp_new_path;
+
+static int unit_file_create_dropin(const char *unit_name, const char *user_home, const char *user_runtime, char **ret_new_path, char **ret_tmp_path) {
+ char *tmp_new_path, *ending;
char *tmp_tmp_path;
int r;
@@ -5944,7 +5961,8 @@ static int unit_file_create_drop_in(const char *unit_name, const char *user_home
assert(ret_new_path);
assert(ret_tmp_path);
- r = get_drop_in_to_edit(unit_name, user_home, user_runtime, &tmp_new_path);
+ ending = strappenda(unit_name, ".d/override.conf");
+ r = get_file_to_edit(ending, user_home, user_runtime, &tmp_new_path);
if (r < 0)
return r;
@@ -5960,91 +5978,6 @@ static int unit_file_create_drop_in(const char *unit_name, const char *user_home
return 0;
}
-static bool unit_is_editable(const char *unit_name, const char *fragment_path, const char *user_home) {
- bool editable = true;
- const char *invalid_path;
-
- assert(unit_name);
-
- if (!arg_runtime)
- return true;
-
- switch (arg_scope) {
- case UNIT_FILE_SYSTEM:
- if (path_startswith(fragment_path, "/etc/systemd/system")) {
- editable = false;
- invalid_path = "/etc/systemd/system";
- } else if (path_startswith(fragment_path, SYSTEM_CONFIG_UNIT_PATH)) {
- editable = false;
- invalid_path = SYSTEM_CONFIG_UNIT_PATH;
- }
- break;
- case UNIT_FILE_GLOBAL:
- if (path_startswith(fragment_path, "/etc/systemd/user")) {
- editable = false;
- invalid_path = "/etc/systemd/user";
- } else if (path_startswith(fragment_path, USER_CONFIG_UNIT_PATH)) {
- editable = false;
- invalid_path = USER_CONFIG_UNIT_PATH;
- }
- break;
- case UNIT_FILE_USER:
- assert(user_home);
-
- if (path_startswith(fragment_path, "/etc/systemd/user")) {
- editable = false;
- invalid_path = "/etc/systemd/user";
- } else if (path_startswith(fragment_path, USER_CONFIG_UNIT_PATH)) {
- editable = false;
- invalid_path = USER_CONFIG_UNIT_PATH;
- } else if (path_startswith(fragment_path, user_home)) {
- editable = false;
- invalid_path = user_home;
- }
- break;
- default:
- assert_not_reached("Invalid scope");
- }
-
- if (!editable)
- log_error("%s ignored: cannot temporarily edit units from %s", unit_name, invalid_path);
-
- return editable;
-}
-
-static int get_copy_to_edit(const char *unit_name, const char *fragment_path, const char *user_home, const char *user_runtime, char **ret_path) {
- char *tmp_new_path;
-
- assert(unit_name);
- assert(ret_path);
-
- if (!unit_is_editable(unit_name, fragment_path, user_home))
- return -EINVAL;
-
- switch (arg_scope) {
- case UNIT_FILE_SYSTEM:
- tmp_new_path = path_join(arg_root, arg_runtime ? "/run/systemd/system/" : SYSTEM_CONFIG_UNIT_PATH, unit_name);
- break;
- case UNIT_FILE_GLOBAL:
- tmp_new_path = path_join(arg_root, arg_runtime ? "/run/systemd/user/" : USER_CONFIG_UNIT_PATH, unit_name);
- break;
- case UNIT_FILE_USER:
- assert(user_home);
- assert(user_runtime);
-
- tmp_new_path = path_join(arg_root, arg_runtime ? user_runtime : user_home, unit_name);
- break;
- default:
- assert_not_reached("Invalid scope");
- }
- if (!tmp_new_path)
- return log_oom();
-
- *ret_path = tmp_new_path;
-
- return 0;
-}
-
static int unit_file_create_copy(const char *unit_name,
const char *fragment_path,
const char *user_home,
@@ -6060,7 +5993,7 @@ static int unit_file_create_copy(const char *unit_name,
assert(ret_new_path);
assert(ret_tmp_path);
- r = get_copy_to_edit(unit_name, fragment_path, user_home, user_runtime, &tmp_new_path);
+ r = get_file_to_edit(unit_name, user_home, user_runtime, &tmp_new_path);
if (r < 0)
return r;
@@ -6192,7 +6125,7 @@ static int find_paths_to_edit(sd_bus *bus, char **names, char ***paths) {
if (arg_full)
r = unit_file_create_copy(*name, path, user_home, user_runtime, &new_path, &tmp_path);
else
- r = unit_file_create_drop_in(*name, user_home, user_runtime, &new_path, &tmp_path);
+ r = unit_file_create_dropin(*name, user_home, user_runtime, &new_path, &tmp_path);
if (r < 0)
return r;
diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c
index 58b456a291..11aa52aaed 100644
--- a/src/test/test-path-util.c
+++ b/src/test/test-path-util.c
@@ -176,13 +176,13 @@ static void test_path_join(void) {
test_join("/root", "/a/b", "/c", "/root/a/b/c");
test_join("/root", "a/b", "c", "/root/a/b/c");
test_join("/root", "/a/b", "c", "/root/a/b/c");
- test_join("/root", "/", "c", "/root//c");
+ test_join("/root", "/", "c", "/root/c");
test_join("/root", "/", NULL, "/root/");
test_join(NULL, "/a/b", "/c", "/a/b/c");
test_join(NULL, "a/b", "c", "a/b/c");
test_join(NULL, "/a/b", "c", "/a/b/c");
- test_join(NULL, "/", "c", "//c");
+ test_join(NULL, "/", "c", "/c");
test_join(NULL, "/", NULL, "/");
}