chiark / gitweb /
Add set_consume which always takes ownership
[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
42 int cg_enumerate_processes(const char *controller, const char *path, FILE **_f) {
43         _cleanup_free_ char *fs = NULL;
44         FILE *f;
45         int r;
46
47         assert(_f);
48
49         r = cg_get_path(controller, path, "cgroup.procs", &fs);
50         if (r < 0)
51                 return r;
52
53         f = fopen(fs, "re");
54         if (!f)
55                 return -errno;
56
57         *_f = f;
58         return 0;
59 }
60
61 int cg_enumerate_tasks(const char *controller, const char *path, FILE **_f) {
62         _cleanup_free_ char *fs = NULL;
63         FILE *f;
64         int r;
65
66         assert(_f);
67
68         r = cg_get_path(controller, path, "tasks", &fs);
69         if (r < 0)
70                 return r;
71
72         f = fopen(fs, "re");
73         if (!f)
74                 return -errno;
75
76         *_f = f;
77         return 0;
78 }
79
80 int cg_read_pid(FILE *f, pid_t *_pid) {
81         unsigned long ul;
82
83         /* Note that the cgroup.procs might contain duplicates! See
84          * cgroups.txt for details. */
85
86         assert(f);
87         assert(_pid);
88
89         errno = 0;
90         if (fscanf(f, "%lu", &ul) != 1) {
91
92                 if (feof(f))
93                         return 0;
94
95                 return errno ? -errno : -EIO;
96         }
97
98         if (ul <= 0)
99                 return -EIO;
100
101         *_pid = (pid_t) ul;
102         return 1;
103 }
104
105 int cg_enumerate_subgroups(const char *controller, const char *path, DIR **_d) {
106         _cleanup_free_ char *fs = NULL;
107         int r;
108         DIR *d;
109
110         assert(_d);
111
112         /* This is not recursive! */
113
114         r = cg_get_path(controller, path, NULL, &fs);
115         if (r < 0)
116                 return r;
117
118         d = opendir(fs);
119         if (!d)
120                 return -errno;
121
122         *_d = d;
123         return 0;
124 }
125
126 int cg_read_subgroup(DIR *d, char **fn) {
127         struct dirent *de;
128
129         assert(d);
130         assert(fn);
131
132         FOREACH_DIRENT(de, d, return -errno) {
133                 char *b;
134
135                 if (de->d_type != DT_DIR)
136                         continue;
137
138                 if (streq(de->d_name, ".") ||
139                     streq(de->d_name, ".."))
140                         continue;
141
142                 b = strdup(de->d_name);
143                 if (!b)
144                         return -ENOMEM;
145
146                 *fn = b;
147                 return 1;
148         }
149
150         return 0;
151 }
152
153 int cg_rmdir(const char *controller, const char *path, bool honour_sticky) {
154         _cleanup_free_ char *p = NULL;
155         int r;
156
157         r = cg_get_path(controller, path, NULL, &p);
158         if (r < 0)
159                 return r;
160
161         if (honour_sticky) {
162                 char *tasks;
163
164                 /* If the sticky bit is set don't remove the directory */
165
166                 tasks = strappend(p, "/tasks");
167                 if (!tasks)
168                         return -ENOMEM;
169
170                 r = file_is_priv_sticky(tasks);
171                 free(tasks);
172
173                 if (r > 0)
174                         return 0;
175         }
176
177         r = rmdir(p);
178         if (r < 0 && errno != ENOENT)
179                 return -errno;
180
181         return 0;
182 }
183
184 int cg_kill(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, Set *s) {
185         _cleanup_set_free_ Set *allocated_set = NULL;
186         bool done = false;
187         int r, ret = 0;
188         pid_t my_pid;
189
190         assert(sig >= 0);
191
192         /* This goes through the tasks list and kills them all. This
193          * is repeated until no further processes are added to the
194          * tasks list, to properly handle forking processes */
195
196         if (!s) {
197                 s = allocated_set = set_new(trivial_hash_func, trivial_compare_func);
198                 if (!s)
199                         return -ENOMEM;
200         }
201
202         my_pid = getpid();
203
204         do {
205                 _cleanup_fclose_ FILE *f = NULL;
206                 pid_t pid = 0;
207                 done = true;
208
209                 r = cg_enumerate_processes(controller, path, &f);
210                 if (r < 0) {
211                         if (ret >= 0 && r != -ENOENT)
212                                 return r;
213
214                         return ret;
215                 }
216
217                 while ((r = cg_read_pid(f, &pid)) > 0) {
218
219                         if (ignore_self && pid == my_pid)
220                                 continue;
221
222                         if (set_get(s, LONG_TO_PTR(pid)) == LONG_TO_PTR(pid))
223                                 continue;
224
225                         /* If we haven't killed this process yet, kill
226                          * it */
227                         if (kill(pid, sig) < 0) {
228                                 if (ret >= 0 && errno != ESRCH)
229                                         ret = -errno;
230                         } else if (ret == 0) {
231
232                                 if (sigcont)
233                                         kill(pid, SIGCONT);
234
235                                 ret = 1;
236                         }
237
238                         done = false;
239
240                         r = set_put(s, LONG_TO_PTR(pid));
241                         if (r < 0) {
242                                 if (ret >= 0)
243                                         return r;
244
245                                 return ret;
246                         }
247                 }
248
249                 if (r < 0) {
250                         if (ret >= 0)
251                                 return r;
252
253                         return ret;
254                 }
255
256                 /* To avoid racing against processes which fork
257                  * quicker than we can kill them we repeat this until
258                  * no new pids need to be killed. */
259
260         } while (!done);
261
262         return ret;
263 }
264
265 int cg_kill_recursive(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, bool rem, Set *s) {
266         _cleanup_set_free_ Set *allocated_set = NULL;
267         _cleanup_closedir_ DIR *d = NULL;
268         int r, ret = 0;
269         char *fn;
270
271         assert(path);
272         assert(sig >= 0);
273
274         if (!s) {
275                 s = allocated_set = set_new(trivial_hash_func, trivial_compare_func);
276                 if (!s)
277                         return -ENOMEM;
278         }
279
280         ret = cg_kill(controller, path, sig, sigcont, ignore_self, s);
281
282         r = cg_enumerate_subgroups(controller, path, &d);
283         if (r < 0) {
284                 if (ret >= 0 && r != -ENOENT)
285                         return r;
286
287                 return ret;
288         }
289
290         while ((r = cg_read_subgroup(d, &fn)) > 0) {
291                 _cleanup_free_ char *p = NULL;
292
293                 p = strjoin(path, "/", fn, NULL);
294                 free(fn);
295                 if (!p)
296                         return -ENOMEM;
297
298                 r = cg_kill_recursive(controller, p, sig, sigcont, ignore_self, rem, s);
299                 if (ret >= 0 && r != 0)
300                         ret = r;
301         }
302
303         if (ret >= 0 && r < 0)
304                 ret = r;
305
306         if (rem) {
307                 r = cg_rmdir(controller, path, true);
308                 if (r < 0 && ret >= 0 && r != -ENOENT && r != -EBUSY)
309                         return r;
310         }
311
312         return ret;
313 }
314
315 int cg_kill_recursive_and_wait(const char *controller, const char *path, bool rem) {
316         unsigned i;
317
318         assert(path);
319
320         /* This safely kills all processes; first it sends a SIGTERM,
321          * then checks 8 times after 200ms whether the group is now
322          * empty, then kills everything that is left with SIGKILL and
323          * finally checks 5 times after 200ms each whether the group
324          * is finally empty. */
325
326         for (i = 0; i < 15; i++) {
327                 int sig, r;
328
329                 if (i <= 0)
330                         sig = SIGTERM;
331                 else if (i == 9)
332                         sig = SIGKILL;
333                 else
334                         sig = 0;
335
336                 r = cg_kill_recursive(controller, path, sig, true, true, rem, NULL);
337                 if (r <= 0)
338                         return r;
339
340                 usleep(200 * USEC_PER_MSEC);
341         }
342
343         return 0;
344 }
345
346 int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self) {
347         bool done = false;
348         _cleanup_set_free_ Set *s = NULL;
349         int r, ret = 0;
350         pid_t my_pid;
351
352         assert(cfrom);
353         assert(pfrom);
354         assert(cto);
355         assert(pto);
356
357         s = set_new(trivial_hash_func, trivial_compare_func);
358         if (!s)
359                 return -ENOMEM;
360
361         my_pid = getpid();
362
363         do {
364                 _cleanup_fclose_ FILE *f = NULL;
365                 pid_t pid = 0;
366                 done = true;
367
368                 r = cg_enumerate_tasks(cfrom, pfrom, &f);
369                 if (r < 0) {
370                         if (ret >= 0 && r != -ENOENT)
371                                 return r;
372
373                         return ret;
374                 }
375
376                 while ((r = cg_read_pid(f, &pid)) > 0) {
377
378                         /* This might do weird stuff if we aren't a
379                          * single-threaded program. However, we
380                          * luckily know we are not */
381                         if (ignore_self && pid == my_pid)
382                                 continue;
383
384                         if (set_get(s, LONG_TO_PTR(pid)) == LONG_TO_PTR(pid))
385                                 continue;
386
387                         r = cg_attach(cto, pto, pid);
388                         if (r < 0) {
389                                 if (ret >= 0 && r != -ESRCH)
390                                         ret = r;
391                         } else if (ret == 0)
392                                 ret = 1;
393
394                         done = false;
395
396                         r = set_put(s, LONG_TO_PTR(pid));
397                         if (r < 0) {
398                                 if (ret >= 0)
399                                         return r;
400
401                                 return ret;
402                         }
403                 }
404
405                 if (r < 0) {
406                         if (ret >= 0)
407                                 return r;
408
409                         return ret;
410                 }
411         } while (!done);
412
413         return ret;
414 }
415
416 int cg_migrate_recursive(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self, bool rem) {
417         _cleanup_closedir_ DIR *d = NULL;
418         int r, ret = 0;
419         char *fn;
420
421         assert(cfrom);
422         assert(pfrom);
423         assert(cto);
424         assert(pto);
425
426         ret = cg_migrate(cfrom, pfrom, cto, pto, ignore_self);
427
428         r = cg_enumerate_subgroups(cfrom, pfrom, &d);
429         if (r < 0) {
430                 if (ret >= 0 && r != -ENOENT)
431                         return r;
432
433                 return ret;
434         }
435
436         while ((r = cg_read_subgroup(d, &fn)) > 0) {
437                 _cleanup_free_ char *p = NULL;
438
439                 p = strjoin(pfrom, "/", fn, NULL);
440                 free(fn);
441                 if (!p) {
442                         if (ret >= 0)
443                                 return -ENOMEM;
444
445                         return ret;
446                 }
447
448                 r = cg_migrate_recursive(cfrom, p, cto, pto, ignore_self, rem);
449                 if (r != 0 && ret >= 0)
450                         ret = r;
451         }
452
453         if (r < 0 && ret >= 0)
454                 ret = r;
455
456         if (rem) {
457                 r = cg_rmdir(cfrom, pfrom, true);
458                 if (r < 0 && ret >= 0 && r != -ENOENT && r != -EBUSY)
459                         return r;
460         }
461
462         return ret;
463 }
464
465 static const char *normalize_controller(const char *controller) {
466
467         assert(controller);
468
469         if (streq(controller, SYSTEMD_CGROUP_CONTROLLER))
470                 return "systemd";
471         else if (startswith(controller, "name="))
472                 return controller + 5;
473         else
474                 return controller;
475 }
476
477 static int join_path(const char *controller, const char *path, const char *suffix, char **fs) {
478         char *t = NULL;
479
480         if (controller) {
481                 if (path && suffix)
482                         t = strjoin("/sys/fs/cgroup/", controller, "/", path, "/", suffix, NULL);
483                 else if (path)
484                         t = strjoin("/sys/fs/cgroup/", controller, "/", path, NULL);
485                 else if (suffix)
486                         t = strjoin("/sys/fs/cgroup/", controller, "/", suffix, NULL);
487                 else
488                         t = strappend("/sys/fs/cgroup/", controller);
489         } else {
490                 if (path && suffix)
491                         t = strjoin(path, "/", suffix, NULL);
492                 else if (path)
493                         t = strdup(path);
494                 else
495                         return -EINVAL;
496         }
497
498         if (!t)
499                 return -ENOMEM;
500
501         path_kill_slashes(t);
502
503         *fs = t;
504         return 0;
505 }
506
507 int cg_get_path(const char *controller, const char *path, const char *suffix, char **fs) {
508         const char *p;
509         static __thread bool good = false;
510
511         assert(fs);
512
513         if (_unlikely_(!good)) {
514                 int r;
515
516                 r = path_is_mount_point("/sys/fs/cgroup", false);
517                 if (r <= 0)
518                         return r < 0 ? r : -ENOENT;
519
520                 /* Cache this to save a few stat()s */
521                 good = true;
522         }
523
524         p = controller ? normalize_controller(controller) : NULL;
525
526         return join_path(p, path, suffix, fs);
527 }
528
529 static int check_hierarchy(const char *p) {
530         char *cc;
531
532         assert(p);
533
534         /* Check if this controller actually really exists */
535         cc = alloca(sizeof("/sys/fs/cgroup/") + strlen(p));
536         strcpy(stpcpy(cc, "/sys/fs/cgroup/"), p);
537         if (access(cc, F_OK) < 0)
538                 return -errno;
539
540         return 0;
541 }
542
543 int cg_get_path_and_check(const char *controller, const char *path, const char *suffix, char **fs) {
544         const char *p;
545         int r;
546
547         assert(fs);
548
549         if (isempty(controller))
550                 return -EINVAL;
551
552         /* Normalize the controller syntax */
553         p = normalize_controller(controller);
554
555         /* Check if this controller actually really exists */
556         r = check_hierarchy(p);
557         if (r < 0)
558                 return r;
559
560         return join_path(p, path, suffix, fs);
561 }
562
563 static int trim_cb(const char *path, const struct stat *sb, int typeflag, struct FTW *ftwbuf) {
564         char *p;
565         bool is_sticky;
566
567         if (typeflag != FTW_DP)
568                 return 0;
569
570         if (ftwbuf->level < 1)
571                 return 0;
572
573         p = strappend(path, "/tasks");
574         if (!p) {
575                 errno = ENOMEM;
576                 return 1;
577         }
578
579         is_sticky = file_is_priv_sticky(p) > 0;
580         free(p);
581
582         if (is_sticky)
583                 return 0;
584
585         rmdir(path);
586         return 0;
587 }
588
589 int cg_trim(const char *controller, const char *path, bool delete_root) {
590         _cleanup_free_ char *fs = NULL;
591         int r = 0;
592
593         assert(path);
594
595         r = cg_get_path(controller, path, NULL, &fs);
596         if (r < 0)
597                 return r;
598
599         errno = 0;
600         if (nftw(fs, trim_cb, 64, FTW_DEPTH|FTW_MOUNT|FTW_PHYS) != 0)
601                 r = errno ? -errno : -EIO;
602
603         if (delete_root) {
604                 bool is_sticky;
605                 char *p;
606
607                 p = strappend(fs, "/tasks");
608                 if (!p)
609                         return -ENOMEM;
610
611                 is_sticky = file_is_priv_sticky(p) > 0;
612                 free(p);
613
614                 if (!is_sticky)
615                         if (rmdir(fs) < 0 && errno != ENOENT && r == 0)
616                                 return -errno;
617         }
618
619         return r;
620 }
621
622 int cg_delete(const char *controller, const char *path) {
623         _cleanup_free_ char *parent = NULL;
624         int r;
625
626         assert(path);
627
628         r = path_get_parent(path, &parent);
629         if (r < 0)
630                 return r;
631
632         r = cg_migrate_recursive(controller, path, controller, parent, false, true);
633         return r == -ENOENT ? 0 : r;
634 }
635
636 int cg_attach(const char *controller, const char *path, pid_t pid) {
637         _cleanup_free_ char *fs = NULL;
638         char c[DECIMAL_STR_MAX(pid_t) + 2];
639         int r;
640
641         assert(path);
642         assert(pid >= 0);
643
644         r = cg_get_path_and_check(controller, path, "tasks", &fs);
645         if (r < 0)
646                 return r;
647
648         if (pid == 0)
649                 pid = getpid();
650
651         snprintf(c, sizeof(c), "%lu\n", (unsigned long) pid);
652
653         return write_string_file(fs, c);
654 }
655
656 int cg_set_group_access(
657                 const char *controller,
658                 const char *path,
659                 mode_t mode,
660                 uid_t uid,
661                 gid_t gid) {
662
663         _cleanup_free_ char *fs = NULL;
664         int r;
665
666         assert(path);
667
668         if (mode != (mode_t) -1)
669                 mode &= 0777;
670
671         r = cg_get_path(controller, path, NULL, &fs);
672         if (r < 0)
673                 return r;
674
675         return chmod_and_chown(fs, mode, uid, gid);
676 }
677
678 int cg_set_task_access(
679                 const char *controller,
680                 const char *path,
681                 mode_t mode,
682                 uid_t uid,
683                 gid_t gid,
684                 int sticky) {
685
686         _cleanup_free_ char *fs = NULL, *procs = NULL;
687         int r;
688
689         assert(path);
690
691         if (mode == (mode_t) -1 && uid == (uid_t) -1 && gid == (gid_t) -1 && sticky < 0)
692                 return 0;
693
694         if (mode != (mode_t) -1)
695                 mode &= 0666;
696
697         r = cg_get_path(controller, path, "tasks", &fs);
698         if (r < 0)
699                 return r;
700
701         if (sticky >= 0 && mode != (mode_t) -1)
702                 /* Both mode and sticky param are passed */
703                 mode |= (sticky ? S_ISVTX : 0);
704         else if ((sticky >= 0 && mode == (mode_t) -1) ||
705                  (mode != (mode_t) -1 && sticky < 0)) {
706                 struct stat st;
707
708                 /* Only one param is passed, hence read the current
709                  * mode from the file itself */
710
711                 r = lstat(fs, &st);
712                 if (r < 0)
713                         return -errno;
714
715                 if (mode == (mode_t) -1)
716                         /* No mode set, we just shall set the sticky bit */
717                         mode = (st.st_mode & ~S_ISVTX) | (sticky ? S_ISVTX : 0);
718                 else
719                         /* Only mode set, leave sticky bit untouched */
720                         mode = (st.st_mode & ~0777) | mode;
721         }
722
723         r = chmod_and_chown(fs, mode, uid, gid);
724         if (r < 0)
725                 return r;
726
727         /* Always keep values for "cgroup.procs" in sync with "tasks" */
728         r = cg_get_path(controller, path, "cgroup.procs", &procs);
729         if (r < 0)
730                 return r;
731
732         return chmod_and_chown(procs, mode, uid, gid);
733 }
734
735 int cg_pid_get_path(const char *controller, pid_t pid, char **path) {
736         char fs[sizeof("/proc/") - 1 + DECIMAL_STR_MAX(pid_t) + sizeof("/cgroup")];
737         _cleanup_fclose_ FILE *f = NULL;
738         char line[LINE_MAX];
739         size_t cs;
740
741         assert(path);
742         assert(pid >= 0);
743
744         if (!controller)
745                 controller = SYSTEMD_CGROUP_CONTROLLER;
746
747         if (pid == 0)
748                 pid = getpid();
749
750         sprintf(fs, "/proc/%lu/cgroup", (unsigned long) pid);
751         f = fopen(fs, "re");
752         if (!f)
753                 return errno == ENOENT ? -ESRCH : -errno;
754
755         cs = strlen(controller);
756
757         FOREACH_LINE(line, f, return -errno) {
758                 char *l, *p;
759
760                 truncate_nl(line);
761
762                 l = strchr(line, ':');
763                 if (!l)
764                         continue;
765
766                 l++;
767                 if (!strneq(l, controller, cs))
768                         continue;
769
770                 if (l[cs] != ':')
771                         continue;
772
773                 p = strdup(l + cs + 1);
774                 if (!p)
775                         return -ENOMEM;
776
777                 *path = p;
778                 return 0;
779         }
780
781         return -ENOENT;
782 }
783
784 int cg_install_release_agent(const char *controller, const char *agent) {
785         _cleanup_free_ char *fs = NULL, *contents = NULL;
786         char *sc;
787         int r;
788
789         assert(agent);
790
791         r = cg_get_path(controller, NULL, "release_agent", &fs);
792         if (r < 0)
793                 return r;
794
795         r = read_one_line_file(fs, &contents);
796         if (r < 0)
797                 return r;
798
799         sc = strstrip(contents);
800         if (sc[0] == 0) {
801                 r = write_string_file(fs, agent);
802                 if (r < 0)
803                         return r;
804         } else if (!streq(sc, agent))
805                 return -EEXIST;
806
807         free(fs);
808         fs = NULL;
809         r = cg_get_path(controller, NULL, "notify_on_release", &fs);
810         if (r < 0)
811                 return r;
812
813         free(contents);
814         contents = NULL;
815         r = read_one_line_file(fs, &contents);
816         if (r < 0)
817                 return r;
818
819         sc = strstrip(contents);
820         if (streq(sc, "0")) {
821                 r = write_string_file(fs, "1");
822                 if (r < 0)
823                         return r;
824
825                 return 1;
826         }
827
828         if (!streq(sc, "1"))
829                 return -EIO;
830
831         return 0;
832 }
833
834 int cg_is_empty(const char *controller, const char *path, bool ignore_self) {
835         _cleanup_fclose_ FILE *f = NULL;
836         pid_t pid = 0, self_pid;
837         bool found = false;
838         int r;
839
840         assert(path);
841
842         r = cg_enumerate_tasks(controller, path, &f);
843         if (r < 0)
844                 return r == -ENOENT ? 1 : r;
845
846         self_pid = getpid();
847
848         while ((r = cg_read_pid(f, &pid)) > 0) {
849
850                 if (ignore_self && pid == self_pid)
851                         continue;
852
853                 found = true;
854                 break;
855         }
856
857         if (r < 0)
858                 return r;
859
860         return !found;
861 }
862
863 int cg_is_empty_by_spec(const char *spec, bool ignore_self) {
864         _cleanup_free_ char *controller = NULL, *path = NULL;
865         int r;
866
867         assert(spec);
868
869         r = cg_split_spec(spec, &controller, &path);
870         if (r < 0)
871                 return r;
872
873         return cg_is_empty(controller, path, ignore_self);
874 }
875
876 int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_self) {
877         _cleanup_closedir_ DIR *d = NULL;
878         char *fn;
879         int r;
880
881         assert(path);
882
883         r = cg_is_empty(controller, path, ignore_self);
884         if (r <= 0)
885                 return r;
886
887         r = cg_enumerate_subgroups(controller, path, &d);
888         if (r < 0)
889                 return r == -ENOENT ? 1 : r;
890
891         while ((r = cg_read_subgroup(d, &fn)) > 0) {
892                 _cleanup_free_ char *p = NULL;
893
894                 p = strjoin(path, "/", fn, NULL);
895                 free(fn);
896                 if (!p)
897                         return -ENOMEM;
898
899                 r = cg_is_empty_recursive(controller, p, ignore_self);
900                 if (r <= 0)
901                         return r;
902         }
903
904         if (r < 0)
905                 return r;
906
907         return 1;
908 }
909
910 int cg_split_spec(const char *spec, char **controller, char **path) {
911         const char *e;
912         char *t = NULL, *u = NULL;
913
914         assert(spec);
915
916         if (*spec == '/') {
917                 if (!path_is_safe(spec))
918                         return -EINVAL;
919
920                 if (path) {
921                         t = strdup(spec);
922                         if (!t)
923                                 return -ENOMEM;
924
925                         *path = t;
926                 }
927
928                 if (controller)
929                         *controller = NULL;
930
931                 return 0;
932         }
933
934         e = strchr(spec, ':');
935         if (!e) {
936                 if (!filename_is_safe(spec))
937                         return -EINVAL;
938
939                 if (controller) {
940                         t = strdup(spec);
941                         if (!t)
942                                 return -ENOMEM;
943
944                         *controller = t;
945                 }
946
947                 if (path)
948                         *path = NULL;
949
950                 return 0;
951         }
952
953         t = strndup(spec, e-spec);
954         if (!t)
955                 return -ENOMEM;
956         if (!filename_is_safe(t)) {
957                 free(t);
958                 return -EINVAL;
959         }
960
961         u = strdup(e+1);
962         if (!u) {
963                 free(t);
964                 return -ENOMEM;
965         }
966         if (!path_is_safe(u)) {
967                 free(t);
968                 free(u);
969                 return -EINVAL;
970         }
971
972         if (controller)
973                 *controller = t;
974         else
975                 free(t);
976
977         if (path)
978                 *path = u;
979         else
980                 free(u);
981
982         return 0;
983 }
984
985 int cg_join_spec(const char *controller, const char *path, char **spec) {
986         char *s;
987
988         assert(path);
989
990         if (!controller)
991                 controller = "systemd";
992         else if (controller[0] == 0 ||
993                  strchr(controller, ':') ||
994                  strchr(controller, '/'))
995                 return -EINVAL;
996
997         if (!path_is_absolute(path))
998                 return -EINVAL;
999
1000         controller = normalize_controller(controller);
1001
1002         s = strjoin(controller, ":", path, NULL);
1003         if (!s)
1004                 return -ENOMEM;
1005
1006         *spec = s;
1007         return 0;
1008 }
1009
1010 int cg_mangle_path(const char *path, char **result) {
1011         char *t, *c, *p;
1012         int r;
1013
1014         assert(path);
1015         assert(result);
1016
1017         /* First check if it already is a filesystem path */
1018         if (path_startswith(path, "/sys/fs/cgroup")) {
1019
1020                 t = strdup(path);
1021                 if (!t)
1022                         return -ENOMEM;
1023
1024                 *result = t;
1025                 return 0;
1026         }
1027
1028         /* Otherwise treat it as cg spec */
1029         r = cg_split_spec(path, &c, &p);
1030         if (r < 0)
1031                 return r;
1032
1033         r = cg_get_path(c ? c : SYSTEMD_CGROUP_CONTROLLER, p ? p : "/", NULL, result);
1034         free(c);
1035         free(p);
1036
1037         return r;
1038 }
1039
1040 int cg_get_system_path(char **path) {
1041         char *p;
1042         int r;
1043
1044         assert(path);
1045
1046         r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 1, &p);
1047         if (r < 0) {
1048                 p = strdup("/system");
1049                 if (!p)
1050                         return -ENOMEM;
1051         }
1052
1053         if (endswith(p, "/system"))
1054                 *path = p;
1055         else {
1056                 char *q;
1057
1058                 q = strappend(p, "/system");
1059                 free(p);
1060                 if (!q)
1061                         return -ENOMEM;
1062
1063                 *path = q;
1064         }
1065
1066         return 0;
1067 }
1068
1069 int cg_get_root_path(char **path) {
1070         char *root, *e;
1071         int r;
1072
1073         assert(path);
1074
1075         r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 1, &root);
1076         if (r < 0)
1077                 return r;
1078
1079         e = endswith(root, "/system");
1080         if (e == root)
1081                 e[1] = 0;
1082         else if (e)
1083                 *e = 0;
1084
1085         *path = root;
1086         return 0;
1087 }
1088
1089 int cg_get_user_path(char **path) {
1090         _cleanup_free_ char *root = NULL;
1091         char *p;
1092
1093         assert(path);
1094
1095         /* Figure out the place to put user cgroups below. We use the
1096          * same as PID 1 has but with the "/system" suffix replaced by
1097          * "/user" */
1098
1099         if (cg_get_root_path(&root) < 0 || streq(root, "/"))
1100                 p = strdup("/user");
1101         else
1102                 p = strappend(root, "/user");
1103
1104         if (!p)
1105                 return -ENOMEM;
1106
1107         *path = p;
1108         return 0;
1109 }
1110
1111 int cg_get_machine_path(char **path) {
1112         _cleanup_free_ char *root = NULL;
1113         char *p;
1114
1115         assert(path);
1116
1117         if (cg_get_root_path(&root) < 0 || streq(root, "/"))
1118                 p = strdup("/machine");
1119         else
1120                 p = strappend(root, "/machine");
1121
1122         if (!p)
1123                 return -ENOMEM;
1124
1125         *path = p;
1126         return 0;
1127 }
1128
1129 char **cg_shorten_controllers(char **controllers) {
1130         char **f, **t;
1131
1132         if (!controllers)
1133                 return controllers;
1134
1135         for (f = controllers, t = controllers; *f; f++) {
1136                 const char *p;
1137                 int r;
1138
1139                 p = normalize_controller(*f);
1140
1141                 if (streq(*f, "systemd")) {
1142                         free(*f);
1143                         continue;
1144                 }
1145
1146                 r = check_hierarchy(p);
1147                 if (r < 0) {
1148                         log_debug("Controller %s is not available, removing from controllers list.", *f);
1149                         free(*f);
1150                         continue;
1151                 }
1152
1153                 *(t++) = *f;
1154         }
1155
1156         *t = NULL;
1157         return strv_uniq(controllers);
1158 }
1159
1160 int cg_pid_get_path_shifted(pid_t pid, char **root, char **cgroup) {
1161         _cleanup_free_ char *cg_root = NULL;
1162         char *cg_process, *p;
1163         int r;
1164
1165         r = cg_get_root_path(&cg_root);
1166         if (r < 0)
1167                 return r;
1168
1169         r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cg_process);
1170         if (r < 0)
1171                 return r;
1172
1173         p = path_startswith(cg_process, cg_root);
1174         if (p)
1175                 p--;
1176         else
1177                 p = cg_process;
1178
1179         if (cgroup) {
1180                 char* c;
1181
1182                 c = strdup(p);
1183                 if (!c) {
1184                         free(cg_process);
1185                         return -ENOMEM;
1186                 }
1187
1188                 *cgroup = c;
1189         }
1190
1191         if (root) {
1192                 cg_process[p-cg_process] = 0;
1193                 *root = cg_process;
1194         } else
1195                 free(cg_process);
1196
1197         return 0;
1198 }
1199
1200 int cg_path_decode_unit(const char *cgroup, char **unit){
1201         _cleanup_free_ char *unescaped = NULL;
1202         char *p, *e, *c, *s, *k;
1203
1204         assert(cgroup);
1205         assert(unit);
1206
1207         e = strchrnul(cgroup, '/');
1208         c = strndupa(cgroup, e - cgroup);
1209         c = cg_unescape(c);
1210
1211         /* Could this be a valid unit name? */
1212         if (!unit_name_is_valid(c, true))
1213                 return -EINVAL;
1214
1215         if (!unit_name_is_template(c))
1216                 s = strdup(c);
1217         else {
1218                 if (*e != '/')
1219                         return -EINVAL;
1220
1221                 e += strspn(e, "/");
1222
1223                 p = strchrnul(e, '/');
1224                 k = strndupa(e, p - e);
1225                 k = cg_unescape(k);
1226
1227                 if (!unit_name_is_valid(k, false))
1228                         return -EINVAL;
1229
1230                 s = strdup(k);
1231         }
1232
1233         if (!s)
1234                 return -ENOMEM;
1235
1236         *unit = s;
1237         return 0;
1238 }
1239
1240 int cg_path_get_unit(const char *path, char **unit) {
1241         const char *e;
1242
1243         assert(path);
1244         assert(unit);
1245
1246         e = path_startswith(path, "/system/");
1247         if (!e)
1248                 return -ENOENT;
1249
1250         return cg_path_decode_unit(e, unit);
1251 }
1252
1253 int cg_pid_get_unit(pid_t pid, char **unit) {
1254         _cleanup_free_ char *cgroup = NULL;
1255         int r;
1256
1257         assert(unit);
1258
1259         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1260         if (r < 0)
1261                 return r;
1262
1263         return cg_path_get_unit(cgroup, unit);
1264 }
1265
1266 static const char *skip_label(const char *e) {
1267         assert(e);
1268
1269         e = strchr(e, '/');
1270         if (!e)
1271                 return NULL;
1272
1273         e += strspn(e, "/");
1274         return e;
1275 }
1276
1277 int cg_path_get_user_unit(const char *path, char **unit) {
1278         const char *e;
1279
1280         assert(path);
1281         assert(unit);
1282
1283         /* We always have to parse the path from the beginning as unit
1284          * cgroups might have arbitrary child cgroups and we shouldn't get
1285          * confused by those */
1286
1287         e = path_startswith(path, "/user/");
1288         if (!e)
1289                 return -ENOENT;
1290
1291         /* Skip the user name */
1292         e = skip_label(e);
1293         if (!e)
1294                 return -ENOENT;
1295
1296         /* Skip the session ID */
1297         e = skip_label(e);
1298         if (!e)
1299                 return -ENOENT;
1300
1301         /* Skip the systemd cgroup */
1302         e = skip_label(e);
1303         if (!e)
1304                 return -ENOENT;
1305
1306         return cg_path_decode_unit(e, unit);
1307 }
1308
1309 int cg_pid_get_user_unit(pid_t pid, char **unit) {
1310         _cleanup_free_ char *cgroup = NULL;
1311         int r;
1312
1313         assert(unit);
1314
1315         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1316         if (r < 0)
1317                 return r;
1318
1319         return cg_path_get_user_unit(cgroup, unit);
1320 }
1321
1322 int cg_path_get_machine_name(const char *path, char **machine) {
1323         const char *e, *n;
1324         char *s, *r;
1325
1326         assert(path);
1327         assert(machine);
1328
1329         e = path_startswith(path, "/machine/");
1330         if (!e)
1331                 return -ENOENT;
1332
1333         n = strchrnul(e, '/');
1334         if (e == n)
1335                 return -ENOENT;
1336
1337         s = strndupa(e, n - e);
1338
1339         r = strdup(cg_unescape(s));
1340         if (!r)
1341                 return -ENOMEM;
1342
1343         *machine = r;
1344         return 0;
1345 }
1346
1347 int cg_pid_get_machine_name(pid_t pid, char **machine) {
1348         _cleanup_free_ char *cgroup = NULL;
1349         int r;
1350
1351         assert(machine);
1352
1353         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1354         if (r < 0)
1355                 return r;
1356
1357         return cg_path_get_machine_name(cgroup, machine);
1358 }
1359
1360 int cg_path_get_session(const char *path, char **session) {
1361         const char *e, *n;
1362         char *s;
1363
1364         assert(path);
1365         assert(session);
1366
1367         e = path_startswith(path, "/user/");
1368         if (!e)
1369                 return -ENOENT;
1370
1371         /* Skip the user name */
1372         e = skip_label(e);
1373         if (!e)
1374                 return -ENOENT;
1375
1376         n = strchrnul(e, '/');
1377         if (n - e < 8)
1378                 return -ENOENT;
1379         if (memcmp(n - 8, ".session", 8) != 0)
1380                 return -ENOENT;
1381
1382         s = strndup(e, n - e - 8);
1383         if (!s)
1384                 return -ENOMEM;
1385
1386         *session = s;
1387         return 0;
1388 }
1389
1390 int cg_pid_get_session(pid_t pid, char **session) {
1391         _cleanup_free_ char *cgroup = NULL;
1392         int r;
1393
1394         assert(session);
1395
1396         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1397         if (r < 0)
1398                 return r;
1399
1400         return cg_path_get_session(cgroup, session);
1401 }
1402
1403 int cg_path_get_owner_uid(const char *path, uid_t *uid) {
1404         const char *e, *n;
1405         char *s;
1406
1407         assert(path);
1408         assert(uid);
1409
1410         e = path_startswith(path, "/user/");
1411         if (!e)
1412                 return -ENOENT;
1413
1414         n = strchrnul(e, '/');
1415         if (n - e < 5)
1416                 return -ENOENT;
1417         if (memcmp(n - 5, ".user", 5) != 0)
1418                 return -ENOENT;
1419
1420         s = strndupa(e, n - e - 5);
1421         if (!s)
1422                 return -ENOMEM;
1423
1424         return parse_uid(s, uid);
1425 }
1426
1427 int cg_pid_get_owner_uid(pid_t pid, uid_t *uid) {
1428         _cleanup_free_ char *cgroup = NULL;
1429         int r;
1430
1431         assert(uid);
1432
1433         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1434         if (r < 0)
1435                 return r;
1436
1437         return cg_path_get_owner_uid(cgroup, uid);
1438 }
1439
1440 int cg_controller_from_attr(const char *attr, char **controller) {
1441         const char *dot;
1442         char *c;
1443
1444         assert(attr);
1445         assert(controller);
1446
1447         if (!filename_is_safe(attr))
1448                 return -EINVAL;
1449
1450         dot = strchr(attr, '.');
1451         if (!dot) {
1452                 *controller = NULL;
1453                 return 0;
1454         }
1455
1456         c = strndup(attr, dot - attr);
1457         if (!c)
1458                 return -ENOMEM;
1459
1460         if (!filename_is_safe(c)) {
1461                 free(c);
1462                 return -EINVAL;
1463         }
1464
1465         *controller = c;
1466         return 1;
1467 }
1468
1469 char *cg_escape(const char *p) {
1470         bool need_prefix = false;
1471
1472         /* This implements very minimal escaping for names to be used
1473          * as file names in the cgroup tree: any name which might
1474          * conflict with a kernel name or is prefixed with '_' is
1475          * prefixed with a '_'. That way, when reading cgroup names it
1476          * is sufficient to remove a single prefixing underscore if
1477          * there is one. */
1478
1479         /* The return value of this function (unlike cg_unescape())
1480          * needs free()! */
1481
1482         if (p[0] == '_' || streq(p, "notify_on_release") || streq(p, "release_agent") || streq(p, "tasks"))
1483                 need_prefix = true;
1484         else {
1485                 const char *dot;
1486
1487                 dot = strrchr(p, '.');
1488                 if (dot) {
1489
1490                         if (dot - p == 6 && memcmp(p, "cgroup", 6) == 0)
1491                                 need_prefix = true;
1492                         else {
1493                                 char *n;
1494
1495                                 n = strndupa(p, dot - p);
1496
1497                                 if (check_hierarchy(n) >= 0)
1498                                         need_prefix = true;
1499                         }
1500                 }
1501         }
1502
1503         if (need_prefix)
1504                 return strappend("_", p);
1505         else
1506                 return strdup(p);
1507 }
1508
1509 char *cg_unescape(const char *p) {
1510         assert(p);
1511
1512         /* The return value of this function (unlike cg_escape())
1513          * doesn't need free()! */
1514
1515         if (p[0] == '_')
1516                 return (char*) p+1;
1517
1518         return (char*) p;
1519 }