chiark / gitweb /
path-util: fix more path_is_mount e792e890f fallout
[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;
491                 if (r == 0)
492                         return -ENOENT;
493
494                 /* Cache this to save a few stat()s */
495                 good = true;
496         }
497
498         p = controller ? normalize_controller(controller) : NULL;
499
500         return join_path(p, path, suffix, fs);
501 }
502
503 static int check_hierarchy(const char *p) {
504         const char *cc;
505
506         assert(p);
507
508         if (!filename_is_valid(p))
509                 return 0;
510
511         /* Check if this controller actually really exists */
512         cc = strjoina("/sys/fs/cgroup/", p);
513         if (laccess(cc, F_OK) < 0)
514                 return -errno;
515
516         return 0;
517 }
518
519 int cg_get_path_and_check(const char *controller, const char *path, const char *suffix, char **fs) {
520         const char *p;
521         int r;
522
523         assert(fs);
524
525         if (!cg_controller_is_valid(controller, true))
526                 return -EINVAL;
527
528         /* Normalize the controller syntax */
529         p = normalize_controller(controller);
530
531         /* Check if this controller actually really exists */
532         r = check_hierarchy(p);
533         if (r < 0)
534                 return r;
535
536         return join_path(p, path, suffix, fs);
537 }
538
539 static int trim_cb(const char *path, const struct stat *sb, int typeflag, struct FTW *ftwbuf) {
540         assert(path);
541         assert(sb);
542         assert(ftwbuf);
543
544         if (typeflag != FTW_DP)
545                 return 0;
546
547         if (ftwbuf->level < 1)
548                 return 0;
549
550         rmdir(path);
551         return 0;
552 }
553
554 int cg_trim(const char *controller, const char *path, bool delete_root) {
555         _cleanup_free_ char *fs = NULL;
556         int r = 0;
557
558         assert(path);
559
560         r = cg_get_path(controller, path, NULL, &fs);
561         if (r < 0)
562                 return r;
563
564         errno = 0;
565         if (nftw(fs, trim_cb, 64, FTW_DEPTH|FTW_MOUNT|FTW_PHYS) != 0)
566                 r = errno ? -errno : -EIO;
567
568         if (delete_root) {
569                 if (rmdir(fs) < 0 && errno != ENOENT)
570                         return -errno;
571         }
572
573         return r;
574 }
575
576 int cg_delete(const char *controller, const char *path) {
577         _cleanup_free_ char *parent = NULL;
578         int r;
579
580         assert(path);
581
582         r = path_get_parent(path, &parent);
583         if (r < 0)
584                 return r;
585
586         r = cg_migrate_recursive(controller, path, controller, parent, false, true);
587         return r == -ENOENT ? 0 : r;
588 }
589
590 int cg_create(const char *controller, const char *path) {
591         _cleanup_free_ char *fs = NULL;
592         int r;
593
594         r = cg_get_path_and_check(controller, path, NULL, &fs);
595         if (r < 0)
596                 return r;
597
598         r = mkdir_parents(fs, 0755);
599         if (r < 0)
600                 return r;
601
602         if (mkdir(fs, 0755) < 0) {
603
604                 if (errno == EEXIST)
605                         return 0;
606
607                 return -errno;
608         }
609
610         return 1;
611 }
612
613 int cg_create_and_attach(const char *controller, const char *path, pid_t pid) {
614         int r, q;
615
616         assert(pid >= 0);
617
618         r = cg_create(controller, path);
619         if (r < 0)
620                 return r;
621
622         q = cg_attach(controller, path, pid);
623         if (q < 0)
624                 return q;
625
626         /* This does not remove the cgroup on failure */
627         return r;
628 }
629
630 int cg_attach(const char *controller, const char *path, pid_t pid) {
631         _cleanup_free_ char *fs = NULL;
632         char c[DECIMAL_STR_MAX(pid_t) + 2];
633         int r;
634
635         assert(path);
636         assert(pid >= 0);
637
638         r = cg_get_path_and_check(controller, path, "cgroup.procs", &fs);
639         if (r < 0)
640                 return r;
641
642         if (pid == 0)
643                 pid = getpid();
644
645         snprintf(c, sizeof(c), PID_FMT"\n", pid);
646
647         return write_string_file_no_create(fs, c);
648 }
649
650 int cg_attach_fallback(const char *controller, const char *path, pid_t pid) {
651         int r;
652
653         assert(controller);
654         assert(path);
655         assert(pid >= 0);
656
657         r = cg_attach(controller, path, pid);
658         if (r < 0) {
659                 char prefix[strlen(path) + 1];
660
661                 /* This didn't work? Then let's try all prefixes of
662                  * the destination */
663
664                 PATH_FOREACH_PREFIX(prefix, path) {
665                         r = cg_attach(controller, prefix, pid);
666                         if (r >= 0)
667                                 break;
668                 }
669         }
670
671         return 0;
672 }
673
674 int cg_set_group_access(
675                 const char *controller,
676                 const char *path,
677                 mode_t mode,
678                 uid_t uid,
679                 gid_t gid) {
680
681         _cleanup_free_ char *fs = NULL;
682         int r;
683
684         assert(path);
685
686         if (mode != MODE_INVALID)
687                 mode &= 0777;
688
689         r = cg_get_path(controller, path, NULL, &fs);
690         if (r < 0)
691                 return r;
692
693         return chmod_and_chown(fs, mode, uid, gid);
694 }
695
696 int cg_set_task_access(
697                 const char *controller,
698                 const char *path,
699                 mode_t mode,
700                 uid_t uid,
701                 gid_t gid) {
702
703         _cleanup_free_ char *fs = NULL, *procs = NULL;
704         int r;
705
706         assert(path);
707
708         if (mode == MODE_INVALID && uid == UID_INVALID && gid == GID_INVALID)
709                 return 0;
710
711         if (mode != MODE_INVALID)
712                 mode &= 0666;
713
714         r = cg_get_path(controller, path, "cgroup.procs", &fs);
715         if (r < 0)
716                 return r;
717
718         r = chmod_and_chown(fs, mode, uid, gid);
719         if (r < 0)
720                 return r;
721
722         /* Compatibility, Always keep values for "tasks" in sync with
723          * "cgroup.procs" */
724         r = cg_get_path(controller, path, "tasks", &procs);
725         if (r < 0)
726                 return r;
727
728         return chmod_and_chown(procs, mode, uid, gid);
729 }
730
731 int cg_pid_get_path(const char *controller, pid_t pid, char **path) {
732         _cleanup_fclose_ FILE *f = NULL;
733         char line[LINE_MAX];
734         const char *fs;
735         size_t cs;
736
737         assert(path);
738         assert(pid >= 0);
739
740         if (controller) {
741                 if (!cg_controller_is_valid(controller, true))
742                         return -EINVAL;
743
744                 controller = normalize_controller(controller);
745         } else
746                 controller = SYSTEMD_CGROUP_CONTROLLER;
747
748         fs = procfs_file_alloca(pid, "cgroup");
749
750         f = fopen(fs, "re");
751         if (!f)
752                 return errno == ENOENT ? -ESRCH : -errno;
753
754         cs = strlen(controller);
755
756         FOREACH_LINE(line, f, return -errno) {
757                 char *l, *p, *e;
758                 size_t k;
759                 const char *word, *state;
760                 bool found = false;
761
762                 truncate_nl(line);
763
764                 l = strchr(line, ':');
765                 if (!l)
766                         continue;
767
768                 l++;
769                 e = strchr(l, ':');
770                 if (!e)
771                         continue;
772
773                 *e = 0;
774
775                 FOREACH_WORD_SEPARATOR(word, k, l, ",", state) {
776
777                         if (k == cs && memcmp(word, controller, cs) == 0) {
778                                 found = true;
779                                 break;
780                         }
781
782                         if (k == 5 + cs &&
783                             memcmp(word, "name=", 5) == 0 &&
784                             memcmp(word+5, controller, cs) == 0) {
785                                 found = true;
786                                 break;
787                         }
788                 }
789
790                 if (!found)
791                         continue;
792
793                 p = strdup(e + 1);
794                 if (!p)
795                         return -ENOMEM;
796
797                 *path = p;
798                 return 0;
799         }
800
801         return -ENOENT;
802 }
803
804 int cg_install_release_agent(const char *controller, const char *agent) {
805         _cleanup_free_ char *fs = NULL, *contents = NULL;
806         char *sc;
807         int r;
808
809         assert(agent);
810
811         r = cg_get_path(controller, NULL, "release_agent", &fs);
812         if (r < 0)
813                 return r;
814
815         r = read_one_line_file(fs, &contents);
816         if (r < 0)
817                 return r;
818
819         sc = strstrip(contents);
820         if (sc[0] == 0) {
821                 r = write_string_file_no_create(fs, agent);
822                 if (r < 0)
823                         return r;
824         } else if (!streq(sc, agent))
825                 return -EEXIST;
826
827         free(fs);
828         fs = NULL;
829         r = cg_get_path(controller, NULL, "notify_on_release", &fs);
830         if (r < 0)
831                 return r;
832
833         free(contents);
834         contents = NULL;
835         r = read_one_line_file(fs, &contents);
836         if (r < 0)
837                 return r;
838
839         sc = strstrip(contents);
840         if (streq(sc, "0")) {
841                 r = write_string_file_no_create(fs, "1");
842                 if (r < 0)
843                         return r;
844
845                 return 1;
846         }
847
848         if (!streq(sc, "1"))
849                 return -EIO;
850
851         return 0;
852 }
853
854 int cg_uninstall_release_agent(const char *controller) {
855         _cleanup_free_ char *fs = NULL;
856         int r;
857
858         r = cg_get_path(controller, NULL, "notify_on_release", &fs);
859         if (r < 0)
860                 return r;
861
862         r = write_string_file_no_create(fs, "0");
863         if (r < 0)
864                 return r;
865
866         free(fs);
867         fs = NULL;
868
869         r = cg_get_path(controller, NULL, "release_agent", &fs);
870         if (r < 0)
871                 return r;
872
873         r = write_string_file_no_create(fs, "");
874         if (r < 0)
875                 return r;
876
877         return 0;
878 }
879
880 int cg_is_empty(const char *controller, const char *path, bool ignore_self) {
881         _cleanup_fclose_ FILE *f = NULL;
882         pid_t pid = 0, self_pid;
883         bool found = false;
884         int r;
885
886         assert(path);
887
888         r = cg_enumerate_processes(controller, path, &f);
889         if (r < 0)
890                 return r == -ENOENT ? 1 : r;
891
892         self_pid = getpid();
893
894         while ((r = cg_read_pid(f, &pid)) > 0) {
895
896                 if (ignore_self && pid == self_pid)
897                         continue;
898
899                 found = true;
900                 break;
901         }
902
903         if (r < 0)
904                 return r;
905
906         return !found;
907 }
908
909 int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_self) {
910         _cleanup_closedir_ DIR *d = NULL;
911         char *fn;
912         int r;
913
914         assert(path);
915
916         r = cg_is_empty(controller, path, ignore_self);
917         if (r <= 0)
918                 return r;
919
920         r = cg_enumerate_subgroups(controller, path, &d);
921         if (r < 0)
922                 return r == -ENOENT ? 1 : r;
923
924         while ((r = cg_read_subgroup(d, &fn)) > 0) {
925                 _cleanup_free_ char *p = NULL;
926
927                 p = strjoin(path, "/", fn, NULL);
928                 free(fn);
929                 if (!p)
930                         return -ENOMEM;
931
932                 r = cg_is_empty_recursive(controller, p, ignore_self);
933                 if (r <= 0)
934                         return r;
935         }
936
937         if (r < 0)
938                 return r;
939
940         return 1;
941 }
942
943 int cg_split_spec(const char *spec, char **controller, char **path) {
944         const char *e;
945         char *t = NULL, *u = NULL;
946         _cleanup_free_ char *v = NULL;
947
948         assert(spec);
949
950         if (*spec == '/') {
951                 if (!path_is_safe(spec))
952                         return -EINVAL;
953
954                 if (path) {
955                         t = strdup(spec);
956                         if (!t)
957                                 return -ENOMEM;
958
959                         *path = path_kill_slashes(t);
960                 }
961
962                 if (controller)
963                         *controller = NULL;
964
965                 return 0;
966         }
967
968         e = strchr(spec, ':');
969         if (!e) {
970                 if (!cg_controller_is_valid(spec, true))
971                         return -EINVAL;
972
973                 if (controller) {
974                         t = strdup(normalize_controller(spec));
975                         if (!t)
976                                 return -ENOMEM;
977
978                         *controller = t;
979                 }
980
981                 if (path)
982                         *path = NULL;
983
984                 return 0;
985         }
986
987         v = strndup(spec, e-spec);
988         if (!v)
989                 return -ENOMEM;
990         t = strdup(normalize_controller(v));
991         if (!t)
992                 return -ENOMEM;
993         if (!cg_controller_is_valid(t, true)) {
994                 free(t);
995                 return -EINVAL;
996         }
997
998         if (streq(e+1, "")) {
999                 u = strdup("/");
1000                 if (!u) {
1001                         free(t);
1002                         return -ENOMEM;
1003                 }
1004         } else {
1005                 u = strdup(e+1);
1006                 if (!u) {
1007                         free(t);
1008                         return -ENOMEM;
1009                 }
1010
1011                 if (!path_is_safe(u) ||
1012                     !path_is_absolute(u)) {
1013                         free(t);
1014                         free(u);
1015                         return -EINVAL;
1016                 }
1017
1018                 path_kill_slashes(u);
1019         }
1020
1021         if (controller)
1022                 *controller = t;
1023         else
1024                 free(t);
1025
1026         if (path)
1027                 *path = u;
1028         else
1029                 free(u);
1030
1031         return 0;
1032 }
1033
1034 int cg_mangle_path(const char *path, char **result) {
1035         _cleanup_free_ char *c = NULL, *p = NULL;
1036         char *t;
1037         int r;
1038
1039         assert(path);
1040         assert(result);
1041
1042         /* First, check if it already is a filesystem path */
1043         if (path_startswith(path, "/sys/fs/cgroup")) {
1044
1045                 t = strdup(path);
1046                 if (!t)
1047                         return -ENOMEM;
1048
1049                 *result = path_kill_slashes(t);
1050                 return 0;
1051         }
1052
1053         /* Otherwise, treat it as cg spec */
1054         r = cg_split_spec(path, &c, &p);
1055         if (r < 0)
1056                 return r;
1057
1058         return cg_get_path(c ? c : SYSTEMD_CGROUP_CONTROLLER, p ? p : "/", NULL, result);
1059 }
1060
1061 int cg_get_root_path(char **path) {
1062         assert(path);
1063
1064         return cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 1, path);
1065 }
1066
1067 int cg_shift_path(const char *cgroup, const char *root, const char **shifted) {
1068         _cleanup_free_ char *rt = NULL;
1069         char *p;
1070         int r;
1071
1072         assert(cgroup);
1073         assert(shifted);
1074
1075         if (!root) {
1076                 /* If the root was specified let's use that, otherwise
1077                  * let's determine it from PID 1 */
1078
1079                 r = cg_get_root_path(&rt);
1080                 if (r < 0)
1081                         return r;
1082
1083                 root = rt;
1084         }
1085
1086         p = path_startswith(cgroup, root);
1087         if (p)
1088                 *shifted = p - 1;
1089         else
1090                 *shifted = cgroup;
1091
1092         return 0;
1093 }
1094
1095 int cg_pid_get_path_shifted(pid_t pid, const char *root, char **cgroup) {
1096         _cleanup_free_ char *raw = NULL;
1097         const char *c;
1098         int r;
1099
1100         assert(pid >= 0);
1101         assert(cgroup);
1102
1103         r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &raw);
1104         if (r < 0)
1105                 return r;
1106
1107         r = cg_shift_path(raw, root, &c);
1108         if (r < 0)
1109                 return r;
1110
1111         if (c == raw) {
1112                 *cgroup = raw;
1113                 raw = NULL;
1114         } else {
1115                 char *n;
1116
1117                 n = strdup(c);
1118                 if (!n)
1119                         return -ENOMEM;
1120
1121                 *cgroup = n;
1122         }
1123
1124         return 0;
1125 }
1126
1127 int cg_path_get_session(const char *path, char **session) {
1128         const char *e, *n, *s;
1129
1130         /* Elogind uses a flat hierarchy, just "/SESSION".  The only
1131            wrinkle is that SESSION might be escaped.  */
1132
1133         assert(path);
1134         assert(path[0] == '/');
1135
1136         e = path + 1;
1137         n = strchrnul(e, '/');
1138         if (e == n)
1139                 return -ENOENT;
1140
1141         s = strndupa(e, n - e);
1142         s = cg_unescape(s);
1143
1144         if (!s[0])
1145                 return -ENOENT;
1146
1147         if (session) {
1148                 char *r;
1149
1150                 r = strdup(s);
1151                 if (!r)
1152                         return -ENOMEM;
1153
1154                 *session = r;
1155         }
1156
1157         return 0;
1158 }
1159
1160 int cg_pid_get_session(pid_t pid, char **session) {
1161         _cleanup_free_ char *cgroup = NULL;
1162         int r;
1163
1164         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1165         if (r < 0)
1166                 return r;
1167
1168         return cg_path_get_session(cgroup, session);
1169 }
1170
1171 char *cg_escape(const char *p) {
1172         bool need_prefix = false;
1173
1174         /* This implements very minimal escaping for names to be used
1175          * as file names in the cgroup tree: any name which might
1176          * conflict with a kernel name or is prefixed with '_' is
1177          * prefixed with a '_'. That way, when reading cgroup names it
1178          * is sufficient to remove a single prefixing underscore if
1179          * there is one. */
1180
1181         /* The return value of this function (unlike cg_unescape())
1182          * needs free()! */
1183
1184         if (p[0] == 0 ||
1185             p[0] == '_' ||
1186             p[0] == '.' ||
1187             streq(p, "notify_on_release") ||
1188             streq(p, "release_agent") ||
1189             streq(p, "tasks"))
1190                 need_prefix = true;
1191         else {
1192                 const char *dot;
1193
1194                 dot = strrchr(p, '.');
1195                 if (dot) {
1196
1197                         if (dot - p == 6 && memcmp(p, "cgroup", 6) == 0)
1198                                 need_prefix = true;
1199                         else {
1200                                 char *n;
1201
1202                                 n = strndupa(p, dot - p);
1203
1204                                 if (check_hierarchy(n) >= 0)
1205                                         need_prefix = true;
1206                         }
1207                 }
1208         }
1209
1210         if (need_prefix)
1211                 return strappend("_", p);
1212         else
1213                 return strdup(p);
1214 }
1215
1216 char *cg_unescape(const char *p) {
1217         assert(p);
1218
1219         /* The return value of this function (unlike cg_escape())
1220          * doesn't need free()! */
1221
1222         if (p[0] == '_')
1223                 return (char*) p+1;
1224
1225         return (char*) p;
1226 }
1227
1228 #define CONTROLLER_VALID                        \
1229         DIGITS LETTERS                          \
1230         "_"
1231
1232 bool cg_controller_is_valid(const char *p, bool allow_named) {
1233         const char *t, *s;
1234
1235         if (!p)
1236                 return false;
1237
1238         if (allow_named) {
1239                 s = startswith(p, "name=");
1240                 if (s)
1241                         p = s;
1242         }
1243
1244         if (*p == 0 || *p == '_')
1245                 return false;
1246
1247         for (t = p; *t; t++)
1248                 if (!strchr(CONTROLLER_VALID, *t))
1249                         return false;
1250
1251         if (t - p > FILENAME_MAX)
1252                 return false;
1253
1254         return true;
1255 }
1256
1257 int cg_set_attribute(const char *controller, const char *path, const char *attribute, const char *value) {
1258         _cleanup_free_ char *p = NULL;
1259         int r;
1260
1261         r = cg_get_path(controller, path, attribute, &p);
1262         if (r < 0)
1263                 return r;
1264
1265         return write_string_file_no_create(p, value);
1266 }
1267
1268 int cg_get_attribute(const char *controller, const char *path, const char *attribute, char **ret) {
1269         _cleanup_free_ char *p = NULL;
1270         int r;
1271
1272         r = cg_get_path(controller, path, attribute, &p);
1273         if (r < 0)
1274                 return r;
1275
1276         return read_one_line_file(p, ret);
1277 }
1278
1279 static const char mask_names[] =
1280         "cpu\0"
1281         "cpuacct\0"
1282         "blkio\0"
1283         "memory\0"
1284         "devices\0";
1285
1286 int cg_create_everywhere(CGroupControllerMask supported, CGroupControllerMask mask, const char *path) {
1287         CGroupControllerMask bit = 1;
1288         const char *n;
1289         int r;
1290
1291         /* This one will create a cgroup in our private tree, but also
1292          * duplicate it in the trees specified in mask, and remove it
1293          * in all others */
1294
1295         /* First create the cgroup in our own hierarchy. */
1296         r = cg_create(SYSTEMD_CGROUP_CONTROLLER, path);
1297         if (r < 0)
1298                 return r;
1299
1300         /* Then, do the same in the other hierarchies */
1301         NULSTR_FOREACH(n, mask_names) {
1302                 if (mask & bit)
1303                         cg_create(n, path);
1304                 else if (supported & bit)
1305                         cg_trim(n, path, true);
1306
1307                 bit <<= 1;
1308         }
1309
1310         return 0;
1311 }
1312
1313 int cg_attach_everywhere(CGroupControllerMask supported, const char *path, pid_t pid, cg_migrate_callback_t path_callback, void *userdata) {
1314         CGroupControllerMask bit = 1;
1315         const char *n;
1316         int r;
1317
1318         r = cg_attach(SYSTEMD_CGROUP_CONTROLLER, path, pid);
1319         if (r < 0)
1320                 return r;
1321
1322         NULSTR_FOREACH(n, mask_names) {
1323
1324                 if (supported & bit) {
1325                         const char *p = NULL;
1326
1327                         if (path_callback)
1328                                 p = path_callback(bit, userdata);
1329
1330                         if (!p)
1331                                 p = path;
1332
1333                         cg_attach_fallback(n, path, pid);
1334                 }
1335
1336                 bit <<= 1;
1337         }
1338
1339         return 0;
1340 }
1341
1342 int cg_attach_many_everywhere(CGroupControllerMask supported, const char *path, Set* pids, cg_migrate_callback_t path_callback, void *userdata) {
1343         Iterator i;
1344         void *pidp;
1345         int r = 0;
1346
1347         SET_FOREACH(pidp, pids, i) {
1348                 pid_t pid = PTR_TO_LONG(pidp);
1349                 int q;
1350
1351                 q = cg_attach_everywhere(supported, path, pid, path_callback, userdata);
1352                 if (q < 0)
1353                         r = q;
1354         }
1355
1356         return r;
1357 }
1358
1359 int cg_migrate_everywhere(CGroupControllerMask supported, const char *from, const char *to, cg_migrate_callback_t to_callback, void *userdata) {
1360         CGroupControllerMask bit = 1;
1361         const char *n;
1362         int r;
1363
1364         if (!path_equal(from, to))  {
1365                 r = cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, from, SYSTEMD_CGROUP_CONTROLLER, to, false, true);
1366                 if (r < 0)
1367                         return r;
1368         }
1369
1370         NULSTR_FOREACH(n, mask_names) {
1371                 if (supported & bit) {
1372                         const char *p = NULL;
1373
1374                         if (to_callback)
1375                                 p = to_callback(bit, userdata);
1376
1377                         if (!p)
1378                                 p = to;
1379
1380                         cg_migrate_recursive_fallback(SYSTEMD_CGROUP_CONTROLLER, to, n, p, false, false);
1381                 }
1382
1383                 bit <<= 1;
1384         }
1385
1386         return 0;
1387 }
1388
1389 int cg_trim_everywhere(CGroupControllerMask supported, const char *path, bool delete_root) {
1390         CGroupControllerMask bit = 1;
1391         const char *n;
1392         int r;
1393
1394         r = cg_trim(SYSTEMD_CGROUP_CONTROLLER, path, delete_root);
1395         if (r < 0)
1396                 return r;
1397
1398         NULSTR_FOREACH(n, mask_names) {
1399                 if (supported & bit)
1400                         cg_trim(n, path, delete_root);
1401
1402                 bit <<= 1;
1403         }
1404
1405         return 0;
1406 }
1407
1408 CGroupControllerMask cg_mask_supported(void) {
1409         CGroupControllerMask bit = 1, mask = 0;
1410         const char *n;
1411
1412         NULSTR_FOREACH(n, mask_names) {
1413                 if (check_hierarchy(n) >= 0)
1414                         mask |= bit;
1415
1416                 bit <<= 1;
1417         }
1418
1419         return mask;
1420 }
1421
1422 int cg_kernel_controllers(Set *controllers) {
1423         _cleanup_fclose_ FILE *f = NULL;
1424         char buf[LINE_MAX];
1425         int r;
1426
1427         assert(controllers);
1428
1429         f = fopen("/proc/cgroups", "re");
1430         if (!f) {
1431                 if (errno == ENOENT)
1432                         return 0;
1433                 return -errno;
1434         }
1435
1436         /* Ignore the header line */
1437         (void) fgets(buf, sizeof(buf), f);
1438
1439         for (;;) {
1440                 char *controller;
1441                 int enabled = 0;
1442
1443                 errno = 0;
1444                 if (fscanf(f, "%ms %*i %*i %i", &controller, &enabled) != 2) {
1445
1446                         if (feof(f))
1447                                 break;
1448
1449                         if (ferror(f) && errno)
1450                                 return -errno;
1451
1452                         return -EBADMSG;
1453                 }
1454
1455                 if (!enabled) {
1456                         free(controller);
1457                         continue;
1458                 }
1459
1460                 if (!filename_is_valid(controller)) {
1461                         free(controller);
1462                         return -EBADMSG;
1463                 }
1464
1465                 r = set_consume(controllers, controller);
1466                 if (r < 0)
1467                         return r;
1468         }
1469
1470         return 0;
1471 }