1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
5 #include "analyze-dump.h"
8 #include "bus-locator.h"
12 static int dump_fallback(sd_bus
*bus
) {
13 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
14 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
20 r
= bus_call_method(bus
, bus_systemd_mgr
, "Dump", &error
, &reply
, NULL
);
22 return log_error_errno(r
, "Failed to call Dump: %s", bus_error_message(&error
, r
));
24 r
= sd_bus_message_read(reply
, "s", &text
);
26 return bus_log_parse_error(r
);
32 static int dump(sd_bus
*bus
) {
33 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
34 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
37 r
= bus_call_method(bus
, bus_systemd_mgr
, "DumpByFileDescriptor", &error
, &reply
, NULL
);
38 if (IN_SET(r
, -EACCES
, -EBADR
))
39 return 0; /* Fall back to non-fd method. We need to do this even if the bus supports sending
40 * fds to cater to very old managers which didn't have the fd-based method. */
42 return log_error_errno(r
, "Failed to call DumpByFileDescriptor: %s",
43 bus_error_message(&error
, r
));
45 return dump_fd_reply(reply
);
48 static int dump_patterns_fallback(sd_bus
*bus
, char **patterns
) {
49 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
50 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
, *m
= NULL
;
54 r
= bus_message_new_method_call(bus
, &m
, bus_systemd_mgr
, "DumpUnitsMatchingPatterns");
56 return bus_log_create_error(r
);
58 r
= sd_bus_message_append_strv(m
, patterns
);
60 return bus_log_create_error(r
);
62 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
64 return log_error_errno(r
, "Failed to call DumpUnitsMatchingPatterns: %s",
65 bus_error_message(&error
, r
));
67 r
= sd_bus_message_read(reply
, "s", &text
);
69 return bus_log_parse_error(r
);
75 static int dump_patterns(sd_bus
*bus
, char **patterns
) {
76 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
77 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
, *m
= NULL
;
80 r
= bus_message_new_method_call(bus
, &m
, bus_systemd_mgr
, "DumpUnitsMatchingPatternsByFileDescriptor");
82 return bus_log_create_error(r
);
84 r
= sd_bus_message_append_strv(m
, patterns
);
86 return bus_log_create_error(r
);
88 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
90 return log_error_errno(r
, "Failed to call DumpUnitsMatchingPatternsByFileDescriptor: %s",
91 bus_error_message(&error
, r
));
93 return dump_fd_reply(reply
);
96 static int mangle_patterns(char **args
, char ***ret
) {
97 _cleanup_strv_free_
char **mangled
= NULL
;
100 STRV_FOREACH(arg
, args
) {
103 r
= unit_name_mangle_with_suffix(*arg
, NULL
, UNIT_NAME_MANGLE_GLOB
, ".service", &t
);
105 return log_error_errno(r
, "Failed to mangle name '%s': %m", *arg
);
107 r
= strv_consume(&mangled
, t
);
112 if (strv_isempty(mangled
))
113 mangled
= strv_free(mangled
);
115 *ret
= TAKE_PTR(mangled
);
119 int verb_dump(int argc
, char *argv
[], void *userdata
) {
120 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
121 _cleanup_strv_free_
char **patterns
= NULL
;
124 r
= acquire_bus(&bus
, NULL
);
126 return bus_log_connect_error(r
, arg_transport
);
128 pager_open(arg_pager_flags
);
130 r
= mangle_patterns(strv_skip(argv
, 1), &patterns
);
134 r
= sd_bus_can_send(bus
, SD_BUS_TYPE_UNIX_FD
);
136 return log_error_errno(r
, "Unable to determine if bus connection supports fd passing: %m");
138 r
= patterns
? dump_patterns(bus
, patterns
) : dump(bus
);
139 if (r
== 0) /* wasn't supported */
140 r
= patterns
? dump_patterns_fallback(bus
, patterns
) : dump_fallback(bus
);