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