chiark / gitweb /
analyze: add missing --help text entries
[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(
718                 const char *controller,
719                 const char *path,
720                 mode_t mode,
721                 uid_t uid,
722                 gid_t gid,
723                 int sticky) {
724
725         _cleanup_free_ char *fs = NULL, *procs = NULL;
726         int r;
727
728         assert(controller);
729         assert(path);
730
731         if (mode == (mode_t) -1 && uid == (uid_t) -1 && gid == (gid_t) -1 && sticky < 0)
732                 return 0;
733
734         if (mode != (mode_t) -1)
735                 mode &= 0666;
736
737         r = cg_get_path(controller, path, "tasks", &fs);
738         if (r < 0)
739                 return r;
740
741         if (sticky >= 0 && mode != (mode_t) -1)
742                 /* Both mode and sticky param are passed */
743                 mode |= (sticky ? S_ISVTX : 0);
744         else if ((sticky >= 0 && mode == (mode_t) -1) ||
745                  (mode != (mode_t) -1 && sticky < 0)) {
746                 struct stat st;
747
748                 /* Only one param is passed, hence read the current
749                  * mode from the file itself */
750
751                 r = lstat(fs, &st);
752                 if (r < 0)
753                         return -errno;
754
755                 if (mode == (mode_t) -1)
756                         /* No mode set, we just shall set the sticky bit */
757                         mode = (st.st_mode & ~S_ISVTX) | (sticky ? S_ISVTX : 0);
758                 else
759                         /* Only mode set, leave sticky bit untouched */
760                         mode = (st.st_mode & ~0777) | mode;
761         }
762
763         r = chmod_and_chown(fs, mode, uid, gid);
764         if (r < 0)
765                 return r;
766
767         /* Always keep values for "cgroup.procs" in sync with "tasks" */
768         r = cg_get_path(controller, path, "cgroup.procs", &procs);
769         if (r < 0)
770                 return r;
771
772         return chmod_and_chown(procs, mode, uid, gid);
773 }
774
775 int cg_get_by_pid(const char *controller, pid_t pid, char **path) {
776         int r;
777         char *p = NULL;
778         FILE *f;
779         char *fs;
780         size_t cs;
781
782         assert(controller);
783         assert(path);
784         assert(pid >= 0);
785
786         if (pid == 0)
787                 pid = getpid();
788
789         if (asprintf(&fs, "/proc/%lu/cgroup", (unsigned long) pid) < 0)
790                 return -ENOMEM;
791
792         f = fopen(fs, "re");
793         free(fs);
794
795         if (!f)
796                 return errno == ENOENT ? -ESRCH : -errno;
797
798         cs = strlen(controller);
799
800         while (!feof(f)) {
801                 char line[LINE_MAX];
802                 char *l;
803
804                 errno = 0;
805                 if (!(fgets(line, sizeof(line), f))) {
806                         if (feof(f))
807                                 break;
808
809                         r = errno ? -errno : -EIO;
810                         goto finish;
811                 }
812
813                 truncate_nl(line);
814
815                 if (!(l = strchr(line, ':')))
816                         continue;
817
818                 l++;
819                 if (!strneq(l, controller, cs))
820                         continue;
821
822                 if (l[cs] != ':')
823                         continue;
824
825                 if (!(p = strdup(l + cs + 1))) {
826                         r = -ENOMEM;
827                         goto finish;
828                 }
829
830                 *path = p;
831                 r = 0;
832                 goto finish;
833         }
834
835         r = -ENOENT;
836
837 finish:
838         fclose(f);
839
840         return r;
841 }
842
843 int cg_install_release_agent(const char *controller, const char *agent) {
844         char *fs = NULL, *contents = NULL, *line = NULL, *sc;
845         int r;
846
847         assert(controller);
848         assert(agent);
849
850         if ((r = cg_get_path(controller, NULL, "release_agent", &fs)) < 0)
851                 return r;
852
853         if ((r = read_one_line_file(fs, &contents)) < 0)
854                 goto finish;
855
856         sc = strstrip(contents);
857         if (sc[0] == 0) {
858
859                 if (asprintf(&line, "%s\n", agent) < 0) {
860                         r = -ENOMEM;
861                         goto finish;
862                 }
863
864                 r = write_string_file(fs, line);
865                 if (r < 0)
866                         goto finish;
867
868         } else if (!streq(sc, agent)) {
869                 r = -EEXIST;
870                 goto finish;
871         }
872
873         free(fs);
874         fs = NULL;
875         if ((r = cg_get_path(controller, NULL, "notify_on_release", &fs)) < 0)
876                 goto finish;
877
878         free(contents);
879         contents = NULL;
880         if ((r = read_one_line_file(fs, &contents)) < 0)
881                 goto finish;
882
883         sc = strstrip(contents);
884
885         if (streq(sc, "0")) {
886                 if ((r = write_string_file(fs, "1\n")) < 0)
887                         goto finish;
888
889                 r = 1;
890         } else if (!streq(sc, "1")) {
891                 r = -EIO;
892                 goto finish;
893         } else
894                 r = 0;
895
896 finish:
897         free(fs);
898         free(contents);
899         free(line);
900
901         return r;
902 }
903
904 int cg_is_empty(const char *controller, const char *path, bool ignore_self) {
905         pid_t pid = 0, self_pid;
906         int r;
907         FILE *f = NULL;
908         bool found = false;
909
910         assert(path);
911
912         r = cg_enumerate_tasks(controller, path, &f);
913         if (r < 0)
914                 return r == -ENOENT ? 1 : r;
915
916         self_pid = getpid();
917
918         while ((r = cg_read_pid(f, &pid)) > 0) {
919
920                 if (ignore_self && pid == self_pid)
921                         continue;
922
923                 found = true;
924                 break;
925         }
926
927         fclose(f);
928
929         if (r < 0)
930                 return r;
931
932         return !found;
933 }
934
935 int cg_is_empty_by_spec(const char *spec, bool ignore_self) {
936         int r;
937         _cleanup_free_ char *controller = NULL, *path = NULL;
938
939         assert(spec);
940
941         r = cg_split_spec(spec, &controller, &path);
942         if (r < 0)
943                 return r;
944
945         return cg_is_empty(controller, path, ignore_self);
946 }
947
948 int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_self) {
949         int r;
950         DIR *d = NULL;
951         char *fn;
952
953         assert(path);
954
955         r = cg_is_empty(controller, path, ignore_self);
956         if (r <= 0)
957                 return r;
958
959         r = cg_enumerate_subgroups(controller, path, &d);
960         if (r < 0)
961                 return r == -ENOENT ? 1 : r;
962
963         while ((r = cg_read_subgroup(d, &fn)) > 0) {
964                 char *p = NULL;
965
966                 r = asprintf(&p, "%s/%s", path, fn);
967                 free(fn);
968
969                 if (r < 0) {
970                         r = -ENOMEM;
971                         goto finish;
972                 }
973
974                 r = cg_is_empty_recursive(controller, p, ignore_self);
975                 free(p);
976
977                 if (r <= 0)
978                         goto finish;
979         }
980
981         if (r >= 0)
982                 r = 1;
983
984 finish:
985
986         if (d)
987                 closedir(d);
988
989         return r;
990 }
991
992 int cg_split_spec(const char *spec, char **controller, char **path) {
993         const char *e;
994         char *t = NULL, *u = NULL;
995
996         assert(spec);
997
998         if (*spec == '/') {
999                 if (!path_is_safe(spec))
1000                         return -EINVAL;
1001
1002                 if (path) {
1003                         t = strdup(spec);
1004                         if (!t)
1005                                 return -ENOMEM;
1006
1007                         *path = t;
1008                 }
1009
1010                 if (controller)
1011                         *controller = NULL;
1012
1013                 return 0;
1014         }
1015
1016         e = strchr(spec, ':');
1017         if (!e) {
1018                 if (!filename_is_safe(spec))
1019                         return -EINVAL;
1020
1021                 if (controller) {
1022                         t = strdup(spec);
1023                         if (!t)
1024                                 return -ENOMEM;
1025
1026                         *controller = t;
1027                 }
1028
1029                 if (path)
1030                         *path = NULL;
1031
1032                 return 0;
1033         }
1034
1035         t = strndup(spec, e-spec);
1036         if (!t)
1037                 return -ENOMEM;
1038         if (!filename_is_safe(t)) {
1039                 free(t);
1040                 return -EINVAL;
1041         }
1042
1043         u = strdup(e+1);
1044         if (!u) {
1045                 free(t);
1046                 return -ENOMEM;
1047         }
1048         if (!path_is_safe(u)) {
1049                 free(t);
1050                 free(u);
1051                 return -EINVAL;
1052         }
1053
1054         if (controller)
1055                 *controller = t;
1056         else
1057                 free(t);
1058
1059         if (path)
1060                 *path = u;
1061         else
1062                 free(u);
1063
1064         return 0;
1065 }
1066
1067 int cg_join_spec(const char *controller, const char *path, char **spec) {
1068         assert(controller);
1069         assert(path);
1070
1071         if (!path_is_absolute(path) ||
1072             controller[0] == 0 ||
1073             strchr(controller, ':') ||
1074             strchr(controller, '/'))
1075                 return -EINVAL;
1076
1077         if (asprintf(spec, "%s:%s", controller, path) < 0)
1078                 return -ENOMEM;
1079
1080         return 0;
1081 }
1082
1083 int cg_fix_path(const char *path, char **result) {
1084         char *t, *c, *p;
1085         int r;
1086
1087         assert(path);
1088         assert(result);
1089
1090         /* First check if it already is a filesystem path */
1091         if (path_startswith(path, "/sys/fs/cgroup") &&
1092             access(path, F_OK) >= 0) {
1093
1094                 t = strdup(path);
1095                 if (!t)
1096                         return -ENOMEM;
1097
1098                 *result = t;
1099                 return 0;
1100         }
1101
1102         /* Otherwise treat it as cg spec */
1103         r = cg_split_spec(path, &c, &p);
1104         if (r < 0)
1105                 return r;
1106
1107         r = cg_get_path(c ? c : SYSTEMD_CGROUP_CONTROLLER, p ? p : "/", NULL, result);
1108         free(c);
1109         free(p);
1110
1111         return r;
1112 }
1113
1114 int cg_get_user_path(char **path) {
1115         char *root, *p;
1116
1117         assert(path);
1118
1119         /* Figure out the place to put user cgroups below. We use the
1120          * same as PID 1 has but with the "/system" suffix replaced by
1121          * "/user" */
1122
1123         if (cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 1, &root) < 0)
1124                 p = strdup("/user");
1125         else {
1126                 if (endswith(root, "/system"))
1127                         root[strlen(root) - 7] = 0;
1128                 else if (streq(root, "/"))
1129                         root[0] = 0;
1130
1131                 p = strappend(root, "/user");
1132                 free(root);
1133         }
1134
1135         if (!p)
1136                 return -ENOMEM;
1137
1138         *path = p;
1139         return 0;
1140 }
1141
1142 char **cg_shorten_controllers(char **controllers) {
1143         char **f, **t;
1144
1145         controllers = strv_uniq(controllers);
1146
1147         if (!controllers)
1148                 return controllers;
1149
1150         for (f = controllers, t = controllers; *f; f++) {
1151                 int r;
1152                 const char *p;
1153
1154                 if (streq(*f, "systemd") || streq(*f, SYSTEMD_CGROUP_CONTROLLER)) {
1155                         free(*f);
1156                         continue;
1157                 }
1158
1159                 p = normalize_controller(*f);
1160
1161                 r = check(p);
1162                 if (r < 0) {
1163                         log_debug("Controller %s is not available, removing from controllers list.", *f);
1164                         free(*f);
1165                         continue;
1166                 }
1167
1168                 *(t++) = *f;
1169         }
1170
1171         *t = NULL;
1172         return controllers;
1173 }
1174
1175 int cg_pid_get_cgroup(pid_t pid, char **root, char **cgroup) {
1176         char *cg_process, *cg_init, *p;
1177         int r;
1178
1179         assert(pid >= 0);
1180
1181         if (pid == 0)
1182                 pid = getpid();
1183
1184         r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, pid, &cg_process);
1185         if (r < 0)
1186                 return r;
1187
1188         r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 1, &cg_init);
1189         if (r < 0) {
1190                 free(cg_process);
1191                 return r;
1192         }
1193
1194         if (endswith(cg_init, "/system"))
1195                 cg_init[strlen(cg_init)-7] = 0;
1196         else if (streq(cg_init, "/"))
1197                 cg_init[0] = 0;
1198
1199         if (startswith(cg_process, cg_init))
1200                 p = cg_process + strlen(cg_init);
1201         else
1202                 p = cg_process;
1203
1204         free(cg_init);
1205
1206         if (cgroup) {
1207                 char* c;
1208
1209                 c = strdup(p);
1210                 if (!c) {
1211                         free(cg_process);
1212                         return -ENOMEM;
1213                 }
1214
1215                 *cgroup = c;
1216         }
1217
1218         if (root) {
1219                 cg_process[p-cg_process] = 0;
1220                 *root = cg_process;
1221         } else
1222                 free(cg_process);
1223
1224         return 0;
1225 }
1226
1227 static int instance_unit_from_cgroup(char *cgroup){
1228         char *at;
1229
1230         assert(cgroup);
1231
1232         at = strstr(cgroup, "@.");
1233         if (at) {
1234                 /* This is a templated service */
1235
1236                 char *i;
1237                 char _cleanup_free_ *i2 = NULL, *s = NULL;
1238
1239                 i = strchr(at, '/');
1240                 if (!i || !i[1]) /* disallow empty instances */
1241                         return -EINVAL;
1242
1243                 s = strndup(at + 1, i - at - 1);
1244                 i2 = strdup(i + 1);
1245                 if (!s || !i2)
1246                         return -ENOMEM;
1247
1248                 strcpy(at + 1, i2);
1249                 strcat(at + 1, s);
1250         }
1251
1252         return 0;
1253 }
1254
1255 /* non-static only for testing purposes */
1256 int cgroup_to_unit(char *cgroup, char **unit){
1257         int r;
1258         char *p;
1259
1260         assert(cgroup);
1261         assert(unit);
1262
1263         r = instance_unit_from_cgroup(cgroup);
1264         if (r < 0)
1265                 return r;
1266
1267         p = strrchr(cgroup, '/');
1268         assert(p);
1269
1270         r = unit_name_is_valid(p + 1, true);
1271         if (!r)
1272                 return -EINVAL;
1273
1274         *unit = strdup(p + 1);
1275         if (!*unit)
1276                 return -ENOMEM;
1277
1278         return 0;
1279 }
1280
1281 static int cg_pid_get(const char *prefix, pid_t pid, char **unit) {
1282         int r;
1283         char _cleanup_free_ *cgroup = NULL;
1284
1285         assert(pid >= 0);
1286         assert(unit);
1287
1288         r = cg_pid_get_cgroup(pid, NULL, &cgroup);
1289         if (r < 0)
1290                 return r;
1291
1292         if (!startswith(cgroup, prefix))
1293                 return -ENOENT;
1294
1295         r = cgroup_to_unit(cgroup, unit);
1296         return r;
1297 }
1298
1299 int cg_pid_get_unit(pid_t pid, char **unit) {
1300         return cg_pid_get("/system/", pid, unit);
1301 }
1302
1303 int cg_pid_get_user_unit(pid_t pid, char **unit) {
1304         return cg_pid_get("/user/", pid, unit);
1305 }
1306
1307 int cg_controller_from_attr(const char *attr, char **controller) {
1308         const char *dot;
1309         char *c;
1310
1311         assert(attr);
1312         assert(controller);
1313
1314         if (!filename_is_safe(attr))
1315                 return -EINVAL;
1316
1317         dot = strchr(attr, '.');
1318         if (!dot) {
1319                 *controller = NULL;
1320                 return 0;
1321         }
1322
1323         c = strndup(attr, dot - attr);
1324         if (!c)
1325                 return -ENOMEM;
1326
1327         if (!filename_is_safe(c)) {
1328                 free(c);
1329                 return -EINVAL;
1330         }
1331
1332         *controller = c;
1333         return 1;
1334 }