]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/bus-print-properties.c
Merge pull request #30513 from rpigott/resolved-ede
[thirdparty/systemd.git] / src / shared / bus-print-properties.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
9176326b
LP
2
3#include "bus-print-properties.h"
4#include "cap-list.h"
5#include "cgroup-util.h"
6#include "escape.h"
7#include "mountpoint-util.h"
8#include "nsflags.h"
9#include "parse-util.h"
10#include "stdio-util.h"
11#include "string-util.h"
12#include "strv.h"
13#include "time-util.h"
14#include "user-util.h"
15
255b1fc8 16int bus_print_property_value(const char *name, const char *expected_value, BusPrintPropertyFlags flags, const char *value) {
9176326b
LP
17 assert(name);
18
19 if (expected_value && !streq_ptr(expected_value, value))
20 return 0;
21
255b1fc8
YW
22 if (!FLAGS_SET(flags, BUS_PRINT_PROPERTY_SHOW_EMPTY) && isempty(value))
23 return 0;
24
25 if (FLAGS_SET(flags, BUS_PRINT_PROPERTY_ONLY_VALUE))
26 puts(strempty(value));
9176326b 27 else
255b1fc8 28 printf("%s=%s\n", name, strempty(value));
9176326b
LP
29
30 return 0;
31}
32
255b1fc8
YW
33int bus_print_property_valuef(const char *name, const char *expected_value, BusPrintPropertyFlags flags, const char *fmt, ...) {
34 _cleanup_free_ char *s = NULL;
9176326b
LP
35 va_list ap;
36 int r;
37
38 assert(name);
39 assert(fmt);
40
9176326b 41 va_start(ap, fmt);
255b1fc8 42 r = vasprintf(&s, fmt, ap);
9176326b 43 va_end(ap);
255b1fc8
YW
44 if (r < 0)
45 return -ENOMEM;
9176326b 46
255b1fc8 47 return bus_print_property_value(name, expected_value, flags, s);
9176326b
LP
48}
49
255b1fc8 50static int bus_print_property(const char *name, const char *expected_value, sd_bus_message *m, BusPrintPropertyFlags flags) {
9176326b
LP
51 char type;
52 const char *contents;
53 int r;
54
55 assert(name);
56 assert(m);
57
58 r = sd_bus_message_peek_type(m, &type, &contents);
59 if (r < 0)
60 return r;
61
62 switch (type) {
63
64 case SD_BUS_TYPE_STRING: {
65 const char *s;
66
67 r = sd_bus_message_read_basic(m, type, &s);
68 if (r < 0)
69 return r;
70
255b1fc8 71 if (FLAGS_SET(flags, BUS_PRINT_PROPERTY_SHOW_EMPTY) || !isempty(s)) {
9176326b
LP
72 bool good;
73
74 /* This property has a single value, so we need to take
75 * care not to print a new line, everything else is OK. */
76 good = !strchr(s, '\n');
255b1fc8 77 bus_print_property_value(name, expected_value, flags, good ? s : "[unprintable]");
9176326b
LP
78 }
79
80 return 1;
81 }
82
83 case SD_BUS_TYPE_BOOLEAN: {
84 int b;
85
86 r = sd_bus_message_read_basic(m, type, &b);
87 if (r < 0)
88 return r;
89
90 if (expected_value && parse_boolean(expected_value) != b)
91 return 1;
92
255b1fc8 93 bus_print_property_value(name, NULL, flags, yes_no(b));
9176326b
LP
94 return 1;
95 }
96
97 case SD_BUS_TYPE_UINT64: {
98 uint64_t u;
99
100 r = sd_bus_message_read_basic(m, type, &u);
101 if (r < 0)
102 return r;
103
104 /* Yes, heuristics! But we can change this check
105 * should it turn out to not be sufficient */
106
107 if (endswith(name, "Timestamp") ||
04f5c018 108 STR_IN_SET(name, "NextElapseUSecRealtime", "LastTriggerUSec", "TimeUSec", "RTCTimeUSec"))
9176326b 109
04f5c018 110 bus_print_property_value(name, expected_value, flags, FORMAT_TIMESTAMP(u));
9176326b 111
5291f26d
ZJS
112 else if (strstr(name, "USec"))
113 bus_print_property_value(name, expected_value, flags, FORMAT_TIMESPAN(u, 0));
9176326b 114
5291f26d 115 else if (streq(name, "CoredumpFilter"))
255b1fc8 116 bus_print_property_valuef(name, expected_value, flags, "0x%"PRIx64, u);
9176326b 117
255b1fc8 118 else if (streq(name, "RestrictNamespaces")) {
9176326b
LP
119 _cleanup_free_ char *s = NULL;
120 const char *result;
121
122 if ((u & NAMESPACE_FLAGS_ALL) == 0)
123 result = "yes";
124 else if (FLAGS_SET(u, NAMESPACE_FLAGS_ALL))
125 result = "no";
126 else {
127 r = namespace_flags_to_string(u, &s);
128 if (r < 0)
129 return r;
130
255b1fc8 131 result = s;
9176326b
LP
132 }
133
255b1fc8 134 bus_print_property_value(name, expected_value, flags, result);
9176326b
LP
135
136 } else if (streq(name, "MountFlags")) {
137 const char *result;
138
b205e59a 139 result = mount_propagation_flag_to_string(u);
9176326b
LP
140 if (!result)
141 return -EINVAL;
142
255b1fc8 143 bus_print_property_value(name, expected_value, flags, result);
9176326b
LP
144
145 } else if (STR_IN_SET(name, "CapabilityBoundingSet", "AmbientCapabilities")) {
146 _cleanup_free_ char *s = NULL;
147
8142d735 148 r = capability_set_to_string(u, &s);
9176326b
LP
149 if (r < 0)
150 return r;
151
255b1fc8 152 bus_print_property_value(name, expected_value, flags, s);
9176326b 153
c8340822 154 } else if (STR_IN_SET(name, "CPUWeight", "StartupCPUWeight") && u == CGROUP_WEIGHT_IDLE)
155 bus_print_property_value(name, expected_value, flags, "idle");
156
157 else if ((STR_IN_SET(name, "CPUWeight", "StartupCPUWeight", "IOWeight", "StartupIOWeight") && u == CGROUP_WEIGHT_INVALID) ||
9176326b
LP
158 (STR_IN_SET(name, "CPUShares", "StartupCPUShares") && u == CGROUP_CPU_SHARES_INVALID) ||
159 (STR_IN_SET(name, "BlockIOWeight", "StartupBlockIOWeight") && u == CGROUP_BLKIO_WEIGHT_INVALID) ||
3565c709 160 (STR_IN_SET(name, "MemoryCurrent", "MemoryAvailable", "TasksCurrent") && u == UINT64_MAX) ||
3f362012 161 (startswith(name, "Memory") && ENDSWITH_SET(name, "Current", "Peak") && u == CGROUP_LIMIT_MAX) ||
bfb6b121 162 (startswith(name, "IO") && ENDSWITH_SET(name, "Bytes", "Operations") && u == UINT64_MAX) ||
f5fbe71d 163 (endswith(name, "NSec") && u == UINT64_MAX))
9176326b 164
255b1fc8 165 bus_print_property_value(name, expected_value, flags, "[not set]");
9176326b 166
4fb0d2dc
MK
167 else if ((ENDSWITH_SET(name, "MemoryLow", "MemoryMin",
168 "MemoryHigh", "MemoryMax",
169 "MemorySwapMax", "MemoryZSwapMax", "MemoryLimit") &&
bfb6b121 170 u == CGROUP_LIMIT_MAX) ||
4fb0d2dc 171 (endswith(name, "TasksMax") && u == UINT64_MAX) ||
f5fbe71d
YW
172 (startswith(name, "Limit") && u == UINT64_MAX) ||
173 (startswith(name, "DefaultLimit") && u == UINT64_MAX))
9176326b 174
255b1fc8 175 bus_print_property_value(name, expected_value, flags, "infinity");
f5fbe71d 176 else if (STR_IN_SET(name, "IPIngressBytes", "IPIngressPackets", "IPEgressBytes", "IPEgressPackets") && u == UINT64_MAX)
255b1fc8 177 bus_print_property_value(name, expected_value, flags, "[no data]");
9176326b 178 else
255b1fc8 179 bus_print_property_valuef(name, expected_value, flags, "%"PRIu64, u);
9176326b
LP
180
181 return 1;
182 }
183
184 case SD_BUS_TYPE_INT64: {
185 int64_t i;
186
187 r = sd_bus_message_read_basic(m, type, &i);
188 if (r < 0)
189 return r;
190
255b1fc8 191 bus_print_property_valuef(name, expected_value, flags, "%"PRIi64, i);
9176326b
LP
192 return 1;
193 }
194
195 case SD_BUS_TYPE_UINT32: {
196 uint32_t u;
197
198 r = sd_bus_message_read_basic(m, type, &u);
199 if (r < 0)
200 return r;
201
202 if (strstr(name, "UMask") || strstr(name, "Mode"))
255b1fc8 203 bus_print_property_valuef(name, expected_value, flags, "%04o", u);
9176326b
LP
204
205 else if (streq(name, "UID")) {
206 if (u == UID_INVALID)
255b1fc8 207 bus_print_property_value(name, expected_value, flags, "[not set]");
9176326b 208 else
255b1fc8 209 bus_print_property_valuef(name, expected_value, flags, "%"PRIu32, u);
9176326b
LP
210 } else if (streq(name, "GID")) {
211 if (u == GID_INVALID)
255b1fc8 212 bus_print_property_value(name, expected_value, flags, "[not set]");
9176326b 213 else
255b1fc8 214 bus_print_property_valuef(name, expected_value, flags, "%"PRIu32, u);
9176326b 215 } else
255b1fc8 216 bus_print_property_valuef(name, expected_value, flags, "%"PRIu32, u);
9176326b
LP
217
218 return 1;
219 }
220
221 case SD_BUS_TYPE_INT32: {
222 int32_t i;
223
224 r = sd_bus_message_read_basic(m, type, &i);
225 if (r < 0)
226 return r;
227
255b1fc8 228 bus_print_property_valuef(name, expected_value, flags, "%"PRIi32, i);
9176326b
LP
229 return 1;
230 }
231
232 case SD_BUS_TYPE_DOUBLE: {
233 double d;
234
235 r = sd_bus_message_read_basic(m, type, &d);
236 if (r < 0)
237 return r;
238
255b1fc8 239 bus_print_property_valuef(name, expected_value, flags, "%g", d);
9176326b
LP
240 return 1;
241 }
242
243 case SD_BUS_TYPE_ARRAY:
244 if (streq(contents, "s")) {
245 bool first = true;
246 const char *str;
247
248 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, contents);
249 if (r < 0)
250 return r;
251
252 while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &str)) > 0) {
253 _cleanup_free_ char *e = NULL;
254
9e53c10a 255 e = shell_maybe_quote(str, 0);
9176326b
LP
256 if (!e)
257 return -ENOMEM;
258
259 if (first) {
255b1fc8 260 if (!FLAGS_SET(flags, BUS_PRINT_PROPERTY_ONLY_VALUE))
9176326b
LP
261 printf("%s=", name);
262 first = false;
263 } else
264 fputs(" ", stdout);
265
266 fputs(e, stdout);
267 }
268 if (r < 0)
269 return r;
270
255b1fc8 271 if (first && FLAGS_SET(flags, BUS_PRINT_PROPERTY_SHOW_EMPTY) && !FLAGS_SET(flags, BUS_PRINT_PROPERTY_ONLY_VALUE))
9176326b 272 printf("%s=", name);
255b1fc8 273 if (!first || FLAGS_SET(flags, BUS_PRINT_PROPERTY_SHOW_EMPTY))
9176326b
LP
274 puts("");
275
276 r = sd_bus_message_exit_container(m);
277 if (r < 0)
278 return r;
279
280 return 1;
281
282 } else if (streq(contents, "y")) {
283 const uint8_t *u;
284 size_t n;
285
286 r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
287 if (r < 0)
288 return r;
289
255b1fc8 290 if (FLAGS_SET(flags, BUS_PRINT_PROPERTY_SHOW_EMPTY) || n > 0) {
9176326b
LP
291 unsigned i;
292
255b1fc8 293 if (!FLAGS_SET(flags, BUS_PRINT_PROPERTY_ONLY_VALUE))
9176326b
LP
294 printf("%s=", name);
295
296 for (i = 0; i < n; i++)
297 printf("%02x", u[i]);
298
299 puts("");
300 }
301
302 return 1;
303
304 } else if (streq(contents, "u")) {
305 uint32_t *u;
306 size_t n;
307
308 r = sd_bus_message_read_array(m, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
309 if (r < 0)
310 return r;
311
255b1fc8 312 if (FLAGS_SET(flags, BUS_PRINT_PROPERTY_SHOW_EMPTY) || n > 0) {
9176326b
LP
313 unsigned i;
314
255b1fc8 315 if (!FLAGS_SET(flags, BUS_PRINT_PROPERTY_ONLY_VALUE))
9176326b
LP
316 printf("%s=", name);
317
318 for (i = 0; i < n; i++)
319 printf("%08x", u[i]);
320
321 puts("");
322 }
323
324 return 1;
325 }
326
327 break;
328 }
329
330 return 0;
331}
332
333int bus_message_print_all_properties(
334 sd_bus_message *m,
335 bus_message_print_t func,
336 char **filter,
255b1fc8 337 BusPrintPropertyFlags flags,
9176326b
LP
338 Set **found_properties) {
339
340 int r;
341
342 assert(m);
343
344 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
345 if (r < 0)
346 return r;
347
348 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
349 _cleanup_free_ char *name_with_equal = NULL;
350 const char *name, *contents, *expected_value = NULL;
351
352 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &name);
353 if (r < 0)
354 return r;
355
356 if (found_properties) {
357 r = set_ensure_put(found_properties, &string_hash_ops, name);
358 if (r < 0)
359 return log_oom();
360 }
361
362 name_with_equal = strjoin(name, "=");
363 if (!name_with_equal)
364 return log_oom();
365
d29cc4d6 366 if (!filter || strv_contains(filter, name) ||
9176326b
LP
367 (expected_value = strv_find_startswith(filter, name_with_equal))) {
368 r = sd_bus_message_peek_type(m, NULL, &contents);
369 if (r < 0)
370 return r;
371
372 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
373 if (r < 0)
374 return r;
375
376 if (func)
255b1fc8 377 r = func(name, expected_value, m, flags);
9176326b 378 if (!func || r == 0)
255b1fc8 379 r = bus_print_property(name, expected_value, m, flags);
9176326b
LP
380 if (r < 0)
381 return r;
382 if (r == 0) {
255b1fc8 383 if (FLAGS_SET(flags, BUS_PRINT_PROPERTY_SHOW_EMPTY) && !expected_value)
9176326b
LP
384 printf("%s=[unprintable]\n", name);
385 /* skip what we didn't read */
386 r = sd_bus_message_skip(m, contents);
387 if (r < 0)
388 return r;
389 }
390
391 r = sd_bus_message_exit_container(m);
392 if (r < 0)
393 return r;
394 } else {
395 r = sd_bus_message_skip(m, "v");
396 if (r < 0)
397 return r;
398 }
399
400 r = sd_bus_message_exit_container(m);
401 if (r < 0)
402 return r;
403 }
404 if (r < 0)
405 return r;
406
407 r = sd_bus_message_exit_container(m);
408 if (r < 0)
409 return r;
410
411 return 0;
412}
413
414int bus_print_all_properties(
415 sd_bus *bus,
416 const char *dest,
417 const char *path,
418 bus_message_print_t func,
419 char **filter,
255b1fc8 420 BusPrintPropertyFlags flags,
9176326b
LP
421 Set **found_properties) {
422
423 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
424 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
425 int r;
426
427 assert(bus);
428 assert(path);
429
430 r = sd_bus_call_method(bus,
431 dest,
432 path,
433 "org.freedesktop.DBus.Properties",
434 "GetAll",
435 &error,
436 &reply,
437 "s", "");
438 if (r < 0)
439 return r;
440
255b1fc8 441 return bus_message_print_all_properties(reply, func, filter, flags, found_properties);
9176326b 442}