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