]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
analyze: split out "dot" verb
authorLennart Poettering <lennart@poettering.net>
Mon, 21 Feb 2022 09:47:48 +0000 (10:47 +0100)
committerLennart Poettering <lennart@poettering.net>
Mon, 21 Feb 2022 16:22:23 +0000 (17:22 +0100)
src/analyze/analyze-dot.c [new file with mode: 0644]
src/analyze/analyze-dot.h [new file with mode: 0644]
src/analyze/analyze.c
src/analyze/analyze.h
src/analyze/meson.build

diff --git a/src/analyze/analyze-dot.c b/src/analyze/analyze-dot.c
new file mode 100644 (file)
index 0000000..08f9910
--- /dev/null
@@ -0,0 +1,184 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "analyze.h"
+#include "analyze-dot.h"
+#include "bus-error.h"
+#include "bus-locator.h"
+#include "bus-unit-util.h"
+#include "glob-util.h"
+#include "terminal-util.h"
+
+static int graph_one_property(
+                sd_bus *bus,
+                const UnitInfo *u,
+                const char *prop,
+                const char *color,
+                char *patterns[],
+                char *from_patterns[],
+                char *to_patterns[]) {
+
+        _cleanup_strv_free_ char **units = NULL;
+        char **unit;
+        int r;
+        bool match_patterns;
+
+        assert(u);
+        assert(prop);
+        assert(color);
+
+        match_patterns = strv_fnmatch(patterns, u->id);
+
+        if (!strv_isempty(from_patterns) && !match_patterns && !strv_fnmatch(from_patterns, u->id))
+                return 0;
+
+        r = bus_get_unit_property_strv(bus, u->unit_path, prop, &units);
+        if (r < 0)
+                return r;
+
+        STRV_FOREACH(unit, units) {
+                bool match_patterns2;
+
+                match_patterns2 = strv_fnmatch(patterns, *unit);
+
+                if (!strv_isempty(to_patterns) && !match_patterns2 && !strv_fnmatch(to_patterns, *unit))
+                        continue;
+
+                if (!strv_isempty(patterns) && !match_patterns && !match_patterns2)
+                        continue;
+
+                printf("\t\"%s\"->\"%s\" [color=\"%s\"];\n", u->id, *unit, color);
+        }
+
+        return 0;
+}
+
+static int graph_one(sd_bus *bus, const UnitInfo *u, char *patterns[], char *from_patterns[], char *to_patterns[]) {
+        int r;
+
+        assert(bus);
+        assert(u);
+
+        if (IN_SET(arg_dot, DEP_ORDER, DEP_ALL)) {
+                r = graph_one_property(bus, u, "After", "green", patterns, from_patterns, to_patterns);
+                if (r < 0)
+                        return r;
+        }
+
+        if (IN_SET(arg_dot, DEP_REQUIRE, DEP_ALL)) {
+                r = graph_one_property(bus, u, "Requires", "black", patterns, from_patterns, to_patterns);
+                if (r < 0)
+                        return r;
+                r = graph_one_property(bus, u, "Requisite", "darkblue", patterns, from_patterns, to_patterns);
+                if (r < 0)
+                        return r;
+                r = graph_one_property(bus, u, "Wants", "grey66", patterns, from_patterns, to_patterns);
+                if (r < 0)
+                        return r;
+                r = graph_one_property(bus, u, "Conflicts", "red", patterns, from_patterns, to_patterns);
+                if (r < 0)
+                        return r;
+        }
+
+        return 0;
+}
+
+static int expand_patterns(sd_bus *bus, char **patterns, char ***ret) {
+        _cleanup_strv_free_ char **expanded_patterns = NULL;
+        char **pattern;
+        int r;
+
+        STRV_FOREACH(pattern, patterns) {
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+                _cleanup_free_ char *unit = NULL, *unit_id = NULL;
+
+                if (strv_extend(&expanded_patterns, *pattern) < 0)
+                        return log_oom();
+
+                if (string_is_glob(*pattern))
+                        continue;
+
+                unit = unit_dbus_path_from_name(*pattern);
+                if (!unit)
+                        return log_oom();
+
+                r = sd_bus_get_property_string(
+                                bus,
+                                "org.freedesktop.systemd1",
+                                unit,
+                                "org.freedesktop.systemd1.Unit",
+                                "Id",
+                                &error,
+                                &unit_id);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to get ID: %s", bus_error_message(&error, r));
+
+                if (!streq(*pattern, unit_id)) {
+                        if (strv_extend(&expanded_patterns, unit_id) < 0)
+                                return log_oom();
+                }
+        }
+
+        *ret = TAKE_PTR(expanded_patterns); /* do not free */
+
+        return 0;
+}
+
+int dot(int argc, char *argv[], void *userdata) {
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+        _cleanup_strv_free_ char **expanded_patterns = NULL;
+        _cleanup_strv_free_ char **expanded_from_patterns = NULL;
+        _cleanup_strv_free_ char **expanded_to_patterns = NULL;
+        int r;
+        UnitInfo u;
+
+        r = acquire_bus(&bus, NULL);
+        if (r < 0)
+                return bus_log_connect_error(r, arg_transport);
+
+        r = expand_patterns(bus, strv_skip(argv, 1), &expanded_patterns);
+        if (r < 0)
+                return r;
+
+        r = expand_patterns(bus, arg_dot_from_patterns, &expanded_from_patterns);
+        if (r < 0)
+                return r;
+
+        r = expand_patterns(bus, arg_dot_to_patterns, &expanded_to_patterns);
+        if (r < 0)
+                return r;
+
+        r = bus_call_method(bus, bus_systemd_mgr, "ListUnits", &error, &reply, NULL);
+        if (r < 0)
+                log_error_errno(r, "Failed to list units: %s", bus_error_message(&error, r));
+
+        r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
+        if (r < 0)
+                return bus_log_parse_error(r);
+
+        printf("digraph systemd {\n");
+
+        while ((r = bus_parse_unit_info(reply, &u)) > 0) {
+
+                r = graph_one(bus, &u, expanded_patterns, expanded_from_patterns, expanded_to_patterns);
+                if (r < 0)
+                        return r;
+        }
+        if (r < 0)
+                return bus_log_parse_error(r);
+
+        printf("}\n");
+
+        log_info("   Color legend: black     = Requires\n"
+                 "                 dark blue = Requisite\n"
+                 "                 dark grey = Wants\n"
+                 "                 red       = Conflicts\n"
+                 "                 green     = After\n");
+
+        if (on_tty() && !arg_quiet)
+                log_notice("-- You probably want to process this output with graphviz' dot tool.\n"
+                           "-- Try a shell pipeline like 'systemd-analyze dot | dot -Tsvg > systemd.svg'!\n");
+
+        return 0;
+}
diff --git a/src/analyze/analyze-dot.h b/src/analyze/analyze-dot.h
new file mode 100644 (file)
index 0000000..9017c18
--- /dev/null
@@ -0,0 +1,4 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+int dot(int argc, char *argv[], void *userdata);
index f9790d99ee8154371b13f2c1b076873b435e01de..8326cfa49e671e5c66cc94d035caa613406b4cf6 100644 (file)
@@ -15,6 +15,7 @@
 #include "analyze.h"
 #include "analyze-calendar.h"
 #include "analyze-condition.h"
