chiark / gitweb /
1f310d31f0967b07b670d5cf866725459ff3213e
[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 "strv.h"
38
39 int cg_enumerate_processes(const char *controller, const char *path, FILE **_f) {
40         char *fs;
41         int r;
42         FILE *f;
43
44         assert(path);
45         assert(_f);
46
47         r = cg_get_path(controller, path, "cgroup.procs", &fs);
48         if (r < 0)
49                 return r;
50
51         f = fopen(fs, "re");
52         free(fs);
53
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         char *fs;
63         int r;
64         FILE *f;
65
66         assert(path);
67         assert(_f);
68
69         r = cg_get_path(controller, path, "tasks", &fs);
70         if (r < 0)
71                 return r;
72
73         f = fopen(fs, "re");
74         free(fs);
75
76         if (!f)
77                 return -errno;
78
79         *_f = f;
80         return 0;
81 }
82
83 int cg_read_pid(FILE *f, pid_t *_pid) {
84         unsigned long ul;
85
86         /* Note that the cgroup.procs might contain duplicates! See
87          * cgroups.txt for details. */
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         char *fs;
107         int r;
108         DIR *d;
109
110         assert(path);
111         assert(_d);
112
113         /* This is not recursive! */
114
115         r = cg_get_path(controller, path, NULL, &fs);
116         if (r < 0)
117                 return r;
118
119         d = opendir(fs);
120         free(fs);
121
122         if (!d)
123                 return -errno;
124
125         *_d = d;
126         return 0;
127 }
128
129 int cg_read_subgroup(DIR *d, char **fn) {
130         struct dirent *de;
131
132         assert(d);
133
134         errno = 0;
135         while ((de = readdir(d))) {
136                 char *b;
137
138                 if (de->d_type != DT_DIR)
139                         continue;
140
141                 if (streq(de->d_name, ".") ||
142                     streq(de->d_name, ".."))
143                         continue;
144
145                 if (!(b = strdup(de->d_name)))
146                         return -ENOMEM;
147
148                 *fn = b;
149                 return 1;
150         }
151
152         if (errno)
153                 return -errno;
154
155         return 0;
156 }
157
158 int cg_rmdir(const char *controller, const char *path, bool honour_sticky) {
159         char *p;
160         int r;
161
162         r = cg_get_path(controller, path, NULL, &p);
163         if (r < 0)
164                 return r;
165
166         if (honour_sticky) {
167                 char *tasks;
168
169                 /* If the sticky bit is set don't remove the directory */
170
171                 tasks = strappend(p, "/tasks");
172                 if (!tasks) {
173                         free(p);
174                         return -ENOMEM;
175                 }
176
177                 r = file_is_priv_sticky(tasks);
178                 free(tasks);
179
180                 if (r > 0) {
181                         free(p);
182                         return 0;
183                 }
184         }
185
186         r = rmdir(p);
187         free(p);
188
189         return (r < 0 && errno != ENOENT) ? -errno : 0;
190 }
191
192 int cg_kill(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, Set *s) {
193         bool done = false;
194         int r, ret = 0;
195         pid_t my_pid;
196         FILE *f = NULL;
197         Set *allocated_set = NULL;
198
199         assert(controller);
200         assert(path);
201         assert(sig >= 0);
202
203         /* This goes through the tasks list and kills them all. This
204          * is repeated until no further processes are added to the
205          * tasks list, to properly handle forking processes */
206
207         if (!s)
208                 if (!(s = allocated_set = set_new(trivial_hash_func, trivial_compare_func)))
209                         return -ENOMEM;
210
211         my_pid = getpid();
212
213         do {
214                 pid_t pid = 0;
215                 done = true;
216
217                 if ((r = cg_enumerate_processes(controller, path, &f)) < 0) {
218                         if (ret >= 0 && r != -ENOENT)
219                                 ret = r;
220
221                         goto finish;
222                 }
223
224                 while ((r = cg_read_pid(f, &pid)) > 0) {
225
226                         if (pid == my_pid && ignore_self)
227                                 continue;
228
229                         if (set_get(s, LONG_TO_PTR(pid)) == LONG_TO_PTR(pid))
230                                 continue;
231
232                         /* If we haven't killed this process yet, kill
233                          * it */
234                         if (kill(pid, sig) < 0) {
235                                 if (ret >= 0 && errno != ESRCH)
236                                         ret = -errno;
237                         } else if (ret == 0) {
238
239                                 if (sigcont)
240                                         kill(pid, SIGCONT);
241
242                                 ret = 1;
243                         }
244
245                         done = false;
246
247                         if ((r = set_put(s, LONG_TO_PTR(pid))) < 0) {
248                                 if (ret >= 0)
249                                         ret = r;
250
251                                 goto finish;
252                         }
253                 }
254
255                 if (r < 0) {
256                         if (ret >= 0)
257                                 ret = r;
258
259                         goto finish;
260                 }
261
262                 fclose(f);
263                 f = NULL;
264
265                 /* To avoid racing against processes which fork
266                  * quicker than we can kill them we repeat this until
267                  * no new pids need to be killed. */
268
269         } while (!done);
270
271 finish:
272         if (allocated_set)
273                 set_free(allocated_set);
274
275         if (f)
276                 fclose(f);
277
278         return ret;
279 }
280
281 int cg_kill_recursive(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, bool rem, Set *s) {
282         int r, ret = 0;
283         DIR *d = NULL;
284         char *fn;
285         Set *allocated_set = NULL;
286
287         assert(path);
288         assert(controller);
289         assert(sig >= 0);
290
291         if (!s)
292                 if (!(s = allocated_set = set_new(trivial_hash_func, trivial_compare_func)))
293                         return -ENOMEM;
294
295         ret = cg_kill(controller, path, sig, sigcont, ignore_self, s);
296
297         if ((r = cg_enumerate_subgroups(controller, path, &d)) < 0) {
298                 if (ret >= 0 && r != -ENOENT)
299                         ret = r;
300
301                 goto finish;
302         }
303
304         while ((r = cg_read_subgroup(d, &fn)) > 0) {
305                 char *p = NULL;
306
307                 r = asprintf(&p, "%s/%s", path, fn);
308                 free(fn);
309
310                 if (r < 0) {
311                         if (ret >= 0)
312                                 ret = -ENOMEM;
313
314                         goto finish;
315                 }
316
317                 r = cg_kill_recursive(controller, p, sig, sigcont, ignore_self, rem, s);
318                 free(p);
319
320                 if (r != 0 && ret >= 0)
321                         ret = r;
322         }
323
324         if (r < 0 && ret >= 0)
325                 ret = r;
326
327         if (rem)
328                 if ((r = cg_rmdir(controller, path, true)) < 0) {
329                         if (ret >= 0 &&
330                             r != -ENOENT &&
331                             r != -EBUSY)
332                                 ret = r;
333                 }
334
335 finish:
336         if (d)
337                 closedir(d);
338
339         if (allocated_set)
340                 set_free(allocated_set);
341
342         return ret;
343 }
344
345 int cg_kill_recursive_and_wait(const char *controller, const char *path, bool rem) {
346         unsigned i;
347
348         assert(path);
349         assert(controller);
350
351         /* This safely kills all processes; first it sends a SIGTERM,
352          * then checks 8 times after 200ms whether the group is now
353          * empty, then kills everything that is left with SIGKILL and
354          * finally checks 5 times after 200ms each whether the group
355          * is finally empty. */
356
357         for (i = 0; i < 15; i++) {
358                 int sig, r;
359
360                 if (i <= 0)
361                         sig = SIGTERM;
362                 else if (i == 9)
363                         sig = SIGKILL;
364                 else
365                         sig = 0;
366
367                 if ((r = cg_kill_recursive(controller, path, sig, true, true, rem, NULL)) <= 0)
368                         return r;
369
370                 usleep(200 * USEC_PER_MSEC);
371         }
372
373         return 0;
374 }
375
376 int cg_migrate(const char *controller, const char *from, const char *to, bool ignore_self) {
377         bool done = false;
378         Set *s;
379         int r, ret = 0;
380         pid_t my_pid;
381         FILE *f = NULL;
382
383         assert(controller);
384         assert(from);
385         assert(to);
386
387         if (!(s = set_new(trivial_hash_func, trivial_compare_func)))
388                 return -ENOMEM;
389
390         my_pid = getpid();
391
392         do {
393                 pid_t pid = 0;
394                 done = true;
395
396                 if ((r = cg_enumerate_tasks(controller, from, &f)) < 0) {
397                         if (ret >= 0 && r != -ENOENT)
398                                 ret = r;
399
400                         goto finish;
401                 }
402
403                 while ((r = cg_read_pid(f, &pid)) > 0) {
404
405                         /* This might do weird stuff if we aren't a
406                          * single-threaded program. However, we
407                          * luckily know we are not */
408                         if (pid == my_pid && ignore_self)
409                                 continue;
410
411                         if (set_get(s, LONG_TO_PTR(pid)) == LONG_TO_PTR(pid))
412                                 continue;
413
414                         if ((r = cg_attach(controller, to, pid)) < 0) {
415                                 if (ret >= 0 && r != -ESRCH)
416                                         ret = r;
417                         } else if (ret == 0)
418                                 ret = 1;
419
420                         done = false;
421
422                         if ((r = set_put(s, LONG_TO_PTR(pid))) < 0) {
423                                 if (ret >= 0)
424                                         ret = r;
425
426                                 goto finish;
427                         }
428                 }
429
430                 if (r < 0) {
431                         if (ret >= 0)
432                                 ret = r;
433
434                         goto finish;
435                 }
436
437                 fclose(f);
438                 f = NULL;
439
440         } while (!done);
441
442 finish:
443         set_free(s);
444
445         if (f)
446                 fclose(f);
447
448         return ret;
449 }
450
451 int cg_migrate_recursive(const char *controller, const char *from, const char *to, bool ignore_self, bool rem) {
452         int r, ret = 0;
453         DIR *d = NULL;
454         char *fn;
455
456         assert(controller);
457         assert(from);
458         assert(to);
459
460         ret = cg_migrate(controller, from, to, ignore_self);
461
462         if ((r = cg_enumerate_subgroups(controller, from, &d)) < 0) {
463                 if (ret >= 0 && r != -ENOENT)
464                         ret = r;
465                 goto finish;
466         }
467
468         while ((r = cg_read_subgroup(d, &fn)) > 0) {
469                 char *p = NULL;
470
471                 r = asprintf(&p, "%s/%s", from, fn);
472                 free(fn);
473
474                 if (r < 0) {
475                         if (ret >= 0)
476                                 ret = -ENOMEM;
477
478                         goto finish;
479                 }
480
481                 r = cg_migrate_recursive(controller, p, to, ignore_self, rem);
482                 free(p);
483
484                 if (r != 0 && ret >= 0)
485                         ret = r;
486         }
487
488         if (r < 0 && ret >= 0)
489                 ret = r;
490
491         if (rem)
492                 if ((r = cg_rmdir(controller, from, true)) < 0) {
493                         if (ret >= 0 &&
494                             r != -ENOENT &&
495                             r != -EBUSY)
496                                 ret = r;
497                 }
498
499 finish:
500         if (d)
501                 closedir(d);
502
503         return ret;
504 }
505
506 static const char *normalize_controller(const char *controller) {
507
508         if (streq(controller, SYSTEMD_CGROUP_CONTROLLER))
509                 return "systemd";
510         else if (startswith(controller, "name="))
511                 return controller + 5;
512         else
513                 return controller;
514 }
515
516 static int join_path(const char *controller, const char *path, const char *suffix, char **fs) {
517         char *t = NULL;
518
519         if (!(controller || path))
520                 return -EINVAL;
521
522         if (controller) {
523                 if (path && suffix)
524                         t = join("/sys/fs/cgroup/", controller, "/", path, "/", suffix, NULL);
525                 else if (path)
526                         t = join("/sys/fs/cgroup/", controller, "/", path, NULL);
527                 else if (suffix)
528                         t = join("/sys/fs/cgroup/", controller, "/", suffix, NULL);
529                 else
530                         t = join("/sys/fs/cgroup/", controller, NULL);
531         } else {
532                 if (path && suffix)
533                         t = join(path, "/", suffix, NULL);
534                 else if (path)
535                         t = strdup(path);
536         }
537
538         if (!t)
539                 return -ENOMEM;
540
541         path_kill_slashes(t);
542
543         *fs = t;
544         return 0;
545 }
546
547 int cg_get_path(const char *controller, const char *path, const char *suffix, char **fs) {
548         const char *p;
549         static __thread bool good = false;
550
551         assert(fs);
552
553         if (_unlikely_(!good)) {
554                 int r;
555
556                 r = path_is_mount_point("/sys/fs/cgroup", false);
557                 if (r <= 0)
558                         return r < 0 ? r : -ENOENT;
559
560                 /* Cache this to save a few stat()s */
561                 good = true;
562         }
563
564         p = controller ? normalize_controller(controller) : NULL;
565         return join_path(p, path, suffix, fs);
566 }
567
568 static int check(const char *p) {
569         char *cc;
570
571         assert(p);
572
573         /* Check if this controller actually really exists */
574         cc = alloca(sizeof("/sys/fs/cgroup/") + strlen(p));
575         strcpy(stpcpy(cc, "/sys/fs/cgroup/"), p);
576         if (access(cc, F_OK) < 0)
577                 return -errno;
578
579         return 0;
580 }
581
582 int cg_get_path_and_check(const char *controller, const char *path, const char *suffix, char **fs) {
583         const char *p;
584         int r;
585
586         assert(controller);
587         assert(fs);
588
589         if (isempty(controller))
590                 return -EINVAL;
591
592         /* Normalize the controller syntax */
593         p = normalize_controller(controller);
594
595         /* Check if this controller actually really exists */
596         r = check(p);
597         if (r < 0)
598                 return r;
599
600         return join_path(p, path, suffix, fs);
601 }
602
603 static int trim_cb(const char *path, const struct stat *sb, int typeflag, struct FTW *ftwbuf) {
604         char *p;
605         bool is_sticky;
606
607         if (typeflag != FTW_DP)
608                 return 0;
609
610         if (ftwbuf->level < 1)
611                 return 0;
612
613         p = strappend(path, "/tasks");
614         if (!p) {
615                 errno = ENOMEM;
616                 return 1;
617         }
618
619         is_sticky = file_is_priv_sticky(p) > 0;
620         free(p);
621
622         if (is_sticky)
623                 return 0;
624
625         rmdir(path);
626         return 0;
627 }
628
629 int cg_trim(const char *controller, const char *path, bool delete_root) {
630         char *fs;
631         int r = 0;
632
633         assert(controller);
634         assert(path);
635
636         r = cg_get_path(controller, path, NULL, &fs);
637         if (r < 0)
638                 return r;
639
640         errno = 0;
641         if (nftw(fs, trim_cb, 64, FTW_DEPTH|FTW_MOUNT|FTW_PHYS) < 0)
642                 r = errno ? -errno : -EIO;
643
644         if (delete_root) {
645                 bool is_sticky;
646                 char *p;
647
648                 p = strappend(fs, "/tasks");
649                 if (!p) {
650                         free(fs);
651                         return -ENOMEM;
652                 }
653
654                 is_sticky = file_is_priv_sticky(p) > 0;
655                 free(p);
656
657                 if (!is_sticky)
658                         if (rmdir(fs) < 0 && errno != ENOENT) {
659                                 if (r == 0)
660                                         r = -errno;
661                         }
662         }
663
664         free(fs);
665
666         return r;
667 }
668
669 int cg_delete(const char *controller, const char *path) {
670         char *parent;
671         int r;
672
673         assert(controller);
674         assert(path);
675
676         if ((r = parent_of_path(path, &parent)) < 0)
677                 return r;
678
679         r = cg_migrate_recursive(controller, path, parent, false, true);
680         free(parent);
681
682         return r == -ENOENT ? 0 : r;
683 }
684
685 int cg_attach(const char *controller, const char *path, pid_t pid) {
686         char *fs;
687         int r;
688         char c[32];
689
690         assert(controller);
691         assert(path);
692         assert(pid >= 0);
693
694         r = cg_get_path_and_check(controller, path, "tasks", &fs);
695         if (r < 0)
696                 return r;
697
698         if (pid == 0)
699                 pid = getpid();
700
701         snprintf(c, sizeof(c), "%lu\n", (unsigned long) pid);
702         char_array_0(c);
703
704         r = write_one_line_file(fs, c);
705         free(fs);
706
707         return r;
708 }
709
710 int cg_set_group_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid) {
711         char *fs;
712         int r;
713
714         assert(controller);
715         assert(path);
716
717         if (mode != (mode_t) -1)
718                 mode &= 0777;
719
720         r = cg_get_path(controller, path, NULL, &fs);
721         if (r < 0)
722                 return r;
723
724         r = chmod_and_chown(fs, mode, uid, gid);
725         free(fs);
726
727         return r;
728 }
729
730 int cg_set_task_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid, int sticky) {
731         char *fs;
732         int r;
733
734         assert(controller);
735         assert(path);
736
737         if (mode == (mode_t) -1 && uid == (uid_t) -1 && gid == (gid_t) -1 && sticky < 0)
738                 return 0;
739
740         if (mode != (mode_t) -1)
741                 mode &= 0666;
742
743         r = cg_get_path(controller, path, "tasks", &fs);
744         if (r < 0)
745                 return r;
746
747         if (sticky >= 0 && mode != (mode_t) -1)
748                 /* Both mode and sticky param are passed */
749                 mode |= (sticky ? S_ISVTX : 0);
750         else if ((sticky >= 0 && mode == (mode_t) -1) ||
751                  (mode != (mode_t) -1 && sticky < 0)) {
752                 struct stat st;
753
754                 /* Only one param is passed, hence read the current
755                  * mode from the file itself */
756
757                 r = lstat(fs, &st);
758                 if (r < 0) {
759                         free(fs);
760                         return -errno;
761                 }
762
763                 if (mode == (mode_t) -1)
764                         /* No mode set, we just shall set the sticky bit */
765                         mode = (st.st_mode & ~S_ISVTX) | (sticky ? S_ISVTX : 0);
766                 else
767                         /* Only mode set, leave sticky bit untouched */
768                         mode = (st.st_mode & ~0777) | mode;
769         }
770
771         r = chmod_and_chown(fs, mode, uid, gid);
772         free(fs);
773
774         return r;
775 }
776
777 int cg_get_by_pid(const char *controller, pid_t pid, char **path) {
778         int r;
779         char *p = NULL;
780         FILE *f;
781         char *fs;
782         size_t cs;
783
784         assert(controller);
785         assert(path);
786         assert(pid >= 0);
787
788         if (pid == 0)
789                 pid = getpid();
790
791         if (asprintf(&fs, "/proc/%lu/cgroup", (unsigned long) pid) < 0)
792                 return -ENOMEM;
793
794         f = fopen(fs, "re");
795         free(fs);
796
797         if (!f)
798                 return errno == ENOENT ? -ESRCH : -errno;
799
800         cs = strlen(controller);
801
802         while (!feof(f)) {
803                 char line[LINE_MAX];
804                 char *l;
805
806                 errno = 0;
807                 if (!(fgets(line, sizeof(line), f))) {
808                         if (feof(f))
809                                 break;
810
811                         r = errno ? -errno : -EIO;
812                         goto finish;
813                 }
814
815                 truncate_nl(line);
816
817                 if (!(l = strchr(line, ':')))
818                         continue;
819
820                 l++;
821                 if (strncmp(l, controller, cs) != 0)
822                         continue;
823
824                 if (l[cs] != ':')
825                         continue;
826
827                 if (!(p = strdup(l + cs + 1))) {
828                         r = -ENOMEM;
829                         goto finish;
830                 }
831
832                 *path = p;
833                 r = 0;
834                 goto finish;
835         }
836
837         r = -ENOENT;
838
839 finish:
840         fclose(f);
841
842         return r;
843 }
844
845 int cg_install_release_agent(const char *controller, const char *agent) {
846         char *fs = NULL, *contents = NULL, *line = NULL, *sc;
847         int r;
848
849         assert(controller);
850         assert(agent);
851
852         if ((r = cg_get_path(controller, NULL, "release_agent", &fs)) < 0)
853                 return r;
854
855         if ((r = read_one_line_file(fs, &contents)) < 0)
856                 goto finish;
857
858         sc = strstrip(contents);
859         if (sc[0] == 0) {
860
861                 if (asprintf(&line, "%s\n", agent) < 0) {
862                         r = -ENOMEM;
863                         goto finish;
864                 }
865
866                 if ((r = write_one_line_file(fs, line)) < 0)
867                         goto finish;
868
869         } else if (!streq(sc, agent)) {
870                 r = -EEXIST;
871                 goto finish;
872         }
873
874         free(fs);
875         fs = NULL;
876         if ((r = cg_get_path(controller, NULL, "notify_on_release", &fs)) < 0)
877                 goto finish;
878
879         free(contents);
880         contents = NULL;
881         if ((r = read_one_line_file(fs, &contents)) < 0)
882                 goto finish;
883
884         sc = strstrip(contents);
885
886         if (streq(sc, "0")) {
887                 if ((r = write_one_line_file(fs, "1\n")) < 0)
888                         goto finish;
889
890                 r = 1;
891         } else if (!streq(sc, "1")) {
892                 r = -EIO;
893                 goto finish;
894         } else
895                 r = 0;
896
897 finish:
898         free(fs);
899         free(contents);
900         free(line);
901
902         return r;
903 }
904
905 int cg_is_empty(const char *controller, const char *path, bool ignore_self) {
906         pid_t pid = 0, self_pid;
907         int r;
908         FILE *f = NULL;
909         bool found = false;
910
911         assert(path);
912
913         r = cg_enumerate_tasks(controller, path, &f);
914         if (r < 0)
915                 return r == -ENOENT ? 1 : r;
916
917         self_pid = getpid();
918
919         while ((r = cg_read_pid(f, &pid)) > 0) {
920
921                 if (ignore_self && pid == self_pid)
922                         continue;
923
924                 found = true;
925                 break;
926         }
927
928         fclose(f);
929
930         if (r < 0)
931                 return r;
932
933         return !found;
934 }
935
936 int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_self) {
937         int r;
938         DIR *d = NULL;
939         char *fn;
940
941         assert(path);
942
943         r = cg_is_empty(controller, path, ignore_self);
944         if (r <= 0)
945                 return r;
946
947         r = cg_enumerate_subgroups(controller, path, &d);
948         if (r < 0)
949                 return r == -ENOENT ? 1 : r;
950
951         while ((r = cg_read_subgroup(d, &fn)) > 0) {
952                 char *p = NULL;
953
954                 r = asprintf(&p, "%s/%s", path, fn);
955                 free(fn);
956
957                 if (r < 0) {
958                         r = -ENOMEM;
959                         goto finish;
960                 }
961
962                 r = cg_is_empty_recursive(controller, p, ignore_self);
963                 free(p);
964
965                 if (r <= 0)
966                         goto finish;
967         }
968
969         if (r >= 0)
970                 r = 1;
971
972 finish:
973
974         if (d)
975                 closedir(d);
976
977         return r;
978 }
979
980 int cg_split_spec(const char *spec, char **controller, char **path) {
981         const char *e;
982         char *t = NULL, *u = NULL;
983
984         assert(spec);
985         assert(controller || path);
986
987         if (*spec == '/') {
988
989                 if (path) {
990                         if (!(t = strdup(spec)))
991                                 return -ENOMEM;
992
993                         *path = t;
994                 }
995
996                 if (controller)
997                         *controller = NULL;
998
999                 return 0;
1000         }
1001
1002         if (!(e = strchr(spec, ':'))) {
1003
1004                 if (strchr(spec, '/') || spec[0] == 0)
1005                         return -EINVAL;
1006
1007                 if (controller) {
1008                         if (!(t = strdup(spec)))
1009                                 return -ENOMEM;
1010
1011                         *controller = t;
1012                 }
1013
1014                 if (path)
1015                         *path = NULL;
1016
1017                 return 0;
1018         }
1019
1020         if (e[1] != '/' ||
1021             e == spec ||
1022             memchr(spec, '/', e-spec))
1023                 return -EINVAL;
1024
1025         if (controller)
1026                 if (!(t = strndup(spec, e-spec)))
1027                         return -ENOMEM;
1028
1029         if (path)
1030                 if (!(u = strdup(e+1))) {
1031                         free(t);
1032                         return -ENOMEM;
1033                 }
1034
1035         if (controller)
1036                 *controller = t;
1037
1038         if (path)
1039                 *path = u;
1040
1041         return 0;
1042 }
1043
1044 int cg_join_spec(const char *controller, const char *path, char **spec) {
1045         assert(controller);
1046         assert(path);
1047
1048         if (!path_is_absolute(path) ||
1049             controller[0] == 0 ||
1050             strchr(controller, ':') ||
1051             strchr(controller, '/'))
1052                 return -EINVAL;
1053
1054         if (asprintf(spec, "%s:%s", controller, path) < 0)
1055                 return -ENOMEM;
1056
1057         return 0;
1058 }
1059
1060 int cg_fix_path(const char *path, char **result) {
1061         char *t, *c, *p;
1062         int r;
1063
1064         assert(path);
1065         assert(result);
1066
1067         /* First check if it already is a filesystem path */
1068         if (path_startswith(path, "/sys/fs/cgroup") &&
1069             access(path, F_OK) >= 0) {
1070
1071                 t = strdup(path);
1072                 if (!t)
1073                         return -ENOMEM;
1074
1075                 *result = t;
1076                 return 0;
1077         }
1078
1079         /* Otherwise treat it as cg spec */
1080         r = cg_split_spec(path, &c, &p);
1081         if (r < 0)
1082                 return r;
1083
1084         r = cg_get_path(c ? c : SYSTEMD_CGROUP_CONTROLLER, p ? p : "/", NULL, result);
1085         free(c);
1086         free(p);
1087
1088         return r;
1089 }
1090
1091 int cg_get_user_path(char **path) {
1092         char *root, *p;
1093
1094         assert(path);
1095
1096         /* Figure out the place to put user cgroups below. We use the
1097          * same as PID 1 has but with the "/system" suffix replaced by
1098          * "/user" */
1099
1100         if (cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 1, &root) < 0)
1101                 p = strdup("/user");
1102         else {
1103                 if (endswith(root, "/system"))
1104                         root[strlen(root) - 7] = 0;
1105                 else if (streq(root, "/"))
1106                         root[0] = 0;
1107
1108                 p = strappend(root, "/user");
1109                 free(root);
1110         }
1111
1112         if (!p)
1113                 return -ENOMEM;
1114
1115         *path = p;
1116         return 0;
1117 }
1118
1119 char **cg_shorten_controllers(char **controllers) {
1120         char **f, **t;
1121
1122         controllers = strv_uniq(controllers);
1123
1124         if (!controllers)
1125                 return controllers;
1126
1127         for (f = controllers, t = controllers; *f; f++) {
1128                 int r;
1129                 const char *p;
1130
1131                 if (streq(*f, "systemd") || streq(*f, SYSTEMD_CGROUP_CONTROLLER)) {
1132                         free(*f);
1133                         continue;
1134                 }
1135
1136                 p = normalize_controller(*f);
1137
1138                 r = check(p);
1139                 if (r < 0) {
1140                         log_debug("Controller %s is not available, removing from controllers list.", *f);
1141                         free(*f);
1142                         continue;
1143                 }
1144
1145                 *(t++) = *f;
1146         }
1147
1148         *t = NULL;
1149         return controllers;
1150 }