]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/cgroup-show.c
importd: fix path to download binary
[thirdparty/systemd.git] / src / shared / cgroup-show.c
CommitLineData
d6c9574f 1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
ab35fb1b
LP
2
3/***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
ab35fb1b
LP
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 16 Lesser General Public License for more details.
ab35fb1b 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
ab35fb1b
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <stdio.h>
23#include <string.h>
fa776d8e
LP
24#include <dirent.h>
25#include <errno.h>
ab35fb1b
LP
26
27#include "util.h"
28#include "macro.h"
9eb977db 29#include "path-util.h"
c6c18be3 30#include "cgroup-util.h"
ab35fb1b
LP
31#include "cgroup-show.h"
32
33static int compare(const void *a, const void *b) {
34 const pid_t *p = a, *q = b;
35
36 if (*p < *q)
37 return -1;
38 if (*p > *q)
39 return 1;
40 return 0;
41}
42
3da7a50f
ZJS
43static void show_pid_array(pid_t pids[], unsigned n_pids, const char *prefix, unsigned n_columns, bool extra, bool more, bool kernel_threads, OutputFlags flags) {
44 unsigned i, j, pid_width;
b69d29ce 45
3da7a50f
ZJS
46 assert(n_pids > 0);
47 qsort(pids, n_pids, sizeof(pid_t), compare);
b69d29ce 48
3da7a50f
ZJS
49 /* Filter duplicates */
50 for (j = 0, i = 1; i < n_pids; i++) {
51 if (pids[i] == pids[j])
52 continue;
53 pids[++j] = pids[i];
b69d29ce 54 }
3da7a50f
ZJS
55 n_pids = j + 1;
56 pid_width = DECIMAL_STR_WIDTH(pids[j]);
b69d29ce 57
b47d419c 58 if (flags & OUTPUT_FULL_WIDTH)
9bdbc2e2
LN
59 n_columns = 0;
60 else {
61 if (n_columns > pid_width+2)
62 n_columns -= pid_width+2;
63 else
64 n_columns = 20;
65 }
b69d29ce 66 for (i = 0; i < n_pids; i++) {
b47d419c 67 _cleanup_free_ char *t = NULL;
b69d29ce
LP
68
69 get_process_cmdline(pids[i], n_columns, true, &t);
70
6b01f1d3
LP
71 if (extra)
72 printf("%s%s ", prefix, draw_special_char(DRAW_TRIANGULAR_BULLET));
73 else
74 printf("%s%s", prefix, draw_special_char(((more || i < n_pids-1) ? DRAW_TREE_BRANCH : DRAW_TREE_RIGHT)));
75
3da7a50f 76 printf("%*"PID_PRI" %s\n", pid_width, pids[i], strna(t));
b69d29ce
LP
77 }
78}
79
80
9bdbc2e2 81static int show_cgroup_one_by_path(const char *path, const char *prefix, unsigned n_columns, bool more, bool kernel_threads, OutputFlags flags) {
ab35fb1b 82 char *fn;
7027ff61 83 _cleanup_fclose_ FILE *f = NULL;
ab35fb1b 84 size_t n = 0, n_allocated = 0;
7027ff61 85 _cleanup_free_ pid_t *pids = NULL;
b47d419c 86 _cleanup_free_ char *p = NULL;
b69d29ce 87 pid_t pid;
fa776d8e 88 int r;
ab35fb1b 89
7027ff61 90 r = cg_mangle_path(path, &p);
b69d29ce 91 if (r < 0)
35d2e7ec 92 return r;
ab35fb1b 93
b47d419c 94 fn = strappenda(p, "/cgroup.procs");
fa776d8e 95 f = fopen(fn, "re");
ab35fb1b 96 if (!f)
fa776d8e 97 return -errno;
ab35fb1b 98
c6c18be3 99 while ((r = cg_read_pid(f, &pid)) > 0) {
ab35fb1b 100
1e5678d0
LP
101 if (!kernel_threads && is_kernel_thread(pid) > 0)
102 continue;
103
3da7a50f
ZJS
104 if (!GREEDY_REALLOC(pids, n_allocated, n + 1))
105 return -ENOMEM;
ab35fb1b
LP
106
107 assert(n < n_allocated);
c6c18be3 108 pids[n++] = pid;
ab35fb1b
LP
109 }
110
c6c18be3 111 if (r < 0)
7027ff61 112 return r;
c6c18be3 113
b69d29ce 114 if (n > 0)
9bdbc2e2 115 show_pid_array(pids, n, prefix, n_columns, false, more, kernel_threads, flags);
ab35fb1b 116
7027ff61 117 return 0;
fa776d8e
LP
118}
119
9bdbc2e2 120int show_cgroup_by_path(const char *path, const char *prefix, unsigned n_columns, bool kernel_threads, OutputFlags flags) {
7027ff61
LP
121 _cleanup_free_ char *fn = NULL, *p1 = NULL, *last = NULL, *p2 = NULL;
122 _cleanup_closedir_ DIR *d = NULL;
123 char *gn = NULL;
fa776d8e
LP
124 bool shown_pids = false;
125 int r;
126
b69d29ce
LP
127 assert(path);
128
fa776d8e
LP
129 if (n_columns <= 0)
130 n_columns = columns();
131
132 if (!prefix)
133 prefix = "";
134
7027ff61 135 r = cg_mangle_path(path, &fn);
c3175a7f 136 if (r < 0)
35d2e7ec 137 return r;
fa776d8e 138
c3175a7f 139 d = opendir(fn);
7027ff61 140 if (!d)
fa776d8e 141 return -errno;
fa776d8e 142
35d2e7ec 143 while ((r = cg_read_subgroup(d, &gn)) > 0) {
7027ff61 144 _cleanup_free_ char *k = NULL;
c3175a7f 145
7027ff61 146 k = strjoin(fn, "/", gn, NULL);
c3175a7f 147 free(gn);
7027ff61
LP
148 if (!k)
149 return -ENOMEM;
c3175a7f 150
7027ff61 151 if (!(flags & OUTPUT_SHOW_ALL) && cg_is_empty_recursive(NULL, k, false) > 0)
c3175a7f 152 continue;
fa776d8e
LP
153
154 if (!shown_pids) {
9bdbc2e2 155 show_cgroup_one_by_path(path, prefix, n_columns, true, kernel_threads, flags);
fa776d8e
LP
156 shown_pids = true;
157 }
158
159 if (last) {
45a5ff0d 160 printf("%s%s%s\n", prefix, draw_special_char(DRAW_TREE_BRANCH),
2b6bf07d 161 basename(last));
fa776d8e 162
c3175a7f 163 if (!p1) {
6b01f1d3 164 p1 = strappend(prefix, draw_special_char(DRAW_TREE_VERTICAL));
7027ff61
LP
165 if (!p1)
166 return -ENOMEM;
c3175a7f 167 }
fa776d8e 168
9bdbc2e2 169 show_cgroup_by_path(last, p1, n_columns-2, kernel_threads, flags);
fa776d8e 170 free(last);
fa776d8e
LP
171 }
172
c3175a7f 173 last = k;
7027ff61 174 k = NULL;
fa776d8e
LP
175 }
176
35d2e7ec 177 if (r < 0)
7027ff61 178 return r;
35d2e7ec 179
fa776d8e 180 if (!shown_pids)
9bdbc2e2 181 show_cgroup_one_by_path(path, prefix, n_columns, !!last, kernel_threads, flags);
fa776d8e
LP
182
183 if (last) {
45a5ff0d 184 printf("%s%s%s\n", prefix, draw_special_char(DRAW_TREE_RIGHT),
2b6bf07d 185 basename(last));
fa776d8e 186
c3175a7f
LP
187 if (!p2) {
188 p2 = strappend(prefix, " ");
7027ff61
LP
189 if (!p2)
190 return -ENOMEM;
c3175a7f 191 }
fa776d8e 192
9bdbc2e2 193 show_cgroup_by_path(last, p2, n_columns-2, kernel_threads, flags);
fa776d8e
LP
194 }
195
7027ff61 196 return 0;
ab35fb1b 197}
35d2e7ec 198
9bdbc2e2 199int show_cgroup(const char *controller, const char *path, const char *prefix, unsigned n_columns, bool kernel_threads, OutputFlags flags) {
7027ff61 200 _cleanup_free_ char *p = NULL;
35d2e7ec
LP
201 int r;
202
35d2e7ec
LP
203 assert(path);
204
1e5678d0
LP
205 r = cg_get_path(controller, path, NULL, &p);
206 if (r < 0)
35d2e7ec
LP
207 return r;
208
7027ff61 209 return show_cgroup_by_path(p, prefix, n_columns, kernel_threads, flags);
35d2e7ec 210}
b69d29ce 211
9bdbc2e2 212static int show_extra_pids(const char *controller, const char *path, const char *prefix, unsigned n_columns, const pid_t pids[], unsigned n_pids, OutputFlags flags) {
7fd1b19b 213 _cleanup_free_ pid_t *copy = NULL;
b69d29ce
LP
214 unsigned i, j;
215 int r;
216
b69d29ce
LP
217 assert(path);
218
219 if (n_pids <= 0)
220 return 0;
221
222 if (n_columns <= 0)
223 n_columns = columns();
224
7027ff61 225 prefix = strempty(prefix);
b69d29ce
LP
226
227 copy = new(pid_t, n_pids);
228 if (!copy)
229 return -ENOMEM;
230
231 for (i = 0, j = 0; i < n_pids; i++) {
7fd1b19b 232 _cleanup_free_ char *k = NULL;
b69d29ce 233
7027ff61 234 r = cg_pid_get_path(controller, pids[i], &k);
050fbdb8 235 if (r < 0)
b69d29ce 236 return r;
b69d29ce
LP
237
238 if (path_startswith(k, path))
239 continue;
240
241 copy[j++] = pids[i];
242 }
243
9bdbc2e2 244 show_pid_array(copy, j, prefix, n_columns, true, false, false, flags);
b69d29ce 245
b69d29ce
LP
246 return 0;
247}
248
9bdbc2e2 249int show_cgroup_and_extra(const char *controller, const char *path, const char *prefix, unsigned n_columns, bool kernel_threads, const pid_t extra_pids[], unsigned n_extra_pids, OutputFlags flags) {
b69d29ce
LP
250 int r;
251
b69d29ce
LP
252 assert(path);
253
9bdbc2e2 254 r = show_cgroup(controller, path, prefix, n_columns, kernel_threads, flags);
b69d29ce
LP
255 if (r < 0)
256 return r;
257
9bdbc2e2 258 return show_extra_pids(controller, path, prefix, n_columns, extra_pids, n_extra_pids, flags);
b69d29ce
LP
259}
260
9bdbc2e2 261int show_cgroup_and_extra_by_spec(const char *spec, const char *prefix, unsigned n_columns, bool kernel_threads, const pid_t extra_pids[], unsigned n_extra_pids, OutputFlags flags) {
b08121d0 262 _cleanup_free_ char *controller = NULL, *path = NULL;
7027ff61 263 int r;
b69d29ce
LP
264
265 assert(spec);
266
267 r = cg_split_spec(spec, &controller, &path);
268 if (r < 0)
269 return r;
270
9bdbc2e2 271 return show_cgroup_and_extra(controller, path, prefix, n_columns, kernel_threads, extra_pids, n_extra_pids, flags);
b69d29ce 272}