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