chiark / gitweb /
5647624e8de369f2e6631e79025ceed3bd41411c
[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 General Public License as published by
10   the Free Software Foundation; either version 2 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   General Public License for more details.
17
18   You should have received a copy of the GNU 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 "mkdir.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(controller);
45         assert(path);
46         assert(_f);
47
48         if ((r = cg_get_path(controller, path, "cgroup.procs", &fs)) < 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(controller);
67         assert(path);
68         assert(_f);
69
70         if ((r = cg_get_path(controller, path, "tasks", &fs)) < 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(controller);
111         assert(path);
112         assert(_d);
113
114         /* This is not recursive! */
115
116         if ((r = cg_get_path(controller, path, NULL, &fs)) < 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 int cg_get_path(const char *controller, const char *path, const char *suffix, char **fs) {
507         const char *p;
508         char *t;
509         static __thread bool good = false;
510
511         assert(controller);
512         assert(fs);
513
514         if (_unlikely_(!good)) {
515                 int r;
516
517                 r = path_is_mount_point("/sys/fs/cgroup", false);
518                 if (r <= 0)
519                         return r < 0 ? r : -ENOENT;
520
521                 /* Cache this to save a few stat()s */
522                 good = true;
523         }
524
525         if (isempty(controller))
526                 return -EINVAL;
527
528         /* This is a very minimal lookup from controller names to
529          * paths. Since we have mounted most hierarchies ourselves
530          * should be kinda safe, but eventually we might want to
531          * extend this to have a fallback to actually check
532          * /proc/mounts. Might need caching then. */
533
534         if (streq(controller, SYSTEMD_CGROUP_CONTROLLER))
535                 p = "systemd";
536         else if (startswith(controller, "name="))
537                 p = controller + 5;
538         else
539                 p = controller;
540
541         if (path && suffix)
542                 t = join("/sys/fs/cgroup/", p, "/", path, "/", suffix, NULL);
543         else if (path)
544                 t = join("/sys/fs/cgroup/", p, "/", path, NULL);
545         else if (suffix)
546                 t = join("/sys/fs/cgroup/", p, "/", suffix, NULL);
547         else
548                 t = join("/sys/fs/cgroup/", p, NULL);
549
550         if (!t)
551                 return -ENOMEM;
552
553         path_kill_slashes(t);
554
555         *fs = t;
556         return 0;
557 }
558
559 static int trim_cb(const char *path, const struct stat *sb, int typeflag, struct FTW *ftwbuf) {
560         char *p;
561         bool is_sticky;
562
563         if (typeflag != FTW_DP)
564                 return 0;
565
566         if (ftwbuf->level < 1)
567                 return 0;
568
569         p = strappend(path, "/tasks");
570         if (!p) {
571                 errno = ENOMEM;
572                 return 1;
573         }
574
575         is_sticky = file_is_priv_sticky(p) > 0;
576         free(p);
577
578         if (is_sticky)
579                 return 0;
580
581         rmdir(path);
582         return 0;
583 }
584
585 int cg_trim(const char *controller, const char *path, bool delete_root) {
586         char *fs;
587         int r = 0;
588
589         assert(controller);
590         assert(path);
591
592         r = cg_get_path(controller, path, NULL, &fs);
593         if (r < 0)
594                 return r;
595
596         errno = 0;
597         if (nftw(fs, trim_cb, 64, FTW_DEPTH|FTW_MOUNT|FTW_PHYS) < 0)
598                 r = errno ? -errno : -EIO;
599
600         if (delete_root) {
601                 bool is_sticky;
602                 char *p;
603
604                 p = strappend(fs, "/tasks");
605                 if (!p) {
606                         free(fs);
607                         return -ENOMEM;
608                 }
609
610                 is_sticky = file_is_priv_sticky(p) > 0;
611                 free(p);
612
613                 if (!is_sticky)
614                         if (rmdir(fs) < 0 && errno != ENOENT) {
615                                 if (r == 0)
616                                         r = -errno;
617                         }
618         }
619
620         free(fs);
621
622         return r;
623 }
624
625 int cg_delete(const char *controller, const char *path) {
626         char *parent;
627         int r;
628
629         assert(controller);
630         assert(path);
631
632         if ((r = parent_of_path(path, &parent)) < 0)
633                 return r;
634
635         r = cg_migrate_recursive(controller, path, parent, false, true);
636         free(parent);
637
638         return r == -ENOENT ? 0 : r;
639 }
640
641 int cg_create(const char *controller, const char *path) {
642         char *fs;
643         int r;
644
645         assert(controller);
646         assert(path);
647
648         if ((r = cg_get_path(controller, path, NULL, &fs)) < 0)
649                 return r;
650
651         r = mkdir_parents(fs, 0755);
652
653         if (r >= 0) {
654                 if (mkdir(fs, 0755) >= 0)
655                         r = 1;
656                 else if (errno == EEXIST)
657                         r = 0;
658                 else
659                         r = -errno;
660         }
661
662         free(fs);
663
664         return r;
665 }
666
667 int cg_attach(const char *controller, const char *path, pid_t pid) {
668         char *fs;
669         int r;
670         char c[32];
671
672         assert(controller);
673         assert(path);
674         assert(pid >= 0);
675
676         if ((r = cg_get_path(controller, path, "tasks", &fs)) < 0)
677                 return r;
678
679         if (pid == 0)
680                 pid = getpid();
681
682         snprintf(c, sizeof(c), "%lu\n", (unsigned long) pid);
683         char_array_0(c);
684
685         r = write_one_line_file(fs, c);
686         free(fs);
687
688         return r;
689 }
690
691 int cg_create_and_attach(const char *controller, const char *path, pid_t pid) {
692         int r, q;
693
694         assert(controller);
695         assert(path);
696         assert(pid >= 0);
697
698         if ((r = cg_create(controller, path)) < 0)
699                 return r;
700
701         if ((q = cg_attach(controller, path, pid)) < 0)
702                 return q;
703
704         /* This does not remove the cgroup on failure */
705
706         return r;
707 }
708
709 int cg_set_group_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid) {
710         char *fs;
711         int r;
712
713         assert(controller);
714         assert(path);
715
716         if (mode != (mode_t) -1)
717                 mode &= 0777;
718
719         r = cg_get_path(controller, path, NULL, &fs);
720         if (r < 0)
721                 return r;
722
723         r = chmod_and_chown(fs, mode, uid, gid);
724         free(fs);
725
726         return r;
727 }
728
729 int cg_set_task_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid, int sticky) {
730         char *fs;
731         int r;
732
733         assert(controller);
734         assert(path);
735
736         if (mode == (mode_t) -1 && uid == (uid_t) -1 && gid == (gid_t) -1 && sticky < 0)
737                 return 0;
738
739         if (mode != (mode_t) -1)
740                 mode &= 0666;
741
742         r = cg_get_path(controller, path, "tasks", &fs);
743         if (r < 0)
744                 return r;
745
746         if (sticky >= 0 && mode != (mode_t) -1)
747                 /* Both mode and sticky param are passed */
748                 mode |= (sticky ? S_ISVTX : 0);
749         else if ((sticky >= 0 && mode == (mode_t) -1) ||
750                  (mode != (mode_t) -1 && sticky < 0)) {
751                 struct stat st;
752
753                 /* Only one param is passed, hence read the current
754                  * mode from the file itself */
755
756                 r = lstat(fs, &st);
757                 if (r < 0) {
758                         free(fs);
759                         return -errno;
760                 }
761
762                 if (mode == (mode_t) -1)
763                         /* No mode set, we just shall set the sticky bit */
764                         mode = (st.st_mode & ~S_ISVTX) | (sticky ? S_ISVTX : 0);
765                 else
766                         /* Only mode set, leave sticky bit untouched */
767                         mode = (st.st_mode & ~0777) | mode;
768         }
769
770         r = chmod_and_chown(fs, mode, uid, gid);
771         free(fs);
772
773         return r;
774 }
775
776 int cg_get_by_pid(const char *controller, pid_t pid, char **path) {
777         int r;
778         char *p = NULL;
779         FILE *f;
780         char *fs;
781         size_t cs;
782
783         assert(controller);
784         assert(path);
785         assert(pid >= 0);
786
787         if (pid == 0)
788                 pid = getpid();
789
790         if (asprintf(&fs, "/proc/%lu/cgroup", (unsigned long) pid) < 0)
791                 return -ENOMEM;
792
793         f = fopen(fs, "re");
794         free(fs);
795
796         if (!f)
797                 return errno == ENOENT ? -ESRCH : -errno;
798
799         cs = strlen(controller);
800
801         while (!feof(f)) {
802                 char line[LINE_MAX];
803                 char *l;
804
805                 errno = 0;
806                 if (!(fgets(line, sizeof(line), f))) {
807                         if (feof(f))
808                                 break;
809
810                         r = errno ? -errno : -EIO;
811                         goto finish;
812                 }
813
814                 truncate_nl(line);
815
816                 if (!(l = strchr(line, ':')))
817                         continue;
818
819                 l++;
820                 if (strncmp(l, controller, cs) != 0)
821                         continue;
822
823                 if (l[cs] != ':')
824                         continue;
825
826                 if (!(p = strdup(l + cs + 1))) {
827                         r = -ENOMEM;
828                         goto finish;
829                 }
830
831                 *path = p;
832                 r = 0;
833                 goto finish;
834         }
835
836         r = -ENOENT;
837
838 finish:
839         fclose(f);
840
841         return r;
842 }
843
844 int cg_install_release_agent(const char *controller, const char *agent) {
845         char *fs = NULL, *contents = NULL, *line = NULL, *sc;
846         int r;
847
848         assert(controller);
849         assert(agent);
850
851         if ((r = cg_get_path(controller, NULL, "release_agent", &fs)) < 0)
852                 return r;
853
854         if ((r = read_one_line_file(fs, &contents)) < 0)
855                 goto finish;
856
857         sc = strstrip(contents);
858         if (sc[0] == 0) {
859
860                 if (asprintf(&line, "%s\n", agent) < 0) {
861                         r = -ENOMEM;
862                         goto finish;
863                 }
864
865                 if ((r = write_one_line_file(fs, line)) < 0)
866                         goto finish;
867
868         } else if (!streq(sc, agent)) {
869                 r = -EEXIST;
870                 goto finish;
871         }
872
873         free(fs);
874         fs = NULL;
875         if ((r = cg_get_path(controller, NULL, "notify_on_release", &fs)) < 0)
876                 goto finish;
877
878         free(contents);
879         contents = NULL;
880         if ((r = read_one_line_file(fs, &contents)) < 0)
881                 goto finish;
882
883         sc = strstrip(contents);
884
885         if (streq(sc, "0")) {
886                 if ((r = write_one_line_file(fs, "1\n")) < 0)
887                         goto finish;
888
889                 r = 1;
890         } else if (!streq(sc, "1")) {
891                 r = -EIO;
892                 goto finish;
893         } else
894                 r = 0;
895
896 finish:
897         free(fs);
898         free(contents);
899         free(line);
900
901         return r;
902 }
903
904 int cg_is_empty(const char *controller, const char *path, bool ignore_self) {
905         pid_t pid = 0;
906         int r;
907         FILE *f = NULL;
908         bool found = false;
909
910         assert(controller);
911         assert(path);
912
913         if ((r = cg_enumerate_tasks(controller, path, &f)) < 0)
914                 return r == -ENOENT ? 1 : r;
915
916         while ((r = cg_read_pid(f, &pid)) > 0) {
917
918                 if (ignore_self && pid == getpid())
919                         continue;
920
921                 found = true;
922                 break;
923         }
924
925         fclose(f);
926
927         if (r < 0)
928                 return r;
929
930         return !found;
931 }
932
933 int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_self) {
934         int r;
935         DIR *d = NULL;
936         char *fn;
937
938         assert(controller);
939         assert(path);
940
941         if ((r = cg_is_empty(controller, path, ignore_self)) <= 0)
942                 return r;
943
944         if ((r = cg_enumerate_subgroups(controller, path, &d)) < 0)
945                 return r == -ENOENT ? 1 : r;
946
947         while ((r = cg_read_subgroup(d, &fn)) > 0) {
948                 char *p = NULL;
949
950                 r = asprintf(&p, "%s/%s", path, fn);
951                 free(fn);
952
953                 if (r < 0) {
954                         r = -ENOMEM;
955                         goto finish;
956                 }
957
958                 r = cg_is_empty_recursive(controller, p, ignore_self);
959                 free(p);
960
961                 if (r <= 0)
962                         goto finish;
963         }
964
965         if (r >= 0)
966                 r = 1;
967
968 finish:
969
970         if (d)
971                 closedir(d);
972
973         return r;
974 }
975
976 int cg_split_spec(const char *spec, char **controller, char **path) {
977         const char *e;
978         char *t = NULL, *u = NULL;
979
980         assert(spec);
981         assert(controller || path);
982
983         if (*spec == '/') {
984
985                 if (path) {
986                         if (!(t = strdup(spec)))
987                                 return -ENOMEM;
988
989                         *path = t;
990                 }
991
992                 if (controller)
993                         *controller = NULL;
994
995                 return 0;
996         }
997
998         if (!(e = strchr(spec, ':'))) {
999
1000                 if (strchr(spec, '/') || spec[0] == 0)
1001                         return -EINVAL;
1002
1003                 if (controller) {
1004                         if (!(t = strdup(spec)))
1005                                 return -ENOMEM;
1006
1007                         *controller = t;
1008                 }
1009
1010                 if (path)
1011                         *path = NULL;
1012
1013                 return 0;
1014         }
1015
1016         if (e[1] != '/' ||
1017             e == spec ||
1018             memchr(spec, '/', e-spec))
1019                 return -EINVAL;
1020
1021         if (controller)
1022                 if (!(t = strndup(spec, e-spec)))
1023                         return -ENOMEM;
1024
1025         if (path)
1026                 if (!(u = strdup(e+1))) {
1027                         free(t);
1028                         return -ENOMEM;
1029                 }
1030
1031         if (controller)
1032                 *controller = t;
1033
1034         if (path)
1035                 *path = u;
1036
1037         return 0;
1038 }
1039
1040 int cg_join_spec(const char *controller, const char *path, char **spec) {
1041         assert(controller);
1042         assert(path);
1043
1044         if (!path_is_absolute(path) ||
1045             controller[0] == 0 ||
1046             strchr(controller, ':') ||
1047             strchr(controller, '/'))
1048                 return -EINVAL;
1049
1050         if (asprintf(spec, "%s:%s", controller, path) < 0)
1051                 return -ENOMEM;
1052
1053         return 0;
1054 }
1055
1056 int cg_fix_path(const char *path, char **result) {
1057         char *t, *c, *p;
1058         int r;
1059
1060         assert(path);
1061         assert(result);
1062
1063         /* First check if it already is a filesystem path */
1064         if (path_is_absolute(path) &&
1065             path_startswith(path, "/sys/fs/cgroup") &&
1066             access(path, F_OK) >= 0) {
1067
1068                 if (!(t = strdup(path)))
1069                         return -ENOMEM;
1070
1071                 *result = t;
1072                 return 0;
1073         }
1074
1075         /* Otherwise treat it as cg spec */
1076         if ((r = cg_split_spec(path, &c, &p)) < 0)
1077                 return r;
1078
1079         r = cg_get_path(c ? c : SYSTEMD_CGROUP_CONTROLLER, p ? p : "/", NULL, result);
1080         free(c);
1081         free(p);
1082
1083         return r;
1084 }
1085
1086 int cg_get_user_path(char **path) {
1087         char *root, *p;
1088
1089         assert(path);
1090
1091         /* Figure out the place to put user cgroups below. We use the
1092          * same as PID 1 has but with the "/system" suffix replaced by
1093          * "/user" */
1094
1095         if (cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 1, &root) < 0)
1096                 p = strdup("/user");
1097         else {
1098                 if (endswith(root, "/system"))
1099                         root[strlen(root) - 7] = 0;
1100                 else if (streq(root, "/"))
1101                         root[0] = 0;
1102
1103                 p = strappend(root, "/user");
1104                 free(root);
1105         }
1106
1107         if (!p)
1108                 return -ENOMEM;
1109
1110         *path = p;
1111         return 0;
1112 }