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