]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/cgroup-show.c
util: introduce memdup()
[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"
c6c18be3 29#include "cgroup-util.h"
ab35fb1b
LP
30#include "cgroup-show.h"
31
32static int compare(const void *a, const void *b) {
33 const pid_t *p = a, *q = b;
34
35 if (*p < *q)
36 return -1;
37 if (*p > *q)
38 return 1;
39 return 0;
40}
41
fa776d8e
LP
42static unsigned ilog10(unsigned long ul) {
43 int n = 0;
44
45 while (ul > 0) {
46 n++;
47 ul /= 10;
48 }
49
50 return n;
51}
52
1e5678d0 53static int show_cgroup_one_by_path(const char *path, const char *prefix, unsigned n_columns, bool more, bool kernel_threads) {
ab35fb1b
LP
54 char *fn;
55 FILE *f;
56 size_t n = 0, n_allocated = 0;
57 pid_t *pids = NULL;
fa776d8e 58 char *p;
c6c18be3 59 pid_t pid, biggest = 0;
fa776d8e 60 int r;
ab35fb1b 61
fa776d8e
LP
62 if (n_columns <= 0)
63 n_columns = columns();
ab35fb1b 64
fa776d8e
LP
65 if (!prefix)
66 prefix = "";
67
35d2e7ec
LP
68 if ((r = cg_fix_path(path, &p)) < 0)
69 return r;
ab35fb1b 70
fa776d8e
LP
71 r = asprintf(&fn, "%s/cgroup.procs", p);
72 free(p);
73
74 if (r < 0)
75 return -ENOMEM;
76
77 f = fopen(fn, "re");
ab35fb1b
LP
78 free(fn);
79
80 if (!f)
fa776d8e 81 return -errno;
ab35fb1b 82
c6c18be3 83 while ((r = cg_read_pid(f, &pid)) > 0) {
ab35fb1b 84
1e5678d0
LP
85 if (!kernel_threads && is_kernel_thread(pid) > 0)
86 continue;
87
ab35fb1b
LP
88 if (n >= n_allocated) {
89 pid_t *npids;
90
91 n_allocated = MAX(16U, n*2U);
92
93 if (!(npids = realloc(pids, sizeof(pid_t) * n_allocated))) {
fa776d8e 94 r = -ENOMEM;
ab35fb1b
LP
95 goto finish;
96 }
97
98 pids = npids;
99 }
100
101 assert(n < n_allocated);
c6c18be3 102 pids[n++] = pid;
fa776d8e 103
c6c18be3
LP
104 if (pid > biggest)
105 biggest = pid;
ab35fb1b
LP
106 }
107
c6c18be3
LP
108 if (r < 0)
109 goto finish;
110
ab35fb1b
LP
111 if (n > 0) {
112 unsigned i, m;
113
114 /* Filter duplicates */
115 m = 0;
116 for (i = 0; i < n; i++) {
117 unsigned j;
118
119 for (j = i+1; j < n; j++)
120 if (pids[i] == pids[j])
121 break;
122
123 if (j >= n)
124 pids[m++] = pids[i];
125 }
126 n = m;
127
128 /* And sort */
129 qsort(pids, n, sizeof(pid_t), compare);
130
fa776d8e
LP
131 if (n_columns > 8)
132 n_columns -= 8;
ab35fb1b 133 else
fa776d8e 134 n_columns = 20;
ab35fb1b
LP
135
136 for (i = 0; i < n; i++) {
137 char *t = NULL;
138
87d2c1ff 139 get_process_cmdline(pids[i], n_columns, true, &t);
ab35fb1b 140
fa776d8e 141 printf("%s%s %*lu %s\n",
ab35fb1b 142 prefix,
fa776d8e 143 (more || i < n-1) ? "\342\224\234" : "\342\224\224",
e364ad06 144 (int) ilog10(biggest),
fa776d8e
LP
145 (unsigned long) pids[i],
146 strna(t));
ab35fb1b
LP
147
148 free(t);
149 }
150 }
151
fa776d8e
LP
152 r = 0;
153
ab35fb1b
LP
154finish:
155 free(pids);
156
157 if (f)
158 fclose(f);
fa776d8e
LP
159
160 return r;
161}
162
c3175a7f 163int show_cgroup_by_path(const char *path, const char *prefix, unsigned n_columns, bool kernel_threads, bool all) {
fa776d8e
LP
164 DIR *d;
165 char *last = NULL;
35d2e7ec 166 char *p1 = NULL, *p2 = NULL, *fn = NULL, *gn = NULL;
fa776d8e
LP
167 bool shown_pids = false;
168 int r;
169
fa776d8e
LP
170 if (n_columns <= 0)
171 n_columns = columns();
172
173 if (!prefix)
174 prefix = "";
175
c3175a7f
LP
176 r = cg_fix_path(path, &fn);
177 if (r < 0)
35d2e7ec 178 return r;
fa776d8e 179
c3175a7f
LP
180 d = opendir(fn);
181 if (!d) {
fa776d8e
LP
182 free(fn);
183 return -errno;
184 }
185
35d2e7ec 186 while ((r = cg_read_subgroup(d, &gn)) > 0) {
c3175a7f
LP
187 char *k;
188
189 r = asprintf(&k, "%s/%s", fn, gn);
190 free(gn);
191
192 if (r < 0) {
193 r = -ENOMEM;
194 goto finish;
195 }
196
197 if (!all && cg_is_empty_recursive(NULL, k, false) > 0) {
198 free(k);
199 continue;
200 }
fa776d8e
LP
201
202 if (!shown_pids) {
1e5678d0 203 show_cgroup_one_by_path(path, prefix, n_columns, true, kernel_threads);
fa776d8e
LP
204 shown_pids = true;
205 }
206
207 if (last) {
208 printf("%s\342\224\234 %s\n", prefix, file_name_from_path(last));
209
c3175a7f
LP
210 if (!p1) {
211 p1 = strappend(prefix, "\342\224\202 ");
212 if (!p1) {
213 free(k);
fa776d8e
LP
214 r = -ENOMEM;
215 goto finish;
216 }
c3175a7f 217 }
fa776d8e 218
c3175a7f 219 show_cgroup_by_path(last, p1, n_columns-2, kernel_threads, all);
fa776d8e 220 free(last);
fa776d8e
LP
221 }
222
c3175a7f 223 last = k;
fa776d8e
LP
224 }
225
35d2e7ec
LP
226 if (r < 0)
227 goto finish;
228
fa776d8e 229 if (!shown_pids)
1e5678d0 230 show_cgroup_one_by_path(path, prefix, n_columns, !!last, kernel_threads);
fa776d8e
LP
231
232 if (last) {
233 printf("%s\342\224\224 %s\n", prefix, file_name_from_path(last));
234
c3175a7f
LP
235 if (!p2) {
236 p2 = strappend(prefix, " ");
237 if (!p2) {
fa776d8e
LP
238 r = -ENOMEM;
239 goto finish;
240 }
c3175a7f 241 }
fa776d8e 242
c3175a7f 243 show_cgroup_by_path(last, p2, n_columns-2, kernel_threads, all);
fa776d8e
LP
244 }
245
246 r = 0;
247
248finish:
249 free(p1);
250 free(p2);
251 free(last);
252 free(fn);
253
254 closedir(d);
255
256 return r;
ab35fb1b 257}
35d2e7ec 258
c3175a7f 259int show_cgroup(const char *controller, const char *path, const char *prefix, unsigned n_columns, bool kernel_threads, bool all) {
35d2e7ec
LP
260 char *p;
261 int r;
262
263 assert(controller);
264 assert(path);
265
1e5678d0
LP
266 r = cg_get_path(controller, path, NULL, &p);
267 if (r < 0)
35d2e7ec
LP
268 return r;
269
c3175a7f 270 r = show_cgroup_by_path(p, prefix, n_columns, kernel_threads, all);
35d2e7ec
LP
271 free(p);
272
273 return r;
274}