chiark / gitweb /
cgroup: don't allow hidden cgroups
[elogind.git] / src / basic / cgroup-util.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
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
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
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
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <errno.h>
23 #include <unistd.h>
24 #include <signal.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <dirent.h>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30 #include <ftw.h>
31
32 #include "cgroup-util.h"
33 #include "set.h"
34 #include "macro.h"
35 #include "util.h"
36 #include "formats-util.h"
37 #include "process-util.h"
38 #include "path-util.h"
39 #include "unit-name.h"
40 #include "fileio.h"
41 #include "special.h"
42 #include "mkdir.h"
43 #include "login-util.h"
44
45 int cg_enumerate_processes(const char *controller, const char *path, FILE **_f) {
46         _cleanup_free_ char *fs = NULL;
47         FILE *f;
48         int r;
49
50         assert(_f);
51
52         r = cg_get_path(controller, path, "cgroup.procs", &fs);
53         if (r < 0)
54                 return r;
55
56         f = fopen(fs, "re");
57         if (!f)
58                 return -errno;
59
60         *_f = f;
61         return 0;
62 }
63
64 int cg_read_pid(FILE *f, pid_t *_pid) {
65         unsigned long ul;
66
67         /* Note that the cgroup.procs might contain duplicates! See
68          * cgroups.txt for details. */
69
70         assert(f);
71         assert(_pid);
72
73         errno = 0;
74         if (fscanf(f, "%lu", &ul) != 1) {
75
76                 if (feof(f))
77                         return 0;
78
79                 return errno ? -errno : -EIO;
80         }
81
82         if (ul <= 0)
83                 return -EIO;
84
85         *_pid = (pid_t) ul;
86         return 1;
87 }
88
89 int cg_enumerate_subgroups(const char *controller, const char *path, DIR **_d) {
90         _cleanup_free_ char *fs = NULL;
91         int r;
92         DIR *d;
93
94         assert(_d);
95
96         /* This is not recursive! */
97
98         r = cg_get_path(controller, path, NULL, &fs);
99         if (r < 0)
100                 return r;
101
102         d = opendir(fs);
103         if (!d)
104                 return -errno;
105
106         *_d = d;
107         return 0;
108 }
109
110 int cg_read_subgroup(DIR *d, char **fn) {
111         struct dirent *de;
112
113         assert(d);
114         assert(fn);
115
116         FOREACH_DIRENT_ALL(de, d, return -errno) {
117                 char *b;
118
119                 if (de->d_type != DT_DIR)
120                         continue;
121
122                 if (streq(de->d_name, ".") ||
123                     streq(de->d_name, ".."))
124                         continue;
125
126                 b = strdup(de->d_name);
127                 if (!b)
128                         return -ENOMEM;
129
130                 *fn = b;
131                 return 1;
132         }
133
134         return 0;
135 }
136
137 int cg_rmdir(const char *controller, const char *path) {
138         _cleanup_free_ char *p = NULL;
139         int r;
140
141         r = cg_get_path(controller, path, NULL, &p);
142         if (r < 0)
143                 return r;
144
145         r = rmdir(p);
146         if (r < 0 && errno != ENOENT)
147                 return -errno;
148
149         return 0;
150 }
151
152 int cg_kill(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, Set *s) {
153         _cleanup_set_free_ Set *allocated_set = NULL;
154         bool done = false;
155         int r, ret = 0;
156         pid_t my_pid;
157
158         assert(sig >= 0);
159
160         /* This goes through the tasks list and kills them all. This
161          * is repeated until no further processes are added to the
162          * tasks list, to properly handle forking processes */
163
164         if (!s) {
165                 s = allocated_set = set_new(NULL);
166                 if (!s)
167                         return -ENOMEM;
168         }
169
170         my_pid = getpid();
171
172         do {
173                 _cleanup_fclose_ FILE *f = NULL;
174                 pid_t pid = 0;
175                 done = true;
176
177                 r = cg_enumerate_processes(controller, path, &f);
178                 if (r < 0) {
179                         if (ret >= 0 && r != -ENOENT)
180                                 return r;
181
182                         return ret;
183                 }
184
185                 while ((r = cg_read_pid(f, &pid)) > 0) {
186
187                         if (ignore_self && pid == my_pid)
188                                 continue;
189
190                         if (set_get(s, LONG_TO_PTR(pid)) == LONG_TO_PTR(pid))
191                                 continue;
192
193                         /* If we haven't killed this process yet, kill
194                          * it */
195                         if (kill(pid, sig) < 0) {
196                                 if (ret >= 0 && errno != ESRCH)
197                                         ret = -errno;
198                         } else {
199                                 if (sigcont && sig != SIGKILL)
200                                         kill(pid, SIGCONT);
201
202                                 if (ret == 0)
203                                         ret = 1;
204                         }
205
206                         done = false;
207
208                         r = set_put(s, LONG_TO_PTR(pid));
209                         if (r < 0) {
210                                 if (ret >= 0)
211                                         return r;
212
213                                 return ret;
214                         }
215                 }
216
217                 if (r < 0) {
218                         if (ret >= 0)
219                                 return r;
220
221                         return ret;
222                 }
223
224                 /* To avoid racing against processes which fork
225                  * quicker than we can kill them we repeat this until
226                  * no new pids need to be killed. */
227
228         } while (!done);
229
230         return ret;
231 }
232
233 int cg_kill_recursive(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, bool rem, Set *s) {
234         _cleanup_set_free_ Set *allocated_set = NULL;
235         _cleanup_closedir_ DIR *d = NULL;
236         int r, ret = 0;
237         char *fn;
238
239         assert(path);
240         assert(sig >= 0);
241
242         if (!s) {
243                 s = allocated_set = set_new(NULL);
244                 if (!s)
245                         return -ENOMEM;
246         }
247
248         ret = cg_kill(controller, path, sig, sigcont, ignore_self, s);
249
250         r = cg_enumerate_subgroups(controller, path, &d);
251         if (r < 0) {
252                 if (ret >= 0 && r != -ENOENT)
253                         return r;
254
255                 return ret;
256         }
257
258         while ((r = cg_read_subgroup(d, &fn)) > 0) {
259                 _cleanup_free_ char *p = NULL;
260
261                 p = strjoin(path, "/", fn, NULL);
262                 free(fn);
263                 if (!p)
264                         return -ENOMEM;
265
266                 r = cg_kill_recursive(controller, p, sig, sigcont, ignore_self, rem, s);
267                 if (ret >= 0 && r != 0)
268                         ret = r;
269         }
270
271         if (ret >= 0 && r < 0)
272                 ret = r;
273
274         if (rem) {
275                 r = cg_rmdir(controller, path);
276                 if (r < 0 && ret >= 0 && r != -ENOENT && r != -EBUSY)
277                         return r;
278         }
279
280         return ret;
281 }
282
283 int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self) {
284         bool done = false;
285         _cleanup_set_free_ Set *s = NULL;
286         int r, ret = 0;
287         pid_t my_pid;
288
289         assert(cfrom);
290         assert(pfrom);
291         assert(cto);
292         assert(pto);
293
294         s = set_new(NULL);
295         if (!s)
296                 return -ENOMEM;
297
298         my_pid = getpid();
299
300         do {
301                 _cleanup_fclose_ FILE *f = NULL;
302                 pid_t pid = 0;
303                 done = true;
304
305                 r = cg_enumerate_processes(cfrom, pfrom, &f);
306                 if (r < 0) {
307                         if (ret >= 0 && r != -ENOENT)
308                                 return r;
309
310                         return ret;
311                 }
312
313                 while ((r = cg_read_pid(f, &pid)) > 0) {
314
315                         /* This might do weird stuff if we aren't a
316                          * single-threaded program. However, we
317                          * luckily know we are not */
318                         if (ignore_self && pid == my_pid)
319                                 continue;
320
321                         if (set_get(s, LONG_TO_PTR(pid)) == LONG_TO_PTR(pid))
322                                 continue;
323
324                         /* Ignore kernel threads. Since they can only
325                          * exist in the root cgroup, we only check for
326                          * them there. */
327                         if (cfrom &&
328                             (isempty(pfrom) || path_equal(pfrom, "/")) &&
329                             is_kernel_thread(pid) > 0)
330                                 continue;
331
332                         r = cg_attach(cto, pto, pid);
333                         if (r < 0) {
334                                 if (ret >= 0 && r != -ESRCH)
335                                         ret = r;
336                         } else if (ret == 0)
337                                 ret = 1;
338
339                         done = false;
340
341                         r = set_put(s, LONG_TO_PTR(pid));
342                         if (r < 0) {
343                                 if (ret >= 0)
344                                         return r;
345
346                                 return ret;
347                         }
348                 }
349
350                 if (r < 0) {
351                         if (ret >= 0)
352                                 return r;
353
354                         return ret;
355                 }
356         } while (!done);
357
358         return ret;
359 }
360
361 int cg_migrate_recursive(
362                 const char *cfrom,
363                 const char *pfrom,
364                 const char *cto,
365                 const char *pto,
366                 bool ignore_self,
367                 bool rem) {
368
369         _cleanup_closedir_ DIR *d = NULL;
370         int r, ret = 0;
371         char *fn;
372
373         assert(cfrom);
374         assert(pfrom);
375         assert(cto);
376         assert(pto);
377
378         ret = cg_migrate(cfrom, pfrom, cto, pto, ignore_self);
379
380         r = cg_enumerate_subgroups(cfrom, pfrom, &d);
381         if (r < 0) {
382                 if (ret >= 0 && r != -ENOENT)
383                         return r;
384
385                 return ret;
386         }
387
388         while ((r = cg_read_subgroup(d, &fn)) > 0) {
389                 _cleanup_free_ char *p = NULL;
390
391                 p = strjoin(pfrom, "/", fn, NULL);
392                 free(fn);
393                 if (!p) {
394                         if (ret >= 0)
395                                 return -ENOMEM;
396
397                         return ret;
398                 }
399
400                 r = cg_migrate_recursive(cfrom, p, cto, pto, ignore_self, rem);
401                 if (r != 0 && ret >= 0)
402                         ret = r;
403         }
404
405         if (r < 0 && ret >= 0)
406                 ret = r;
407
408         if (rem) {
409                 r = cg_rmdir(cfrom, pfrom);
410                 if (r < 0 && ret >= 0 && r != -ENOENT && r != -EBUSY)
411                         return r;
412         }
413
414         return ret;
415 }
416
417 int cg_migrate_recursive_fallback(
418                 const char *cfrom,
419                 const char *pfrom,
420                 const char *cto,
421                 const char *pto,
422                 bool ignore_self,
423                 bool rem) {
424
425         int r;
426
427         assert(cfrom);
428         assert(pfrom);
429         assert(cto);
430         assert(pto);
431
432         r = cg_migrate_recursive(cfrom, pfrom, cto, pto, ignore_self, rem);
433         if (r < 0) {
434                 char prefix[strlen(pto) + 1];
435
436                 /* This didn't work? Then let's try all prefixes of the destination */
437
438                 PATH_FOREACH_PREFIX(prefix, pto) {
439                         r = cg_migrate_recursive(cfrom, pfrom, cto, prefix, ignore_self, rem);
440                         if (r >= 0)
441                                 break;
442                 }
443         }
444
445         return 0;
446 }
447
448 static const char *normalize_controller(const char *controller) {
449
450         assert(controller);
451
452         if (startswith(controller, "name="))
453                 return controller + 5;
454         else
455                 return controller;
456 }
457
458 static int join_path(const char *controller, const char *path, const char *suffix, char **fs) {
459         char *t = NULL;
460
461         if (!isempty(controller)) {
462                 if (!isempty(path) && !isempty(suffix))
463                         t = strjoin("/sys/fs/cgroup/", controller, "/", path, "/", suffix, NULL);
464                 else if (!isempty(path))
465                         t = strjoin("/sys/fs/cgroup/", controller, "/", path, NULL);
466                 else if (!isempty(suffix))
467                         t = strjoin("/sys/fs/cgroup/", controller, "/", suffix, NULL);
468                 else
469                         t = strappend("/sys/fs/cgroup/", controller);
470         } else {
471                 if (!isempty(path) && !isempty(suffix))
472                         t = strjoin(path, "/", suffix, NULL);
473                 else if (!isempty(path))
474                         t = strdup(path);
475                 else
476                         return -EINVAL;
477         }
478
479         if (!t)
480                 return -ENOMEM;
481
482         *fs = path_kill_slashes(t);
483         return 0;
484 }
485
486 int cg_get_path(const char *controller, const char *path, const char *suffix, char **fs) {
487         const char *p;
488         static thread_local bool good = false;
489
490         assert(fs);
491
492         if (controller && !cg_controller_is_valid(controller))
493                 return -EINVAL;
494
495         if (_unlikely_(!good)) {
496                 int r;
497
498                 r = path_is_mount_point("/sys/fs/cgroup", 0);
499                 if (r < 0)
500                         return r;
501                 if (r == 0)
502                         return -ENOENT;
503
504                 /* Cache this to save a few stat()s */
505                 good = true;
506         }
507
508         p = controller ? normalize_controller(controller) : NULL;
509
510         return join_path(p, path, suffix, fs);
511 }
512
513 static int check_hierarchy(const char *p) {
514         const char *cc;
515
516         assert(p);
517
518         if (!filename_is_valid(p))
519                 return 0;
520
521         /* Check if this controller actually really exists */
522         cc = strjoina("/sys/fs/cgroup/", p);
523         if (laccess(cc, F_OK) < 0)
524                 return -errno;
525
526         return 0;
527 }
528
529 int cg_get_path_and_check(const char *controller, const char *path, const char *suffix, char **fs) {
530         const char *p;
531         int r;
532
533         assert(fs);
534
535         if (!cg_controller_is_valid(controller))
536                 return -EINVAL;
537
538         /* Normalize the controller syntax */
539         p = normalize_controller(controller);
540
541         /* Check if this controller actually really exists */
542         r = check_hierarchy(p);
543         if (r < 0)
544                 return r;
545
546         return join_path(p, path, suffix, fs);
547 }
548
549 static int trim_cb(const char *path, const struct stat *sb, int typeflag, struct FTW *ftwbuf) {
550         assert(path);
551         assert(sb);
552         assert(ftwbuf);
553
554         if (typeflag != FTW_DP)
555                 return 0;
556
557         if (ftwbuf->level < 1)
558                 return 0;
559
560         rmdir(path);
561         return 0;
562 }
563
564 int cg_trim(const char *controller, const char *path, bool delete_root) {
565         _cleanup_free_ char *fs = NULL;
566         int r = 0;
567
568         assert(path);
569
570         r = cg_get_path(controller, path, NULL, &fs);
571         if (r < 0)
572                 return r;
573
574         errno = 0;
575         if (nftw(fs, trim_cb, 64, FTW_DEPTH|FTW_MOUNT|FTW_PHYS) != 0)
576                 r = errno ? -errno : -EIO;
577
578         if (delete_root) {
579                 if (rmdir(fs) < 0 && errno != ENOENT)
580                         return -errno;
581         }
582
583         return r;
584 }
585
586 /// UNNEDED by elogind
587 #if 0
588 int cg_delete(const char *controller, const char *path) {
589         _cleanup_free_ char *parent = NULL;
590         int r;
591
592         assert(path);
593
594         r = path_get_parent(path, &parent);
595         if (r < 0)
596                 return r;
597
598         r = cg_migrate_recursive(controller, path, controller, parent, false, true);
599         return r == -ENOENT ? 0 : r;
600 }
601 #endif // 0
602
603 int cg_create(const char *controller, const char *path) {
604         _cleanup_free_ char *fs = NULL;
605         int r;
606
607         r = cg_get_path_and_check(controller, path, NULL, &fs);
608         if (r < 0)
609                 return r;
610
611         r = mkdir_parents(fs, 0755);
612         if (r < 0)
613                 return r;
614
615         if (mkdir(fs, 0755) < 0) {
616
617                 if (errno == EEXIST)
618                         return 0;
619
620                 return -errno;
621         }
622
623         return 1;
624 }
625
626 /// UNNEEDED by elogind
627 #if 0
628 int cg_create_and_attach(const char *controller, const char *path, pid_t pid) {
629         int r, q;
630
631         assert(pid >= 0);
632
633         r = cg_create(controller, path);
634         if (r < 0)
635                 return r;
636
637         q = cg_attach(controller, path, pid);
638         if (q < 0)
639                 return q;
640
641         /* This does not remove the cgroup on failure */
642         return r;
643 }
644 #endif // 0
645
646 int cg_attach(const char *controller, const char *path, pid_t pid) {
647         _cleanup_free_ char *fs = NULL;
648         char c[DECIMAL_STR_MAX(pid_t) + 2];
649         int r;
650
651         assert(path);
652         assert(pid >= 0);
653
654         r = cg_get_path_and_check(controller, path, "cgroup.procs", &fs);
655         if (r < 0)
656                 return r;
657
658         if (pid == 0)
659                 pid = getpid();
660
661         snprintf(c, sizeof(c), PID_FMT"\n", pid);
662
663         return write_string_file_no_create(fs, c);
664 }
665
666 int cg_attach_fallback(const char *controller, const char *path, pid_t pid) {
667         int r;
668
669         assert(controller);
670         assert(path);
671         assert(pid >= 0);
672
673         r = cg_attach(controller, path, pid);
674         if (r < 0) {
675                 char prefix[strlen(path) + 1];
676
677                 /* This didn't work? Then let's try all prefixes of
678                  * the destination */
679
680                 PATH_FOREACH_PREFIX(prefix, path) {
681                         r = cg_attach(controller, prefix, pid);
682                         if (r >= 0)
683                                 break;
684                 }
685         }
686
687         return 0;
688 }
689
690 /// UNNEEDED by elogind
691 #if 0
692 int cg_set_group_access(
693                 const char *controller,
694                 const char *path,
695                 mode_t mode,
696                 uid_t uid,
697                 gid_t gid) {
698
699         _cleanup_free_ char *fs = NULL;
700         int r;
701
702         assert(path);
703
704         if (mode != MODE_INVALID)
705                 mode &= 0777;
706
707         r = cg_get_path(controller, path, NULL, &fs);
708         if (r < 0)
709                 return r;
710
711         return chmod_and_chown(fs, mode, uid, gid);
712 }
713
714 int cg_set_task_access(
715                 const char *controller,
716                 const char *path,
717                 mode_t mode,
718                 uid_t uid,
719                 gid_t gid) {
720
721         _cleanup_free_ char *fs = NULL, *procs = NULL;
722         int r;
723
724         assert(path);
725
726         if (mode == MODE_INVALID && uid == UID_INVALID && gid == GID_INVALID)
727                 return 0;
728
729         if (mode != MODE_INVALID)
730                 mode &= 0666;
731
732         r = cg_get_path(controller, path, "cgroup.procs", &fs);
733         if (r < 0)
734                 return r;
735
736         r = chmod_and_chown(fs, mode, uid, gid);
737         if (r < 0)
738                 return r;
739
740         /* Compatibility, Always keep values for "tasks" in sync with
741          * "cgroup.procs" */
742         r = cg_get_path(controller, path, "tasks", &procs);
743         if (r < 0)
744                 return r;
745
746         return chmod_and_chown(procs, mode, uid, gid);
747 }
748 #endif // 0
749
750 int cg_pid_get_path(const char *controller, pid_t pid, char **path) {
751         _cleanup_fclose_ FILE *f = NULL;
752         char line[LINE_MAX];
753         const char *fs;
754         size_t cs;
755
756         assert(path);
757         assert(pid >= 0);
758
759         if (controller) {
760                 if (!cg_controller_is_valid(controller))
761                         return -EINVAL;
762
763                 controller = normalize_controller(controller);
764         } else
765                 controller = ELOGIND_CGROUP_CONTROLLER;
766
767         fs = procfs_file_alloca(pid, "cgroup");
768
769         f = fopen(fs, "re");
770         if (!f)
771                 return errno == ENOENT ? -ESRCH : -errno;
772
773         cs = strlen(controller);
774
775         FOREACH_LINE(line, f, return -errno) {
776                 char *l, *p, *e;
777                 size_t k;
778                 const char *word, *state;
779                 bool found = false;
780
781                 truncate_nl(line);
782
783                 l = strchr(line, ':');
784                 if (!l)
785                         continue;
786
787                 l++;
788                 e = strchr(l, ':');
789                 if (!e)
790                         continue;
791
792                 *e = 0;
793
794                 FOREACH_WORD_SEPARATOR(word, k, l, ",", state) {
795
796                         if (k == cs && memcmp(word, controller, cs) == 0) {
797                                 found = true;
798                                 break;
799                         }
800
801                         if (k == 5 + cs &&
802                             memcmp(word, "name=", 5) == 0 &&
803                             memcmp(word+5, controller, cs) == 0) {
804                                 found = true;
805                                 break;
806                         }
807                 }
808
809                 if (!found)
810                         continue;
811
812                 p = strdup(e + 1);
813                 if (!p)
814                         return -ENOMEM;
815
816                 *path = p;
817                 return 0;
818         }
819
820         return -ENOENT;
821 }
822
823 /// UNNEEDED by elogind
824 #if 0
825 int cg_install_release_agent(const char *controller, const char *agent) {
826         _cleanup_free_ char *fs = NULL, *contents = NULL;
827         char *sc;
828         int r;
829
830         assert(agent);
831
832         r = cg_get_path(controller, NULL, "release_agent", &fs);
833         if (r < 0)
834                 return r;
835
836         r = read_one_line_file(fs, &contents);
837         if (r < 0)
838                 return r;
839
840         sc = strstrip(contents);
841         if (sc[0] == 0) {
842                 r = write_string_file_no_create(fs, agent);
843                 if (r < 0)
844                         return r;
845         } else if (!streq(sc, agent))
846                 return -EEXIST;
847
848         fs = mfree(fs);
849         r = cg_get_path(controller, NULL, "notify_on_release", &fs);
850         if (r < 0)
851                 return r;
852
853         contents = mfree(contents);
854         r = read_one_line_file(fs, &contents);
855         if (r < 0)
856                 return r;
857
858         sc = strstrip(contents);
859         if (streq(sc, "0")) {
860                 r = write_string_file_no_create(fs, "1");
861                 if (r < 0)
862                         return r;
863
864                 return 1;
865         }
866
867         if (!streq(sc, "1"))
868                 return -EIO;
869
870         return 0;
871 }
872
873 int cg_uninstall_release_agent(const char *controller) {
874         _cleanup_free_ char *fs = NULL;
875         int r;
876
877         r = cg_get_path(controller, NULL, "notify_on_release", &fs);
878         if (r < 0)
879                 return r;
880
881         r = write_string_file_no_create(fs, "0");
882         if (r < 0)
883                 return r;
884
885         fs = mfree(fs);
886
887         r = cg_get_path(controller, NULL, "release_agent", &fs);
888         if (r < 0)
889                 return r;
890
891         r = write_string_file_no_create(fs, "");
892         if (r < 0)
893                 return r;
894
895         return 0;
896 }
897 #endif // 0
898
899 int cg_is_empty(const char *controller, const char *path, bool ignore_self) {
900         _cleanup_fclose_ FILE *f = NULL;
901         pid_t pid = 0, self_pid;
902         bool found = false;
903         int r;
904
905         assert(path);
906
907         r = cg_enumerate_processes(controller, path, &f);
908         if (r < 0)
909                 return r == -ENOENT ? 1 : r;
910
911         self_pid = getpid();
912
913         while ((r = cg_read_pid(f, &pid)) > 0) {
914
915                 if (ignore_self && pid == self_pid)
916                         continue;
917
918                 found = true;
919                 break;
920         }
921
922         if (r < 0)
923                 return r;
924
925         return !found;
926 }
927
928 int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_self) {
929         _cleanup_closedir_ DIR *d = NULL;
930         char *fn;
931         int r;
932
933         assert(path);
934
935         r = cg_is_empty(controller, path, ignore_self);
936         if (r <= 0)
937                 return r;
938
939         r = cg_enumerate_subgroups(controller, path, &d);
940         if (r < 0)
941                 return r == -ENOENT ? 1 : r;
942
943         while ((r = cg_read_subgroup(d, &fn)) > 0) {
944                 _cleanup_free_ char *p = NULL;
945
946                 p = strjoin(path, "/", fn, NULL);
947                 free(fn);
948                 if (!p)
949                         return -ENOMEM;
950
951                 r = cg_is_empty_recursive(controller, p, ignore_self);
952                 if (r <= 0)
953                         return r;
954         }
955
956         if (r < 0)
957                 return r;
958
959         return 1;
960 }
961
962 int cg_split_spec(const char *spec, char **controller, char **path) {
963         const char *e;
964         char *t = NULL, *u = NULL;
965         _cleanup_free_ char *v = NULL;
966
967         assert(spec);
968
969         if (*spec == '/') {
970                 if (!path_is_safe(spec))
971                         return -EINVAL;
972
973                 if (path) {
974                         t = strdup(spec);
975                         if (!t)
976                                 return -ENOMEM;
977
978                         *path = path_kill_slashes(t);
979                 }
980
981                 if (controller)
982                         *controller = NULL;
983
984                 return 0;
985         }
986
987         e = strchr(spec, ':');
988         if (!e) {
989                 if (!cg_controller_is_valid(spec))
990                         return -EINVAL;
991
992                 if (controller) {
993                         t = strdup(normalize_controller(spec));
994                         if (!t)
995                                 return -ENOMEM;
996
997                         *controller = t;
998                 }
999
1000                 if (path)
1001                         *path = NULL;
1002
1003                 return 0;
1004         }
1005
1006         v = strndup(spec, e-spec);
1007         if (!v)
1008                 return -ENOMEM;
1009         t = strdup(normalize_controller(v));
1010         if (!t)
1011                 return -ENOMEM;
1012         if (!cg_controller_is_valid(t)) {
1013                 free(t);
1014                 return -EINVAL;
1015         }
1016
1017         if (streq(e+1, "")) {
1018                 u = strdup("/");
1019                 if (!u) {
1020                         free(t);
1021                         return -ENOMEM;
1022                 }
1023         } else {
1024                 u = strdup(e+1);
1025                 if (!u) {
1026                         free(t);
1027                         return -ENOMEM;
1028                 }
1029
1030                 if (!path_is_safe(u) ||
1031                     !path_is_absolute(u)) {
1032                         free(t);
1033                         free(u);
1034                         return -EINVAL;
1035                 }
1036
1037                 path_kill_slashes(u);
1038         }
1039
1040         if (controller)
1041                 *controller = t;
1042         else
1043                 free(t);
1044
1045         if (path)
1046                 *path = u;
1047         else
1048                 free(u);
1049
1050         return 0;
1051 }
1052
1053 int cg_mangle_path(const char *path, char **result) {
1054         _cleanup_free_ char *c = NULL, *p = NULL;
1055         char *t;
1056         int r;
1057
1058         assert(path);
1059         assert(result);
1060
1061         /* First, check if it already is a filesystem path */
1062         if (path_startswith(path, "/sys/fs/cgroup")) {
1063
1064                 t = strdup(path);
1065                 if (!t)
1066                         return -ENOMEM;
1067
1068                 *result = path_kill_slashes(t);
1069                 return 0;
1070         }
1071
1072         /* Otherwise, treat it as cg spec */
1073         r = cg_split_spec(path, &c, &p);
1074         if (r < 0)
1075                 return r;
1076
1077         return cg_get_path(c ? c : ELOGIND_CGROUP_CONTROLLER, p ? p : "/", NULL, result);
1078 }
1079
1080 int cg_get_root_path(char **path) {
1081         char *p, *e;
1082         int r;
1083
1084         assert(path);
1085
1086         r = cg_pid_get_path(ELOGIND_CGROUP_CONTROLLER, 1, &p);
1087         if (r < 0)
1088                 return r;
1089
1090         e = endswith(p, "/" SPECIAL_SYSTEM_SLICE);
1091         if (e)
1092                 *e = 0;
1093
1094         *path = p;
1095         return 0;
1096 }
1097
1098 int cg_shift_path(const char *cgroup, const char *root, const char **shifted) {
1099         _cleanup_free_ char *rt = NULL;
1100         char *p;
1101         int r;
1102
1103         assert(cgroup);
1104         assert(shifted);
1105
1106         if (!root) {
1107                 /* If the root was specified let's use that, otherwise
1108                  * let's determine it from PID 1 */
1109
1110                 r = cg_get_root_path(&rt);
1111                 if (r < 0)
1112                         return r;
1113
1114                 root = rt;
1115         }
1116
1117         p = path_startswith(cgroup, root);
1118         if (p)
1119                 *shifted = p - 1;
1120         else
1121                 *shifted = cgroup;
1122
1123         return 0;
1124 }
1125
1126 int cg_pid_get_path_shifted(pid_t pid, const char *root, char **cgroup) {
1127         _cleanup_free_ char *raw = NULL;
1128         const char *c;
1129         int r;
1130
1131         assert(pid >= 0);
1132         assert(cgroup);
1133
1134         r = cg_pid_get_path(ELOGIND_CGROUP_CONTROLLER, pid, &raw);
1135         if (r < 0)
1136                 return r;
1137
1138         r = cg_shift_path(raw, root, &c);
1139         if (r < 0)
1140                 return r;
1141
1142         if (c == raw) {
1143                 *cgroup = raw;
1144                 raw = NULL;
1145         } else {
1146                 char *n;
1147
1148                 n = strdup(c);
1149                 if (!n)
1150                         return -ENOMEM;
1151
1152                 *cgroup = n;
1153         }
1154
1155         return 0;
1156 }
1157
1158 int cg_path_decode_unit(const char *cgroup, char **unit){
1159         char *c, *s;
1160         size_t n;
1161
1162         assert(cgroup);
1163         assert(unit);
1164
1165         n = strcspn(cgroup, "/");
1166         if (n < 3)
1167                 return -ENXIO;
1168
1169         c = strndupa(cgroup, n);
1170         c = cg_unescape(c);
1171
1172         if (!unit_name_is_valid(c, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE))
1173                 return -ENXIO;
1174
1175         s = strdup(c);
1176         if (!s)
1177                 return -ENOMEM;
1178
1179         *unit = s;
1180         return 0;
1181 }
1182
1183 static bool valid_slice_name(const char *p, size_t n) {
1184
1185         if (!p)
1186                 return false;
1187
1188         if (n < strlen("x.slice"))
1189                 return false;
1190
1191         if (memcmp(p + n - 6, ".slice", 6) == 0) {
1192                 char buf[n+1], *c;
1193
1194                 memcpy(buf, p, n);
1195                 buf[n] = 0;
1196
1197                 c = cg_unescape(buf);
1198
1199                 return unit_name_is_valid(c, UNIT_NAME_PLAIN);
1200         }
1201
1202         return false;
1203 }
1204
1205 static const char *skip_slices(const char *p) {
1206         assert(p);
1207
1208         /* Skips over all slice assignments */
1209
1210         for (;;) {
1211                 size_t n;
1212
1213                 p += strspn(p, "/");
1214
1215                 n = strcspn(p, "/");
1216                 if (!valid_slice_name(p, n))
1217                         return p;
1218
1219                 p += n;
1220         }
1221 }
1222
1223 int cg_path_get_unit(const char *path, char **ret) {
1224         const char *e;
1225         char *unit;
1226         int r;
1227
1228         assert(path);
1229         assert(ret);
1230
1231         e = skip_slices(path);
1232
1233         r = cg_path_decode_unit(e, &unit);
1234         if (r < 0)
1235                 return r;
1236
1237         /* We skipped over the slices, don't accept any now */
1238         if (endswith(unit, ".slice")) {
1239                 free(unit);
1240                 return -ENXIO;
1241         }
1242
1243         *ret = unit;
1244         return 0;
1245 }
1246
1247 int cg_pid_get_unit(pid_t pid, char **unit) {
1248         _cleanup_free_ char *cgroup = NULL;
1249         int r;
1250
1251         assert(unit);
1252
1253         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1254         if (r < 0)
1255                 return r;
1256
1257         return cg_path_get_unit(cgroup, unit);
1258 }
1259
1260 /**
1261  * Skip session-*.scope, but require it to be there.
1262  */
1263 static const char *skip_session(const char *p) {
1264         size_t n;
1265
1266         if (isempty(p))
1267                 return NULL;
1268
1269         p += strspn(p, "/");
1270
1271         n = strcspn(p, "/");
1272         if (n < strlen("session-x.scope"))
1273                 return NULL;
1274
1275         if (memcmp(p, "session-", 8) == 0 && memcmp(p + n - 6, ".scope", 6) == 0) {
1276                 char buf[n - 8 - 6 + 1];
1277
1278                 memcpy(buf, p + 8, n - 8 - 6);
1279                 buf[n - 8 - 6] = 0;
1280
1281                 /* Note that session scopes never need unescaping,
1282                  * since they cannot conflict with the kernel's own
1283                  * names, hence we don't need to call cg_unescape()
1284                  * here. */
1285
1286                 if (!session_id_valid(buf))
1287                         return false;
1288
1289                 p += n;
1290                 p += strspn(p, "/");
1291                 return p;
1292         }
1293
1294         return NULL;
1295 }
1296
1297 /**
1298  * Skip user@*.service, but require it to be there.
1299  */
1300 static const char *skip_user_manager(const char *p) {
1301         size_t n;
1302
1303         if (isempty(p))
1304                 return NULL;
1305
1306         p += strspn(p, "/");
1307
1308         n = strcspn(p, "/");
1309         if (n < strlen("user@x.service"))
1310                 return NULL;
1311
1312         if (memcmp(p, "user@", 5) == 0 && memcmp(p + n - 8, ".service", 8) == 0) {
1313                 char buf[n - 5 - 8 + 1];
1314
1315                 memcpy(buf, p + 5, n - 5 - 8);
1316                 buf[n - 5 - 8] = 0;
1317
1318                 /* Note that user manager services never need unescaping,
1319                  * since they cannot conflict with the kernel's own
1320                  * names, hence we don't need to call cg_unescape()
1321                  * here. */
1322
1323                 if (parse_uid(buf, NULL) < 0)
1324                         return NULL;
1325
1326                 p += n;
1327                 p += strspn(p, "/");
1328
1329                 return p;
1330         }
1331
1332         return NULL;
1333 }
1334
1335 static const char *skip_user_prefix(const char *path) {
1336         const char *e, *t;
1337
1338         assert(path);
1339
1340         /* Skip slices, if there are any */
1341         e = skip_slices(path);
1342
1343         /* Skip the user manager, if it's in the path now... */
1344         t = skip_user_manager(e);
1345         if (t)
1346                 return t;
1347
1348         /* Alternatively skip the user session if it is in the path... */
1349         return skip_session(e);
1350 }
1351
1352 int cg_path_get_user_unit(const char *path, char **ret) {
1353         const char *t;
1354
1355         assert(path);
1356         assert(ret);
1357
1358         t = skip_user_prefix(path);
1359         if (!t)
1360                 return -ENXIO;
1361
1362         /* And from here on it looks pretty much the same as for a
1363          * system unit, hence let's use the same parser from here
1364          * on. */
1365         return cg_path_get_unit(t, ret);
1366 }
1367
1368 int cg_pid_get_user_unit(pid_t pid, char **unit) {
1369         _cleanup_free_ char *cgroup = NULL;
1370         int r;
1371
1372         assert(unit);
1373
1374         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1375         if (r < 0)
1376                 return r;
1377
1378         return cg_path_get_user_unit(cgroup, unit);
1379 }
1380
1381 int cg_path_get_machine_name(const char *path, char **machine) {
1382         _cleanup_free_ char *u = NULL, *sl = NULL;
1383         int r;
1384
1385         r = cg_path_get_unit(path, &u);
1386         if (r < 0)
1387                 return r;
1388
1389         sl = strjoin("/run/systemd/machines/unit:", u, NULL);
1390         if (!sl)
1391                 return -ENOMEM;
1392
1393         return readlink_malloc(sl, machine);
1394 }
1395
1396 int cg_pid_get_machine_name(pid_t pid, char **machine) {
1397         _cleanup_free_ char *cgroup = NULL;
1398         int r;
1399
1400         assert(machine);
1401
1402         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1403         if (r < 0)
1404                 return r;
1405
1406         return cg_path_get_machine_name(cgroup, machine);
1407 }
1408
1409 int cg_path_get_session(const char *path, char **session) {
1410         _cleanup_free_ char *unit = NULL;
1411         char *start, *end;
1412         int r;
1413
1414         assert(path);
1415
1416         r = cg_path_get_unit(path, &unit);
1417         if (r < 0)
1418                 return r;
1419
1420         start = startswith(unit, "session-");
1421         if (!start)
1422                 return -ENXIO;
1423         end = endswith(start, ".scope");
1424         if (!end)
1425                 return -ENXIO;
1426
1427         *end = 0;
1428         if (!session_id_valid(start))
1429                 return -ENXIO;
1430
1431         if (session) {
1432                 char *rr;
1433
1434                 rr = strdup(start);
1435                 if (!rr)
1436                         return -ENOMEM;
1437
1438                 *session = rr;
1439         }
1440
1441         return 0;
1442 }
1443
1444 int cg_pid_get_session(pid_t pid, char **session) {
1445         _cleanup_free_ char *cgroup = NULL;
1446         int r;
1447
1448         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1449         if (r < 0)
1450                 return r;
1451
1452         return cg_path_get_session(cgroup, session);
1453 }
1454
1455 int cg_path_get_owner_uid(const char *path, uid_t *uid) {
1456         _cleanup_free_ char *slice = NULL;
1457         char *start, *end;
1458         int r;
1459
1460         assert(path);
1461
1462         r = cg_path_get_slice(path, &slice);
1463         if (r < 0)
1464                 return r;
1465
1466         start = startswith(slice, "user-");
1467         if (!start)
1468                 return -ENXIO;
1469         end = endswith(start, ".slice");
1470         if (!end)
1471                 return -ENXIO;
1472
1473         *end = 0;
1474         if (parse_uid(start, uid) < 0)
1475                 return -ENXIO;
1476
1477         return 0;
1478 }
1479
1480 int cg_pid_get_owner_uid(pid_t pid, uid_t *uid) {
1481         _cleanup_free_ char *cgroup = NULL;
1482         int r;
1483
1484         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1485         if (r < 0)
1486                 return r;
1487
1488         return cg_path_get_owner_uid(cgroup, uid);
1489 }
1490
1491 int cg_path_get_slice(const char *p, char **slice) {
1492         const char *e = NULL;
1493
1494         assert(p);
1495         assert(slice);
1496
1497         /* Finds the right-most slice unit from the beginning, but
1498          * stops before we come to the first non-slice unit. */
1499
1500         for (;;) {
1501                 size_t n;
1502
1503                 p += strspn(p, "/");
1504
1505                 n = strcspn(p, "/");
1506                 if (!valid_slice_name(p, n)) {
1507
1508                         if (!e) {
1509                                 char *s;
1510
1511                                 s = strdup("-.slice");
1512                                 if (!s)
1513                                         return -ENOMEM;
1514
1515                                 *slice = s;
1516                                 return 0;
1517                         }
1518
1519                         return cg_path_decode_unit(e, slice);
1520                 }
1521
1522                 e = p;
1523                 p += n;
1524         }
1525 }
1526
1527 int cg_pid_get_slice(pid_t pid, char **slice) {
1528         _cleanup_free_ char *cgroup = NULL;
1529         int r;
1530
1531         assert(slice);
1532
1533         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1534         if (r < 0)
1535                 return r;
1536
1537         return cg_path_get_slice(cgroup, slice);
1538 }
1539
1540 int cg_path_get_user_slice(const char *p, char **slice) {
1541         const char *t;
1542         assert(p);
1543         assert(slice);
1544
1545         t = skip_user_prefix(p);
1546         if (!t)
1547                 return -ENXIO;
1548
1549         /* And now it looks pretty much the same as for a system
1550          * slice, so let's just use the same parser from here on. */
1551         return cg_path_get_slice(t, slice);
1552 }
1553
1554 int cg_pid_get_user_slice(pid_t pid, char **slice) {
1555         _cleanup_free_ char *cgroup = NULL;
1556         int r;
1557
1558         assert(slice);
1559
1560         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1561         if (r < 0)
1562                 return r;
1563
1564         return cg_path_get_user_slice(cgroup, slice);
1565 }
1566
1567 char *cg_escape(const char *p) {
1568         bool need_prefix = false;
1569
1570         /* This implements very minimal escaping for names to be used
1571          * as file names in the cgroup tree: any name which might
1572          * conflict with a kernel name or is prefixed with '_' is
1573          * prefixed with a '_'. That way, when reading cgroup names it
1574          * is sufficient to remove a single prefixing underscore if
1575          * there is one. */
1576
1577         /* The return value of this function (unlike cg_unescape())
1578          * needs free()! */
1579
1580         if (p[0] == 0 ||
1581             p[0] == '_' ||
1582             p[0] == '.' ||
1583             streq(p, "notify_on_release") ||
1584             streq(p, "release_agent") ||
1585             streq(p, "tasks"))
1586                 need_prefix = true;
1587         else {
1588                 const char *dot;
1589
1590                 dot = strrchr(p, '.');
1591                 if (dot) {
1592
1593                         if (dot - p == 6 && memcmp(p, "cgroup", 6) == 0)
1594                                 need_prefix = true;
1595                         else {
1596                                 char *n;
1597
1598                                 n = strndupa(p, dot - p);
1599
1600                                 if (check_hierarchy(n) >= 0)
1601                                         need_prefix = true;
1602                         }
1603                 }
1604         }
1605
1606         if (need_prefix)
1607                 return strappend("_", p);
1608         else
1609                 return strdup(p);
1610 }
1611
1612 char *cg_unescape(const char *p) {
1613         assert(p);
1614
1615         /* The return value of this function (unlike cg_escape())
1616          * doesn't need free()! */
1617
1618         if (p[0] == '_')
1619                 return (char*) p+1;
1620
1621         return (char*) p;
1622 }
1623
1624 #define CONTROLLER_VALID                        \
1625         DIGITS LETTERS                          \
1626         "_"
1627
1628 bool cg_controller_is_valid(const char *p) {
1629         const char *t, *s;
1630
1631         if (!p)
1632                 return false;
1633
1634         s = startswith(p, "name=");
1635         if (s)
1636                 p = s;
1637
1638         if (*p == 0 || *p == '_')
1639                 return false;
1640
1641         for (t = p; *t; t++)
1642                 if (!strchr(CONTROLLER_VALID, *t))
1643                         return false;
1644
1645         if (t - p > FILENAME_MAX)
1646                 return false;
1647
1648         return true;
1649 }
1650
1651 /// UNNEEDED by elogind
1652 #if 0
1653 int cg_slice_to_path(const char *unit, char **ret) {
1654         _cleanup_free_ char *p = NULL, *s = NULL, *e = NULL;
1655         const char *dash;
1656         int r;
1657
1658         assert(unit);
1659         assert(ret);
1660
1661         if (streq(unit, "-.slice")) {
1662                 char *x;
1663
1664                 x = strdup("");
1665                 if (!x)
1666                         return -ENOMEM;
1667                 *ret = x;
1668                 return 0;
1669         }
1670
1671         if (!unit_name_is_valid(unit, UNIT_NAME_PLAIN))
1672                 return -EINVAL;
1673
1674         if (!endswith(unit, ".slice"))
1675                 return -EINVAL;
1676
1677         r = unit_name_to_prefix(unit, &p);
1678         if (r < 0)
1679                 return r;
1680
1681         dash = strchr(p, '-');
1682
1683         /* Don't allow initial dashes */
1684         if (dash == p)
1685                 return -EINVAL;
1686
1687         while (dash) {
1688                 _cleanup_free_ char *escaped = NULL;
1689                 char n[dash - p + sizeof(".slice")];
1690
1691                 /* Don't allow trailing or double dashes */
1692                 if (dash[1] == 0 || dash[1] == '-')
1693                         return -EINVAL;
1694
1695                 strcpy(stpncpy(n, p, dash - p), ".slice");
1696                 if (!unit_name_is_valid(n, UNIT_NAME_PLAIN))
1697                         return -EINVAL;
1698
1699                 escaped = cg_escape(n);
1700                 if (!escaped)
1701                         return -ENOMEM;
1702
1703                 if (!strextend(&s, escaped, "/", NULL))
1704                         return -ENOMEM;
1705
1706                 dash = strchr(dash+1, '-');
1707         }
1708
1709         e = cg_escape(unit);
1710         if (!e)
1711                 return -ENOMEM;
1712
1713         if (!strextend(&s, e, NULL))
1714                 return -ENOMEM;
1715
1716         *ret = s;
1717         s = NULL;
1718
1719         return 0;
1720 }
1721
1722 int cg_set_attribute(const char *controller, const char *path, const char *attribute, const char *value) {
1723         _cleanup_free_ char *p = NULL;
1724         int r;
1725
1726         r = cg_get_path(controller, path, attribute, &p);
1727         if (r < 0)
1728                 return r;
1729
1730         return write_string_file_no_create(p, value);
1731 }
1732
1733 int cg_get_attribute(const char *controller, const char *path, const char *attribute, char **ret) {
1734         _cleanup_free_ char *p = NULL;
1735         int r;
1736
1737         r = cg_get_path(controller, path, attribute, &p);
1738         if (r < 0)
1739                 return r;
1740
1741         return read_one_line_file(p, ret);
1742 }
1743 #endif // 0
1744
1745 static const char mask_names[] =
1746         "cpu\0"
1747         "cpuacct\0"
1748         "blkio\0"
1749         "memory\0"
1750         "devices\0";
1751
1752 /// UNNEEDED by elogind
1753 #if 0
1754 int cg_create_everywhere(CGroupControllerMask supported, CGroupControllerMask mask, const char *path) {
1755         CGroupControllerMask bit = 1;
1756         const char *n;
1757         int r;
1758
1759         /* This one will create a cgroup in our private tree, but also
1760          * duplicate it in the trees specified in mask, and remove it
1761          * in all others */
1762
1763         /* First create the cgroup in our own hierarchy. */
1764         r = cg_create(ELOGIND_CGROUP_CONTROLLER, path);
1765         if (r < 0)
1766                 return r;
1767
1768         /* Then, do the same in the other hierarchies */
1769         NULSTR_FOREACH(n, mask_names) {
1770                 if (mask & bit)
1771                         cg_create(n, path);
1772                 else if (supported & bit)
1773                         cg_trim(n, path, true);
1774
1775                 bit <<= 1;
1776         }
1777
1778         return 0;
1779 }
1780 #endif // 0
1781
1782 int cg_attach_everywhere(CGroupControllerMask supported, const char *path, pid_t pid, cg_migrate_callback_t path_callback, void *userdata) {
1783         CGroupControllerMask bit = 1;
1784         const char *n;
1785         int r;
1786
1787         r = cg_attach(ELOGIND_CGROUP_CONTROLLER, path, pid);
1788         if (r < 0)
1789                 return r;
1790
1791         NULSTR_FOREACH(n, mask_names) {
1792
1793                 if (supported & bit) {
1794                         const char *p = NULL;
1795
1796                         if (path_callback)
1797                                 p = path_callback(bit, userdata);
1798
1799                         if (!p)
1800                                 p = path;
1801
1802                         cg_attach_fallback(n, p, pid);
1803                 }
1804
1805                 bit <<= 1;
1806         }
1807
1808         return 0;
1809 }
1810
1811 /// UNNEEDED by elogind
1812 #if 0
1813 int cg_attach_many_everywhere(CGroupControllerMask supported, const char *path, Set* pids, cg_migrate_callback_t path_callback, void *userdata) {
1814         Iterator i;
1815         void *pidp;
1816         int r = 0;
1817
1818         SET_FOREACH(pidp, pids, i) {
1819                 pid_t pid = PTR_TO_LONG(pidp);
1820                 int q;
1821
1822                 q = cg_attach_everywhere(supported, path, pid, path_callback, userdata);
1823                 if (q < 0)
1824                         r = q;
1825         }
1826
1827         return r;
1828 }
1829
1830 int cg_migrate_everywhere(CGroupControllerMask supported, const char *from, const char *to, cg_migrate_callback_t to_callback, void *userdata) {
1831         CGroupControllerMask bit = 1;
1832         const char *n;
1833         int r;
1834
1835         if (!path_equal(from, to))  {
1836                 r = cg_migrate_recursive(ELOGIND_CGROUP_CONTROLLER, from, ELOGIND_CGROUP_CONTROLLER, to, false, true);
1837                 if (r < 0)
1838                         return r;
1839         }
1840
1841         NULSTR_FOREACH(n, mask_names) {
1842                 if (supported & bit) {
1843                         const char *p = NULL;
1844
1845                         if (to_callback)
1846                                 p = to_callback(bit, userdata);
1847
1848                         if (!p)
1849                                 p = to;
1850
1851                         cg_migrate_recursive_fallback(ELOGIND_CGROUP_CONTROLLER, to, n, p, false, false);
1852                 }
1853
1854                 bit <<= 1;
1855         }
1856
1857         return 0;
1858 }
1859
1860 int cg_trim_everywhere(CGroupControllerMask supported, const char *path, bool delete_root) {
1861         CGroupControllerMask bit = 1;
1862         const char *n;
1863         int r;
1864
1865         r = cg_trim(ELOGIND_CGROUP_CONTROLLER, path, delete_root);
1866         if (r < 0)
1867                 return r;
1868
1869         NULSTR_FOREACH(n, mask_names) {
1870                 if (supported & bit)
1871                         cg_trim(n, path, delete_root);
1872
1873                 bit <<= 1;
1874         }
1875
1876         return 0;
1877 }
1878
1879 CGroupControllerMask cg_mask_supported(void) {
1880         CGroupControllerMask bit = 1, mask = 0;
1881         const char *n;
1882
1883         NULSTR_FOREACH(n, mask_names) {
1884                 if (check_hierarchy(n) >= 0)
1885                         mask |= bit;
1886
1887                 bit <<= 1;
1888         }
1889
1890         return mask;
1891 }
1892
1893 int cg_kernel_controllers(Set *controllers) {
1894         _cleanup_fclose_ FILE *f = NULL;
1895         char buf[LINE_MAX];
1896         int r;
1897
1898         assert(controllers);
1899
1900         f = fopen("/proc/cgroups", "re");
1901         if (!f) {
1902                 if (errno == ENOENT)
1903                         return 0;
1904                 return -errno;
1905         }
1906
1907         /* Ignore the header line */
1908         (void) fgets(buf, sizeof(buf), f);
1909
1910         for (;;) {
1911                 char *controller;
1912                 int enabled = 0;
1913
1914                 errno = 0;
1915                 if (fscanf(f, "%ms %*i %*i %i", &controller, &enabled) != 2) {
1916
1917                         if (feof(f))
1918                                 break;
1919
1920                         if (ferror(f) && errno)
1921                                 return -errno;
1922
1923                         return -EBADMSG;
1924                 }
1925
1926                 if (!enabled) {
1927                         free(controller);
1928                         continue;
1929                 }
1930
1931                 if (!filename_is_valid(controller)) {
1932                         free(controller);
1933                         return -EBADMSG;
1934                 }
1935
1936                 r = set_consume(controllers, controller);
1937                 if (r < 0)
1938                         return r;
1939         }
1940
1941         return 0;
1942 }
1943 #endif // 0