]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
implement aliasing for systemd-analyze verify
authorAlbert Brox <albert@exypno.tech>
Wed, 29 Sep 2021 14:09:34 +0000 (10:09 -0400)
committerLuca Boccassi <luca.boccassi@gmail.com>
Mon, 8 Nov 2021 12:08:23 +0000 (12:08 +0000)
man/systemd-analyze.xml
src/analyze/analyze.c
test/units/testsuite-65.sh

index e072d6613126aed7e61a499cbc2d0e11e022a4c9..4c3b6d173b0333f495116b39acf1ecfd1909906f 100644 (file)
@@ -551,7 +551,8 @@ NAutoVTs=8
       <title><command>systemd-analyze verify <replaceable>FILE</replaceable>...</command></title>
 
       <para>This command will load unit files and print warnings if any errors are detected. Files specified
-      on the command line will be loaded, but also any other units referenced by them. The full unit search
+      on the command line will be loaded, but also any other units referenced by them. A unit's name on disk
+      can be overridden by specifying an alias after a colon; see below for an example. The full unit search
       path is formed by combining the directories for all command line arguments, and the usual unit load
       paths. The variable <varname>$SYSTEMD_UNIT_PATH</varname> is supported, and may be used to replace or
       augment the compiled in set of unit load paths; see
@@ -613,6 +614,27 @@ Service a.service not loaded, a.socket cannot be started.
 Service b@0.service not loaded, b.socket cannot be started.
         </programlisting>
       </example>
+
+      <example>
+        <title>Aliasing a unit</title>
+
+        <programlisting>$ cat /tmp/source
+[Unit]
+Description=Hostname printer
+
+[Service]
+Type=simple
+ExecStart=/usr/bin/echo %H
+MysteryKey=true
+
+$ systemd-analyze verify /tmp/source
+Failed to prepare filename /tmp/source: Invalid argument
+
+$ systemd-analyze verify /tmp/source:alias.service
+/tmp/systemd-analyze-XXXXXX/alias.service:7: Unknown key name 'MysteryKey' in section 'Service', ignoring.
+        </programlisting>
+      </example>
+
     </refsect2>
 
     <refsect2>
index 82fdd3deeeacfe6227628af8603cae4b2e5a4fbf..2d6d327f8d81643ed569afefeb48f069a4e86c94 100644 (file)
@@ -26,6 +26,7 @@
 #include "copy.h"
 #include "def.h"
 #include "exit-status.h"
+#include "extract-word.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "filesystems.h"
@@ -42,6 +43,7 @@
 #include "parse-util.h"
 #include "path-util.h"
 #include "pretty-print.h"
+#include "rm-rf.h"
 #if HAVE_SECCOMP
 #  include "seccomp-util.h"
 #endif
@@ -53,6 +55,7 @@
 #include "strxcpyx.h"
 #include "terminal-util.h"
 #include "time-util.h"
+#include "tmpfile-util.h"
 #include "unit-name.h"
 #include "util.h"
 #include "verb-log-control.h"
@@ -230,6 +233,53 @@ static int compare_unit_start(const UnitTimes *a, const UnitTimes *b) {
         return CMP(a->activating, b->activating);
 }
 
+static int process_aliases(char *argv[], char *tempdir, char ***ret) {
+        _cleanup_strv_free_ char **filenames = NULL;
+        char **filename;
+        int r;
+
+        assert(argv);
+        assert(tempdir);
+        assert(ret);
+
+        STRV_FOREACH(filename, strv_skip(argv, 1)) {
+                _cleanup_free_ char *src = NULL, *dst = NULL, *arg = NULL;
+                char *parse_arg;
+
+                arg = strdup(*filename);
+                if (!arg)
+                        return -ENOMEM;
+
+                parse_arg = arg;
+                r = extract_first_word((const char **) &parse_arg, &src, ":", 0);
+                if (r < 0)
+                        return r;
+
+                if (!parse_arg) {
+                        r = strv_extend(&filenames, src);
+                        if (r < 0)
+                                return -ENOMEM;
+
+                        continue;
+                }
+
+                dst = path_join(tempdir, basename(parse_arg));
+                if (!dst)
+                        return -ENOMEM;
+
+                r = copy_file(src, dst, 0, 0644, 0, 0, COPY_REFLINK);
+                if (r < 0)
+                        return r;
+
+                r = strv_consume(&filenames, TAKE_PTR(dst));
+                if (r < 0)
+                        return -ENOMEM;
+        }
+
+        *ret = TAKE_PTR(filenames);
+        return 0;
+}
+
 static UnitTimes* unit_times_free_array(UnitTimes *t) {
         for (UnitTimes *p = t; p && p->has_data; p++)
                 free(p->name);
@@ -2257,7 +2307,19 @@ static int do_condition(int argc, char *argv[], void *userdata) {
 }
 
 static int do_verify(int argc, char *argv[], void *userdata) {
-        return verify_units(strv_skip(argv, 1), arg_scope, arg_man, arg_generators, arg_recursive_errors, arg_root);
+        _cleanup_strv_free_ char **filenames = NULL;
+        _cleanup_(rm_rf_physical_and_freep) char *tempdir = NULL;
+        int r;
+
+        r = mkdtemp_malloc("/tmp/systemd-analyze-XXXXXX", &tempdir);
+        if (r < 0)
+                return log_error_errno(r, "Failed to setup working directory: %m");
+
+        r = process_aliases(argv, tempdir, &filenames);
+        if (r < 0)
+                return log_error_errno(r, "Couldn't process aliases: %m");
+
+        return verify_units(filenames, arg_scope, arg_man, arg_generators, arg_recursive_errors, arg_root);
 }
 
 static int do_security(int argc, char *argv[], void *userdata) {
index 3218462c7691394e2382fb8db7297c7b3868567c..f98a933cb14b0ec2f1fb03911cd90cec4b0e983c 100755 (executable)
@@ -76,6 +76,14 @@ systemd-analyze verify /tmp/.testfile.service
 
 rm /tmp/.testfile.service
 
+# Alias a unit file's name on disk (see #20061)
+cp /tmp/testfile.service /tmp/testsrvc
+
+systemd-analyze verify /tmp/testsrvc \
+    && { echo 'unexpected success'; exit 1; }
+
+systemd-analyze verify /tmp/testsrvc:alias.service
+
 # Zero exit status since the value used for comparison determine exposure to security threats is by default 100
 systemd-analyze security --offline=true /tmp/testfile.service