+#include "analyze-dot.h"
 #include "analyze-dump.h"
 #include "analyze-elf.h"
 #include "analyze-filesystems.h"
                 svg("</text>\n");                                       \
         } while (false)
 
-static enum dot {
-        DEP_ALL,
-        DEP_ORDER,
-        DEP_REQUIRE
-} arg_dot = DEP_ALL;
-static char **arg_dot_from_patterns = NULL;
-static char **arg_dot_to_patterns = NULL;
+DotMode arg_dot = DEP_ALL;
+char **arg_dot_from_patterns = NULL, **arg_dot_to_patterns = NULL;
 static usec_t arg_fuzz = 0;
 PagerFlags arg_pager_flags = 0;
 BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
@@ -217,7 +213,7 @@ static int bus_get_uint64_property(sd_bus *bus, const char *path, const char *in
         return 0;
 }
 
-static int bus_get_unit_property_strv(sd_bus *bus, const char *path, const char *property, char ***strv) {
+int bus_get_unit_property_strv(sd_bus *bus, const char *path, const char *property, char ***strv) {
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
 
@@ -1204,181 +1200,6 @@ static int analyze_time(int argc, char *argv[], void *userdata) {
         return 0;
 }
 
-static int graph_one_property(
-                sd_bus *bus,
-                const UnitInfo *u,
-                const char *prop,
-                const char *color,
-                char *patterns[],
-                char *from_patterns[],
-                char *to_patterns[]) {
-
-        _cleanup_strv_free_ char **units = NULL;
-        char **unit;
-        int r;
-        bool match_patterns;
-
-        assert(u);
-        assert(prop);
-        assert(color);
-
-        match_patterns = strv_fnmatch(patterns, u->id);
-
-        if (!strv_isempty(from_patterns) && !match_patterns && !strv_fnmatch(from_patterns, u->id))
-                return 0;
-
-        r = bus_get_unit_property_strv(bus, u->unit_path, prop, &units);
-        if (r < 0)
-                return r;
-
-        STRV_FOREACH(unit, units) {
-                bool match_patterns2;
-
-                match_patterns2 = strv_fnmatch(patterns, *unit);
-
-                if (!strv_isempty(to_patterns) && !match_patterns2 && !strv_fnmatch(to_patterns, *unit))
-                        continue;
-
-                if (!strv_isempty(patterns) && !match_patterns && !match_patterns2)
-                        continue;
-
-                printf("\t\"%s\"->\"%s\" [color=\"%s\"];\n", u->id, *unit, color);
-        }
-
-        return 0;
-}
-
-static int graph_one(sd_bus *bus, const UnitInfo *u, char *patterns[], char *from_patterns[], char *to_patterns[]) {
-        int r;
-
-        assert(bus);
-        assert(u);
-
-        if (IN_SET(arg_dot, DEP_ORDER, DEP_ALL)) {
-                r = graph_one_property(bus, u, "After", "green", patterns, from_patterns, to_patterns);
-                if (r < 0)
-                        return r;
-        }
-
-        if (IN_SET(arg_dot, DEP_REQUIRE, DEP_ALL)) {
-                r = graph_one_property(bus, u, "Requires", "black", patterns, from_patterns, to_patterns);
-                if (r < 0)
-                        return r;
-                r = graph_one_property(bus, u, "Requisite", "darkblue", patterns, from_patterns, to_patterns);
-                if (r < 0)
-                        return r;
-                r = graph_one_property(bus, u, "Wants", "grey66", patterns, from_patterns, to_patterns);
-                if (r < 0)
-                        return r;
-                r = graph_one_property(bus, u, "Conflicts", "red", patterns, from_patterns, to_patterns);
-                if (r < 0)
-                        return r;
-        }
-
-        return 0;
-}
-
-static int expand_patterns(sd_bus *bus, char **patterns, char ***ret) {
-        _cleanup_strv_free_ char **expanded_patterns = NULL;
-        char **pattern;
-        int r;
-
-        STRV_FOREACH(pattern, patterns) {
-                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-                _cleanup_free_ char *unit = NULL, *unit_id = NULL;
-
-                if (strv_extend(&expanded_patterns, *pattern) < 0)
-                        return log_oom();
-
-                if (string_is_glob(*pattern))
-                        continue;
-
-                unit = unit_dbus_path_from_name(*pattern);
-                if (!unit)
-                        return log_oom();
-
-                r = sd_bus_get_property_string(
-                                bus,
-                                "org.freedesktop.systemd1",
-                                unit,
-                                "org.freedesktop.systemd1.Unit",
-                                "Id",
-                                &error,
-                                &unit_id);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to get ID: %s", bus_error_message(&error, r));
-
-                if (!streq(*pattern, unit_id)) {
-                        if (strv_extend(&expanded_patterns, unit_id) < 0)
-                                return log_oom();
-                }
-        }
-
-        *ret = TAKE_PTR(expanded_patterns); /* do not free */
-
-        return 0;
-}
-
-static int dot(int argc, char *argv[], void *userdata) {
-        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
-        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
-        _cleanup_strv_free_ char **expanded_patterns = NULL;
-        _cleanup_strv_free_ char **expanded_from_patterns = NULL;
-        _cleanup_strv_free_ char **expanded_to_patterns = NULL;
-        int r;
-        UnitInfo u;
-
-        r = acquire_bus(&bus, NULL);
-        if (r < 0)
-                return bus_log_connect_error(r, arg_transport);
-
-        r = expand_patterns(bus, strv_skip(argv, 1), &expanded_patterns);
-        if (r < 0)
-                return r;
-
-        r = expand_patterns(bus, arg_dot_from_patterns, &expanded_from_patterns);
-        if (r < 0)
-                return r;
-
-        r = expand_patterns(bus, arg_dot_to_patterns, &expanded_to_patterns);
-        if (r < 0)
-                return r;
-
-        r = bus_call_method(bus, bus_systemd_mgr, "ListUnits", &error, &reply, NULL);
-        if (r < 0)
-                log_error_errno(r, "Failed to list units: %s", bus_error_message(&error, r));
-
-        r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
-        if (r < 0)
-                return bus_log_parse_error(r);
-
-        printf("digraph systemd {\n");
-
-        while ((r = bus_parse_unit_info(reply, &u)) > 0) {
-
-                r = graph_one(bus, &u, expanded_patterns, expanded_from_patterns, expanded_to_patterns);
-                if (r < 0)
-                        return r;
-        }
-        if (r < 0)
-                return bus_log_parse_error(r);
-
-        printf("}\n");
-
-        log_info("   Color legend: black     = Requires\n"
-                 "                 dark blue = Requisite\n"
-                 "                 dark grey = Wants\n"
-                 "                 red       = Conflicts\n"
-                 "                 green     = After\n");
-
-        if (on_tty() && !arg_quiet)
-                log_notice("-- You probably want to process this output with graphviz' dot tool.\n"
-                           "-- Try a shell pipeline like 'systemd-analyze dot | dot -Tsvg > systemd.svg'!\n");
-
-        return 0;
-}
-
 static int cat_config(int argc, char *argv[], void *userdata) {
         char **arg, **list;
         int r;
index 243e3544588883a51ddb64d1da458d1a5ccdea7f..1819b5d731d8a585485b651fbe0845a5de076b3c 100644 (file)
@@ -7,6 +7,14 @@
 #include "pager.h"
 #include "time-util.h"
 
+typedef enum DotMode {
+        DEP_ALL,
+        DEP_ORDER,
+        DEP_REQUIRE,
+} DotMode;
+
+extern DotMode arg_dot;
+extern char **arg_dot_from_patterns, **arg_dot_to_patterns;
 extern PagerFlags arg_pager_flags;
 extern BusTransport arg_transport;
 extern unsigned arg_iterations;
@@ -15,4 +23,6 @@ extern bool arg_quiet;
 
 int acquire_bus(sd_bus **bus, bool *use_full_bus);
 
+int bus_get_unit_property_strv(sd_bus *bus, const char *path, const char *property, char ***strv);
+
 void time_parsing_hint(const char *p, bool calendar, bool timestamp, bool timespan);
index 2d62412641193b5859a56048bc728d36bd8e01dd..922a343e6995c17986a557630f8125a61f987989 100644 (file)
@@ -5,6 +5,8 @@ systemd_analyze_sources = files('''
         analyze-calendar.h
         analyze-condition.c
         analyze-condition.h
+        analyze-dot.c
+        analyze-dot.h
         analyze-dump.c
         analyze-dump.h
         analyze-elf.c