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