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