]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
systemctl: allow 'edit' to work on templates again
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Mon, 16 Jul 2018 13:18:21 +0000 (15:18 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Mon, 16 Jul 2018 13:52:40 +0000 (15:52 +0200)
This got broken in 9d9dd746d461e4524fb3644b20b8138448d666f2, because a template
is not a valid unit, so the check for being masked failed. Avoid this by
handling templates specially. Fixes #9554.

Also, this improves 'cat' with masked units:

(before) $ systemctl cat foofoofoo@.service
Failed to derive unit name prefix from unit name: Invalid argument
Failed to derive unit name prefix from unit name: Invalid argument
Failed to derive unit name prefix from unit name: Invalid argument
Failed to derive unit name prefix from unit name: Invalid argument
Failed to derive unit name prefix from unit name: Invalid argument
Failed to derive unit name prefix from unit name: Invalid argument
Failed to derive unit name prefix from unit name: Invalid argument
Failed to derive unit name prefix from unit name: Invalid argument
Failed to derive unit name prefix from unit name: Invalid argument
Failed to derive unit name prefix from unit name: Invalid argument

(after) $ build/systemctl cat foofoofoo@.service

In check_triggering_units(), the call to unit_is_masked() is replaced with an
open-coded check. This is a bit unfortunate, but unit_is_masked() now requires
LookupPaths to be initialized, which we don't have or need in this case, so it
seems easiest to just accept this tiny code duplication.

src/systemctl/systemctl.c

index 0b5def60f3ac5a2e66510e2e14f714060e058b7d..23a9e44abdce612a35283218a221977a847cd83e 100644 (file)
@@ -2436,7 +2436,7 @@ static int unit_file_find_path(LookupPaths *lp, const char *unit_name, char **un
                 if (r == -ENOMEM)
                         return log_oom();
                 if (r < 0)
-                        return log_error_errno(r, "Failed to access path '%s': %m", path);
+                        return log_error_errno(r, "Failed to access path \"%s\": %m", path);
 
                 if (unit_path)
                         *unit_path = TAKE_PTR(lpath);
@@ -2544,12 +2544,16 @@ static int unit_find_paths(
                 if (r < 0)
                         return r;
 
-                if (r > 0)
+                if (r > 0) {
+                        if (null_or_empty_path(path))
+                                /* The template is masked. Let's cut the process short. */
+                                return -ERFKILL;
+
                         /* We found the unit file. If we followed symlinks, this name might be
                          * different then the unit_name with started with. Look for dropins matching
                          * that "final" name. */
                         r = set_put(names, basename(path));
-                else if (!template)
+                else if (!template)
                         /* No unit file, let's look for dropins matching the original name.
                          * systemd has fairly complicated rules (based on unit type and provenience),
                          * which units are allowed not to have the main unit file. We err on the
@@ -2623,10 +2627,24 @@ static int get_state_one_unit(sd_bus *bus, const char *name, UnitActiveState *ac
         return 0;
 }
 
-static int unit_is_masked(sd_bus *bus, const char *name) {
+static int unit_is_masked(sd_bus *bus, LookupPaths *lp, const char *name) {
         _cleanup_free_ char *load_state = NULL;
         int r;
 
+        if (unit_name_is_valid(name, UNIT_NAME_TEMPLATE)) {
+                _cleanup_free_ char *path = NULL;
+
+                /* A template cannot be loaded, but it can be still masked, so
+                 * we need to use a different method. */
+
+                r = unit_file_find_path(lp, name, &path);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        return false;
+                return null_or_empty_path(path);
+        }
+
         r = unit_load_state(bus, name, &load_state);
         if (r < 0)
                 return r;
@@ -2636,7 +2654,7 @@ static int unit_is_masked(sd_bus *bus, const char *name) {
 
 static int check_triggering_units(sd_bus *bus, const char *name) {
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_free_ char *n = NULL, *path = NULL;
+        _cleanup_free_ char *n = NULL, *path = NULL, *load_state = NULL;
         _cleanup_strv_free_ char **triggered_by = NULL;
         bool print_warning_label = true;
         UnitActiveState active_state;
@@ -2647,9 +2665,12 @@ static int check_triggering_units(sd_bus *bus, const char *name) {
         if (r < 0)
                 return log_error_errno(r, "Failed to mangle unit name: %m");
 
-        r = unit_is_masked(bus, n);
-        if (r != 0)
-                return r < 0 ? r : 0;
+        r = unit_load_state(bus, name, &load_state);
+        if (r < 0)
+                return r;
+
+        if (streq(load_state, "masked"))
+                return 0;
 
         path = unit_dbus_path_from_name(n);
         if (!path)
@@ -3125,7 +3146,7 @@ static int start_unit(int argc, char *argv[], void *userdata) {
                  * another active unit (socket, path, timer) */
                 if (!arg_quiet && streq(method, "StopUnit"))
                         STRV_FOREACH(name, names)
-                                check_triggering_units(bus, *name);
+                                (void) check_triggering_units(bus, *name);
         }
 
         if (r >= 0 && arg_wait) {
@@ -5355,6 +5376,13 @@ static int cat(int argc, char *argv[], void *userdata) {
                 _cleanup_strv_free_ char **dropin_paths = NULL;
 
                 r = unit_find_paths(bus, *name, &lp, &fragment_path, &dropin_paths);
+                if (r == -ERFKILL) {
+                        printf("%s# unit %s is masked%s\n",
+                               ansi_highlight_magenta(),
+                               *name,
+                               ansi_normal());
+                        continue;
+                }
                 if (r < 0)
                         return r;
                 else if (r == 0)
@@ -6921,6 +6949,7 @@ static int find_paths_to_edit(sd_bus *bus, char **names, char ***paths) {
 }
 
 static int edit(int argc, char *argv[], void *userdata) {
+        _cleanup_(lookup_paths_free) LookupPaths lp = {};
         _cleanup_strv_free_ char **names = NULL;
         _cleanup_strv_free_ char **paths = NULL;
         char **original, **tmp;
@@ -6937,6 +6966,10 @@ static int edit(int argc, char *argv[], void *userdata) {
                 return -EINVAL;
         }
 
+        r = lookup_paths_init(&lp, arg_scope, 0, arg_root);
+        if (r < 0)
+                return log_error_errno(r, "Failed to determine unit paths: %m");
+
         r = acquire_bus(BUS_MANAGER, &bus);
         if (r < 0)
                 return r;
@@ -6946,7 +6979,7 @@ static int edit(int argc, char *argv[], void *userdata) {
                 return log_error_errno(r, "Failed to expand names: %m");
 
         STRV_FOREACH(tmp, names) {
-                r = unit_is_masked(bus, *tmp);
+                r = unit_is_masked(bus, &lp, *tmp);
                 if (r < 0)
                         return r;