chiark / gitweb /
dc0fe85ee22a3fb189253b1c2f044348bf453e2a
[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         u = strdup(e+1);
1007         if (!u) {
1008                 free(t);
1009                 return -ENOMEM;
1010         }
1011         if (!path_is_safe(u) ||
1012             !path_is_absolute(u)) {
1013                 free(t);
1014                 free(u);
1015                 return -EINVAL;
1016         }
1017
1018         path_kill_slashes(u);
1019
1020         if (controller)
1021                 *controller = t;
1022         else
1023                 free(t);
1024
1025         if (path)
1026                 *path = u;
1027         else
1028                 free(u);
1029
1030         return 0;
1031 }
1032
1033 int cg_join_spec(const char *controller, const char *path, char **spec) {
1034         char *s;
1035
1036         assert(path);
1037
1038         if (!controller)
1039                 controller = "systemd";
1040         else {
1041                 if (!cg_controller_is_valid(controller, true))
1042                         return -EINVAL;
1043
1044                 controller = normalize_controller(controller);
1045         }
1046
1047         if (!path_is_absolute(path))
1048                 return -EINVAL;
1049
1050         s = strjoin(controller, ":", path, NULL);
1051         if (!s)
1052                 return -ENOMEM;
1053
1054         path_kill_slashes(s + strlen(controller) + 1);
1055
1056         *spec = s;
1057         return 0;
1058 }
1059
1060 int cg_mangle_path(const char *path, char **result) {
1061         _cleanup_free_ char *c = NULL, *p = NULL;
1062         char *t;
1063         int r;
1064
1065         assert(path);
1066         assert(result);
1067
1068         /* First check if it already is a filesystem path */
1069         if (path_startswith(path, "/sys/fs/cgroup")) {
1070
1071                 t = strdup(path);
1072                 if (!t)
1073                         return -ENOMEM;
1074
1075                 path_kill_slashes(t);
1076                 *result = t;
1077                 return 0;
1078         }
1079
1080         /* Otherwise treat it as cg spec */
1081         r = cg_split_spec(path, &c, &p);
1082         if (r < 0)
1083                 return r;
1084
1085         return cg_get_path(c ? c : SYSTEMD_CGROUP_CONTROLLER, p ? p : "/", NULL, result);
1086 }
1087
1088 int cg_get_root_path(char **path) {
1089         char *p, *e;
1090         int r;
1091
1092         assert(path);
1093
1094         r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 1, &p);
1095         if (r < 0)
1096                 return r;
1097
1098         e = endswith(p, "/" SPECIAL_SYSTEM_SLICE);
1099         if (e)
1100                 *e = 0;
1101
1102         *path = p;
1103         return 0;
1104 }
1105
1106 char **cg_shorten_controllers(char **controllers) {
1107         char **f, **t;
1108
1109         if (!controllers)
1110                 return controllers;
1111
1112         for (f = controllers, t = controllers; *f; f++) {
1113                 const char *p;
1114                 int r;
1115
1116                 p = normalize_controller(*f);
1117
1118                 if (streq(p, "systemd")) {
1119                         free(*f);
1120                         continue;
1121                 }
1122
1123                 if (!cg_controller_is_valid(p, true)) {
1124                         log_warning("Controller %s is not valid, removing from controllers list.", p);
1125                         free(*f);
1126                         continue;
1127                 }
1128
1129                 r = check_hierarchy(p);
1130                 if (r < 0) {
1131                         log_debug("Controller %s is not available, removing from controllers list.", p);
1132                         free(*f);
1133                         continue;
1134                 }
1135
1136                 *(t++) = *f;
1137         }
1138
1139         *t = NULL;
1140         return strv_uniq(controllers);
1141 }
1142
1143 int cg_pid_get_path_shifted(pid_t pid, char **root, char **cgroup) {
1144         _cleanup_free_ char *cg_root = NULL;
1145         char *cg_process, *p;
1146         int r;
1147
1148         r = cg_get_root_path(&cg_root);
1149         if (r < 0)
1150                 return r;
1151
1152         r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cg_process);
1153         if (r < 0)
1154                 return r;
1155
1156         p = path_startswith(cg_process, cg_root);
1157         if (p)
1158                 p--;
1159         else
1160                 p = cg_process;
1161
1162         if (cgroup) {
1163                 char* c;
1164
1165                 c = strdup(p);
1166                 if (!c) {
1167                         free(cg_process);
1168                         return -ENOMEM;
1169                 }
1170
1171                 *cgroup = c;
1172         }
1173
1174         if (root) {
1175                 cg_process[p-cg_process] = 0;
1176                 *root = cg_process;
1177         } else
1178                 free(cg_process);
1179
1180         return 0;
1181 }
1182
1183 int cg_path_decode_unit(const char *cgroup, char **unit){
1184         char *e, *c, *s;
1185
1186         assert(cgroup);
1187         assert(unit);
1188
1189         e = strchrnul(cgroup, '/');
1190         c = strndupa(cgroup, e - cgroup);
1191         c = cg_unescape(c);
1192
1193         if (!unit_name_is_valid(c, false))
1194                 return -EINVAL;
1195
1196         s = strdup(c);
1197         if (!s)
1198                 return -ENOMEM;
1199
1200         *unit = s;
1201         return 0;
1202 }
1203
1204 static const char *skip_slices(const char *p) {
1205         /* Skips over all slice assignments */
1206
1207         for (;;) {
1208                 size_t n;
1209
1210                 p += strspn(p, "/");
1211
1212                 n = strcspn(p, "/");
1213                 if (n <= 6 || memcmp(p + n - 6, ".slice", 6) != 0)
1214                         return p;
1215
1216                 p += n;
1217         }
1218 }
1219
1220 int cg_path_get_unit(const char *path, char **unit) {
1221         const char *e;
1222
1223         assert(path);
1224         assert(unit);
1225
1226         e = skip_slices(path);
1227
1228         return cg_path_decode_unit(e, unit);
1229 }
1230
1231 int cg_pid_get_unit(pid_t pid, char **unit) {
1232         _cleanup_free_ char *cgroup = NULL;
1233         int r;
1234
1235         assert(unit);
1236
1237         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1238         if (r < 0)
1239                 return r;
1240
1241         return cg_path_get_unit(cgroup, unit);
1242 }
1243
1244 static const char *skip_session(const char *p) {
1245         size_t n;
1246
1247         assert(p);
1248
1249         p += strspn(p, "/");
1250
1251         n = strcspn(p, "/");
1252         if (n <= 12 || memcmp(p, "session-", 8) != 0 || memcmp(p + n - 6, ".scope", 6) != 0)
1253                 return NULL;
1254
1255         p += n;
1256         p += strspn(p, "/");
1257
1258         return p;
1259 }
1260
1261 int cg_path_get_user_unit(const char *path, char **unit) {
1262         const char *e;
1263
1264         assert(path);
1265         assert(unit);
1266
1267         /* We always have to parse the path from the beginning as unit
1268          * cgroups might have arbitrary child cgroups and we shouldn't get
1269          * confused by those */
1270
1271         /* Skip slices, if there are any */
1272         e = skip_slices(path);
1273
1274         /* Skip the session scope, require that there is one */
1275         e = skip_session(e);
1276         if (!e)
1277                 return -ENOENT;
1278
1279         /* And skip more slices */
1280         e = skip_slices(e);
1281
1282         return cg_path_decode_unit(e, unit);
1283 }
1284
1285 int cg_pid_get_user_unit(pid_t pid, char **unit) {
1286         _cleanup_free_ char *cgroup = NULL;
1287         int r;
1288
1289         assert(unit);
1290
1291         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1292         if (r < 0)
1293                 return r;
1294
1295         return cg_path_get_user_unit(cgroup, unit);
1296 }
1297
1298 int cg_path_get_machine_name(const char *path, char **machine) {
1299         const char *e, *n, *x;
1300         char *s, *r;
1301         size_t l;
1302
1303         assert(path);
1304         assert(machine);
1305
1306         /* Skip slices, if there are any */
1307         e = skip_slices(path);
1308
1309         n = strchrnul(e, '/');
1310         if (e == n)
1311                 return -ENOENT;
1312
1313         s = strndupa(e, n - e);
1314         s = cg_unescape(s);
1315
1316         x = startswith(s, "machine-");
1317         if (!x)
1318                 return -ENOENT;
1319         if (!endswith(x, ".scope"))
1320                 return -ENOENT;
1321
1322         l = strlen(x);
1323         if (l <= 6)
1324                 return -ENOENT;
1325
1326         r = strndup(x, l - 6);
1327         if (!r)
1328                 return -ENOMEM;
1329
1330         *machine = r;
1331         return 0;
1332 }
1333
1334 int cg_pid_get_machine_name(pid_t pid, char **machine) {
1335         _cleanup_free_ char *cgroup = NULL;
1336         int r;
1337
1338         assert(machine);
1339
1340         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1341         if (r < 0)
1342                 return r;
1343
1344         return cg_path_get_machine_name(cgroup, machine);
1345 }
1346
1347 int cg_path_get_session(const char *path, char **session) {
1348         const char *e, *n, *x;
1349         char *s, *r;
1350         size_t l;
1351
1352         assert(path);
1353         assert(session);
1354
1355         /* Skip slices, if there are any */
1356         e = skip_slices(path);
1357
1358         n = strchrnul(e, '/');
1359         if (e == n)
1360                 return -ENOENT;
1361
1362         s = strndupa(e, n - e);
1363         s = cg_unescape(s);
1364
1365         x = startswith(s, "session-");
1366         if (!x)
1367                 return -ENOENT;
1368         if (!endswith(x, ".scope"))
1369                 return -ENOENT;
1370
1371         l = strlen(x);
1372         if (l <= 6)
1373                 return -ENOENT;
1374
1375         r = strndup(x, l - 6);
1376         if (!r)
1377                 return -ENOMEM;
1378
1379         *session = r;
1380         return 0;
1381 }
1382
1383 int cg_pid_get_session(pid_t pid, char **session) {
1384         _cleanup_free_ char *cgroup = NULL;
1385         int r;
1386
1387         assert(session);
1388
1389         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1390         if (r < 0)
1391                 return r;
1392
1393         return cg_path_get_session(cgroup, session);
1394 }
1395
1396 int cg_path_get_owner_uid(const char *path, uid_t *uid) {
1397         _cleanup_free_ char *slice = NULL;
1398         const char *e;
1399         char *s;
1400         int r;
1401
1402         assert(path);
1403         assert(uid);
1404
1405         r = cg_path_get_slice(path, &slice);
1406         if (r < 0)
1407                 return r;
1408
1409         e = startswith(slice, "user-");
1410         if (!e)
1411                 return -ENOENT;
1412         if (!endswith(slice, ".slice"))
1413                 return -ENOENT;
1414
1415         s = strndupa(e, strlen(e) - 6);
1416         if (!s)
1417                 return -ENOMEM;
1418
1419         return parse_uid(s, uid);
1420 }
1421
1422 int cg_pid_get_owner_uid(pid_t pid, uid_t *uid) {
1423         _cleanup_free_ char *cgroup = NULL;
1424         int r;
1425
1426         assert(uid);
1427
1428         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1429         if (r < 0)
1430                 return r;
1431
1432         return cg_path_get_owner_uid(cgroup, uid);
1433 }
1434
1435 int cg_path_get_slice(const char *p, char **slice) {
1436         const char *e = NULL;
1437         size_t m = 0;
1438
1439         assert(p);
1440         assert(slice);
1441
1442         for (;;) {
1443                 size_t n;
1444
1445                 p += strspn(p, "/");
1446
1447                 n = strcspn(p, "/");
1448                 if (n <= 6 || memcmp(p + n - 6, ".slice", 6) != 0) {
1449                         char *s;
1450
1451                         if (!e)
1452                                 return -ENOENT;
1453
1454                         s = strndup(e, m);
1455                         if (!s)
1456                                 return -ENOMEM;
1457
1458                         *slice = s;
1459                         return 0;
1460                 }
1461
1462                 e = p;
1463                 m = n;
1464
1465                 p += n;
1466         }
1467 }
1468
1469 int cg_pid_get_slice(pid_t pid, char **slice) {
1470         _cleanup_free_ char *cgroup = NULL;
1471         int r;
1472
1473         assert(slice);
1474
1475         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1476         if (r < 0)
1477                 return r;
1478
1479         return cg_path_get_slice(cgroup, slice);
1480 }
1481
1482 int cg_controller_from_attr(const char *attr, char **controller) {
1483         const char *dot;
1484         char *c;
1485
1486         assert(attr);
1487         assert(controller);
1488
1489         if (!filename_is_safe(attr))
1490                 return -EINVAL;
1491
1492         dot = strchr(attr, '.');
1493         if (!dot) {
1494                 *controller = NULL;
1495                 return 0;
1496         }
1497
1498         c = strndup(attr, dot - attr);
1499         if (!c)
1500                 return -ENOMEM;
1501
1502         if (!cg_controller_is_valid(c, false)) {
1503                 free(c);
1504                 return -EINVAL;
1505         }
1506
1507         *controller = c;
1508         return 1;
1509 }
1510
1511 char *cg_escape(const char *p) {
1512         bool need_prefix = false;
1513
1514         /* This implements very minimal escaping for names to be used
1515          * as file names in the cgroup tree: any name which might
1516          * conflict with a kernel name or is prefixed with '_' is
1517          * prefixed with a '_'. That way, when reading cgroup names it
1518          * is sufficient to remove a single prefixing underscore if
1519          * there is one. */
1520
1521         /* The return value of this function (unlike cg_unescape())
1522          * needs free()! */
1523
1524         if (p[0] == 0 ||
1525             p[0] == '_' ||
1526             p[0] == '.' ||
1527             streq(p, "notify_on_release") ||
1528             streq(p, "release_agent") ||
1529             streq(p, "tasks"))
1530                 need_prefix = true;
1531         else {
1532                 const char *dot;
1533
1534                 dot = strrchr(p, '.');
1535                 if (dot) {
1536
1537                         if (dot - p == 6 && memcmp(p, "cgroup", 6) == 0)
1538                                 need_prefix = true;
1539                         else {
1540                                 char *n;
1541
1542                                 n = strndupa(p, dot - p);
1543
1544                                 if (check_hierarchy(n) >= 0)
1545                                         need_prefix = true;
1546                         }
1547                 }
1548         }
1549
1550         if (need_prefix)
1551                 return strappend("_", p);
1552         else
1553                 return strdup(p);
1554 }
1555
1556 char *cg_unescape(const char *p) {
1557         assert(p);
1558
1559         /* The return value of this function (unlike cg_escape())
1560          * doesn't need free()! */
1561
1562         if (p[0] == '_')
1563                 return (char*) p+1;
1564
1565         return (char*) p;
1566 }
1567
1568 #define CONTROLLER_VALID                        \
1569         DIGITS LETTERS                          \
1570         "_"
1571
1572 bool cg_controller_is_valid(const char *p, bool allow_named) {
1573         const char *t, *s;
1574
1575         if (!p)
1576                 return false;
1577
1578         if (allow_named) {
1579                 s = startswith(p, "name=");
1580                 if (s)
1581                         p = s;
1582         }
1583
1584         if (*p == 0 || *p == '_')
1585                 return false;
1586
1587         for (t = p; *t; t++)
1588                 if (!strchr(CONTROLLER_VALID, *t))
1589                         return false;
1590
1591         if (t - p > FILENAME_MAX)
1592                 return false;
1593
1594         return true;
1595 }
1596
1597 int cg_slice_to_path(const char *unit, char **ret) {
1598         _cleanup_free_ char *p = NULL, *s = NULL, *e = NULL;
1599         const char *dash;
1600
1601         assert(unit);
1602         assert(ret);
1603
1604         if (!unit_name_is_valid(unit, false))
1605                 return -EINVAL;
1606
1607         if (!endswith(unit, ".slice"))
1608                 return -EINVAL;
1609
1610         p = unit_name_to_prefix(unit);
1611         if (!p)
1612                 return -ENOMEM;
1613
1614         dash = strchr(p, '-');
1615         while (dash) {
1616                 _cleanup_free_ char *escaped = NULL;
1617                 char n[dash - p + sizeof(".slice")];
1618
1619                 strcpy(stpncpy(n, p, dash - p), ".slice");
1620
1621                 if (!unit_name_is_valid(n, false))
1622                         return -EINVAL;
1623
1624                 escaped = cg_escape(n);
1625                 if (!escaped)
1626                         return -ENOMEM;
1627
1628                 if (!strextend(&s, escaped, "/", NULL))
1629                         return -ENOMEM;
1630
1631                 dash = strchr(dash+1, '-');
1632         }
1633
1634         e = cg_escape(unit);
1635         if (!e)
1636                 return -ENOMEM;
1637
1638         if (!strextend(&s, e, NULL))
1639                 return -ENOMEM;
1640
1641         *ret = s;
1642         s = NULL;
1643
1644         return 0;
1645 }
1646
1647 int cg_set_attribute(const char *controller, const char *path, const char *attribute, const char *value) {
1648         _cleanup_free_ char *p = NULL;
1649         int r;
1650
1651         r = cg_get_path(controller, path, attribute, &p);
1652         if (r < 0)
1653                 return r;
1654
1655         return write_string_file(p, value);
1656 }
1657
1658 static const char mask_names[] =
1659         "cpu\0"
1660         "cpuacct\0"
1661         "blkio\0"
1662         "memory\0"
1663         "devices\0";
1664
1665 int cg_create_everywhere(CGroupControllerMask supported, CGroupControllerMask mask, const char *path) {
1666         CGroupControllerMask bit = 1;
1667         const char *n;
1668         int r;
1669
1670         /* This one will create a cgroup in our private tree, but also
1671          * duplicate it in the trees specified in mask, and remove it
1672          * in all others */
1673
1674         /* First create the cgroup in our own hierarchy. */
1675         r = cg_create(SYSTEMD_CGROUP_CONTROLLER, path);
1676         if (r < 0)
1677                 return r;
1678
1679         /* Then, do the same in the other hierarchies */
1680         NULSTR_FOREACH(n, mask_names) {
1681                 if (mask & bit)
1682                         cg_create(n, path);
1683                 else if (supported & bit)
1684                         cg_trim(n, path, true);
1685
1686                 bit <<= 1;
1687         }
1688
1689         return 0;
1690 }
1691
1692 int cg_attach_everywhere(CGroupControllerMask supported, const char *path, pid_t pid) {
1693         CGroupControllerMask bit = 1;
1694         const char *n;
1695         int r;
1696
1697         r = cg_attach(SYSTEMD_CGROUP_CONTROLLER, path, pid);
1698         if (r < 0)
1699                 return r;
1700
1701         NULSTR_FOREACH(n, mask_names) {
1702                 if (supported & bit)
1703                         cg_attach_fallback(n, path, pid);
1704
1705                 bit <<= 1;
1706         }
1707
1708         return 0;
1709 }
1710
1711 int cg_attach_many_everywhere(CGroupControllerMask supported, const char *path, Set* pids) {
1712         Iterator i;
1713         void *pidp;
1714         int r = 0;
1715
1716         SET_FOREACH(pidp, pids, i) {
1717                 pid_t pid = PTR_TO_LONG(pidp);
1718                 int q;
1719
1720                 q = cg_attach_everywhere(supported, path, pid);
1721                 if (q < 0)
1722                         r = q;
1723         }
1724
1725         return r;
1726 }
1727
1728 int cg_migrate_everywhere(CGroupControllerMask supported, const char *from, const char *to) {
1729         CGroupControllerMask bit = 1;
1730         const char *n;
1731         int r;
1732
1733         if (!path_equal(from, to))  {
1734                 r = cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, from, SYSTEMD_CGROUP_CONTROLLER, to, false, true);
1735                 if (r < 0)
1736                         return r;
1737         }
1738
1739         NULSTR_FOREACH(n, mask_names) {
1740                 if (supported & bit)
1741                         cg_migrate_recursive_fallback(SYSTEMD_CGROUP_CONTROLLER, to, n, to, false, false);
1742
1743                 bit <<= 1;
1744         }
1745
1746         return 0;
1747 }
1748
1749 int cg_trim_everywhere(CGroupControllerMask supported, const char *path, bool delete_root) {
1750         CGroupControllerMask bit = 1;
1751         const char *n;
1752         int r;
1753
1754         r = cg_trim(SYSTEMD_CGROUP_CONTROLLER, path, delete_root);
1755         if (r < 0)
1756                 return r;
1757
1758         NULSTR_FOREACH(n, mask_names) {
1759                 if (supported & bit)
1760                         cg_trim(n, path, delete_root);
1761
1762                 bit <<= 1;
1763         }
1764
1765         return 0;
1766 }
1767
1768 CGroupControllerMask cg_mask_supported(void) {
1769         CGroupControllerMask bit = 1, mask = 0;
1770         const char *n;
1771
1772         NULSTR_FOREACH(n, mask_names) {
1773                 if (check_hierarchy(n) >= 0)
1774                         mask |= bit;
1775
1776                 bit <<= 1;
1777         }
1778
1779         return mask;
1780 }