From b74df547a90a794ca75eea99238b9ae14a562720 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 19 Feb 2017 16:52:09 -0500 Subject: systemctl: when told to edit an instance, do not edit the template Fixes #5383. --- src/systemctl/systemctl.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 60f8bc3df5..4fe2f126d8 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -6806,7 +6806,8 @@ static int find_paths_to_edit(sd_bus *bus, char **names, char ***paths) { return r; STRV_FOREACH(name, names) { - _cleanup_free_ char *path = NULL, *new_path = NULL, *tmp_path = NULL; + _cleanup_free_ char *path = NULL, *new_path = NULL, *tmp_path = NULL, *tmp_name = NULL; + const char *unit_name; r = unit_find_paths(bus, *name, &lp, &path, NULL); if (r < 0) @@ -6822,11 +6823,28 @@ static int find_paths_to_edit(sd_bus *bus, char **names, char ***paths) { } } + unit_name = basename(path); + /* We follow unit aliases, but we need to propagate the instance */ + if (unit_name_is_valid(*name, UNIT_NAME_INSTANCE) && + unit_name_is_valid(unit_name, UNIT_NAME_TEMPLATE)) { + _cleanup_free_ char *instance = NULL; + + r = unit_name_to_instance(*name, &instance); + if (r < 0) + return r; + + r = unit_name_replace_instance(unit_name, instance, &tmp_name); + if (r < 0) + return r; + + unit_name = tmp_name; + } + if (path) { if (arg_full) - r = unit_file_create_copy(&lp, basename(path), path, &new_path, &tmp_path); + r = unit_file_create_copy(&lp, unit_name, path, &new_path, &tmp_path); else - r = unit_file_create_new(&lp, basename(path), ".d/override.conf", &new_path, &tmp_path); + r = unit_file_create_new(&lp, unit_name, ".d/override.conf", &new_path, &tmp_path); } else r = unit_file_create_new(&lp, *name, NULL, &new_path, &tmp_path); if (r < 0) -- cgit v1.2.3-54-g00ecf From b3734d9841b1540c8cc81a4eca998911871a15ad Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 19 Feb 2017 17:30:53 -0500 Subject: systemctl: fix editing of units with no fragment "systemctl --user edit --force --full tmp.mount" would crash, when we'd do basename(NULL). Fix this by creating a new unit or a new override even if not path is found. Tested with: systemctl --user edit --force --full tmp.mount systemctl --user edit --force tmp.mount systemctl --user edit foo@.service systemctl --user edit foo@bar.service systemctl --user edit --full foo@.service systemctl --user edit --full foo@bar.service --- src/systemctl/systemctl.c | 50 +++++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 4fe2f126d8..90ff08538e 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -6812,41 +6812,45 @@ static int find_paths_to_edit(sd_bus *bus, char **names, char ***paths) { r = unit_find_paths(bus, *name, &lp, &path, NULL); if (r < 0) return r; - else if (!arg_force) { - if (r == 0) { + + if (r == 0) { + assert(!path); + + if (!arg_force) { log_error("Run 'systemctl edit --force %s' to create a new unit.", *name); return -ENOENT; - } else if (!path) { - // FIXME: support units with path==NULL (no FragmentPath) - log_error("No fragment exists for %s.", *name); - return -ENOENT; } - } - unit_name = basename(path); - /* We follow unit aliases, but we need to propagate the instance */ - if (unit_name_is_valid(*name, UNIT_NAME_INSTANCE) && - unit_name_is_valid(unit_name, UNIT_NAME_TEMPLATE)) { - _cleanup_free_ char *instance = NULL; + /* Create a new unit from scratch */ + unit_name = *name; + r = unit_file_create_new(&lp, unit_name, + arg_full ? NULL : ".d/override.conf", + &new_path, &tmp_path); + } else { + assert(path); - r = unit_name_to_instance(*name, &instance); - if (r < 0) - return r; + unit_name = basename(path); + /* We follow unit aliases, but we need to propagate the instance */ + if (unit_name_is_valid(*name, UNIT_NAME_INSTANCE) && + unit_name_is_valid(unit_name, UNIT_NAME_TEMPLATE)) { + _cleanup_free_ char *instance = NULL; - r = unit_name_replace_instance(unit_name, instance, &tmp_name); - if (r < 0) - return r; + r = unit_name_to_instance(*name, &instance); + if (r < 0) + return r; - unit_name = tmp_name; - } + r = unit_name_replace_instance(unit_name, instance, &tmp_name); + if (r < 0) + return r; + + unit_name = tmp_name; + } - if (path) { if (arg_full) r = unit_file_create_copy(&lp, unit_name, path, &new_path, &tmp_path); else r = unit_file_create_new(&lp, unit_name, ".d/override.conf", &new_path, &tmp_path); - } else - r = unit_file_create_new(&lp, *name, NULL, &new_path, &tmp_path); + } if (r < 0) return r; -- cgit v1.2.3-54-g00ecf From 0dcabf0968ce00fd1295e3f501c9abd0f8d0ed9c Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 19 Feb 2017 17:41:38 -0500 Subject: systemctl: fix hint with edit --global/--user --- src/systemctl/systemctl.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 90ff08538e..7ab5559b28 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -6817,7 +6817,10 @@ static int find_paths_to_edit(sd_bus *bus, char **names, char ***paths) { assert(!path); if (!arg_force) { - log_error("Run 'systemctl edit --force %s' to create a new unit.", *name); + log_error("Run 'systemctl edit%s --force %s' to create a new unit.", + arg_scope == UNIT_FILE_GLOBAL ? " --global" : + arg_scope == UNIT_FILE_USER ? " --user" : "", + *name); return -ENOENT; } -- cgit v1.2.3-54-g00ecf From 2b0f4e6f212bce25f9338d3c5c01fde3d15114d9 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 19 Feb 2017 18:53:10 -0500 Subject: systemctl: give a hint about --force --force when communication with manager fails The hint is not too explicit, and just refers to the man page, because this option is slightly dangereous. This was we don't have to discuss the limitation in the hint itself. Fixes #4002. --- src/systemctl/systemctl.c | 59 +++++++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 7ab5559b28..9ca5210dd1 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -3482,6 +3482,8 @@ static int set_exit_code(uint8_t code) { static int start_special(int argc, char *argv[], void *userdata) { enum action a; int r; + bool termination_action; /* an action that terminates the manager, + * can be performed also by signal. */ assert(argv); @@ -3521,40 +3523,43 @@ static int start_special(int argc, char *argv[], void *userdata) { return r; } - if (arg_force >= 2 && - IN_SET(a, - ACTION_HALT, - ACTION_POWEROFF, - ACTION_REBOOT)) + termination_action = IN_SET(a, + ACTION_HALT, + ACTION_POWEROFF, + ACTION_REBOOT); + if (termination_action && arg_force >= 2) return halt_now(a); if (arg_force >= 1 && - IN_SET(a, - ACTION_HALT, - ACTION_POWEROFF, - ACTION_REBOOT, - ACTION_KEXEC, - ACTION_EXIT)) - return trivial_method(argc, argv, userdata); + (termination_action || IN_SET(ACTION_KEXEC, ACTION_EXIT))) + r = trivial_method(argc, argv, userdata); + else { + /* First try logind, to allow authentication with polkit */ + if (IN_SET(a, + ACTION_POWEROFF, + ACTION_REBOOT, + ACTION_SUSPEND, + ACTION_HIBERNATE, + ACTION_HYBRID_SLEEP)) { + + r = logind_reboot(a); + if (r >= 0) + return r; + if (IN_SET(r, -EOPNOTSUPP, -EINPROGRESS)) + /* requested operation is not supported or already in progress */ + return r; - /* First try logind, to allow authentication with polkit */ - if (IN_SET(a, - ACTION_POWEROFF, - ACTION_REBOOT, - ACTION_SUSPEND, - ACTION_HIBERNATE, - ACTION_HYBRID_SLEEP)) { - r = logind_reboot(a); - if (r >= 0) - return r; - if (IN_SET(r, -EOPNOTSUPP, -EINPROGRESS)) - /* requested operation is not supported or already in progress */ - return r; + /* On all other errors, try low-level operation */ + } - /* On all other errors, try low-level operation */ + r = start_unit(argc, argv, userdata); } - return start_unit(argc, argv, userdata); + if (termination_action && arg_force < 2 && + IN_SET(r, -ENOENT, -ETIMEDOUT)) + log_notice("It is possible to perform action directly, see discussion of --force --force in systemctl(1)."); + + return r; } static int start_system_special(int argc, char *argv[], void *userdata) { -- cgit v1.2.3-54-g00ecf