summaryrefslogtreecommitdiffstats
path: root/src/analyze/analyze-dump.c
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2022-10-17 15:03:16 +0200
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2022-10-18 08:45:45 +0200
commitb08d86dc4a5179ca879074a83de48c69f289612e (patch)
treec0ec0d797048201edc2d001c2b3c52f1c481aa66 /src/analyze/analyze-dump.c
parentmanager: add DumpUnitsMatchingPatternsByFileDescriptor() (diff)
downloadsystemd-b08d86dc4a5179ca879074a83de48c69f289612e.tar.xz
systemd-b08d86dc4a5179ca879074a83de48c69f289612e.zip
analyze: use DumpUnitsMatchingPatternsByFileDescriptor
Similarly to DumpByFileDescriptor vs Dump, DumpUnitsMatchingPatternsByFileDescriptor is used in preference. Dissimilarly, a fallback to DumpUnitsMatchingPatterns is not done on error, because there is no need for backwards compatibility. The code is still more verbose than I'd like, but there are four different code paths with slightly different rules in each case, so it's hard to make this all very brief. Since we have a separate file dedicated to making those calls, the verbose-but-easy-to-follow implementation should be OK. Closes #24989. I only did a quick test that all both variants works locally and over ssh.
Diffstat (limited to '')
-rw-r--r--src/analyze/analyze-dump.c131
1 files changed, 90 insertions, 41 deletions
diff --git a/src/analyze/analyze-dump.c b/src/analyze/analyze-dump.c
index ac2b31ae26..2e838c906f 100644
--- a/src/analyze/analyze-dump.c
+++ b/src/analyze/analyze-dump.c
@@ -12,14 +12,14 @@
static int dump_fallback(sd_bus *bus) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- const char *text = NULL;
+ const char *text;
int r;
assert(bus);
r = bus_call_method(bus, bus_systemd_mgr, "Dump", &error, &reply, NULL);
if (r < 0)
- return log_error_errno(r, "Failed to issue method call Dump: %s", bus_error_message(&error, r));
+ return log_error_errno(r, "Failed to call Dump: %s", bus_error_message(&error, r));
r = sd_bus_message_read(reply, "s", &text);
if (r < 0)
@@ -29,10 +29,40 @@ static int dump_fallback(sd_bus *bus) {
return 0;
}
-static int dump_patterns(sd_bus *bus, char **patterns) {
+static int dump_fd_reply(sd_bus_message *message) {
+ int fd, r;
+
+ r = sd_bus_message_read(message, "h", &fd);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ fflush(stdout);
+ r = copy_bytes(fd, STDOUT_FILENO, UINT64_MAX, 0);
+ if (r < 0)
+ return r;
+
+ return 1; /* Success */
+}
+
+static int dump(sd_bus *bus) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ int r;
+
+ r = bus_call_method(bus, bus_systemd_mgr, "DumpByFileDescriptor", &error, &reply, NULL);
+ if (IN_SET(r, -EACCES, -EBADR))
+ return 0; /* Fall back to non-fd method. We need to do this even if the bus supports sending
+ * fds to cater to very old managers which didn't have the fd-based method. */
+ if (r < 0)
+ return log_error_errno(r, "Failed to call DumpByFileDescriptor: %s",
+ bus_error_message(&error, r));
+
+ return dump_fd_reply(reply);
+}
+
+static int dump_patterns_fallback(sd_bus *bus, char **patterns) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL;
- _cleanup_strv_free_ char **mangled = NULL;
const char *text;
int r;
@@ -40,25 +70,13 @@ static int dump_patterns(sd_bus *bus, char **patterns) {
if (r < 0)
return bus_log_create_error(r);
- STRV_FOREACH(pattern, patterns) {
- char *t;
-
- r = unit_name_mangle_with_suffix(*pattern, NULL, UNIT_NAME_MANGLE_GLOB, ".service", &t);
- if (r < 0)
- return log_error_errno(r, "Failed to mangle name: %m");
-
- r = strv_consume(&mangled, t);
- if (r < 0)
- return log_oom();
- }
-
- r = sd_bus_message_append_strv(m, mangled);
+ r = sd_bus_message_append_strv(m, patterns);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_call(bus, m, 0, &error, &reply);
if (r < 0)
- return log_error_errno(r, "Failed to issue method call DumpUnitsMatchingPatterns: %s",
+ return log_error_errno(r, "Failed to call DumpUnitsMatchingPatterns: %s",
bus_error_message(&error, r));
r = sd_bus_message_read(reply, "s", &text);
@@ -66,44 +84,75 @@ static int dump_patterns(sd_bus *bus, char **patterns) {
return bus_log_parse_error(r);
fputs(text, stdout);
- return r;
+ return 0;
}
-int verb_dump(int argc, char *argv[], void *userdata) {
+static int dump_patterns(sd_bus *bus, char **patterns) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
- int fd = -1;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL;
int r;
- r = acquire_bus(&bus, NULL);
+ r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "DumpUnitsMatchingPatternsByFileDescriptor");
if (r < 0)
- return bus_log_connect_error(r, arg_transport);
+ return bus_log_create_error(r);
- pager_open(arg_pager_flags);
+ r = sd_bus_message_append_strv(m, patterns);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_call(bus, m, 0, &error, &reply);
+ if (r < 0)
+ return log_error_errno(r, "Failed to call DumpUnitsMatchingPatternsByFileDescriptor: %s",
+ bus_error_message(&error, r));
- if (argc > 1)
- return dump_patterns(bus, strv_skip(argv, 1));
+ return dump_fd_reply(reply);
+}
- if (!sd_bus_can_send(bus, SD_BUS_TYPE_UNIX_FD))
- return dump_fallback(bus);
+static int mangle_patterns(char **args, char ***ret) {
+ _cleanup_strv_free_ char **mangled = NULL;
+ int r;
- r = bus_call_method(bus, bus_systemd_mgr, "DumpByFileDescriptor", &error, &reply, NULL);
- if (r < 0) {
- /* fall back to Dump if DumpByFileDescriptor is not supported */
- if (!IN_SET(r, -EACCES, -EBADR))
- return log_error_errno(r, "Failed to issue method call DumpByFileDescriptor: %s",
- bus_error_message(&error, r));
+ STRV_FOREACH(arg, args) {
+ char *t;
- return dump_fallback(bus);
+ r = unit_name_mangle_with_suffix(*arg, NULL, UNIT_NAME_MANGLE_GLOB, ".service", &t);
+ if (r < 0)
+ return log_error_errno(r, "Failed to mangle name '%s': %m", *arg);
+
+ r = strv_consume(&mangled, t);
+ if (r < 0)
+ return log_oom();
}
- r = sd_bus_message_read(reply, "h", &fd);
+ if (strv_isempty(mangled))
+ mangled = strv_free(mangled);
+
+ *ret = TAKE_PTR(mangled);
+ return 0;
+}
+
+int verb_dump(int argc, char *argv[], void *userdata) {
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+ _cleanup_strv_free_ char **patterns = NULL;
+ int r;
+
+ r = acquire_bus(&bus, NULL);
if (r < 0)
- return bus_log_parse_error(r);
+ return bus_log_connect_error(r, arg_transport);
- fflush(stdout);
- r = copy_bytes(fd, STDOUT_FILENO, UINT64_MAX, 0);
+ pager_open(arg_pager_flags);
+
+ r = mangle_patterns(strv_skip(argv, 1), &patterns);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_can_send(bus, SD_BUS_TYPE_UNIX_FD);
+ if (r < 0)
+ return log_error_errno(r, "Unable to determine if bus connection supports fd passing: %m");
+ if (r > 0)
+ r = patterns ? dump_patterns(bus, patterns) : dump(bus);
+ if (r == 0) /* wasn't supported */
+ r = patterns ? dump_patterns_fallback(bus, patterns) : dump_fallback(bus);
if (r < 0)
return r;