]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/cgroup-show.c
util-lib: split out globbing related calls into glob-util.[ch]
[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
fa776d8e
LP
22#include <dirent.h>
23#include <errno.h>
07630cea
LP
24#include <stdio.h>
25#include <string.h>
ab35fb1b 26
3ffd4af2 27#include "cgroup-show.h"
07630cea 28#include "cgroup-util.h"
3ffd4af2 29#include "fd-util.h"
6482f626 30#include "formats-util.h"
8752c575 31#include "locale-util.h"
ab35fb1b 32#include "macro.h"
9eb977db 33#include "path-util.h"
07630cea
LP
34#include "process-util.h"
35#include "string-util.h"
288a74cc 36#include "terminal-util.h"
07630cea 37#include "util.h"
ab35fb1b
LP
38
39static int compare(const void *a, const void *b) {
40 const pid_t *p = a, *q = b;
41
42 if (*p < *q)
43 return -1;
44 if (*p > *q)
45 return 1;
46 return 0;
47}
48
3da7a50f
ZJS
49static 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) {
50 unsigned i, j, pid_width;
b69d29ce 51
da41abc5 52 if (n_pids == 0)
3637713a
LP
53 return;
54
3da7a50f 55 qsort(pids, n_pids, sizeof(pid_t), compare);
b69d29ce 56
3da7a50f
ZJS
57 /* Filter duplicates */
58 for (j = 0, i = 1; i < n_pids; i++) {
59 if (pids[i] == pids[j])
60 continue;
61 pids[++j] = pids[i];
b69d29ce 62 }
3da7a50f
ZJS
63 n_pids = j + 1;
64 pid_width = DECIMAL_STR_WIDTH(pids[j]);
b69d29ce 65
b47d419c 66 if (flags & OUTPUT_FULL_WIDTH)
9bdbc2e2
LN
67 n_columns = 0;
68 else {
69 if (n_columns > pid_width+2)
70 n_columns -= pid_width+2;
71 else
72 n_columns = 20;
73 }
b69d29ce 74 for (i = 0; i < n_pids; i++) {
b47d419c 75 _cleanup_free_ char *t = NULL;
b69d29ce
LP
76
77 get_process_cmdline(pids[i], n_columns, true, &t);
78
6b01f1d3
LP
79 if (extra)
80 printf("%s%s ", prefix, draw_special_char(DRAW_TRIANGULAR_BULLET));
81 else
82 printf("%s%s", prefix, draw_special_char(((more || i < n_pids-1) ? DRAW_TREE_BRANCH : DRAW_TREE_RIGHT)));
83
3da7a50f 84 printf("%*"PID_PRI" %s\n", pid_width, pids[i], strna(t));
b69d29ce
LP
85 }
86}
87
88
9bdbc2e2 89static int show_cgroup_one_by_path(const char *path, const char *prefix, unsigned n_columns, bool more, bool kernel_threads, OutputFlags flags) {
ab35fb1b 90 char *fn;
7027ff61 91 _cleanup_fclose_ FILE *f = NULL;
ab35fb1b 92 size_t n = 0, n_allocated = 0;
7027ff61 93 _cleanup_free_ pid_t *pids = NULL;
b47d419c 94 _cleanup_free_ char *p = NULL;
b69d29ce 95 pid_t pid;
fa776d8e 96 int r;
ab35fb1b 97
7027ff61 98 r = cg_mangle_path(path, &p);
b69d29ce 99 if (r < 0)
35d2e7ec 100 return r;
ab35fb1b 101
63c372cb 102 fn = strjoina(p, "/cgroup.procs");
fa776d8e 103 f = fopen(fn, "re");
ab35fb1b 104 if (!f)
fa776d8e 105 return -errno;
ab35fb1b 106
c6c18be3 107 while ((r = cg_read_pid(f, &pid)) > 0) {
ab35fb1b 108
1e5678d0
LP
109 if (!kernel_threads && is_kernel_thread(pid) > 0)
110 continue;
111
3da7a50f
ZJS
112 if (!GREEDY_REALLOC(pids, n_allocated, n + 1))
113 return -ENOMEM;
ab35fb1b
LP
114
115 assert(n < n_allocated);
c6c18be3 116 pids[n++] = pid;
ab35fb1b
LP
117 }
118
c6c18be3 119 if (r < 0)
7027ff61 120 return r;
c6c18be3 121
da41abc5 122 show_pid_array(pids, n, prefix, n_columns, false, more, kernel_threads, flags);
ab35fb1b 123
7027ff61 124 return 0;
fa776d8e
LP
125}
126
9bdbc2e2 127int show_cgroup_by_path(const char *path, const char *prefix, unsigned n_columns, bool kernel_threads, OutputFlags flags) {
7027ff61
LP
128 _cleanup_free_ char *fn = NULL, *p1 = NULL, *last = NULL, *p2 = NULL;
129 _cleanup_closedir_ DIR *d = NULL;
130 char *gn = NULL;
fa776d8e
LP
131 bool shown_pids = false;
132 int r;
133
b69d29ce
LP
134 assert(path);
135
fa776d8e
LP
136 if (n_columns <= 0)
137 n_columns = columns();
138
139 if (!prefix)
140 prefix = "";
141
7027ff61 142 r = cg_mangle_path(path, &fn);
c3175a7f 143 if (r < 0)
35d2e7ec 144 return r;
fa776d8e 145
c3175a7f 146 d = opendir(fn);
7027ff61 147 if (!d)
fa776d8e 148 return -errno;
fa776d8e 149
35d2e7ec 150 while ((r = cg_read_subgroup(d, &gn)) > 0) {
7027ff61 151 _cleanup_free_ char *k = NULL;
c3175a7f 152
7027ff61 153 k = strjoin(fn, "/", gn, NULL);
c3175a7f 154 free(gn);
7027ff61
LP
155 if (!k)
156 return -ENOMEM;
c3175a7f 157
6f883237 158 if (!(flags & OUTPUT_SHOW_ALL) && cg_is_empty_recursive(NULL, k) > 0)
c3175a7f 159 continue;
fa776d8e
LP
160
161 if (!shown_pids) {
9bdbc2e2 162 show_cgroup_one_by_path(path, prefix, n_columns, true, kernel_threads, flags);
fa776d8e
LP
163 shown_pids = true;
164 }
165
166 if (last) {
3d9495a8 167 printf("%s%s%s\n", prefix, draw_special_char(DRAW_TREE_BRANCH), cg_unescape(basename(last)));
fa776d8e 168
c3175a7f 169 if (!p1) {
6b01f1d3 170 p1 = strappend(prefix, draw_special_char(DRAW_TREE_VERTICAL));
7027ff61
LP
171 if (!p1)
172 return -ENOMEM;
c3175a7f 173 }
fa776d8e 174
9bdbc2e2 175 show_cgroup_by_path(last, p1, n_columns-2, kernel_threads, flags);
fa776d8e 176 free(last);
fa776d8e
LP
177 }
178
c3175a7f 179 last = k;
7027ff61 180 k = NULL;
fa776d8e
LP
181 }
182
35d2e7ec 183 if (r < 0)
7027ff61 184 return r;
35d2e7ec 185
fa776d8e 186 if (!shown_pids)
9bdbc2e2 187 show_cgroup_one_by_path(path, prefix, n_columns, !!last, kernel_threads, flags);
fa776d8e
LP
188
189 if (last) {
3d9495a8 190 printf("%s%s%s\n", prefix, draw_special_char(DRAW_TREE_RIGHT), cg_unescape(basename(last)));
fa776d8e 191
c3175a7f
LP
192 if (!p2) {
193 p2 = strappend(prefix, " ");
7027ff61
LP
194 if (!p2)
195 return -ENOMEM;
c3175a7f 196 }
fa776d8e 197
9bdbc2e2 198 show_cgroup_by_path(last, p2, n_columns-2, kernel_threads, flags);
fa776d8e
LP
199 }
200
7027ff61 201 return 0;
ab35fb1b 202}
35d2e7ec 203
9bdbc2e2 204int show_cgroup(const char *controller, const char *path, const char *prefix, unsigned n_columns, bool kernel_threads, OutputFlags flags) {
7027ff61 205 _cleanup_free_ char *p = NULL;
35d2e7ec
LP
206 int r;
207
35d2e7ec
LP
208 assert(path);
209
1e5678d0
LP
210 r = cg_get_path(controller, path, NULL, &p);
211 if (r < 0)
35d2e7ec
LP
212 return r;
213
7027ff61 214 return show_cgroup_by_path(p, prefix, n_columns, kernel_threads, flags);
35d2e7ec 215}
b69d29ce 216
9bdbc2e2 217static 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 218 _cleanup_free_ pid_t *copy = NULL;
b69d29ce
LP
219 unsigned i, j;
220 int r;
221
b69d29ce
LP
222 assert(path);
223
224 if (n_pids <= 0)
225 return 0;
226
227 if (n_columns <= 0)
228 n_columns = columns();
229
7027ff61 230 prefix = strempty(prefix);
b69d29ce
LP
231
232 copy = new(pid_t, n_pids);
233 if (!copy)
234 return -ENOMEM;
235
236 for (i = 0, j = 0; i < n_pids; i++) {
7fd1b19b 237 _cleanup_free_ char *k = NULL;
b69d29ce 238
7027ff61 239 r = cg_pid_get_path(controller, pids[i], &k);
050fbdb8 240 if (r < 0)
b69d29ce 241 return r;
b69d29ce
LP
242
243 if (path_startswith(k, path))
244 continue;
245
246 copy[j++] = pids[i];
247 }
248
9bdbc2e2 249 show_pid_array(copy, j, prefix, n_columns, true, false, false, flags);
b69d29ce 250
b69d29ce
LP
251 return 0;
252}
253
9bdbc2e2 254int 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
255 int r;
256
b69d29ce
LP
257 assert(path);
258
9bdbc2e2 259 r = show_cgroup(controller, path, prefix, n_columns, kernel_threads, flags);
b69d29ce
LP
260 if (r < 0)
261 return r;
262
9bdbc2e2 263 return show_extra_pids(controller, path, prefix, n_columns, extra_pids, n_extra_pids, flags);
b69d29ce
LP
264}
265
9bdbc2e2 266int 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 267 _cleanup_free_ char *controller = NULL, *path = NULL;
7027ff61 268 int r;
b69d29ce
LP
269
270 assert(spec);
271
272 r = cg_split_spec(spec, &controller, &path);
273 if (r < 0)
274 return r;
275
9bdbc2e2 276 return show_cgroup_and_extra(controller, path, prefix, n_columns, kernel_threads, extra_pids, n_extra_pids, flags);
b69d29ce 277}