]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/cgroup-show.c
seccomp: always handle seccomp_load() failing the same way
[thirdparty/systemd.git] / src / shared / cgroup-show.c
CommitLineData
ab35fb1b
LP
1/***
2 This file is part of systemd.
3
4 Copyright 2010 Lennart Poettering
5
6 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
ab35fb1b
LP
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 14 Lesser General Public License for more details.
ab35fb1b 15
5430f7f2 16 You should have received a copy of the GNU Lesser General Public License
ab35fb1b
LP
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18***/
19
fa776d8e
LP
20#include <dirent.h>
21#include <errno.h>
a8fbdf54 22#include <stddef.h>
07630cea 23#include <stdio.h>
a8fbdf54 24#include <stdlib.h>
07630cea 25#include <string.h>
ab35fb1b 26
b5efdb8a 27#include "alloc-util.h"
049cb73b
ZJS
28#include "bus-error.h"
29#include "bus-util.h"
3ffd4af2 30#include "cgroup-show.h"
07630cea 31#include "cgroup-util.h"
3ffd4af2 32#include "fd-util.h"
049cb73b 33#include "fileio.h"
f97b34a6 34#include "format-util.h"
8752c575 35#include "locale-util.h"
ab35fb1b 36#include "macro.h"
a8fbdf54 37#include "output-mode.h"
9eb977db 38#include "path-util.h"
07630cea
LP
39#include "process-util.h"
40#include "string-util.h"
288a74cc 41#include "terminal-util.h"
049cb73b 42#include "unit-name.h"
ab35fb1b 43
0ff308c8
LP
44static void show_pid_array(
45 pid_t pids[],
46 unsigned n_pids,
47 const char *prefix,
48 unsigned n_columns,
49 bool extra,
50 bool more,
51 OutputFlags flags) {
52
3da7a50f 53 unsigned i, j, pid_width;
b69d29ce 54
da41abc5 55 if (n_pids == 0)
3637713a
LP
56 return;
57
291d565a 58 qsort(pids, n_pids, sizeof(pid_t), pid_compare_func);
b69d29ce 59
3da7a50f
ZJS
60 /* Filter duplicates */
61 for (j = 0, i = 1; i < n_pids; i++) {
62 if (pids[i] == pids[j])
63 continue;
64 pids[++j] = pids[i];
b69d29ce 65 }
3da7a50f
ZJS
66 n_pids = j + 1;
67 pid_width = DECIMAL_STR_WIDTH(pids[j]);
b69d29ce 68
b47d419c 69 if (flags & OUTPUT_FULL_WIDTH)
9bdbc2e2
LN
70 n_columns = 0;
71 else {
72 if (n_columns > pid_width+2)
73 n_columns -= pid_width+2;
74 else
75 n_columns = 20;
76 }
b69d29ce 77 for (i = 0; i < n_pids; i++) {
b47d419c 78 _cleanup_free_ char *t = NULL;
b69d29ce 79
db284505 80 (void) get_process_cmdline(pids[i], n_columns, true, &t);
b69d29ce 81
6b01f1d3 82 if (extra)
323b7dc9 83 printf("%s%s ", prefix, special_glyph(TRIANGULAR_BULLET));
6b01f1d3 84 else
323b7dc9 85 printf("%s%s", prefix, special_glyph(((more || i < n_pids-1) ? TREE_BRANCH : TREE_RIGHT)));
6b01f1d3 86
3da7a50f 87 printf("%*"PID_PRI" %s\n", pid_width, pids[i], strna(t));
b69d29ce
LP
88 }
89}
90
291d565a
LP
91static int show_cgroup_one_by_path(
92 const char *path,
93 const char *prefix,
94 unsigned n_columns,
95 bool more,
291d565a 96 OutputFlags flags) {
b69d29ce 97
ab35fb1b 98 char *fn;
7027ff61 99 _cleanup_fclose_ FILE *f = NULL;
ab35fb1b 100 size_t n = 0, n_allocated = 0;
7027ff61 101 _cleanup_free_ pid_t *pids = NULL;
b47d419c 102 _cleanup_free_ char *p = NULL;
b69d29ce 103 pid_t pid;
fa776d8e 104 int r;
ab35fb1b 105
7027ff61 106 r = cg_mangle_path(path, &p);
b69d29ce 107 if (r < 0)
35d2e7ec 108 return r;
ab35fb1b 109
63c372cb 110 fn = strjoina(p, "/cgroup.procs");
fa776d8e 111 f = fopen(fn, "re");
ab35fb1b 112 if (!f)
fa776d8e 113 return -errno;
ab35fb1b 114
c6c18be3 115 while ((r = cg_read_pid(f, &pid)) > 0) {
ab35fb1b 116
0ff308c8 117 if (!(flags & OUTPUT_KERNEL_THREADS) && is_kernel_thread(pid) > 0)
1e5678d0
LP
118 continue;
119
3da7a50f
ZJS
120 if (!GREEDY_REALLOC(pids, n_allocated, n + 1))
121 return -ENOMEM;
ab35fb1b
LP
122
123 assert(n < n_allocated);
c6c18be3 124 pids[n++] = pid;
ab35fb1b
LP
125 }
126
c6c18be3 127 if (r < 0)
7027ff61 128 return r;
c6c18be3 129
0ff308c8 130 show_pid_array(pids, n, prefix, n_columns, false, more, flags);
ab35fb1b 131
7027ff61 132 return 0;
fa776d8e
LP
133}
134
291d565a
LP
135int show_cgroup_by_path(
136 const char *path,
137 const char *prefix,
138 unsigned n_columns,
291d565a
LP
139 OutputFlags flags) {
140
7027ff61
LP
141 _cleanup_free_ char *fn = NULL, *p1 = NULL, *last = NULL, *p2 = NULL;
142 _cleanup_closedir_ DIR *d = NULL;
143 char *gn = NULL;
fa776d8e
LP
144 bool shown_pids = false;
145 int r;
146
b69d29ce
LP
147 assert(path);
148
fa776d8e
LP
149 if (n_columns <= 0)
150 n_columns = columns();
151
291d565a 152 prefix = strempty(prefix);
fa776d8e 153
7027ff61 154 r = cg_mangle_path(path, &fn);
c3175a7f 155 if (r < 0)
35d2e7ec 156 return r;
fa776d8e 157
c3175a7f 158 d = opendir(fn);
7027ff61 159 if (!d)
fa776d8e 160 return -errno;
fa776d8e 161
35d2e7ec 162 while ((r = cg_read_subgroup(d, &gn)) > 0) {
7027ff61 163 _cleanup_free_ char *k = NULL;
c3175a7f 164
605405c6 165 k = strjoin(fn, "/", gn);
c3175a7f 166 free(gn);
7027ff61
LP
167 if (!k)
168 return -ENOMEM;
c3175a7f 169
6f883237 170 if (!(flags & OUTPUT_SHOW_ALL) && cg_is_empty_recursive(NULL, k) > 0)
c3175a7f 171 continue;
fa776d8e
LP
172
173 if (!shown_pids) {
0ff308c8 174 show_cgroup_one_by_path(path, prefix, n_columns, true, flags);
fa776d8e
LP
175 shown_pids = true;
176 }
177
178 if (last) {
323b7dc9 179 printf("%s%s%s\n", prefix, special_glyph(TREE_BRANCH), cg_unescape(basename(last)));
fa776d8e 180
c3175a7f 181 if (!p1) {
323b7dc9 182 p1 = strappend(prefix, special_glyph(TREE_VERTICAL));
7027ff61
LP
183 if (!p1)
184 return -ENOMEM;
c3175a7f 185 }
fa776d8e 186
0ff308c8 187 show_cgroup_by_path(last, p1, n_columns-2, flags);
fa776d8e 188 free(last);
fa776d8e
LP
189 }
190
c3175a7f 191 last = k;
7027ff61 192 k = NULL;
fa776d8e
LP
193 }
194
35d2e7ec 195 if (r < 0)
7027ff61 196 return r;
35d2e7ec 197
fa776d8e 198 if (!shown_pids)
0ff308c8 199 show_cgroup_one_by_path(path, prefix, n_columns, !!last, flags);
fa776d8e
LP
200
201 if (last) {
323b7dc9 202 printf("%s%s%s\n", prefix, special_glyph(TREE_RIGHT), cg_unescape(basename(last)));
fa776d8e 203
c3175a7f
LP
204 if (!p2) {
205 p2 = strappend(prefix, " ");
7027ff61
LP
206 if (!p2)
207 return -ENOMEM;
c3175a7f 208 }
fa776d8e 209
0ff308c8 210 show_cgroup_by_path(last, p2, n_columns-2, flags);
fa776d8e
LP
211 }
212
7027ff61 213 return 0;
ab35fb1b 214}
35d2e7ec 215
291d565a
LP
216int show_cgroup(const char *controller,
217 const char *path,
218 const char *prefix,
219 unsigned n_columns,
291d565a 220 OutputFlags flags) {
7027ff61 221 _cleanup_free_ char *p = NULL;
35d2e7ec
LP
222 int r;
223
35d2e7ec
LP
224 assert(path);
225
1e5678d0
LP
226 r = cg_get_path(controller, path, NULL, &p);
227 if (r < 0)
35d2e7ec
LP
228 return r;
229
0ff308c8 230 return show_cgroup_by_path(p, prefix, n_columns, flags);
35d2e7ec 231}
b69d29ce 232
291d565a
LP
233static int show_extra_pids(
234 const char *controller,
235 const char *path,
236 const char *prefix,
237 unsigned n_columns,
238 const pid_t pids[],
239 unsigned n_pids,
240 OutputFlags flags) {
241
7fd1b19b 242 _cleanup_free_ pid_t *copy = NULL;
b69d29ce
LP
243 unsigned i, j;
244 int r;
245
b69d29ce
LP
246 assert(path);
247
248 if (n_pids <= 0)
249 return 0;
250
251 if (n_columns <= 0)
252 n_columns = columns();
253
7027ff61 254 prefix = strempty(prefix);
b69d29ce
LP
255
256 copy = new(pid_t, n_pids);
257 if (!copy)
258 return -ENOMEM;
259
260 for (i = 0, j = 0; i < n_pids; i++) {
7fd1b19b 261 _cleanup_free_ char *k = NULL;
b69d29ce 262
7027ff61 263 r = cg_pid_get_path(controller, pids[i], &k);
050fbdb8 264 if (r < 0)
b69d29ce 265 return r;
b69d29ce
LP
266
267 if (path_startswith(k, path))
268 continue;
269
270 copy[j++] = pids[i];
271 }
272
0ff308c8 273 show_pid_array(copy, j, prefix, n_columns, true, false, flags);
b69d29ce 274
b69d29ce
LP
275 return 0;
276}
277
291d565a
LP
278int show_cgroup_and_extra(
279 const char *controller,
280 const char *path,
281 const char *prefix,
282 unsigned n_columns,
291d565a
LP
283 const pid_t extra_pids[],
284 unsigned n_extra_pids,
285 OutputFlags flags) {
286
b69d29ce
LP
287 int r;
288
b69d29ce
LP
289 assert(path);
290
0ff308c8 291 r = show_cgroup(controller, path, prefix, n_columns, flags);
b69d29ce
LP
292 if (r < 0)
293 return r;
294
9bdbc2e2 295 return show_extra_pids(controller, path, prefix, n_columns, extra_pids, n_extra_pids, flags);
b69d29ce
LP
296}
297
291d565a
LP
298int show_cgroup_and_extra_by_spec(
299 const char *spec,
300 const char *prefix,
301 unsigned n_columns,
291d565a
LP
302 const pid_t extra_pids[],
303 unsigned n_extra_pids,
304 OutputFlags flags) {
305
b08121d0 306 _cleanup_free_ char *controller = NULL, *path = NULL;
7027ff61 307 int r;
b69d29ce
LP
308
309 assert(spec);
310
311 r = cg_split_spec(spec, &controller, &path);
312 if (r < 0)
313 return r;
314
0ff308c8 315 return show_cgroup_and_extra(controller, path, prefix, n_columns, extra_pids, n_extra_pids, flags);
b69d29ce 316}
049cb73b 317
bc06be75
ZJS
318int show_cgroup_get_unit_path_and_warn(
319 sd_bus *bus,
320 const char *unit,
321 char **ret) {
322
323 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
324 _cleanup_free_ char *path = NULL;
325 int r;
326
327 path = unit_dbus_path_from_name(unit);
328 if (!path)
329 return log_oom();
330
331 r = sd_bus_get_property_string(
332 bus,
333 "org.freedesktop.systemd1",
334 path,
335 unit_dbus_interface_from_name(unit),
336 "ControlGroup",
337 &error,
338 ret);
339 if (r < 0)
340 return log_error_errno(r, "Failed to query unit control group path: %s",
341 bus_error_message(&error, r));
342
343 return 0;
344}
345
d3e8277d 346int show_cgroup_get_path_and_warn(
049cb73b 347 const char *machine,
d3e8277d 348 const char *prefix,
049cb73b
ZJS
349 char **ret) {
350
049cb73b 351 int r;
d3e8277d
ZJS
352 _cleanup_free_ char *root = NULL;
353
354 if (machine) {
d3e8277d 355 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
bc06be75 356 _cleanup_free_ char *unit = NULL;
d3e8277d
ZJS
357 const char *m;
358
359 m = strjoina("/run/systemd/machines/", machine);
360 r = parse_env_file(m, NEWLINE, "SCOPE", &unit, NULL);
361 if (r < 0)
362 return log_error_errno(r, "Failed to load machine data: %m");
049cb73b 363
d3e8277d
ZJS
364 r = bus_connect_transport_systemd(BUS_TRANSPORT_LOCAL, NULL, false, &bus);
365 if (r < 0)
366 return log_error_errno(r, "Failed to create bus connection: %m");
367
bc06be75 368 r = show_cgroup_get_unit_path_and_warn(bus, unit, &root);
d3e8277d 369 if (r < 0)
bc06be75 370 return r;
d3e8277d
ZJS
371 } else {
372 r = cg_get_root_path(&root);
049cb73b
ZJS
373 if (r == -ENOMEDIUM)
374 return log_error_errno(r, "Failed to get root control group path.\n"
375 "No cgroup filesystem mounted on /sys/fs/cgroup");
376 else if (r < 0)
377 return log_error_errno(r, "Failed to get root control group path: %m");
049cb73b
ZJS
378 }
379
d3e8277d
ZJS
380 if (prefix) {
381 char *t;
049cb73b 382
d3e8277d
ZJS
383 t = strjoin(root, prefix);
384 if (!t)
385 return log_oom();
049cb73b 386
d3e8277d
ZJS
387 *ret = t;
388 } else {
389 *ret = root;
390 root = NULL;
391 }
049cb73b
ZJS
392
393 return 0;
394}