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