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