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