]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
systemctl: fix masking of template units 6741/head
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Sun, 3 Sep 2017 14:45:54 +0000 (17:45 +0300)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Sun, 3 Sep 2017 14:55:10 +0000 (17:55 +0300)
systemctl would try to load the properties of the unit, which is impossible
for template names, and the whole operation would fail. It seems that this
regression was introduced in 00c83b430020914499bebf22be6b258f518ae291.

Export the part of unit_find_paths() responsible for locating instance unit
fragments and reuse it from unit_exists() to fix the handling of template
units.

Fixes #6412.

src/systemctl/systemctl.c

index 398c60196f0b3894a1a427f0a3e127d2fa6bb646..e3853c68c80e752cc9b0150e88a52e0f0b4e711d 100644 (file)
@@ -2480,7 +2480,6 @@ static int unit_file_find_path(LookupPaths *lp, const char *unit_name, char **un
 
         assert(lp);
         assert(unit_name);
-        assert(unit_path);
 
         STRV_FOREACH(p, lp->search_path) {
                 _cleanup_free_ char *path = NULL, *lpath = NULL;
@@ -2498,14 +2497,48 @@ static int unit_file_find_path(LookupPaths *lp, const char *unit_name, char **un
                 if (r < 0)
                         return log_error_errno(r, "Failed to access path '%s': %m", path);
 
-                *unit_path = lpath;
-                lpath = NULL;
+                if (unit_path) {
+                        *unit_path = lpath;
+                        lpath = NULL;
+                }
                 return 1;
         }
 
         return 0;
 }
 
+static int unit_find_template_path(
+                const char *unit_name,
+                LookupPaths *lp,
+                char **fragment_path,
+                char **template) {
+
+        _cleanup_free_ char *_template = NULL;
+        int r;
+
+        /* Returns 1 if a fragment was found, 0 if not found, negative on error. */
+
+        r = unit_file_find_path(lp, unit_name, fragment_path);
+        if (r != 0)
+                return r; /* error or found a real unit */
+
+        r = unit_name_template(unit_name, &_template);
+        if (r == -EINVAL)
+                return 0; /* not a template, does not exist */
+        if (r < 0)
+                return log_error_errno(r, "Failed to determine template name: %m");
+
+        r = unit_file_find_path(lp, _template, fragment_path);
+        if (r < 0)
+                return r;
+
+        if (template) {
+                *template = _template;
+                _template = NULL;
+        }
+        return r;
+}
+
 static int unit_find_paths(
                 sd_bus *bus,
                 const char *unit_name,
@@ -2561,29 +2594,18 @@ static int unit_find_paths(
                                 return log_error_errno(r, "Failed to get DropInPaths: %s", bus_error_message(&error, r));
                 }
         } else {
-                _cleanup_set_free_ Set *names;
+                _cleanup_set_free_ Set *names = NULL;
                 _cleanup_free_ char *template = NULL;
 
                 names = set_new(NULL);
                 if (!names)
                         return log_oom();
 
-                r = unit_file_find_path(lp, unit_name, &path);
+                r = unit_find_template_path(unit_name, lp, &path, &template);
                 if (r < 0)
                         return r;
 
-                if (r == 0) {
-                        r = unit_name_template(unit_name, &template);
-                        if (r < 0 && r != -EINVAL)
-                                return log_error_errno(r, "Failed to determine template name: %m");
-                        if (r >= 0) {
-                                r = unit_file_find_path(lp, template, &path);
-                                if (r < 0)
-                                        return r;
-                        }
-                }
-
-                if (path)
+                if (r > 0)
                         /* 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. */
@@ -6084,7 +6106,7 @@ static int normalize_names(char **names, bool warn_if_path) {
         return 0;
 }
 
-static int unit_exists(const char *unit) {
+static int unit_exists(LookupPaths *lp, const char *unit) {
         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         _cleanup_free_ char *path = NULL;
@@ -6097,6 +6119,9 @@ static int unit_exists(const char *unit) {
         sd_bus *bus;
         int r;
 
+        if (unit_name_is_valid(unit, UNIT_NAME_TEMPLATE))
+                return unit_find_template_path(unit, lp, NULL, NULL);
+
         path = unit_dbus_path_from_name(unit);
         if (!path)
                 return log_oom();
@@ -6202,9 +6227,14 @@ static int enable_unit(int argc, char *argv[], void *userdata) {
 
                 if (STR_IN_SET(verb, "mask", "unmask")) {
                         char **name;
+                        _cleanup_lookup_paths_free_ LookupPaths lp = {};
+
+                        r = lookup_paths_init(&lp, arg_scope, 0, arg_root);
+                        if (r < 0)
+                                return r;
 
                         STRV_FOREACH(name, names) {
-                                r = unit_exists(*name);
+                                r = unit_exists(&lp, *name);
                                 if (r < 0)
                                         return r;
                                 if (r == 0)