chiark / gitweb /
disable the cgroups release agent when shutting down
[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, "release_agent", &fs);
798         if (r < 0)
799                 return r;
800
801         r = write_string_file(fs, "");
802         if (r < 0)
803                 return r;
804
805         return 0;
806 }
807
808 int cg_is_empty(const char *controller, const char *path, bool ignore_self) {
809         _cleanup_fclose_ FILE *f = NULL;
810         pid_t pid = 0, self_pid;
811         bool found = false;
812         int r;
813
814         assert(path);
815
816         r = cg_enumerate_processes(controller, path, &f);
817         if (r < 0)
818                 return r == -ENOENT ? 1 : r;
819
820         self_pid = getpid();
821
822         while ((r = cg_read_pid(f, &pid)) > 0) {
823
824                 if (ignore_self && pid == self_pid)
825                         continue;
826
827                 found = true;
828                 break;
829         }
830
831         if (r < 0)
832                 return r;
833
834         return !found;
835 }
836
837 int cg_is_empty_by_spec(const char *spec, bool ignore_self) {
838         _cleanup_free_ char *controller = NULL, *path = NULL;
839         int r;
840
841         assert(spec);
842
843         r = cg_split_spec(spec, &controller, &path);
844         if (r < 0)
845                 return r;
846
847         return cg_is_empty(controller, path, ignore_self);
848 }
849
850 int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_self) {
851         _cleanup_closedir_ DIR *d = NULL;
852         char *fn;
853         int r;
854
855         assert(path);
856
857         r = cg_is_empty(controller, path, ignore_self);
858         if (r <= 0)
859                 return r;
860
861         r = cg_enumerate_subgroups(controller, path, &d);
862         if (r < 0)
863                 return r == -ENOENT ? 1 : r;
864
865         while ((r = cg_read_subgroup(d, &fn)) > 0) {
866                 _cleanup_free_ char *p = NULL;
867
868                 p = strjoin(path, "/", fn, NULL);
869                 free(fn);
870                 if (!p)
871                         return -ENOMEM;
872
873                 r = cg_is_empty_recursive(controller, p, ignore_self);
874                 if (r <= 0)
875                         return r;
876         }
877
878         if (r < 0)
879                 return r;
880
881         return 1;
882 }
883
884 int cg_split_spec(const char *spec, char **controller, char **path) {
885         const char *e;
886         char *t = NULL, *u = NULL;
887         _cleanup_free_ char *v = NULL;
888
889         assert(spec);
890
891         if (*spec == '/') {
892                 if (!path_is_safe(spec))
893                         return -EINVAL;
894
895                 if (path) {
896                         t = strdup(spec);
897                         if (!t)
898                                 return -ENOMEM;
899
900                         path_kill_slashes(t);
901                         *path = t;
902                 }
903
904                 if (controller)
905                         *controller = NULL;
906
907                 return 0;
908         }
909
910         e = strchr(spec, ':');
911         if (!e) {
912                 if (!cg_controller_is_valid(spec, true))
913                         return -EINVAL;
914
915                 if (controller) {
916                         t = strdup(normalize_controller(spec));
917                         if (!t)
918                                 return -ENOMEM;
919
920                         *controller = t;
921                 }
922
923                 if (path)
924                         *path = NULL;
925
926                 return 0;
927         }
928
929         v = strndup(spec, e-spec);
930         if (!v)
931                 return -ENOMEM;
932         t = strdup(normalize_controller(v));
933         if (!t)
934                 return -ENOMEM;
935         if (!cg_controller_is_valid(t, true)) {
936                 free(t);
937                 return -EINVAL;
938         }
939
940         u = strdup(e+1);
941         if (!u) {
942                 free(t);
943                 return -ENOMEM;
944         }
945         if (!path_is_safe(u) ||
946             !path_is_absolute(u)) {
947                 free(t);
948                 free(u);
949                 return -EINVAL;
950         }
951
952         path_kill_slashes(u);
953
954         if (controller)
955                 *controller = t;
956         else
957                 free(t);
958
959         if (path)
960                 *path = u;
961         else
962                 free(u);
963
964         return 0;
965 }
966
967 int cg_join_spec(const char *controller, const char *path, char **spec) {
968         char *s;
969
970         assert(path);
971
972         if (!controller)
973                 controller = "systemd";
974         else {
975                 if (!cg_controller_is_valid(controller, true))
976                         return -EINVAL;
977
978                 controller = normalize_controller(controller);
979         }
980
981         if (!path_is_absolute(path))
982                 return -EINVAL;
983
984         s = strjoin(controller, ":", path, NULL);
985         if (!s)
986                 return -ENOMEM;
987
988         path_kill_slashes(s + strlen(controller) + 1);
989
990         *spec = s;
991         return 0;
992 }
993
994 int cg_mangle_path(const char *path, char **result) {
995         _cleanup_free_ char *c = NULL, *p = NULL;
996         char *t;
997         int r;
998
999         assert(path);
1000         assert(result);
1001
1002         /* First check if it already is a filesystem path */
1003         if (path_startswith(path, "/sys/fs/cgroup")) {
1004
1005                 t = strdup(path);
1006                 if (!t)
1007                         return -ENOMEM;
1008
1009                 path_kill_slashes(t);
1010                 *result = t;
1011                 return 0;
1012         }
1013
1014         /* Otherwise treat it as cg spec */
1015         r = cg_split_spec(path, &c, &p);
1016         if (r < 0)
1017                 return r;
1018
1019         return cg_get_path(c ? c : SYSTEMD_CGROUP_CONTROLLER, p ? p : "/", NULL, result);
1020 }
1021
1022 int cg_get_root_path(char **path) {
1023         char *p, *e;
1024         int r;
1025
1026         assert(path);
1027
1028         r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 1, &p);
1029         if (r < 0)
1030                 return r;
1031
1032         e = endswith(p, "/" SPECIAL_SYSTEM_SLICE);
1033         if (e)
1034                 *e = 0;
1035
1036         *path = p;
1037         return 0;
1038 }
1039
1040 char **cg_shorten_controllers(char **controllers) {
1041         char **f, **t;
1042
1043         if (!controllers)
1044                 return controllers;
1045
1046         for (f = controllers, t = controllers; *f; f++) {
1047                 const char *p;
1048                 int r;
1049
1050                 p = normalize_controller(*f);
1051
1052                 if (streq(p, "systemd")) {
1053                         free(*f);
1054                         continue;
1055                 }
1056
1057                 if (!cg_controller_is_valid(p, true)) {
1058                         log_warning("Controller %s is not valid, removing from controllers list.", p);
1059                         free(*f);
1060                         continue;
1061                 }
1062
1063                 r = check_hierarchy(p);
1064                 if (r < 0) {
1065                         log_debug("Controller %s is not available, removing from controllers list.", p);
1066                         free(*f);
1067                         continue;
1068                 }
1069
1070                 *(t++) = *f;
1071         }
1072
1073         *t = NULL;
1074         return strv_uniq(controllers);
1075 }
1076
1077 int cg_pid_get_path_shifted(pid_t pid, char **root, char **cgroup) {
1078         _cleanup_free_ char *cg_root = NULL;
1079         char *cg_process, *p;
1080         int r;
1081
1082         r = cg_get_root_path(&cg_root);
1083         if (r < 0)
1084                 return r;
1085
1086         r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cg_process);
1087         if (r < 0)
1088                 return r;
1089
1090         p = path_startswith(cg_process, cg_root);
1091         if (p)
1092                 p--;
1093         else
1094                 p = cg_process;
1095
1096         if (cgroup) {
1097                 char* c;
1098
1099                 c = strdup(p);
1100                 if (!c) {
1101                         free(cg_process);
1102                         return -ENOMEM;
1103                 }
1104
1105                 *cgroup = c;
1106         }
1107
1108         if (root) {
1109                 cg_process[p-cg_process] = 0;
1110                 *root = cg_process;
1111         } else
1112                 free(cg_process);
1113
1114         return 0;
1115 }
1116
1117 int cg_path_decode_unit(const char *cgroup, char **unit){
1118         char *p, *e, *c, *s, *k;
1119
1120         assert(cgroup);
1121         assert(unit);
1122
1123         e = strchrnul(cgroup, '/');
1124         c = strndupa(cgroup, e - cgroup);
1125         c = cg_unescape(c);
1126
1127         /* Could this be a valid unit name? */
1128         if (!unit_name_is_valid(c, true))
1129                 return -EINVAL;
1130
1131         if (!unit_name_is_template(c))
1132                 s = strdup(c);
1133         else {
1134                 if (*e != '/')
1135                         return -EINVAL;
1136
1137                 e += strspn(e, "/");
1138
1139                 p = strchrnul(e, '/');
1140                 k = strndupa(e, p - e);
1141                 k = cg_unescape(k);
1142
1143                 if (!unit_name_is_valid(k, false))
1144                         return -EINVAL;
1145
1146                 s = strdup(k);
1147         }
1148
1149         if (!s)
1150                 return -ENOMEM;
1151
1152         *unit = s;
1153         return 0;
1154 }
1155
1156 static const char *skip_slices(const char *p) {
1157         /* Skips over all slice assignments */
1158
1159         for (;;) {
1160                 size_t n;
1161
1162                 p += strspn(p, "/");
1163
1164                 n = strcspn(p, "/");
1165                 if (n <= 6 || memcmp(p + n - 6, ".slice", 6) != 0)
1166                         return p;
1167
1168                 p += n;
1169         }
1170 }
1171
1172 int cg_path_get_unit(const char *path, char **unit) {
1173         const char *e;
1174
1175         assert(path);
1176         assert(unit);
1177
1178         e = skip_slices(path);
1179
1180         return cg_path_decode_unit(e, unit);
1181 }
1182
1183 int cg_pid_get_unit(pid_t pid, char **unit) {
1184         _cleanup_free_ char *cgroup = NULL;
1185         int r;
1186
1187         assert(unit);
1188
1189         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1190         if (r < 0)
1191                 return r;
1192
1193         return cg_path_get_unit(cgroup, unit);
1194 }
1195
1196 static const char *skip_session(const char *p) {
1197         size_t n;
1198
1199         assert(p);
1200
1201         p += strspn(p, "/");
1202
1203         n = strcspn(p, "/");
1204         if (n <= 12 || memcmp(p, "session-", 8) != 0 || memcmp(p + n - 6, ".scope", 6) != 0)
1205                 return NULL;
1206
1207         p += n;
1208         p += strspn(p, "/");
1209
1210         return p;
1211 }
1212
1213 int cg_path_get_user_unit(const char *path, char **unit) {
1214         const char *e;
1215
1216         assert(path);
1217         assert(unit);
1218
1219         /* We always have to parse the path from the beginning as unit
1220          * cgroups might have arbitrary child cgroups and we shouldn't get
1221          * confused by those */
1222
1223         /* Skip slices, if there are any */
1224         e = skip_slices(path);
1225
1226         /* Skip the session scope, require that there is one */
1227         e = skip_session(e);
1228         if (!e)
1229                 return -ENOENT;
1230
1231         /* And skip more slices */
1232         e = skip_slices(e);
1233
1234         return cg_path_decode_unit(e, unit);
1235 }
1236
1237 int cg_pid_get_user_unit(pid_t pid, char **unit) {
1238         _cleanup_free_ char *cgroup = NULL;
1239         int r;
1240
1241         assert(unit);
1242
1243         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1244         if (r < 0)
1245                 return r;
1246
1247         return cg_path_get_user_unit(cgroup, unit);
1248 }
1249
1250 int cg_path_get_machine_name(const char *path, char **machine) {
1251         const char *e, *n, *x;
1252         char *s, *r;
1253         size_t l;
1254
1255         assert(path);
1256         assert(machine);
1257
1258         /* Skip slices, if there are any */
1259         e = skip_slices(path);
1260
1261         n = strchrnul(e, '/');
1262         if (e == n)
1263                 return -ENOENT;
1264
1265         s = strndupa(e, n - e);
1266         s = cg_unescape(s);
1267
1268         x = startswith(s, "machine-");
1269         if (!x)
1270                 return -ENOENT;
1271         if (!endswith(x, ".scope"))
1272                 return -ENOENT;
1273
1274         l = strlen(x);
1275         if (l <= 6)
1276                 return -ENOENT;
1277
1278         r = strndup(x, l - 6);
1279         if (!r)
1280                 return -ENOMEM;
1281
1282         *machine = r;
1283         return 0;
1284 }
1285
1286 int cg_pid_get_machine_name(pid_t pid, char **machine) {
1287         _cleanup_free_ char *cgroup = NULL;
1288         int r;
1289
1290         assert(machine);
1291
1292         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1293         if (r < 0)
1294                 return r;
1295
1296         return cg_path_get_machine_name(cgroup, machine);
1297 }
1298
1299 int cg_path_get_session(const char *path, char **session) {
1300         const char *e, *n, *x;
1301         char *s, *r;
1302         size_t l;
1303
1304         assert(path);
1305         assert(session);
1306
1307         /* Skip slices, if there are any */
1308         e = skip_slices(path);
1309
1310         n = strchrnul(e, '/');
1311         if (e == n)
1312                 return -ENOENT;
1313
1314         s = strndupa(e, n - e);
1315         s = cg_unescape(s);
1316
1317         x = startswith(s, "session-");
1318         if (!x)
1319                 return -ENOENT;
1320         if (!endswith(x, ".scope"))
1321                 return -ENOENT;
1322
1323         l = strlen(x);
1324         if (l <= 6)
1325                 return -ENOENT;
1326
1327         r = strndup(x, l - 6);
1328         if (!r)
1329                 return -ENOMEM;
1330
1331         *session = r;
1332         return 0;
1333 }
1334
1335 int cg_pid_get_session(pid_t pid, char **session) {
1336         _cleanup_free_ char *cgroup = NULL;
1337         int r;
1338
1339         assert(session);
1340
1341         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1342         if (r < 0)
1343                 return r;
1344
1345         return cg_path_get_session(cgroup, session);
1346 }
1347
1348 int cg_path_get_owner_uid(const char *path, uid_t *uid) {
1349         _cleanup_free_ char *slice = NULL;
1350         const char *e;
1351         char *s;
1352         int r;
1353
1354         assert(path);
1355         assert(uid);
1356
1357         r = cg_path_get_slice(path, &slice);
1358         if (r < 0)
1359                 return r;
1360
1361         e = startswith(slice, "user-");
1362         if (!e)
1363                 return -ENOENT;
1364         if (!endswith(slice, ".slice"))
1365                 return -ENOENT;
1366
1367         s = strndupa(e, strlen(e) - 6);
1368         if (!s)
1369                 return -ENOMEM;
1370
1371         return parse_uid(s, uid);
1372 }
1373
1374 int cg_pid_get_owner_uid(pid_t pid, uid_t *uid) {
1375         _cleanup_free_ char *cgroup = NULL;
1376         int r;
1377
1378         assert(uid);
1379
1380         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1381         if (r < 0)
1382                 return r;
1383
1384         return cg_path_get_owner_uid(cgroup, uid);
1385 }
1386
1387 int cg_path_get_slice(const char *p, char **slice) {
1388         const char *e = NULL;
1389         size_t m = 0;
1390
1391         assert(p);
1392         assert(slice);
1393
1394         for (;;) {
1395                 size_t n;
1396
1397                 p += strspn(p, "/");
1398
1399                 n = strcspn(p, "/");
1400                 if (n <= 6 || memcmp(p + n - 6, ".slice", 6) != 0) {
1401                         char *s;
1402
1403                         if (!e)
1404                                 return -ENOENT;
1405
1406                         s = strndup(e, m);
1407                         if (!s)
1408                                 return -ENOMEM;
1409
1410                         *slice = s;
1411                         return 0;
1412                 }
1413
1414                 e = p;
1415                 m = n;
1416
1417                 p += n;
1418         }
1419 }
1420
1421 int cg_pid_get_slice(pid_t pid, char **slice) {
1422         _cleanup_free_ char *cgroup = NULL;
1423         int r;
1424
1425         assert(slice);
1426
1427         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1428         if (r < 0)
1429                 return r;
1430
1431         return cg_path_get_slice(cgroup, slice);
1432 }
1433
1434 int cg_controller_from_attr(const char *attr, char **controller) {
1435         const char *dot;
1436         char *c;
1437
1438         assert(attr);
1439         assert(controller);
1440
1441         if (!filename_is_safe(attr))
1442                 return -EINVAL;
1443
1444         dot = strchr(attr, '.');
1445         if (!dot) {
1446                 *controller = NULL;
1447                 return 0;
1448         }
1449
1450         c = strndup(attr, dot - attr);
1451         if (!c)
1452                 return -ENOMEM;
1453
1454         if (!cg_controller_is_valid(c, false)) {
1455                 free(c);
1456                 return -EINVAL;
1457         }
1458
1459         *controller = c;
1460         return 1;
1461 }
1462
1463 char *cg_escape(const char *p) {
1464         bool need_prefix = false;
1465
1466         /* This implements very minimal escaping for names to be used
1467          * as file names in the cgroup tree: any name which might
1468          * conflict with a kernel name or is prefixed with '_' is
1469          * prefixed with a '_'. That way, when reading cgroup names it
1470          * is sufficient to remove a single prefixing underscore if
1471          * there is one. */
1472
1473         /* The return value of this function (unlike cg_unescape())
1474          * needs free()! */
1475
1476         if (p[0] == 0 ||
1477             p[0] == '_' ||
1478             p[0] == '.' ||
1479             streq(p, "notify_on_release") ||
1480             streq(p, "release_agent") ||
1481             streq(p, "tasks"))
1482                 need_prefix = true;
1483         else {
1484                 const char *dot;
1485
1486                 dot = strrchr(p, '.');
1487                 if (dot) {
1488
1489                         if (dot - p == 6 && memcmp(p, "cgroup", 6) == 0)
1490                                 need_prefix = true;
1491                         else {
1492                                 char *n;
1493
1494                                 n = strndupa(p, dot - p);
1495
1496                                 if (check_hierarchy(n) >= 0)
1497                                         need_prefix = true;
1498                         }
1499                 }
1500         }
1501
1502         if (need_prefix)
1503                 return strappend("_", p);
1504         else
1505                 return strdup(p);
1506 }
1507
1508 char *cg_unescape(const char *p) {
1509         assert(p);
1510
1511         /* The return value of this function (unlike cg_escape())
1512          * doesn't need free()! */
1513
1514         if (p[0] == '_')
1515                 return (char*) p+1;
1516
1517         return (char*) p;
1518 }
1519
1520 #define CONTROLLER_VALID                        \
1521         "0123456789"                            \
1522         "abcdefghijklmnopqrstuvwxyz"            \
1523         "ABCDEFGHIJKLMNOPQRSTUVWXYZ"            \
1524         "_"
1525
1526 bool cg_controller_is_valid(const char *p, bool allow_named) {
1527         const char *t, *s;
1528
1529         if (!p)
1530                 return false;
1531
1532         if (allow_named) {
1533                 s = startswith(p, "name=");
1534                 if (s)
1535                         p = s;
1536         }
1537
1538         if (*p == 0 || *p == '_')
1539                 return false;
1540
1541         for (t = p; *t; t++)
1542                 if (!strchr(CONTROLLER_VALID, *t))
1543                         return false;
1544
1545         if (t - p > FILENAME_MAX)
1546                 return false;
1547
1548         return true;
1549 }
1550
1551 int cg_slice_to_path(const char *unit, char **ret) {
1552         _cleanup_free_ char *p = NULL, *s = NULL, *e = NULL;
1553         const char *dash;
1554
1555         assert(unit);
1556         assert(ret);
1557
1558         if (!unit_name_is_valid(unit, false))
1559                 return -EINVAL;
1560
1561         if (!endswith(unit, ".slice"))
1562                 return -EINVAL;
1563
1564         p = unit_name_to_prefix(unit);
1565         if (!p)
1566                 return -ENOMEM;
1567
1568         dash = strchr(p, '-');
1569         while (dash) {
1570                 _cleanup_free_ char *escaped = NULL;
1571                 char n[dash - p + sizeof(".slice")];
1572
1573                 strcpy(stpncpy(n, p, dash - p), ".slice");
1574
1575                 if (!unit_name_is_valid(n, false))
1576                         return -EINVAL;
1577
1578                 escaped = cg_escape(n);
1579                 if (!escaped)
1580                         return -ENOMEM;
1581
1582                 if (!strextend(&s, escaped, "/", NULL))
1583                         return -ENOMEM;
1584
1585                 dash = strchr(dash+1, '-');
1586         }
1587
1588         e = cg_escape(unit);
1589         if (!e)
1590                 return -ENOMEM;
1591
1592         if (!strextend(&s, e, NULL))
1593                 return -ENOMEM;
1594
1595         *ret = s;
1596         s = NULL;
1597
1598         return 0;
1599 }
1600
1601 int cg_set_attribute(const char *controller, const char *path, const char *attribute, const char *value) {
1602         _cleanup_free_ char *p = NULL;
1603         int r;
1604
1605         r = cg_get_path(controller, path, attribute, &p);
1606         if (r < 0)
1607                 return r;
1608
1609         return write_string_file(p, value);
1610 }
1611
1612 static const char mask_names[] =
1613         "cpu\0"
1614         "cpuacct\0"
1615         "blkio\0"
1616         "memory\0"
1617         "devices\0";
1618
1619 int cg_create_with_mask(CGroupControllerMask mask, const char *path) {
1620         CGroupControllerMask bit = 1;
1621         const char *n;
1622         int r;
1623
1624         /* This one will create a cgroup in our private tree, but also
1625          * duplicate it in the trees specified in mask, and remove it
1626          * in all others */
1627
1628         /* First create the cgroup in our own hierarchy. */
1629         r = cg_create(SYSTEMD_CGROUP_CONTROLLER, path);
1630         if (r < 0)
1631                 return r;
1632
1633         /* Then, do the same in the other hierarchies */
1634         NULSTR_FOREACH(n, mask_names) {
1635                 if (bit & mask)
1636                         cg_create(n, path);
1637                 else
1638                         cg_trim(n, path, true);
1639
1640                 bit <<= 1;
1641         }
1642
1643         return r;
1644 }
1645
1646 int cg_attach_with_mask(CGroupControllerMask mask, const char *path, pid_t pid) {
1647         CGroupControllerMask bit = 1;
1648         const char *n;
1649         int r;
1650
1651         r = cg_attach(SYSTEMD_CGROUP_CONTROLLER, path, pid);
1652
1653         NULSTR_FOREACH(n, mask_names) {
1654                 if (bit & mask)
1655                         cg_attach(n, path, pid);
1656                 else {
1657                         char prefix[strlen(path) + 1], *slash;
1658
1659                         /* OK, this one is a bit harder... Now we need
1660                          * to add to the closest parent cgroup we
1661                          * can find */
1662                         strcpy(prefix, path);
1663                         while ((slash = strrchr(prefix, '/'))) {
1664                                 int q;
1665                                 *slash = 0;
1666
1667                                 q = cg_attach(n, prefix, pid);
1668                                 if (q >= 0)
1669                                         break;
1670                         }
1671                 }
1672
1673                 bit <<= 1;
1674         }
1675
1676         return r;
1677 }
1678
1679 int cg_attach_many_with_mask(CGroupControllerMask mask, const char *path, Set* pids) {
1680         Iterator i;
1681         void *pidp;
1682         int r = 0;
1683
1684         SET_FOREACH(pidp, pids, i) {
1685                 pid_t pid = PTR_TO_LONG(pidp);
1686                 int k;
1687
1688                 k = cg_attach_with_mask(mask, path, pid);
1689                 if (k < 0)
1690                         r = k;
1691         }
1692
1693         return r;
1694 }
1695
1696 int cg_migrate_with_mask(CGroupControllerMask mask, const char *from, const char *to) {
1697         CGroupControllerMask bit = 1;
1698         const char *n;
1699         int r;
1700
1701         if (path_equal(from, to))
1702                 return 0;
1703
1704         r = cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, from, SYSTEMD_CGROUP_CONTROLLER, to, false, true);
1705
1706         NULSTR_FOREACH(n, mask_names) {
1707                 if (bit & mask)
1708                         cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, to, n, to, false, false);
1709                 else {
1710                         char prefix[strlen(to) + 1], *slash;
1711
1712                         strcpy(prefix, to);
1713                         while ((slash = strrchr(prefix, '/'))) {
1714                                 int q;
1715
1716                                 *slash = 0;
1717
1718                                 q = cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, to, n, prefix, false, false);
1719                                 if (q >= 0)
1720                                         break;
1721                         }
1722                 }
1723
1724                 bit <<= 1;
1725         }
1726
1727         return r;
1728 }
1729
1730 int cg_trim_with_mask(CGroupControllerMask mask, const char *path, bool delete_root) {
1731         CGroupControllerMask bit = 1;
1732         const char *n;
1733         int r;
1734
1735         r = cg_trim(SYSTEMD_CGROUP_CONTROLLER, path, delete_root);
1736         if (r < 0)
1737                 return r;
1738
1739         NULSTR_FOREACH(n, mask_names) {
1740                 if (bit & mask)
1741                         cg_trim(n, path, delete_root);
1742
1743                 bit <<= 1;
1744         }
1745
1746         return r;
1747 }
1748
1749 CGroupControllerMask cg_mask_supported(void) {
1750         CGroupControllerMask bit = 1, mask = 0;
1751         const char *n;
1752
1753         NULSTR_FOREACH(n, mask_names) {
1754                 if (check_hierarchy(n) >= 0)
1755                         mask |= bit;
1756
1757                 bit <<= 1;
1758         }
1759
1760         return mask;
1761 }