chiark / gitweb /
Classify processes from sessions into cgroups
[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 "path-util.h"
37 #include "fileio.h"
38 #include "special.h"
39 #include "mkdir.h"
40
41 int cg_enumerate_processes(const char *controller, const char *path, FILE **_f) {
42         _cleanup_free_ char *fs = NULL;
43         FILE *f;
44         int r;
45
46         assert(_f);
47
48         r = cg_get_path(controller, path, "cgroup.procs", &fs);
49         if (r < 0)
50                 return r;
51
52         f = fopen(fs, "re");
53         if (!f)
54                 return -errno;
55
56         *_f = f;
57         return 0;
58 }
59
60 int cg_read_pid(FILE *f, pid_t *_pid) {
61         unsigned long ul;
62
63         /* Note that the cgroup.procs might contain duplicates! See
64          * cgroups.txt for details. */
65
66         assert(f);
67         assert(_pid);
68
69         errno = 0;
70         if (fscanf(f, "%lu", &ul) != 1) {
71
72                 if (feof(f))
73                         return 0;
74
75                 return errno ? -errno : -EIO;
76         }
77
78         if (ul <= 0)
79                 return -EIO;
80
81         *_pid = (pid_t) ul;
82         return 1;
83 }
84
85 int cg_enumerate_subgroups(const char *controller, const char *path, DIR **_d) {
86         _cleanup_free_ char *fs = NULL;
87         int r;
88         DIR *d;
89
90         assert(_d);
91
92         /* This is not recursive! */
93
94         r = cg_get_path(controller, path, NULL, &fs);
95         if (r < 0)
96                 return r;
97
98         d = opendir(fs);
99         if (!d)
100                 return -errno;
101
102         *_d = d;
103         return 0;
104 }
105
106 int cg_read_subgroup(DIR *d, char **fn) {
107         struct dirent *de;
108
109         assert(d);
110         assert(fn);
111
112         FOREACH_DIRENT(de, d, return -errno) {
113                 char *b;
114
115                 if (de->d_type != DT_DIR)
116                         continue;
117
118                 if (streq(de->d_name, ".") ||
119                     streq(de->d_name, ".."))
120                         continue;
121
122                 b = strdup(de->d_name);
123                 if (!b)
124                         return -ENOMEM;
125
126                 *fn = b;
127                 return 1;
128         }
129
130         return 0;
131 }
132
133 int cg_rmdir(const char *controller, const char *path) {
134         _cleanup_free_ char *p = NULL;
135         int r;
136
137         r = cg_get_path(controller, path, NULL, &p);
138         if (r < 0)
139                 return r;
140
141         r = rmdir(p);
142         if (r < 0 && errno != ENOENT)
143                 return -errno;
144
145         return 0;
146 }
147
148 int cg_kill(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, Set *s) {
149         _cleanup_set_free_ Set *allocated_set = NULL;
150         bool done = false;
151         int r, ret = 0;
152         pid_t my_pid;
153
154         assert(sig >= 0);
155
156         /* This goes through the tasks list and kills them all. This
157          * is repeated until no further processes are added to the
158          * tasks list, to properly handle forking processes */
159
160         if (!s) {
161                 s = allocated_set = set_new(NULL);
162                 if (!s)
163                         return -ENOMEM;
164         }
165
166         my_pid = getpid();
167
168         do {
169                 _cleanup_fclose_ FILE *f = NULL;
170                 pid_t pid = 0;
171                 done = true;
172
173                 r = cg_enumerate_processes(controller, path, &f);
174                 if (r < 0) {
175                         if (ret >= 0 && r != -ENOENT)
176                                 return r;
177
178                         return ret;
179                 }
180
181                 while ((r = cg_read_pid(f, &pid)) > 0) {
182
183                         if (ignore_self && pid == my_pid)
184                                 continue;
185
186                         if (set_get(s, LONG_TO_PTR(pid)) == LONG_TO_PTR(pid))
187                                 continue;
188
189                         /* If we haven't killed this process yet, kill
190                          * it */
191                         if (kill(pid, sig) < 0) {
192                                 if (ret >= 0 && errno != ESRCH)
193                                         ret = -errno;
194                         } else {
195                                 if (sigcont && sig != SIGKILL)
196                                         kill(pid, SIGCONT);
197
198                                 if (ret == 0)
199                                         ret = 1;
200                         }
201
202                         done = false;
203
204                         r = set_put(s, LONG_TO_PTR(pid));
205                         if (r < 0) {
206                                 if (ret >= 0)
207                                         return r;
208
209                                 return ret;
210                         }
211                 }
212
213                 if (r < 0) {
214                         if (ret >= 0)
215                                 return r;
216
217                         return ret;
218                 }
219
220                 /* To avoid racing against processes which fork
221                  * quicker than we can kill them we repeat this until
222                  * no new pids need to be killed. */
223
224         } while (!done);
225
226         return ret;
227 }
228
229 int cg_kill_recursive(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, bool rem, Set *s) {
230         _cleanup_set_free_ Set *allocated_set = NULL;
231         _cleanup_closedir_ DIR *d = NULL;
232         int r, ret = 0;
233         char *fn;
234
235         assert(path);
236         assert(sig >= 0);
237
238         if (!s) {
239                 s = allocated_set = set_new(NULL);
240                 if (!s)
241                         return -ENOMEM;
242         }
243
244         ret = cg_kill(controller, path, sig, sigcont, ignore_self, s);
245
246         r = cg_enumerate_subgroups(controller, path, &d);
247         if (r < 0) {
248                 if (ret >= 0 && r != -ENOENT)
249                         return r;
250
251                 return ret;
252         }
253
254         while ((r = cg_read_subgroup(d, &fn)) > 0) {
255                 _cleanup_free_ char *p = NULL;
256
257                 p = strjoin(path, "/", fn, NULL);
258                 free(fn);
259                 if (!p)
260                         return -ENOMEM;
261
262                 r = cg_kill_recursive(controller, p, sig, sigcont, ignore_self, rem, s);
263                 if (ret >= 0 && r != 0)
264                         ret = r;
265         }
266
267         if (ret >= 0 && r < 0)
268                 ret = r;
269
270         if (rem) {
271                 r = cg_rmdir(controller, path);
272                 if (r < 0 && ret >= 0 && r != -ENOENT && r != -EBUSY)
273                         return r;
274         }
275
276         return ret;
277 }
278
279 int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self) {
280         bool done = false;
281         _cleanup_set_free_ Set *s = NULL;
282         int r, ret = 0;
283         pid_t my_pid;
284
285         assert(cfrom);
286         assert(pfrom);
287         assert(cto);
288         assert(pto);
289
290         s = set_new(NULL);
291         if (!s)
292                 return -ENOMEM;
293
294         my_pid = getpid();
295
296         do {
297                 _cleanup_fclose_ FILE *f = NULL;
298                 pid_t pid = 0;
299                 done = true;
300
301                 r = cg_enumerate_processes(cfrom, pfrom, &f);
302                 if (r < 0) {
303                         if (ret >= 0 && r != -ENOENT)
304                                 return r;
305
306                         return ret;
307                 }
308
309                 while ((r = cg_read_pid(f, &pid)) > 0) {
310
311                         /* This might do weird stuff if we aren't a
312                          * single-threaded program. However, we
313                          * luckily know we are not */
314                         if (ignore_self && pid == my_pid)
315                                 continue;
316
317                         if (set_get(s, LONG_TO_PTR(pid)) == LONG_TO_PTR(pid))
318                                 continue;
319
320                         r = cg_attach(cto, pto, pid);
321                         if (r < 0) {
322                                 if (ret >= 0 && r != -ESRCH)
323                                         ret = r;
324                         } else if (ret == 0)
325                                 ret = 1;
326
327                         done = false;
328
329                         r = set_put(s, LONG_TO_PTR(pid));
330                         if (r < 0) {
331                                 if (ret >= 0)
332                                         return r;
333
334                                 return ret;
335                         }
336                 }
337
338                 if (r < 0) {
339                         if (ret >= 0)
340                                 return r;
341
342                         return ret;
343                 }
344         } while (!done);
345
346         return ret;
347 }
348
349 int cg_migrate_recursive(
350                 const char *cfrom,
351                 const char *pfrom,
352                 const char *cto,
353                 const char *pto,
354                 bool ignore_self,
355                 bool rem) {
356
357         _cleanup_closedir_ DIR *d = NULL;
358         int r, ret = 0;
359         char *fn;
360
361         assert(cfrom);
362         assert(pfrom);
363         assert(cto);
364         assert(pto);
365
366         ret = cg_migrate(cfrom, pfrom, cto, pto, ignore_self);
367
368         r = cg_enumerate_subgroups(cfrom, pfrom, &d);
369         if (r < 0) {
370                 if (ret >= 0 && r != -ENOENT)
371                         return r;
372
373                 return ret;
374         }
375
376         while ((r = cg_read_subgroup(d, &fn)) > 0) {
377                 _cleanup_free_ char *p = NULL;
378
379                 p = strjoin(pfrom, "/", fn, NULL);
380                 free(fn);
381                 if (!p) {
382                         if (ret >= 0)
383                                 return -ENOMEM;
384
385                         return ret;
386                 }
387
388                 r = cg_migrate_recursive(cfrom, p, cto, pto, ignore_self, rem);
389                 if (r != 0 && ret >= 0)
390                         ret = r;
391         }
392
393         if (r < 0 && ret >= 0)
394                 ret = r;
395
396         if (rem) {
397                 r = cg_rmdir(cfrom, pfrom);
398                 if (r < 0 && ret >= 0 && r != -ENOENT && r != -EBUSY)
399                         return r;
400         }
401
402         return ret;
403 }
404
405 int cg_migrate_recursive_fallback(
406                 const char *cfrom,
407                 const char *pfrom,
408                 const char *cto,
409                 const char *pto,
410                 bool ignore_self,
411                 bool rem) {
412
413         int r;
414
415         assert(cfrom);
416         assert(pfrom);
417         assert(cto);
418         assert(pto);
419
420         r = cg_migrate_recursive(cfrom, pfrom, cto, pto, ignore_self, rem);
421         if (r < 0) {
422                 char prefix[strlen(pto) + 1];
423
424                 /* This didn't work? Then let's try all prefixes of the destination */
425
426                 PATH_FOREACH_PREFIX(prefix, pto) {
427                         r = cg_migrate_recursive(cfrom, pfrom, cto, prefix, ignore_self, rem);
428                         if (r >= 0)
429                                 break;
430                 }
431         }
432
433         return 0;
434 }
435
436 static const char *normalize_controller(const char *controller) {
437
438         assert(controller);
439
440         if (streq(controller, SYSTEMD_CGROUP_CONTROLLER))
441                 return "elogind";
442         else if (startswith(controller, "name="))
443                 return controller + 5;
444         else
445                 return controller;
446 }
447
448 static int join_path(const char *controller, const char *path, const char *suffix, char **fs) {
449         char *t = NULL;
450
451         if (!isempty(controller)) {
452                 if (!isempty(path) && !isempty(suffix))
453                         t = strjoin("/sys/fs/cgroup/", controller, "/", path, "/", suffix, NULL);
454                 else if (!isempty(path))
455                         t = strjoin("/sys/fs/cgroup/", controller, "/", path, NULL);
456                 else if (!isempty(suffix))
457                         t = strjoin("/sys/fs/cgroup/", controller, "/", suffix, NULL);
458                 else
459                         t = strappend("/sys/fs/cgroup/", controller);
460         } else {
461                 if (!isempty(path) && !isempty(suffix))
462                         t = strjoin(path, "/", suffix, NULL);
463                 else if (!isempty(path))
464                         t = strdup(path);
465                 else
466                         return -EINVAL;
467         }
468
469         if (!t)
470                 return -ENOMEM;
471
472         *fs = path_kill_slashes(t);
473         return 0;
474 }
475
476 int cg_get_path(const char *controller, const char *path, const char *suffix, char **fs) {
477         const char *p;
478         static thread_local bool good = false;
479
480         assert(fs);
481
482         if (controller && !cg_controller_is_valid(controller, true))
483                 return -EINVAL;
484
485         if (_unlikely_(!good)) {
486                 int r;
487
488                 r = path_is_mount_point("/sys/fs/cgroup", false);
489                 if (r <= 0)
490                         return r < 0 ? r : -ENOENT;
491
492                 /* Cache this to save a few stat()s */
493                 good = true;
494         }
495
496         p = controller ? normalize_controller(controller) : NULL;
497
498         return join_path(p, path, suffix, fs);
499 }
500
501 static int check_hierarchy(const char *p) {
502         const char *cc;
503
504         assert(p);
505
506         if (!filename_is_valid(p))
507                 return 0;
508
509         /* Check if this controller actually really exists */
510         cc = strjoina("/sys/fs/cgroup/", p);
511         if (laccess(cc, F_OK) < 0)
512                 return -errno;
513
514         return 0;
515 }
516
517 int cg_get_path_and_check(const char *controller, const char *path, const char *suffix, char **fs) {
518         const char *p;
519         int r;
520
521         assert(fs);
522
523         if (!cg_controller_is_valid(controller, true))
524                 return -EINVAL;
525
526         /* Normalize the controller syntax */
527         p = normalize_controller(controller);
528
529         /* Check if this controller actually really exists */
530         r = check_hierarchy(p);
531         if (r < 0)
532                 return r;
533
534         return join_path(p, path, suffix, fs);
535 }
536
537 static int trim_cb(const char *path, const struct stat *sb, int typeflag, struct FTW *ftwbuf) {
538         assert(path);
539         assert(sb);
540         assert(ftwbuf);
541
542         if (typeflag != FTW_DP)
543                 return 0;
544
545         if (ftwbuf->level < 1)
546                 return 0;
547
548         rmdir(path);
549         return 0;
550 }
551
552 int cg_trim(const char *controller, const char *path, bool delete_root) {
553         _cleanup_free_ char *fs = NULL;
554         int r = 0;
555
556         assert(path);
557
558         r = cg_get_path(controller, path, NULL, &fs);
559         if (r < 0)
560                 return r;
561
562         errno = 0;
563         if (nftw(fs, trim_cb, 64, FTW_DEPTH|FTW_MOUNT|FTW_PHYS) != 0)
564                 r = errno ? -errno : -EIO;
565
566         if (delete_root) {
567                 if (rmdir(fs) < 0 && errno != ENOENT)
568                         return -errno;
569         }
570
571         return r;
572 }
573
574 int cg_delete(const char *controller, const char *path) {
575         _cleanup_free_ char *parent = NULL;
576         int r;
577
578         assert(path);
579
580         r = path_get_parent(path, &parent);
581         if (r < 0)
582                 return r;
583
584         r = cg_migrate_recursive(controller, path, controller, parent, false, true);
585         return r == -ENOENT ? 0 : r;
586 }
587
588 int cg_create(const char *controller, const char *path) {
589         _cleanup_free_ char *fs = NULL;
590         int r;
591
592         r = cg_get_path_and_check(controller, path, NULL, &fs);
593         if (r < 0)
594                 return r;
595
596         r = mkdir_parents(fs, 0755);
597         if (r < 0)
598                 return r;
599
600         if (mkdir(fs, 0755) < 0) {
601
602                 if (errno == EEXIST)
603                         return 0;
604
605                 return -errno;
606         }
607
608         return 1;
609 }
610
611 int cg_create_and_attach(const char *controller, const char *path, pid_t pid) {
612         int r, q;
613
614         assert(pid >= 0);
615
616         r = cg_create(controller, path);
617         if (r < 0)
618                 return r;
619
620         q = cg_attach(controller, path, pid);
621         if (q < 0)
622                 return q;
623
624         /* This does not remove the cgroup on failure */
625         return r;
626 }
627
628 int cg_attach(const char *controller, const char *path, pid_t pid) {
629         _cleanup_free_ char *fs = NULL;
630         char c[DECIMAL_STR_MAX(pid_t) + 2];
631         int r;
632
633         assert(path);
634         assert(pid >= 0);
635
636         r = cg_get_path_and_check(controller, path, "cgroup.procs", &fs);
637         if (r < 0)
638                 return r;
639
640         if (pid == 0)
641                 pid = getpid();
642
643         snprintf(c, sizeof(c), PID_FMT"\n", pid);
644
645         return write_string_file_no_create(fs, c);
646 }
647
648 int cg_attach_fallback(const char *controller, const char *path, pid_t pid) {
649         int r;
650
651         assert(controller);
652         assert(path);
653         assert(pid >= 0);
654
655         r = cg_attach(controller, path, pid);
656         if (r < 0) {
657                 char prefix[strlen(path) + 1];
658
659                 /* This didn't work? Then let's try all prefixes of
660                  * the destination */
661
662                 PATH_FOREACH_PREFIX(prefix, path) {
663                         r = cg_attach(controller, prefix, pid);
664                         if (r >= 0)
665                                 break;
666                 }
667         }
668
669         return 0;
670 }
671
672 int cg_set_group_access(
673                 const char *controller,
674                 const char *path,
675                 mode_t mode,
676                 uid_t uid,
677                 gid_t gid) {
678
679         _cleanup_free_ char *fs = NULL;
680         int r;
681
682         assert(path);
683
684         if (mode != MODE_INVALID)
685                 mode &= 0777;
686
687         r = cg_get_path(controller, path, NULL, &fs);
688         if (r < 0)
689                 return r;
690
691         return chmod_and_chown(fs, mode, uid, gid);
692 }
693
694 int cg_set_task_access(
695                 const char *controller,
696                 const char *path,
697                 mode_t mode,
698                 uid_t uid,
699                 gid_t gid) {
700
701         _cleanup_free_ char *fs = NULL, *procs = NULL;
702         int r;
703
704         assert(path);
705
706         if (mode == MODE_INVALID && uid == UID_INVALID && gid == GID_INVALID)
707                 return 0;
708
709         if (mode != MODE_INVALID)
710                 mode &= 0666;
711
712         r = cg_get_path(controller, path, "cgroup.procs", &fs);
713         if (r < 0)
714                 return r;
715
716         r = chmod_and_chown(fs, mode, uid, gid);
717         if (r < 0)
718                 return r;
719
720         /* Compatibility, Always keep values for "tasks" in sync with
721          * "cgroup.procs" */
722         r = cg_get_path(controller, path, "tasks", &procs);
723         if (r < 0)
724                 return r;
725
726         return chmod_and_chown(procs, mode, uid, gid);
727 }
728
729 int cg_pid_get_path(const char *controller, pid_t pid, char **path) {
730         _cleanup_fclose_ FILE *f = NULL;
731         char line[LINE_MAX];
732         const char *fs;
733         size_t cs;
734
735         assert(path);
736         assert(pid >= 0);
737
738         if (controller) {
739                 if (!cg_controller_is_valid(controller, true))
740                         return -EINVAL;
741
742                 controller = normalize_controller(controller);
743         } else
744                 controller = SYSTEMD_CGROUP_CONTROLLER;
745
746         fs = procfs_file_alloca(pid, "cgroup");
747
748         f = fopen(fs, "re");
749         if (!f)
750                 return errno == ENOENT ? -ESRCH : -errno;
751
752         cs = strlen(controller);
753
754         FOREACH_LINE(line, f, return -errno) {
755                 char *l, *p, *e;
756                 size_t k;
757                 const char *word, *state;
758                 bool found = false;
759
760                 truncate_nl(line);
761
762                 l = strchr(line, ':');
763                 if (!l)
764                         continue;
765
766                 l++;
767                 e = strchr(l, ':');
768                 if (!e)
769                         continue;
770
771                 *e = 0;
772
773                 FOREACH_WORD_SEPARATOR(word, k, l, ",", state) {
774
775                         if (k == cs && memcmp(word, controller, cs) == 0) {
776                                 found = true;
777                                 break;
778                         }
779
780                         if (k == 5 + cs &&
781                             memcmp(word, "name=", 5) == 0 &&
782                             memcmp(word+5, controller, cs) == 0) {
783                                 found = true;
784                                 break;
785                         }
786                 }
787
788                 if (!found)
789                         continue;
790
791                 p = strdup(e + 1);
792                 if (!p)
793                         return -ENOMEM;
794
795                 *path = p;
796                 return 0;
797         }
798
799         return -ENOENT;
800 }
801
802 int cg_install_release_agent(const char *controller, const char *agent) {
803         _cleanup_free_ char *fs = NULL, *contents = NULL;
804         char *sc;
805         int r;
806
807         assert(agent);
808
809         r = cg_get_path(controller, NULL, "release_agent", &fs);
810         if (r < 0)
811                 return r;
812
813         r = read_one_line_file(fs, &contents);
814         if (r < 0)
815                 return r;
816
817         sc = strstrip(contents);
818         if (sc[0] == 0) {
819                 r = write_string_file_no_create(fs, agent);
820                 if (r < 0)
821                         return r;
822         } else if (!streq(sc, agent))
823                 return -EEXIST;
824
825         free(fs);
826         fs = NULL;
827         r = cg_get_path(controller, NULL, "notify_on_release", &fs);
828         if (r < 0)
829                 return r;
830
831         free(contents);
832         contents = NULL;
833         r = read_one_line_file(fs, &contents);
834         if (r < 0)
835                 return r;
836
837         sc = strstrip(contents);
838         if (streq(sc, "0")) {
839                 r = write_string_file_no_create(fs, "1");
840                 if (r < 0)
841                         return r;
842
843                 return 1;
844         }
845
846         if (!streq(sc, "1"))
847                 return -EIO;
848
849         return 0;
850 }
851
852 int cg_uninstall_release_agent(const char *controller) {
853         _cleanup_free_ char *fs = NULL;
854         int r;
855
856         r = cg_get_path(controller, NULL, "notify_on_release", &fs);
857         if (r < 0)
858                 return r;
859
860         r = write_string_file_no_create(fs, "0");
861         if (r < 0)
862                 return r;
863
864         free(fs);
865         fs = NULL;
866
867         r = cg_get_path(controller, NULL, "release_agent", &fs);
868         if (r < 0)
869                 return r;
870
871         r = write_string_file_no_create(fs, "");
872         if (r < 0)
873                 return r;
874
875         return 0;
876 }
877
878 int cg_is_empty(const char *controller, const char *path, bool ignore_self) {
879         _cleanup_fclose_ FILE *f = NULL;
880         pid_t pid = 0, self_pid;
881         bool found = false;
882         int r;
883
884         assert(path);
885
886         r = cg_enumerate_processes(controller, path, &f);
887         if (r < 0)
888                 return r == -ENOENT ? 1 : r;
889
890         self_pid = getpid();
891
892         while ((r = cg_read_pid(f, &pid)) > 0) {
893
894                 if (ignore_self && pid == self_pid)
895                         continue;
896
897                 found = true;
898                 break;
899         }
900
901         if (r < 0)
902                 return r;
903
904         return !found;
905 }
906
907 int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_self) {
908         _cleanup_closedir_ DIR *d = NULL;
909         char *fn;
910         int r;
911
912         assert(path);
913
914         r = cg_is_empty(controller, path, ignore_self);
915         if (r <= 0)
916                 return r;
917
918         r = cg_enumerate_subgroups(controller, path, &d);
919         if (r < 0)
920                 return r == -ENOENT ? 1 : r;
921
922         while ((r = cg_read_subgroup(d, &fn)) > 0) {
923                 _cleanup_free_ char *p = NULL;
924
925                 p = strjoin(path, "/", fn, NULL);
926                 free(fn);
927                 if (!p)
928                         return -ENOMEM;
929
930                 r = cg_is_empty_recursive(controller, p, ignore_self);
931                 if (r <= 0)
932                         return r;
933         }
934
935         if (r < 0)
936                 return r;
937
938         return 1;
939 }
940
941 int cg_split_spec(const char *spec, char **controller, char **path) {
942         const char *e;
943         char *t = NULL, *u = NULL;
944         _cleanup_free_ char *v = NULL;
945
946         assert(spec);
947
948         if (*spec == '/') {
949                 if (!path_is_safe(spec))
950                         return -EINVAL;
951
952                 if (path) {
953                         t = strdup(spec);
954                         if (!t)
955                                 return -ENOMEM;
956
957                         *path = path_kill_slashes(t);
958                 }
959
960                 if (controller)
961                         *controller = NULL;
962
963                 return 0;
964         }
965
966         e = strchr(spec, ':');
967         if (!e) {
968                 if (!cg_controller_is_valid(spec, true))
969                         return -EINVAL;
970
971                 if (controller) {
972                         t = strdup(normalize_controller(spec));
973                         if (!t)
974                                 return -ENOMEM;
975
976                         *controller = t;
977                 }
978
979                 if (path)
980                         *path = NULL;
981
982                 return 0;
983         }
984
985         v = strndup(spec, e-spec);
986         if (!v)
987                 return -ENOMEM;
988         t = strdup(normalize_controller(v));
989         if (!t)
990                 return -ENOMEM;
991         if (!cg_controller_is_valid(t, true)) {
992                 free(t);
993                 return -EINVAL;
994         }
995
996         if (streq(e+1, "")) {
997                 u = strdup("/");
998                 if (!u) {
999                         free(t);
1000                         return -ENOMEM;
1001                 }
1002         } else {
1003                 u = strdup(e+1);
1004                 if (!u) {
1005                         free(t);
1006                         return -ENOMEM;
1007                 }
1008
1009                 if (!path_is_safe(u) ||
1010                     !path_is_absolute(u)) {
1011                         free(t);
1012                         free(u);
1013                         return -EINVAL;
1014                 }
1015
1016                 path_kill_slashes(u);
1017         }
1018
1019         if (controller)
1020                 *controller = t;
1021         else
1022                 free(t);
1023
1024         if (path)
1025                 *path = u;
1026         else
1027                 free(u);
1028
1029         return 0;
1030 }
1031
1032 int cg_mangle_path(const char *path, char **result) {
1033         _cleanup_free_ char *c = NULL, *p = NULL;
1034         char *t;
1035         int r;
1036
1037         assert(path);
1038         assert(result);
1039
1040         /* First, check if it already is a filesystem path */
1041         if (path_startswith(path, "/sys/fs/cgroup")) {
1042
1043                 t = strdup(path);
1044                 if (!t)
1045                         return -ENOMEM;
1046
1047                 *result = path_kill_slashes(t);
1048                 return 0;
1049         }
1050
1051         /* Otherwise, treat it as cg spec */
1052         r = cg_split_spec(path, &c, &p);
1053         if (r < 0)
1054                 return r;
1055
1056         return cg_get_path(c ? c : SYSTEMD_CGROUP_CONTROLLER, p ? p : "/", NULL, result);
1057 }
1058
1059 int cg_get_root_path(char **path) {
1060         assert(path);
1061
1062         return cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 1, path);
1063 }
1064
1065 int cg_shift_path(const char *cgroup, const char *root, const char **shifted) {
1066         _cleanup_free_ char *rt = NULL;
1067         char *p;
1068         int r;
1069
1070         assert(cgroup);
1071         assert(shifted);
1072
1073         if (!root) {
1074                 /* If the root was specified let's use that, otherwise
1075                  * let's determine it from PID 1 */
1076
1077                 r = cg_get_root_path(&rt);
1078                 if (r < 0)
1079                         return r;
1080
1081                 root = rt;
1082         }
1083
1084         p = path_startswith(cgroup, root);
1085         if (p)
1086                 *shifted = p - 1;
1087         else
1088                 *shifted = cgroup;
1089
1090         return 0;
1091 }
1092
1093 int cg_pid_get_path_shifted(pid_t pid, const char *root, char **cgroup) {
1094         _cleanup_free_ char *raw = NULL;
1095         const char *c;
1096         int r;
1097
1098         assert(pid >= 0);
1099         assert(cgroup);
1100
1101         r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &raw);
1102         if (r < 0)
1103                 return r;
1104
1105         r = cg_shift_path(raw, root, &c);
1106         if (r < 0)
1107                 return r;
1108
1109         if (c == raw) {
1110                 *cgroup = raw;
1111                 raw = NULL;
1112         } else {
1113                 char *n;
1114
1115                 n = strdup(c);
1116                 if (!n)
1117                         return -ENOMEM;
1118
1119                 *cgroup = n;
1120         }
1121
1122         return 0;
1123 }
1124
1125 int cg_path_get_session(const char *path, char **session) {
1126         const char *e, *n, *s;
1127
1128         /* Elogind uses a flat hierarchy, just "/SESSION".  The only
1129            wrinkle is that SESSION might be escaped.  */
1130
1131         assert(path);
1132         assert(path[0] == '/');
1133
1134         e = path + 1;
1135         n = strchrnul(e, '/');
1136         if (e == n)
1137                 return -ENOENT;
1138
1139         s = strndupa(e, n - e);
1140         s = cg_unescape(s);
1141
1142         if (!s[0])
1143                 return -ENOENT;
1144
1145         if (session) {
1146                 char *r;
1147
1148                 r = strdup(s);
1149                 if (!r)
1150                         return -ENOMEM;
1151
1152                 *session = r;
1153         }
1154
1155         return 0;
1156 }
1157
1158 int cg_pid_get_session(pid_t pid, char **session) {
1159         _cleanup_free_ char *cgroup = NULL;
1160         int r;
1161
1162         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1163         if (r < 0)
1164                 return r;
1165
1166         return cg_path_get_session(cgroup, session);
1167 }
1168
1169 char *cg_escape(const char *p) {
1170         bool need_prefix = false;
1171
1172         /* This implements very minimal escaping for names to be used
1173          * as file names in the cgroup tree: any name which might
1174          * conflict with a kernel name or is prefixed with '_' is
1175          * prefixed with a '_'. That way, when reading cgroup names it
1176          * is sufficient to remove a single prefixing underscore if
1177          * there is one. */
1178
1179         /* The return value of this function (unlike cg_unescape())
1180          * needs free()! */
1181
1182         if (p[0] == 0 ||
1183             p[0] == '_' ||
1184             p[0] == '.' ||
1185             streq(p, "notify_on_release") ||
1186             streq(p, "release_agent") ||
1187             streq(p, "tasks"))
1188                 need_prefix = true;
1189         else {
1190                 const char *dot;
1191
1192                 dot = strrchr(p, '.');
1193                 if (dot) {
1194
1195                         if (dot - p == 6 && memcmp(p, "cgroup", 6) == 0)
1196                                 need_prefix = true;
1197                         else {
1198                                 char *n;
1199
1200                                 n = strndupa(p, dot - p);
1201
1202                                 if (check_hierarchy(n) >= 0)
1203                                         need_prefix = true;
1204                         }
1205                 }
1206         }
1207
1208         if (need_prefix)
1209                 return strappend("_", p);
1210         else
1211                 return strdup(p);
1212 }
1213
1214 char *cg_unescape(const char *p) {
1215         assert(p);
1216
1217         /* The return value of this function (unlike cg_escape())
1218          * doesn't need free()! */
1219
1220         if (p[0] == '_')
1221                 return (char*) p+1;
1222
1223         return (char*) p;
1224 }
1225
1226 #define CONTROLLER_VALID                        \
1227         DIGITS LETTERS                          \
1228         "_"
1229
1230 bool cg_controller_is_valid(const char *p, bool allow_named) {
1231         const char *t, *s;
1232
1233         if (!p)
1234                 return false;
1235
1236         if (allow_named) {
1237                 s = startswith(p, "name=");
1238                 if (s)
1239                         p = s;
1240         }
1241
1242         if (*p == 0 || *p == '_')
1243                 return false;
1244
1245         for (t = p; *t; t++)
1246                 if (!strchr(CONTROLLER_VALID, *t))
1247                         return false;
1248
1249         if (t - p > FILENAME_MAX)
1250                 return false;
1251
1252         return true;
1253 }
1254
1255 int cg_set_attribute(const char *controller, const char *path, const char *attribute, const char *value) {
1256         _cleanup_free_ char *p = NULL;
1257         int r;
1258
1259         r = cg_get_path(controller, path, attribute, &p);
1260         if (r < 0)
1261                 return r;
1262
1263         return write_string_file_no_create(p, value);
1264 }
1265
1266 int cg_get_attribute(const char *controller, const char *path, const char *attribute, char **ret) {
1267         _cleanup_free_ char *p = NULL;
1268         int r;
1269
1270         r = cg_get_path(controller, path, attribute, &p);
1271         if (r < 0)
1272                 return r;
1273
1274         return read_one_line_file(p, ret);
1275 }
1276
1277 static const char mask_names[] =
1278         "cpu\0"
1279         "cpuacct\0"
1280         "blkio\0"
1281         "memory\0"
1282         "devices\0";
1283
1284 int cg_create_everywhere(CGroupControllerMask supported, CGroupControllerMask mask, const char *path) {
1285         CGroupControllerMask bit = 1;
1286         const char *n;
1287         int r;
1288
1289         /* This one will create a cgroup in our private tree, but also
1290          * duplicate it in the trees specified in mask, and remove it
1291          * in all others */
1292
1293         /* First create the cgroup in our own hierarchy. */
1294         r = cg_create(SYSTEMD_CGROUP_CONTROLLER, path);
1295         if (r < 0)
1296                 return r;
1297
1298         /* Then, do the same in the other hierarchies */
1299         NULSTR_FOREACH(n, mask_names) {
1300                 if (mask & bit)
1301                         cg_create(n, path);
1302                 else if (supported & bit)
1303                         cg_trim(n, path, true);
1304
1305                 bit <<= 1;
1306         }
1307
1308         return 0;
1309 }
1310
1311 int cg_attach_everywhere(CGroupControllerMask supported, const char *path, pid_t pid, cg_migrate_callback_t path_callback, void *userdata) {
1312         CGroupControllerMask bit = 1;
1313         const char *n;
1314         int r;
1315
1316         r = cg_attach(SYSTEMD_CGROUP_CONTROLLER, path, pid);
1317         if (r < 0)
1318                 return r;
1319
1320         NULSTR_FOREACH(n, mask_names) {
1321
1322                 if (supported & bit) {
1323                         const char *p = NULL;
1324
1325                         if (path_callback)
1326                                 p = path_callback(bit, userdata);
1327
1328                         if (!p)
1329                                 p = path;
1330
1331                         cg_attach_fallback(n, path, pid);
1332                 }
1333
1334                 bit <<= 1;
1335         }
1336
1337         return 0;
1338 }
1339
1340 int cg_attach_many_everywhere(CGroupControllerMask supported, const char *path, Set* pids, cg_migrate_callback_t path_callback, void *userdata) {
1341         Iterator i;
1342         void *pidp;
1343         int r = 0;
1344
1345         SET_FOREACH(pidp, pids, i) {
1346                 pid_t pid = PTR_TO_LONG(pidp);
1347                 int q;
1348
1349                 q = cg_attach_everywhere(supported, path, pid, path_callback, userdata);
1350                 if (q < 0)
1351                         r = q;
1352         }
1353
1354         return r;
1355 }
1356
1357 int cg_migrate_everywhere(CGroupControllerMask supported, const char *from, const char *to, cg_migrate_callback_t to_callback, void *userdata) {
1358         CGroupControllerMask bit = 1;
1359         const char *n;
1360         int r;
1361
1362         if (!path_equal(from, to))  {
1363                 r = cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, from, SYSTEMD_CGROUP_CONTROLLER, to, false, true);
1364                 if (r < 0)
1365                         return r;
1366         }
1367
1368         NULSTR_FOREACH(n, mask_names) {
1369                 if (supported & bit) {
1370                         const char *p = NULL;
1371
1372                         if (to_callback)
1373                                 p = to_callback(bit, userdata);
1374
1375                         if (!p)
1376                                 p = to;
1377
1378                         cg_migrate_recursive_fallback(SYSTEMD_CGROUP_CONTROLLER, to, n, p, false, false);
1379                 }
1380
1381                 bit <<= 1;
1382         }
1383
1384         return 0;
1385 }
1386
1387 int cg_trim_everywhere(CGroupControllerMask supported, const char *path, bool delete_root) {
1388         CGroupControllerMask bit = 1;
1389         const char *n;
1390         int r;
1391
1392         r = cg_trim(SYSTEMD_CGROUP_CONTROLLER, path, delete_root);
1393         if (r < 0)
1394                 return r;
1395
1396         NULSTR_FOREACH(n, mask_names) {
1397                 if (supported & bit)
1398                         cg_trim(n, path, delete_root);
1399
1400                 bit <<= 1;
1401         }
1402
1403         return 0;
1404 }
1405
1406 CGroupControllerMask cg_mask_supported(void) {
1407         CGroupControllerMask bit = 1, mask = 0;
1408         const char *n;
1409
1410         NULSTR_FOREACH(n, mask_names) {
1411                 if (check_hierarchy(n) >= 0)
1412                         mask |= bit;
1413
1414                 bit <<= 1;
1415         }
1416
1417         return mask;
1418 }
1419
1420 int cg_kernel_controllers(Set *controllers) {
1421         _cleanup_fclose_ FILE *f = NULL;
1422         char buf[LINE_MAX];
1423         int r;
1424
1425         assert(controllers);
1426
1427         f = fopen("/proc/cgroups", "re");
1428         if (!f) {
1429                 if (errno == ENOENT)
1430                         return 0;
1431                 return -errno;
1432         }
1433
1434         /* Ignore the header line */
1435         (void) fgets(buf, sizeof(buf), f);
1436
1437         for (;;) {
1438                 char *controller;
1439                 int enabled = 0;
1440
1441                 errno = 0;
1442                 if (fscanf(f, "%ms %*i %*i %i", &controller, &enabled) != 2) {
1443
1444                         if (feof(f))
1445                                 break;
1446
1447                         if (ferror(f) && errno)
1448                                 return -errno;
1449
1450                         return -EBADMSG;
1451                 }
1452
1453                 if (!enabled) {
1454                         free(controller);
1455                         continue;
1456                 }
1457
1458                 if (!filename_is_valid(controller)) {
1459                         free(controller);
1460                         return -EBADMSG;
1461                 }
1462
1463                 r = set_consume(controllers, controller);
1464                 if (r < 0)
1465                         return r;
1466         }
1467
1468         return 0;
1469 }