chiark / gitweb /
8c2ef455304518d9164fbf70530e21abd7347761
[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 (controller && !cg_controller_is_valid(controller, true))
514                 return -EINVAL;
515
516         if (_unlikely_(!good)) {
517                 int r;
518
519                 r = path_is_mount_point("/sys/fs/cgroup", false);
520                 if (r <= 0)
521                         return r < 0 ? r : -ENOENT;
522
523                 /* Cache this to save a few stat()s */
524                 good = true;
525         }
526
527         p = controller ? normalize_controller(controller) : NULL;
528
529         return join_path(p, path, suffix, fs);
530 }
531
532 static int check_hierarchy(const char *p) {
533         char *cc;
534
535         assert(p);
536
537         /* Check if this controller actually really exists */
538         cc = alloca(sizeof("/sys/fs/cgroup/") + strlen(p));
539         strcpy(stpcpy(cc, "/sys/fs/cgroup/"), p);
540         if (access(cc, F_OK) < 0)
541                 return -errno;
542
543         return 0;
544 }
545
546 int cg_get_path_and_check(const char *controller, const char *path, const char *suffix, char **fs) {
547         const char *p;
548         int r;
549
550         assert(fs);
551
552         if (!cg_controller_is_valid(controller, true))
553                 return -EINVAL;
554
555         /* Normalize the controller syntax */
556         p = normalize_controller(controller);
557
558         /* Check if this controller actually really exists */
559         r = check_hierarchy(p);
560         if (r < 0)
561                 return r;
562
563         return join_path(p, path, suffix, fs);
564 }
565
566 static int trim_cb(const char *path, const struct stat *sb, int typeflag, struct FTW *ftwbuf) {
567         char *p;
568         bool is_sticky;
569
570         if (typeflag != FTW_DP)
571                 return 0;
572
573         if (ftwbuf->level < 1)
574                 return 0;
575
576         p = strappend(path, "/tasks");
577         if (!p) {
578                 errno = ENOMEM;
579                 return 1;
580         }
581
582         is_sticky = file_is_priv_sticky(p) > 0;
583         free(p);
584
585         if (is_sticky)
586                 return 0;
587
588         rmdir(path);
589         return 0;
590 }
591
592 int cg_trim(const char *controller, const char *path, bool delete_root) {
593         _cleanup_free_ char *fs = NULL;
594         int r = 0;
595
596         assert(path);
597
598         r = cg_get_path(controller, path, NULL, &fs);
599         if (r < 0)
600                 return r;
601
602         errno = 0;
603         if (nftw(fs, trim_cb, 64, FTW_DEPTH|FTW_MOUNT|FTW_PHYS) != 0)
604                 r = errno ? -errno : -EIO;
605
606         if (delete_root) {
607                 bool is_sticky;
608                 char *p;
609
610                 p = strappend(fs, "/tasks");
611                 if (!p)
612                         return -ENOMEM;
613
614                 is_sticky = file_is_priv_sticky(p) > 0;
615                 free(p);
616
617                 if (!is_sticky)
618                         if (rmdir(fs) < 0 && errno != ENOENT && r == 0)
619                                 return -errno;
620         }
621
622         return r;
623 }
624
625 int cg_delete(const char *controller, const char *path) {
626         _cleanup_free_ char *parent = NULL;
627         int r;
628
629         assert(path);
630
631         r = path_get_parent(path, &parent);
632         if (r < 0)
633                 return r;
634
635         r = cg_migrate_recursive(controller, path, controller, parent, false, true);
636         return r == -ENOENT ? 0 : r;
637 }
638
639 int cg_attach(const char *controller, const char *path, pid_t pid) {
640         _cleanup_free_ char *fs = NULL;
641         char c[DECIMAL_STR_MAX(pid_t) + 2];
642         int r;
643
644         assert(path);
645         assert(pid >= 0);
646
647         r = cg_get_path_and_check(controller, path, "tasks", &fs);
648         if (r < 0)
649                 return r;
650
651         if (pid == 0)
652                 pid = getpid();
653
654         snprintf(c, sizeof(c), "%lu\n", (unsigned long) pid);
655
656         return write_string_file(fs, c);
657 }
658
659 int cg_set_group_access(
660                 const char *controller,
661                 const char *path,
662                 mode_t mode,
663                 uid_t uid,
664                 gid_t gid) {
665
666         _cleanup_free_ char *fs = NULL;
667         int r;
668
669         assert(path);
670
671         if (mode != (mode_t) -1)
672                 mode &= 0777;
673
674         r = cg_get_path(controller, path, NULL, &fs);
675         if (r < 0)
676                 return r;
677
678         return chmod_and_chown(fs, mode, uid, gid);
679 }
680
681 int cg_set_task_access(
682                 const char *controller,
683                 const char *path,
684                 mode_t mode,
685                 uid_t uid,
686                 gid_t gid,
687                 int sticky) {
688
689         _cleanup_free_ char *fs = NULL, *procs = NULL;
690         int r;
691
692         assert(path);
693
694         if (mode == (mode_t) -1 && uid == (uid_t) -1 && gid == (gid_t) -1 && sticky < 0)
695                 return 0;
696
697         if (mode != (mode_t) -1)
698                 mode &= 0666;
699
700         r = cg_get_path(controller, path, "tasks", &fs);
701         if (r < 0)
702                 return r;
703
704         if (sticky >= 0 && mode != (mode_t) -1)
705                 /* Both mode and sticky param are passed */
706                 mode |= (sticky ? S_ISVTX : 0);
707         else if ((sticky >= 0 && mode == (mode_t) -1) ||
708                  (mode != (mode_t) -1 && sticky < 0)) {
709                 struct stat st;
710
711                 /* Only one param is passed, hence read the current
712                  * mode from the file itself */
713
714                 r = lstat(fs, &st);
715                 if (r < 0)
716                         return -errno;
717
718                 if (mode == (mode_t) -1)
719                         /* No mode set, we just shall set the sticky bit */
720                         mode = (st.st_mode & ~S_ISVTX) | (sticky ? S_ISVTX : 0);
721                 else
722                         /* Only mode set, leave sticky bit untouched */
723                         mode = (st.st_mode & ~0777) | mode;
724         }
725
726         r = chmod_and_chown(fs, mode, uid, gid);
727         if (r < 0)
728                 return r;
729
730         /* Always keep values for "cgroup.procs" in sync with "tasks" */
731         r = cg_get_path(controller, path, "cgroup.procs", &procs);
732         if (r < 0)
733                 return r;
734
735         return chmod_and_chown(procs, mode, uid, gid);
736 }
737
738 int cg_pid_get_path(const char *controller, pid_t pid, char **path) {
739         _cleanup_fclose_ FILE *f = NULL;
740         char line[LINE_MAX];
741         const char *fs;
742         size_t cs;
743
744         assert(path);
745         assert(pid >= 0);
746
747         if (controller) {
748                 if (!cg_controller_is_valid(controller, true))
749                         return -EINVAL;
750
751                 controller = normalize_controller(controller);
752         } else
753                 controller = SYSTEMD_CGROUP_CONTROLLER;
754
755         if (pid == 0)
756                 fs = "/proc/self/cgroup";
757         else
758                 fs = procfs_file_alloca(pid, "cgroup");
759
760         f = fopen(fs, "re");
761         if (!f)
762                 return errno == ENOENT ? -ESRCH : -errno;
763
764         cs = strlen(controller);
765
766         FOREACH_LINE(line, f, return -errno) {
767                 char *l, *p, *w, *e;
768                 size_t k;
769                 char *state;
770                 bool found = false;
771
772                 truncate_nl(line);
773
774                 l = strchr(line, ':');
775                 if (!l)
776                         continue;
777
778                 l++;
779                 e = strchr(l, ':');
780                 if (!e)
781                         continue;
782
783                 *e = 0;
784
785                 FOREACH_WORD_SEPARATOR(w, k, l, ",", state) {
786
787                         if (k == cs && memcmp(w, controller, cs) == 0) {
788                                 found = true;
789                                 break;
790                         }
791
792                         if (k == 5 + cs &&
793                             memcmp(w, "name=", 5) == 0 &&
794                             memcmp(w+5, controller, cs) == 0) {
795                                 found = true;
796                                 break;
797                         }
798                 }
799
800                 if (!found)
801                         continue;
802
803                 p = strdup(e + 1);
804                 if (!p)
805                         return -ENOMEM;
806
807                 *path = p;
808                 return 0;
809         }
810
811         return -ENOENT;
812 }
813
814 int cg_install_release_agent(const char *controller, const char *agent) {
815         _cleanup_free_ char *fs = NULL, *contents = NULL;
816         char *sc;
817         int r;
818
819         assert(agent);
820
821         r = cg_get_path(controller, NULL, "release_agent", &fs);
822         if (r < 0)
823                 return r;
824
825         r = read_one_line_file(fs, &contents);
826         if (r < 0)
827                 return r;
828
829         sc = strstrip(contents);
830         if (sc[0] == 0) {
831                 r = write_string_file(fs, agent);
832                 if (r < 0)
833                         return r;
834         } else if (!streq(sc, agent))
835                 return -EEXIST;
836
837         free(fs);
838         fs = NULL;
839         r = cg_get_path(controller, NULL, "notify_on_release", &fs);
840         if (r < 0)
841                 return r;
842
843         free(contents);
844         contents = NULL;
845         r = read_one_line_file(fs, &contents);
846         if (r < 0)
847                 return r;
848
849         sc = strstrip(contents);
850         if (streq(sc, "0")) {
851                 r = write_string_file(fs, "1");
852                 if (r < 0)
853                         return r;
854
855                 return 1;
856         }
857
858         if (!streq(sc, "1"))
859                 return -EIO;
860
861         return 0;
862 }
863
864 int cg_is_empty(const char *controller, const char *path, bool ignore_self) {
865         _cleanup_fclose_ FILE *f = NULL;
866         pid_t pid = 0, self_pid;
867         bool found = false;
868         int r;
869
870         assert(path);
871
872         r = cg_enumerate_tasks(controller, path, &f);
873         if (r < 0)
874                 return r == -ENOENT ? 1 : r;
875
876         self_pid = getpid();
877
878         while ((r = cg_read_pid(f, &pid)) > 0) {
879
880                 if (ignore_self && pid == self_pid)
881                         continue;
882
883                 found = true;
884                 break;
885         }
886
887         if (r < 0)
888                 return r;
889
890         return !found;
891 }
892
893 int cg_is_empty_by_spec(const char *spec, bool ignore_self) {
894         _cleanup_free_ char *controller = NULL, *path = NULL;
895         int r;
896
897         assert(spec);
898
899         r = cg_split_spec(spec, &controller, &path);
900         if (r < 0)
901                 return r;
902
903         return cg_is_empty(controller, path, ignore_self);
904 }
905
906 int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_self) {
907         _cleanup_closedir_ DIR *d = NULL;
908         char *fn;
909         int r;
910
911         assert(path);
912
913         r = cg_is_empty(controller, path, ignore_self);
914         if (r <= 0)
915                 return r;
916
917         r = cg_enumerate_subgroups(controller, path, &d);
918         if (r < 0)
919                 return r == -ENOENT ? 1 : r;
920
921         while ((r = cg_read_subgroup(d, &fn)) > 0) {
922                 _cleanup_free_ char *p = NULL;
923
924                 p = strjoin(path, "/", fn, NULL);
925                 free(fn);
926                 if (!p)
927                         return -ENOMEM;
928
929                 r = cg_is_empty_recursive(controller, p, ignore_self);
930                 if (r <= 0)
931                         return r;
932         }
933
934         if (r < 0)
935                 return r;
936
937         return 1;
938 }
939
940 int cg_split_spec(const char *spec, char **controller, char **path) {
941         const char *e;
942         char *t = NULL, *u = NULL;
943         _cleanup_free_ char *v = NULL;
944
945         assert(spec);
946
947         if (*spec == '/') {
948                 if (!path_is_safe(spec))
949                         return -EINVAL;
950
951                 if (path) {
952                         t = strdup(spec);
953                         if (!t)
954                                 return -ENOMEM;
955
956                         path_kill_slashes(t);
957                         *path = t;
958                 }
959
960                 if (controller)
961                         *controller = NULL;
962
963                 return 0;
964         }
965
966         e = strchr(spec, ':');
967         if (!e) {
968                 if (!cg_controller_is_valid(spec, true))
969                         return -EINVAL;
970
971                 if (controller) {
972                         t = strdup(normalize_controller(spec));
973                         if (!t)
974                                 return -ENOMEM;
975
976                         *controller = t;
977                 }
978
979                 if (path)
980                         *path = NULL;
981
982                 return 0;
983         }
984
985         v = strndup(spec, e-spec);
986         if (!v)
987                 return -ENOMEM;
988         t = strdup(normalize_controller(v));
989         if (!t)
990                 return -ENOMEM;
991         if (!cg_controller_is_valid(t, true)) {
992                 free(t);
993                 return -EINVAL;
994         }
995
996         u = strdup(e+1);
997         if (!u) {
998                 free(t);
999                 return -ENOMEM;
1000         }
1001         if (!path_is_safe(u) ||
1002             !path_is_absolute(u)) {
1003                 free(t);
1004                 free(u);
1005                 return -EINVAL;
1006         }
1007
1008         path_kill_slashes(u);
1009
1010         if (controller)
1011                 *controller = t;
1012         else
1013                 free(t);
1014
1015         if (path)
1016                 *path = u;
1017         else
1018                 free(u);
1019
1020         return 0;
1021 }
1022
1023 int cg_join_spec(const char *controller, const char *path, char **spec) {
1024         char *s;
1025
1026         assert(path);
1027
1028         if (!controller)
1029                 controller = "systemd";
1030         else {
1031                 if (!cg_controller_is_valid(controller, true))
1032                         return -EINVAL;
1033
1034                 controller = normalize_controller(controller);
1035         }
1036
1037         if (!path_is_absolute(path))
1038                 return -EINVAL;
1039
1040         s = strjoin(controller, ":", path, NULL);
1041         if (!s)
1042                 return -ENOMEM;
1043
1044         path_kill_slashes(s + strlen(controller) + 1);
1045
1046         *spec = s;
1047         return 0;
1048 }
1049
1050 int cg_mangle_path(const char *path, char **result) {
1051         _cleanup_free_ char *c = NULL, *p = NULL;
1052         char *t;
1053         int r;
1054
1055         assert(path);
1056         assert(result);
1057
1058         /* First check if it already is a filesystem path */
1059         if (path_startswith(path, "/sys/fs/cgroup")) {
1060
1061                 t = strdup(path);
1062                 if (!t)
1063                         return -ENOMEM;
1064
1065                 path_kill_slashes(t);
1066                 *result = t;
1067                 return 0;
1068         }
1069
1070         /* Otherwise treat it as cg spec */
1071         r = cg_split_spec(path, &c, &p);
1072         if (r < 0)
1073                 return r;
1074
1075         return cg_get_path(c ? c : SYSTEMD_CGROUP_CONTROLLER, p ? p : "/", NULL, result);
1076 }
1077
1078 int cg_get_system_path(char **path) {
1079         char *p;
1080         int r;
1081
1082         assert(path);
1083
1084         r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 1, &p);
1085         if (r < 0) {
1086                 p = strdup("/system");
1087                 if (!p)
1088                         return -ENOMEM;
1089         }
1090
1091         if (endswith(p, "/system"))
1092                 *path = p;
1093         else {
1094                 char *q;
1095
1096                 q = strappend(p, "/system");
1097                 free(p);
1098                 if (!q)
1099                         return -ENOMEM;
1100
1101                 *path = q;
1102         }
1103
1104         return 0;
1105 }
1106
1107 int cg_get_root_path(char **path) {
1108         char *root, *e;
1109         int r;
1110
1111         assert(path);
1112
1113         r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 1, &root);
1114         if (r < 0)
1115                 return r;
1116
1117         e = endswith(root, "/system");
1118         if (e == root)
1119                 e[1] = 0;
1120         else if (e)
1121                 *e = 0;
1122
1123         *path = root;
1124         return 0;
1125 }
1126
1127 int cg_get_user_path(char **path) {
1128         _cleanup_free_ char *root = NULL;
1129         char *p;
1130
1131         assert(path);
1132
1133         /* Figure out the place to put user cgroups below. We use the
1134          * same as PID 1 has but with the "/system" suffix replaced by
1135          * "/user" */
1136
1137         if (cg_get_root_path(&root) < 0 || streq(root, "/"))
1138                 p = strdup("/user");
1139         else
1140                 p = strappend(root, "/user");
1141
1142         if (!p)
1143                 return -ENOMEM;
1144
1145         *path = p;
1146         return 0;
1147 }
1148
1149 int cg_get_machine_path(const char *machine, char **path) {
1150         _cleanup_free_ char *root = NULL, *escaped = NULL;
1151         char *p;
1152
1153         assert(path);
1154
1155         if (machine) {
1156                 const char *name = strappenda(machine, ".nspawn");
1157
1158                 escaped = cg_escape(name);
1159                 if (!escaped)
1160                         return -ENOMEM;
1161         }
1162
1163         p = strjoin(cg_get_root_path(&root) >= 0 && !streq(root, "/") ? root : "",
1164                     "/machine", machine ? "/" : "", machine ? escaped : "", NULL);
1165         if (!p)
1166                 return -ENOMEM;
1167
1168         *path = p;
1169         return 0;
1170 }
1171
1172 char **cg_shorten_controllers(char **controllers) {
1173         char **f, **t;
1174
1175         if (!controllers)
1176                 return controllers;
1177
1178         for (f = controllers, t = controllers; *f; f++) {
1179                 const char *p;
1180                 int r;
1181
1182                 p = normalize_controller(*f);
1183
1184                 if (streq(p, "systemd")) {
1185                         free(*f);
1186                         continue;
1187                 }
1188
1189                 if (!cg_controller_is_valid(p, true)) {
1190                         log_warning("Controller %s is not valid, removing from controllers list.", p);
1191                         free(*f);
1192                         continue;
1193                 }
1194
1195                 r = check_hierarchy(p);
1196                 if (r < 0) {
1197                         log_debug("Controller %s is not available, removing from controllers list.", p);
1198                         free(*f);
1199                         continue;
1200                 }
1201
1202                 *(t++) = *f;
1203         }
1204
1205         *t = NULL;
1206         return strv_uniq(controllers);
1207 }
1208
1209 int cg_pid_get_path_shifted(pid_t pid, char **root, char **cgroup) {
1210         _cleanup_free_ char *cg_root = NULL;
1211         char *cg_process, *p;
1212         int r;
1213
1214         r = cg_get_root_path(&cg_root);
1215         if (r < 0)
1216                 return r;
1217
1218         r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cg_process);
1219         if (r < 0)
1220                 return r;
1221
1222         p = path_startswith(cg_process, cg_root);
1223         if (p)
1224                 p--;
1225         else
1226                 p = cg_process;
1227
1228         if (cgroup) {
1229                 char* c;
1230
1231                 c = strdup(p);
1232                 if (!c) {
1233                         free(cg_process);
1234                         return -ENOMEM;
1235                 }
1236
1237                 *cgroup = c;
1238         }
1239
1240         if (root) {
1241                 cg_process[p-cg_process] = 0;
1242                 *root = cg_process;
1243         } else
1244                 free(cg_process);
1245
1246         return 0;
1247 }
1248
1249 int cg_path_decode_unit(const char *cgroup, char **unit){
1250         char *p, *e, *c, *s, *k;
1251
1252         assert(cgroup);
1253         assert(unit);
1254
1255         e = strchrnul(cgroup, '/');
1256         c = strndupa(cgroup, e - cgroup);
1257         c = cg_unescape(c);
1258
1259         /* Could this be a valid unit name? */
1260         if (!unit_name_is_valid(c, true))
1261                 return -EINVAL;
1262
1263         if (!unit_name_is_template(c))
1264                 s = strdup(c);
1265         else {
1266                 if (*e != '/')
1267                         return -EINVAL;
1268
1269                 e += strspn(e, "/");
1270
1271                 p = strchrnul(e, '/');
1272                 k = strndupa(e, p - e);
1273                 k = cg_unescape(k);
1274
1275                 if (!unit_name_is_valid(k, false))
1276                         return -EINVAL;
1277
1278                 s = strdup(k);
1279         }
1280
1281         if (!s)
1282                 return -ENOMEM;
1283
1284         *unit = s;
1285         return 0;
1286 }
1287
1288 int cg_path_get_unit(const char *path, char **unit) {
1289         const char *e;
1290
1291         assert(path);
1292         assert(unit);
1293
1294         e = path_startswith(path, "/system/");
1295         if (!e)
1296                 return -ENOENT;
1297
1298         return cg_path_decode_unit(e, unit);
1299 }
1300
1301 int cg_pid_get_unit(pid_t pid, char **unit) {
1302         _cleanup_free_ char *cgroup = NULL;
1303         int r;
1304
1305         assert(unit);
1306
1307         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1308         if (r < 0)
1309                 return r;
1310
1311         return cg_path_get_unit(cgroup, unit);
1312 }
1313
1314 static const char *skip_label(const char *e) {
1315         assert(e);
1316
1317         e = strchr(e, '/');
1318         if (!e)
1319                 return NULL;
1320
1321         e += strspn(e, "/");
1322         return e;
1323 }
1324
1325 int cg_path_get_user_unit(const char *path, char **unit) {
1326         const char *e;
1327
1328         assert(path);
1329         assert(unit);
1330
1331         /* We always have to parse the path from the beginning as unit
1332          * cgroups might have arbitrary child cgroups and we shouldn't get
1333          * confused by those */
1334
1335         e = path_startswith(path, "/user/");
1336         if (!e)
1337                 return -ENOENT;
1338
1339         /* Skip the user name */
1340         e = skip_label(e);
1341         if (!e)
1342                 return -ENOENT;
1343
1344         /* Skip the session ID */
1345         e = skip_label(e);
1346         if (!e)
1347                 return -ENOENT;
1348
1349         /* Skip the systemd cgroup */
1350         e = skip_label(e);
1351         if (!e)
1352                 return -ENOENT;
1353
1354         return cg_path_decode_unit(e, unit);
1355 }
1356
1357 int cg_pid_get_user_unit(pid_t pid, char **unit) {
1358         _cleanup_free_ char *cgroup = NULL;
1359         int r;
1360
1361         assert(unit);
1362
1363         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1364         if (r < 0)
1365                 return r;
1366
1367         return cg_path_get_user_unit(cgroup, unit);
1368 }
1369
1370 int cg_path_get_machine_name(const char *path, char **machine) {
1371         const char *e, *n;
1372         char *s, *r;
1373
1374         assert(path);
1375         assert(machine);
1376
1377         e = path_startswith(path, "/machine/");
1378         if (!e)
1379                 return -ENOENT;
1380
1381         n = strchrnul(e, '/');
1382         if (e == n)
1383                 return -ENOENT;
1384
1385         s = strndupa(e, n - e);
1386
1387         r = strdup(cg_unescape(s));
1388         if (!r)
1389                 return -ENOMEM;
1390
1391         *machine = r;
1392         return 0;
1393 }
1394
1395 int cg_pid_get_machine_name(pid_t pid, char **machine) {
1396         _cleanup_free_ char *cgroup = NULL;
1397         int r;
1398
1399         assert(machine);
1400
1401         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1402         if (r < 0)
1403                 return r;
1404
1405         return cg_path_get_machine_name(cgroup, machine);
1406 }
1407
1408 int cg_path_get_session(const char *path, char **session) {
1409         const char *e, *n;
1410         char *s;
1411
1412         assert(path);
1413         assert(session);
1414
1415         e = path_startswith(path, "/user/");
1416         if (!e)
1417                 return -ENOENT;
1418
1419         /* Skip the user name */
1420         e = skip_label(e);
1421         if (!e)
1422                 return -ENOENT;
1423
1424         n = strchrnul(e, '/');
1425         if (n - e < 8)
1426                 return -ENOENT;
1427         if (memcmp(n - 8, ".session", 8) != 0)
1428                 return -ENOENT;
1429
1430         s = strndup(e, n - e - 8);
1431         if (!s)
1432                 return -ENOMEM;
1433
1434         *session = s;
1435         return 0;
1436 }
1437
1438 int cg_pid_get_session(pid_t pid, char **session) {
1439         _cleanup_free_ char *cgroup = NULL;
1440         int r;
1441
1442         assert(session);
1443
1444         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1445         if (r < 0)
1446                 return r;
1447
1448         return cg_path_get_session(cgroup, session);
1449 }
1450
1451 int cg_path_get_owner_uid(const char *path, uid_t *uid) {
1452         const char *e, *n;
1453         char *s;
1454
1455         assert(path);
1456         assert(uid);
1457
1458         e = path_startswith(path, "/user/");
1459         if (!e)
1460                 return -ENOENT;
1461
1462         n = strchrnul(e, '/');
1463         if (n - e < 5)
1464                 return -ENOENT;
1465         if (memcmp(n - 5, ".user", 5) != 0)
1466                 return -ENOENT;
1467
1468         s = strndupa(e, n - e - 5);
1469         if (!s)
1470                 return -ENOMEM;
1471
1472         return parse_uid(s, uid);
1473 }
1474
1475 int cg_pid_get_owner_uid(pid_t pid, uid_t *uid) {
1476         _cleanup_free_ char *cgroup = NULL;
1477         int r;
1478
1479         assert(uid);
1480
1481         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1482         if (r < 0)
1483                 return r;
1484
1485         return cg_path_get_owner_uid(cgroup, uid);
1486 }
1487
1488 int cg_controller_from_attr(const char *attr, char **controller) {
1489         const char *dot;
1490         char *c;
1491
1492         assert(attr);
1493         assert(controller);
1494
1495         if (!filename_is_safe(attr))
1496                 return -EINVAL;
1497
1498         dot = strchr(attr, '.');
1499         if (!dot) {
1500                 *controller = NULL;
1501                 return 0;
1502         }
1503
1504         c = strndup(attr, dot - attr);
1505         if (!c)
1506                 return -ENOMEM;
1507
1508         if (!cg_controller_is_valid(c, false)) {
1509                 free(c);
1510                 return -EINVAL;
1511         }
1512
1513         *controller = c;
1514         return 1;
1515 }
1516
1517 char *cg_escape(const char *p) {
1518         bool need_prefix = false;
1519
1520         /* This implements very minimal escaping for names to be used
1521          * as file names in the cgroup tree: any name which might
1522          * conflict with a kernel name or is prefixed with '_' is
1523          * prefixed with a '_'. That way, when reading cgroup names it
1524          * is sufficient to remove a single prefixing underscore if
1525          * there is one. */
1526
1527         /* The return value of this function (unlike cg_unescape())
1528          * needs free()! */
1529
1530         if (p[0] == '_' || streq(p, "notify_on_release") || streq(p, "release_agent") || streq(p, "tasks"))
1531                 need_prefix = true;
1532         else {
1533                 const char *dot;
1534
1535                 dot = strrchr(p, '.');
1536                 if (dot) {
1537
1538                         if (dot - p == 6 && memcmp(p, "cgroup", 6) == 0)
1539                                 need_prefix = true;
1540                         else {
1541                                 char *n;
1542
1543                                 n = strndupa(p, dot - p);
1544
1545                                 if (check_hierarchy(n) >= 0)
1546                                         need_prefix = true;
1547                         }
1548                 }
1549         }
1550
1551         if (need_prefix)
1552                 return strappend("_", p);
1553         else
1554                 return strdup(p);
1555 }
1556
1557 char *cg_unescape(const char *p) {
1558         assert(p);
1559
1560         /* The return value of this function (unlike cg_escape())
1561          * doesn't need free()! */
1562
1563         if (p[0] == '_')
1564                 return (char*) p+1;
1565
1566         return (char*) p;
1567 }
1568
1569 #define CONTROLLER_VALID                        \
1570         "0123456789"                            \
1571         "abcdefghijklmnopqrstuvwxyz"            \
1572         "ABCDEFGHIJKLMNOPQRSTUVWXYZ"            \
1573         "_"
1574
1575 bool cg_controller_is_valid(const char *p, bool allow_named) {
1576         const char *t, *s;
1577
1578         if (!p)
1579                 return false;
1580
1581         if (allow_named) {
1582                 s = startswith(p, "name=");
1583                 if (s)
1584                         p = s;
1585         }
1586
1587         if (*p == 0 || *p == '_')
1588                 return false;
1589
1590         for (t = p; *t; t++)
1591                 if (!strchr(CONTROLLER_VALID, *t))
1592                         return false;
1593
1594         if (t - p > FILENAME_MAX)
1595                 return false;
1596
1597         return true;
1598 }