chiark / gitweb /
74889b636324dea71c0426e05740198a5f21286b
[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 #include "special.h"
42 #include "mkdir.h"
43
44 int cg_enumerate_processes(const char *controller, const char *path, FILE **_f) {
45         _cleanup_free_ char *fs = NULL;
46         FILE *f;
47         int r;
48
49         assert(_f);
50
51         r = cg_get_path(controller, path, "cgroup.procs", &fs);
52         if (r < 0)
53                 return r;
54
55         f = fopen(fs, "re");
56         if (!f)
57                 return -errno;
58
59         *_f = f;
60         return 0;
61 }
62
63 int cg_read_pid(FILE *f, pid_t *_pid) {
64         unsigned long ul;
65
66         /* Note that the cgroup.procs might contain duplicates! See
67          * cgroups.txt for details. */
68
69         assert(f);
70         assert(_pid);
71
72         errno = 0;
73         if (fscanf(f, "%lu", &ul) != 1) {
74
75                 if (feof(f))
76                         return 0;
77
78                 return errno ? -errno : -EIO;
79         }
80
81         if (ul <= 0)
82                 return -EIO;
83
84         *_pid = (pid_t) ul;
85         return 1;
86 }
87
88 int cg_enumerate_subgroups(const char *controller, const char *path, DIR **_d) {
89         _cleanup_free_ char *fs = NULL;
90         int r;
91         DIR *d;
92
93         assert(_d);
94
95         /* This is not recursive! */
96
97         r = cg_get_path(controller, path, NULL, &fs);
98         if (r < 0)
99                 return r;
100
101         d = opendir(fs);
102         if (!d)
103                 return -errno;
104
105         *_d = d;
106         return 0;
107 }
108
109 int cg_read_subgroup(DIR *d, char **fn) {
110         struct dirent *de;
111
112         assert(d);
113         assert(fn);
114
115         FOREACH_DIRENT(de, d, return -errno) {
116                 char *b;
117
118                 if (de->d_type != DT_DIR)
119                         continue;
120
121                 if (streq(de->d_name, ".") ||
122                     streq(de->d_name, ".."))
123                         continue;
124
125                 b = strdup(de->d_name);
126                 if (!b)
127                         return -ENOMEM;
128
129                 *fn = b;
130                 return 1;
131         }
132
133         return 0;
134 }
135
136 int cg_rmdir(const char *controller, const char *path) {
137         _cleanup_free_ char *p = NULL;
138         int r;
139
140         r = cg_get_path(controller, path, NULL, &p);
141         if (r < 0)
142                 return r;
143
144         r = rmdir(p);
145         if (r < 0 && errno != ENOENT)
146                 return -errno;
147
148         return 0;
149 }
150
151 int cg_kill(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, Set *s) {
152         _cleanup_set_free_ Set *allocated_set = NULL;
153         bool done = false;
154         int r, ret = 0;
155         pid_t my_pid;
156
157         assert(sig >= 0);
158
159         /* This goes through the tasks list and kills them all. This
160          * is repeated until no further processes are added to the
161          * tasks list, to properly handle forking processes */
162
163         if (!s) {
164                 s = allocated_set = set_new(trivial_hash_func, trivial_compare_func);
165                 if (!s)
166                         return -ENOMEM;
167         }
168
169         my_pid = getpid();
170
171         do {
172                 _cleanup_fclose_ FILE *f = NULL;
173                 pid_t pid = 0;
174                 done = true;
175
176                 r = cg_enumerate_processes(controller, path, &f);
177                 if (r < 0) {
178                         if (ret >= 0 && r != -ENOENT)
179                                 return r;
180
181                         return ret;
182                 }
183
184                 while ((r = cg_read_pid(f, &pid)) > 0) {
185
186                         if (ignore_self && pid == my_pid)
187                                 continue;
188
189                         if (set_get(s, LONG_TO_PTR(pid)) == LONG_TO_PTR(pid))
190                                 continue;
191
192                         /* If we haven't killed this process yet, kill
193                          * it */
194                         if (kill(pid, sig) < 0) {
195                                 if (ret >= 0 && errno != ESRCH)
196                                         ret = -errno;
197                         } else if (ret == 0) {
198
199                                 if (sigcont)
200                                         kill(pid, SIGCONT);
201
202                                 ret = 1;
203                         }
204
205                         done = false;
206
207                         r = set_put(s, LONG_TO_PTR(pid));
208                         if (r < 0) {
209                                 if (ret >= 0)
210                                         return r;
211
212                                 return ret;
213                         }
214                 }
215
216                 if (r < 0) {
217                         if (ret >= 0)
218                                 return r;
219
220                         return ret;
221                 }
222
223                 /* To avoid racing against processes which fork
224                  * quicker than we can kill them we repeat this until
225                  * no new pids need to be killed. */
226
227         } while (!done);
228
229         return ret;
230 }
231
232 int cg_kill_recursive(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, bool rem, Set *s) {
233         _cleanup_set_free_ Set *allocated_set = NULL;
234         _cleanup_closedir_ DIR *d = NULL;
235         int r, ret = 0;
236         char *fn;
237
238         assert(path);
239         assert(sig >= 0);
240
241         if (!s) {
242                 s = allocated_set = set_new(trivial_hash_func, trivial_compare_func);
243                 if (!s)
244                         return -ENOMEM;
245         }
246
247         ret = cg_kill(controller, path, sig, sigcont, ignore_self, s);
248
249         r = cg_enumerate_subgroups(controller, path, &d);
250         if (r < 0) {
251                 if (ret >= 0 && r != -ENOENT)
252                         return r;
253
254                 return ret;
255         }
256
257         while ((r = cg_read_subgroup(d, &fn)) > 0) {
258                 _cleanup_free_ char *p = NULL;
259
260                 p = strjoin(path, "/", fn, NULL);
261                 free(fn);
262                 if (!p)
263                         return -ENOMEM;
264
265                 r = cg_kill_recursive(controller, p, sig, sigcont, ignore_self, rem, s);
266                 if (ret >= 0 && r != 0)
267                         ret = r;
268         }
269
270         if (ret >= 0 && r < 0)
271                 ret = r;
272
273         if (rem) {
274                 r = cg_rmdir(controller, path);
275                 if (r < 0 && ret >= 0 && r != -ENOENT && r != -EBUSY)
276                         return r;
277         }
278
279         return ret;
280 }
281
282 int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self) {
283         bool done = false;
284         _cleanup_set_free_ Set *s = NULL;
285         int r, ret = 0;
286         pid_t my_pid;
287
288         assert(cfrom);
289         assert(pfrom);
290         assert(cto);
291         assert(pto);
292
293         s = set_new(trivial_hash_func, trivial_compare_func);
294         if (!s)
295                 return -ENOMEM;
296
297         my_pid = getpid();
298
299         do {
300                 _cleanup_fclose_ FILE *f = NULL;
301                 pid_t pid = 0;
302                 done = true;
303
304                 r = cg_enumerate_processes(cfrom, pfrom, &f);
305                 if (r < 0) {
306                         if (ret >= 0 && r != -ENOENT)
307                                 return r;
308
309                         return ret;
310                 }
311
312                 while ((r = cg_read_pid(f, &pid)) > 0) {
313
314                         /* This might do weird stuff if we aren't a
315                          * single-threaded program. However, we
316                          * luckily know we are not */
317                         if (ignore_self && pid == my_pid)
318                                 continue;
319
320                         if (set_get(s, LONG_TO_PTR(pid)) == LONG_TO_PTR(pid))
321                                 continue;
322
323                         r = cg_attach(cto, pto, pid);
324                         if (r < 0) {
325                                 if (ret >= 0 && r != -ESRCH)
326                                         ret = r;
327                         } else if (ret == 0)
328                                 ret = 1;
329
330                         done = false;
331
332                         r = set_put(s, LONG_TO_PTR(pid));
333                         if (r < 0) {
334                                 if (ret >= 0)
335                                         return r;
336
337                                 return ret;
338                         }
339                 }
340
341                 if (r < 0) {
342                         if (ret >= 0)
343                                 return r;
344
345                         return ret;
346                 }
347         } while (!done);
348
349         return ret;
350 }
351
352 int cg_migrate_recursive(
353                 const char *cfrom,
354                 const char *pfrom,
355                 const char *cto,
356                 const char *pto,
357                 bool ignore_self,
358                 bool rem) {
359
360         _cleanup_closedir_ DIR *d = NULL;
361         int r, ret = 0;
362         char *fn;
363
364         assert(cfrom);
365         assert(pfrom);
366         assert(cto);
367         assert(pto);
368
369         ret = cg_migrate(cfrom, pfrom, cto, pto, ignore_self);
370
371         r = cg_enumerate_subgroups(cfrom, pfrom, &d);
372         if (r < 0) {
373                 if (ret >= 0 && r != -ENOENT)
374                         return r;
375
376                 return ret;
377         }
378
379         while ((r = cg_read_subgroup(d, &fn)) > 0) {
380                 _cleanup_free_ char *p = NULL;
381
382                 p = strjoin(pfrom, "/", fn, NULL);
383                 free(fn);
384                 if (!p) {
385                         if (ret >= 0)
386                                 return -ENOMEM;
387
388                         return ret;
389                 }
390
391                 r = cg_migrate_recursive(cfrom, p, cto, pto, ignore_self, rem);
392                 if (r != 0 && ret >= 0)
393                         ret = r;
394         }
395
396         if (r < 0 && ret >= 0)
397                 ret = r;
398
399         if (rem) {
400                 r = cg_rmdir(cfrom, pfrom);
401                 if (r < 0 && ret >= 0 && r != -ENOENT && r != -EBUSY)
402                         return r;
403         }
404
405         return ret;
406 }
407
408 int cg_migrate_recursive_fallback(
409                 const char *cfrom,
410                 const char *pfrom,
411                 const char *cto,
412                 const char *pto,
413                 bool ignore_self,
414                 bool rem) {
415
416         int r;
417
418         assert(cfrom);
419         assert(pfrom);
420         assert(cto);
421         assert(pto);
422
423         r = cg_migrate_recursive(cfrom, pfrom, cto, pto, ignore_self, rem);
424         if (r < 0) {
425                 char prefix[strlen(pto) + 1];
426
427                 /* This didn't work? Then let's try all prefixes of the destination */
428
429                 PATH_FOREACH_PREFIX(prefix, pto) {
430                         r = cg_migrate_recursive(cfrom, pfrom, cto, prefix, ignore_self, rem);
431                         if (r >= 0)
432                                 break;
433                 }
434         }
435
436         return 0;
437 }
438
439 static const char *normalize_controller(const char *controller) {
440
441         assert(controller);
442
443         if (streq(controller, SYSTEMD_CGROUP_CONTROLLER))
444                 return "systemd";
445         else if (startswith(controller, "name="))
446                 return controller + 5;
447         else
448                 return controller;
449 }
450
451 static int join_path(const char *controller, const char *path, const char *suffix, char **fs) {
452         char *t = NULL;
453
454         if (!isempty(controller)) {
455                 if (!isempty(path) && !isempty(suffix))
456                         t = strjoin("/sys/fs/cgroup/", controller, "/", path, "/", suffix, NULL);
457                 else if (!isempty(path))
458                         t = strjoin("/sys/fs/cgroup/", controller, "/", path, NULL);
459                 else if (!isempty(suffix))
460                         t = strjoin("/sys/fs/cgroup/", controller, "/", suffix, NULL);
461                 else
462                         t = strappend("/sys/fs/cgroup/", controller);
463         } else {
464                 if (!isempty(path) && !isempty(suffix))
465                         t = strjoin(path, "/", suffix, NULL);
466                 else if (!isempty(path))
467                         t = strdup(path);
468                 else
469                         return -EINVAL;
470         }
471
472         if (!t)
473                 return -ENOMEM;
474
475         path_kill_slashes(t);
476
477         *fs = t;
478         return 0;
479 }
480
481 int cg_get_path(const char *controller, const char *path, const char *suffix, char **fs) {
482         const char *p;
483         static thread_local bool good = false;
484
485         assert(fs);
486
487         if (controller && !cg_controller_is_valid(controller, true))
488                 return -EINVAL;
489
490         if (_unlikely_(!good)) {
491                 int r;
492
493                 r = path_is_mount_point("/sys/fs/cgroup", false);
494                 if (r <= 0)
495                         return r < 0 ? r : -ENOENT;
496
497                 /* Cache this to save a few stat()s */
498                 good = true;
499         }
500
501         p = controller ? normalize_controller(controller) : NULL;
502
503         return join_path(p, path, suffix, fs);
504 }
505
506 static int check_hierarchy(const char *p) {
507         char *cc;
508
509         assert(p);
510
511         /* Check if this controller actually really exists */
512         cc = alloca(sizeof("/sys/fs/cgroup/") + strlen(p));
513         strcpy(stpcpy(cc, "/sys/fs/cgroup/"), p);
514         if (access(cc, F_OK) < 0)
515                 return -errno;
516
517         return 0;
518 }
519
520 int cg_get_path_and_check(const char *controller, const char *path, const char *suffix, char **fs) {
521         const char *p;
522         int r;
523
524         assert(fs);
525
526         if (!cg_controller_is_valid(controller, true))
527                 return -EINVAL;
528
529         /* Normalize the controller syntax */
530         p = normalize_controller(controller);
531
532         /* Check if this controller actually really exists */
533         r = check_hierarchy(p);
534         if (r < 0)
535                 return r;
536
537         return join_path(p, path, suffix, fs);
538 }
539
540 static int trim_cb(const char *path, const struct stat *sb, int typeflag, struct FTW *ftwbuf) {
541         assert(path);
542         assert(sb);
543         assert(ftwbuf);
544
545         if (typeflag != FTW_DP)
546                 return 0;
547
548         if (ftwbuf->level < 1)
549                 return 0;
550
551         rmdir(path);
552         return 0;
553 }
554
555 int cg_trim(const char *controller, const char *path, bool delete_root) {
556         _cleanup_free_ char *fs = NULL;
557         int r = 0;
558
559         assert(path);
560
561         r = cg_get_path(controller, path, NULL, &fs);
562         if (r < 0)
563                 return r;
564
565         errno = 0;
566         if (nftw(fs, trim_cb, 64, FTW_DEPTH|FTW_MOUNT|FTW_PHYS) != 0)
567                 r = errno ? -errno : -EIO;
568
569         if (delete_root) {
570                 if (rmdir(fs) < 0 && errno != ENOENT)
571                         return -errno;
572         }
573
574         return r;
575 }
576
577 int cg_delete(const char *controller, const char *path) {
578         _cleanup_free_ char *parent = NULL;
579         int r;
580
581         assert(path);
582
583         r = path_get_parent(path, &parent);
584         if (r < 0)
585                 return r;
586
587         r = cg_migrate_recursive(controller, path, controller, parent, false, true);
588         return r == -ENOENT ? 0 : r;
589 }
590
591 int cg_create(const char *controller, const char *path) {
592         _cleanup_free_ char *fs = NULL;
593         int r;
594
595         r = cg_get_path_and_check(controller, path, NULL, &fs);
596         if (r < 0)
597                 return r;
598
599         r = mkdir_parents(fs, 0755);
600         if (r < 0)
601                 return r;
602
603         if (mkdir(fs, 0755) < 0) {
604
605                 if (errno == EEXIST)
606                         return 0;
607
608                 return -errno;
609         }
610
611         return 1;
612 }
613
614 int cg_create_and_attach(const char *controller, const char *path, pid_t pid) {
615         int r, q;
616
617         assert(pid >= 0);
618
619         r = cg_create(controller, path);
620         if (r < 0)
621                 return r;
622
623         q = cg_attach(controller, path, pid);
624         if (q < 0)
625                 return q;
626
627         /* This does not remove the cgroup on failure */
628         return r;
629 }
630
631 int cg_attach(const char *controller, const char *path, pid_t pid) {
632         _cleanup_free_ char *fs = NULL;
633         char c[DECIMAL_STR_MAX(pid_t) + 2];
634         int r;
635
636         assert(path);
637         assert(pid >= 0);
638
639         r = cg_get_path_and_check(controller, path, "cgroup.procs", &fs);
640         if (r < 0)
641                 return r;
642
643         if (pid == 0)
644                 pid = getpid();
645
646         snprintf(c, sizeof(c), "%lu\n", (unsigned long) pid);
647
648         return write_string_file(fs, c);
649 }
650
651 int cg_attach_fallback(const char *controller, const char *path, pid_t pid) {
652         int r;
653
654         assert(controller);
655         assert(path);
656         assert(pid >= 0);
657
658         r = cg_attach(controller, path, pid);
659         if (r < 0) {
660                 char prefix[strlen(path) + 1];
661
662                 /* This didn't work? Then let's try all prefixes of
663                  * the destination */
664
665                 PATH_FOREACH_PREFIX(prefix, path) {
666                         r = cg_attach(controller, prefix, pid);
667                         if (r >= 0)
668                                 break;
669                 }
670         }
671
672         return 0;
673 }
674
675 int cg_set_group_access(
676                 const char *controller,
677                 const char *path,
678                 mode_t mode,
679                 uid_t uid,
680                 gid_t gid) {
681
682         _cleanup_free_ char *fs = NULL;
683         int r;
684
685         assert(path);
686
687         if (mode != (mode_t) -1)
688                 mode &= 0777;
689
690         r = cg_get_path(controller, path, NULL, &fs);
691         if (r < 0)
692                 return r;
693
694         return chmod_and_chown(fs, mode, uid, gid);
695 }
696
697 int cg_set_task_access(
698                 const char *controller,
699                 const char *path,
700                 mode_t mode,
701                 uid_t uid,
702                 gid_t gid) {
703
704         _cleanup_free_ char *fs = NULL, *procs = NULL;
705         int r;
706
707         assert(path);
708
709         if (mode == (mode_t) -1 && uid == (uid_t) -1 && gid == (gid_t) -1)
710                 return 0;
711
712         if (mode != (mode_t) -1)
713                 mode &= 0666;
714
715         r = cg_get_path(controller, path, "cgroup.procs", &fs);
716         if (r < 0)
717                 return r;
718
719         r = chmod_and_chown(fs, mode, uid, gid);
720         if (r < 0)
721                 return r;
722
723         /* Compatibility, Always keep values for "tasks" in sync with
724          * "cgroup.procs" */
725         r = cg_get_path(controller, path, "tasks", &procs);
726         if (r < 0)
727                 return r;
728
729         return chmod_and_chown(procs, mode, uid, gid);
730 }
731
732 int cg_pid_get_path(const char *controller, pid_t pid, char **path) {
733         _cleanup_fclose_ FILE *f = NULL;
734         char line[LINE_MAX];
735         const char *fs;
736         size_t cs;
737
738         assert(path);
739         assert(pid >= 0);
740
741         if (controller) {
742                 if (!cg_controller_is_valid(controller, true))
743                         return -EINVAL;
744
745                 controller = normalize_controller(controller);
746         } else
747                 controller = SYSTEMD_CGROUP_CONTROLLER;
748
749         if (pid == 0)
750                 fs = "/proc/self/cgroup";
751         else
752                 fs = procfs_file_alloca(pid, "cgroup");
753
754         f = fopen(fs, "re");
755         if (!f)
756                 return errno == ENOENT ? -ESRCH : -errno;
757
758         cs = strlen(controller);
759
760         FOREACH_LINE(line, f, return -errno) {
761                 char *l, *p, *w, *e;
762                 size_t k;
763                 char *state;
764                 bool found = false;
765
766                 truncate_nl(line);
767
768                 l = strchr(line, ':');
769                 if (!l)
770                         continue;
771
772                 l++;
773                 e = strchr(l, ':');
774                 if (!e)
775                         continue;
776
777                 *e = 0;
778
779                 FOREACH_WORD_SEPARATOR(w, k, l, ",", state) {
780
781                         if (k == cs && memcmp(w, controller, cs) == 0) {
782                                 found = true;
783                                 break;
784                         }
785
786                         if (k == 5 + cs &&
787                             memcmp(w, "name=", 5) == 0 &&
788                             memcmp(w+5, controller, cs) == 0) {
789                                 found = true;
790                                 break;
791                         }
792                 }
793
794                 if (!found)
795                         continue;
796
797                 p = strdup(e + 1);
798                 if (!p)
799                         return -ENOMEM;
800
801                 *path = p;
802                 return 0;
803         }
804
805         return -ENOENT;
806 }
807
808 int cg_install_release_agent(const char *controller, const char *agent) {
809         _cleanup_free_ char *fs = NULL, *contents = NULL;
810         char *sc;
811         int r;
812
813         assert(agent);
814
815         r = cg_get_path(controller, NULL, "release_agent", &fs);
816         if (r < 0)
817                 return r;
818
819         r = read_one_line_file(fs, &contents);
820         if (r < 0)
821                 return r;
822
823         sc = strstrip(contents);
824         if (sc[0] == 0) {
825                 r = write_string_file(fs, agent);
826                 if (r < 0)
827                         return r;
828         } else if (!streq(sc, agent))
829                 return -EEXIST;
830
831         free(fs);
832         fs = NULL;
833         r = cg_get_path(controller, NULL, "notify_on_release", &fs);
834         if (r < 0)
835                 return r;
836
837         free(contents);
838         contents = NULL;
839         r = read_one_line_file(fs, &contents);
840         if (r < 0)
841                 return r;
842
843         sc = strstrip(contents);
844         if (streq(sc, "0")) {
845                 r = write_string_file(fs, "1");
846                 if (r < 0)
847                         return r;
848
849                 return 1;
850         }
851
852         if (!streq(sc, "1"))
853                 return -EIO;
854
855         return 0;
856 }
857
858 int cg_uninstall_release_agent(const char *controller) {
859         _cleanup_free_ char *fs = NULL;
860         int r;
861
862         r = cg_get_path(controller, NULL, "notify_on_release", &fs);
863         if (r < 0)
864                 return r;
865
866         r = write_string_file(fs, "0");
867         if (r < 0)
868                 return r;
869
870         free(fs);
871         fs = NULL;
872
873         r = cg_get_path(controller, NULL, "release_agent", &fs);
874         if (r < 0)
875                 return r;
876
877         r = write_string_file(fs, "");
878         if (r < 0)
879                 return r;
880
881         return 0;
882 }
883
884 int cg_is_empty(const char *controller, const char *path, bool ignore_self) {
885         _cleanup_fclose_ FILE *f = NULL;
886         pid_t pid = 0, self_pid;
887         bool found = false;
888         int r;
889
890         assert(path);
891
892         r = cg_enumerate_processes(controller, path, &f);
893         if (r < 0)
894                 return r == -ENOENT ? 1 : r;
895
896         self_pid = getpid();
897
898         while ((r = cg_read_pid(f, &pid)) > 0) {
899
900                 if (ignore_self && pid == self_pid)
901                         continue;
902
903                 found = true;
904                 break;
905         }
906
907         if (r < 0)
908                 return r;
909
910         return !found;
911 }
912
913 int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_self) {
914         _cleanup_closedir_ DIR *d = NULL;
915         char *fn;
916         int r;
917
918         assert(path);
919
920         r = cg_is_empty(controller, path, ignore_self);
921         if (r <= 0)
922                 return r;
923
924         r = cg_enumerate_subgroups(controller, path, &d);
925         if (r < 0)
926                 return r == -ENOENT ? 1 : r;
927
928         while ((r = cg_read_subgroup(d, &fn)) > 0) {
929                 _cleanup_free_ char *p = NULL;
930
931                 p = strjoin(path, "/", fn, NULL);
932                 free(fn);
933                 if (!p)
934                         return -ENOMEM;
935
936                 r = cg_is_empty_recursive(controller, p, ignore_self);
937                 if (r <= 0)
938                         return r;
939         }
940
941         if (r < 0)
942                 return r;
943
944         return 1;
945 }
946
947 int cg_split_spec(const char *spec, char **controller, char **path) {
948         const char *e;
949         char *t = NULL, *u = NULL;
950         _cleanup_free_ char *v = NULL;
951
952         assert(spec);
953
954         if (*spec == '/') {
955                 if (!path_is_safe(spec))
956                         return -EINVAL;
957
958                 if (path) {
959                         t = strdup(spec);
960                         if (!t)
961                                 return -ENOMEM;
962
963                         path_kill_slashes(t);
964                         *path = t;
965                 }
966
967                 if (controller)
968                         *controller = NULL;
969
970                 return 0;
971         }
972
973         e = strchr(spec, ':');
974         if (!e) {
975                 if (!cg_controller_is_valid(spec, true))
976                         return -EINVAL;
977
978                 if (controller) {
979                         t = strdup(normalize_controller(spec));
980                         if (!t)
981                                 return -ENOMEM;
982
983                         *controller = t;
984                 }
985
986                 if (path)
987                         *path = NULL;
988
989                 return 0;
990         }
991
992         v = strndup(spec, e-spec);
993         if (!v)
994                 return -ENOMEM;
995         t = strdup(normalize_controller(v));
996         if (!t)
997                 return -ENOMEM;
998         if (!cg_controller_is_valid(t, true)) {
999                 free(t);
1000                 return -EINVAL;
1001         }
1002
1003         if (streq(e+1, "")) {
1004                 u = strdup("/");
1005                 if (!u) {
1006                         free(t);
1007                         return -ENOMEM;
1008                 }
1009         } else {
1010                 u = strdup(e+1);
1011                 if (!u) {
1012                         free(t);
1013                         return -ENOMEM;
1014                 }
1015
1016                 if (!path_is_safe(u) ||
1017                     !path_is_absolute(u)) {
1018                         free(t);
1019                         free(u);
1020                         return -EINVAL;
1021                 }
1022
1023                 path_kill_slashes(u);
1024         }
1025
1026         if (controller)
1027                 *controller = t;
1028         else
1029                 free(t);
1030
1031         if (path)
1032                 *path = u;
1033         else
1034                 free(u);
1035
1036         return 0;
1037 }
1038
1039 int cg_mangle_path(const char *path, char **result) {
1040         _cleanup_free_ char *c = NULL, *p = NULL;
1041         char *t;
1042         int r;
1043
1044         assert(path);
1045         assert(result);
1046
1047         /* First check if it already is a filesystem path */
1048         if (path_startswith(path, "/sys/fs/cgroup")) {
1049
1050                 t = strdup(path);
1051                 if (!t)
1052                         return -ENOMEM;
1053
1054                 path_kill_slashes(t);
1055                 *result = t;
1056                 return 0;
1057         }
1058
1059         /* Otherwise treat it as cg spec */
1060         r = cg_split_spec(path, &c, &p);
1061         if (r < 0)
1062                 return r;
1063
1064         return cg_get_path(c ? c : SYSTEMD_CGROUP_CONTROLLER, p ? p : "/", NULL, result);
1065 }
1066
1067 int cg_get_root_path(char **path) {
1068         char *p, *e;
1069         int r;
1070
1071         assert(path);
1072
1073         r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 1, &p);
1074         if (r < 0)
1075                 return r;
1076
1077         e = endswith(p, "/" SPECIAL_SYSTEM_SLICE);
1078         if (e)
1079                 *e = 0;
1080
1081         *path = p;
1082         return 0;
1083 }
1084
1085 int cg_pid_get_path_shifted(pid_t pid, const char *root, char **cgroup) {
1086         _cleanup_free_ char *cg_root = NULL;
1087         char *cg_process, *p;
1088         int r;
1089
1090         assert(pid >= 0);
1091         assert(cgroup);
1092
1093         if (!root) {
1094                 /* If the root was specified let's use that, otherwise
1095                  * let's determine it from PID 1 */
1096
1097                 r = cg_get_root_path(&cg_root);
1098                 if (r < 0)
1099                         return r;
1100
1101                 root = cg_root;
1102         }
1103
1104         r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cg_process);
1105         if (r < 0)
1106                 return r;
1107
1108         p = path_startswith(cg_process, root);
1109         if (p) {
1110                 char *c;
1111
1112                 c = strdup(p - 1);
1113                 free(cg_process);
1114
1115                 if (!c)
1116                         return -ENOMEM;
1117
1118                 *cgroup = c;
1119         } else
1120                 *cgroup = cg_process;
1121
1122         return 0;
1123 }
1124
1125 int cg_path_decode_unit(const char *cgroup, char **unit){
1126         char *e, *c, *s;
1127
1128         assert(cgroup);
1129         assert(unit);
1130
1131         e = strchrnul(cgroup, '/');
1132         c = strndupa(cgroup, e - cgroup);
1133         c = cg_unescape(c);
1134
1135         if (!unit_name_is_valid(c, false))
1136                 return -EINVAL;
1137
1138         s = strdup(c);
1139         if (!s)
1140                 return -ENOMEM;
1141
1142         *unit = s;
1143         return 0;
1144 }
1145
1146 static const char *skip_slices(const char *p) {
1147         /* Skips over all slice assignments */
1148
1149         for (;;) {
1150                 size_t n;
1151
1152                 p += strspn(p, "/");
1153
1154                 n = strcspn(p, "/");
1155                 if (n <= 6 || memcmp(p + n - 6, ".slice", 6) != 0)
1156                         return p;
1157
1158                 p += n;
1159         }
1160 }
1161
1162 int cg_path_get_unit(const char *path, char **unit) {
1163         const char *e;
1164
1165         assert(path);
1166         assert(unit);
1167
1168         e = skip_slices(path);
1169
1170         return cg_path_decode_unit(e, unit);
1171 }
1172
1173 int cg_pid_get_unit(pid_t pid, char **unit) {
1174         _cleanup_free_ char *cgroup = NULL;
1175         int r;
1176
1177         assert(unit);
1178
1179         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1180         if (r < 0)
1181                 return r;
1182
1183         return cg_path_get_unit(cgroup, unit);
1184 }
1185
1186 /**
1187  * Skip session-*.scope, but require it to be there.
1188  */
1189 static const char *skip_session(const char *p) {
1190         size_t n;
1191
1192         assert(p);
1193
1194         p += strspn(p, "/");
1195
1196         n = strcspn(p, "/");
1197         if (n < strlen("session-x.scope") || memcmp(p, "session-", 8) != 0 || memcmp(p + n - 6, ".scope", 6) != 0)
1198                 return NULL;
1199
1200         p += n;
1201         p += strspn(p, "/");
1202
1203         return p;
1204 }
1205
1206 /**
1207  * Skip user@*.service, but require it to be there.
1208  */
1209 static const char *skip_user_manager(const char *p) {
1210         size_t n;
1211
1212         assert(p);
1213
1214         p += strspn(p, "/");
1215
1216         n = strcspn(p, "/");
1217         if (n < strlen("user@x.service") || memcmp(p, "user@", 5) != 0 || memcmp(p + n - 8, ".service", 8) != 0)
1218                 return NULL;
1219
1220         p += n;
1221         p += strspn(p, "/");
1222
1223         return p;
1224 }
1225
1226 int cg_path_get_user_unit(const char *path, char **unit) {
1227         const char *e, *t;
1228
1229         assert(path);
1230         assert(unit);
1231
1232         /* We always have to parse the path from the beginning as unit
1233          * cgroups might have arbitrary child cgroups and we shouldn't get
1234          * confused by those */
1235
1236         /* Skip slices, if there are any */
1237         e = skip_slices(path);
1238
1239         /* Skip the session scope... */
1240         t = skip_session(e);
1241         if (t)
1242                 /* ... and skip more slices if there's one */
1243                 e = skip_slices(t);
1244         else {
1245                 /* ... or require a user manager unit to be there */
1246                 e = skip_user_manager(e);
1247                 if (!e)
1248                         return -ENOENT;
1249         }
1250
1251         return cg_path_decode_unit(e, unit);
1252 }
1253
1254 int cg_pid_get_user_unit(pid_t pid, char **unit) {
1255         _cleanup_free_ char *cgroup = NULL;
1256         int r;
1257
1258         assert(unit);
1259
1260         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1261         if (r < 0)
1262                 return r;
1263
1264         return cg_path_get_user_unit(cgroup, unit);
1265 }
1266
1267 int cg_path_get_machine_name(const char *path, char **machine) {
1268         const char *e, *n, *x;
1269         char *s, *r;
1270         size_t l;
1271
1272         assert(path);
1273         assert(machine);
1274
1275         /* Skip slices, if there are any */
1276         e = skip_slices(path);
1277
1278         n = strchrnul(e, '/');
1279         if (e == n)
1280                 return -ENOENT;
1281
1282         s = strndupa(e, n - e);
1283         s = cg_unescape(s);
1284
1285         x = startswith(s, "machine-");
1286         if (!x)
1287                 return -ENOENT;
1288         if (!endswith(x, ".scope"))
1289                 return -ENOENT;
1290
1291         l = strlen(x);
1292         if (l <= 6)
1293                 return -ENOENT;
1294
1295         r = strndup(x, l - 6);
1296         if (!r)
1297                 return -ENOMEM;
1298
1299         *machine = r;
1300         return 0;
1301 }
1302
1303 int cg_pid_get_machine_name(pid_t pid, char **machine) {
1304         _cleanup_free_ char *cgroup = NULL;
1305         int r;
1306
1307         assert(machine);
1308
1309         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1310         if (r < 0)
1311                 return r;
1312
1313         return cg_path_get_machine_name(cgroup, machine);
1314 }
1315
1316 int cg_path_get_session(const char *path, char **session) {
1317         const char *e, *n, *x;
1318         char *s, *r;
1319         size_t l;
1320
1321         assert(path);
1322         assert(session);
1323
1324         /* Skip slices, if there are any */
1325         e = skip_slices(path);
1326
1327         n = strchrnul(e, '/');
1328         if (e == n)
1329                 return -ENOENT;
1330
1331         s = strndupa(e, n - e);
1332         s = cg_unescape(s);
1333
1334         x = startswith(s, "session-");
1335         if (!x)
1336                 return -ENOENT;
1337         if (!endswith(x, ".scope"))
1338                 return -ENOENT;
1339
1340         l = strlen(x);
1341         if (l <= 6)
1342                 return -ENOENT;
1343
1344         r = strndup(x, l - 6);
1345         if (!r)
1346                 return -ENOMEM;
1347
1348         *session = r;
1349         return 0;
1350 }
1351
1352 int cg_pid_get_session(pid_t pid, char **session) {
1353         _cleanup_free_ char *cgroup = NULL;
1354         int r;
1355
1356         assert(session);
1357
1358         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1359         if (r < 0)
1360                 return r;
1361
1362         return cg_path_get_session(cgroup, session);
1363 }
1364
1365 int cg_path_get_owner_uid(const char *path, uid_t *uid) {
1366         _cleanup_free_ char *slice = NULL;
1367         const char *start, *end;
1368         char *s;
1369         uid_t u;
1370         int r;
1371
1372         assert(path);
1373
1374         r = cg_path_get_slice(path, &slice);
1375         if (r < 0)
1376                 return r;
1377
1378         start = startswith(slice, "user-");
1379         if (!start)
1380                 return -ENOENT;
1381         end = endswith(slice, ".slice");
1382         if (!end)
1383                 return -ENOENT;
1384
1385         s = strndupa(start, end - start);
1386         if (!s)
1387                 return -ENOENT;
1388
1389         if (parse_uid(s, &u) < 0)
1390                 return -EIO;
1391
1392         if (uid)
1393                 *uid = u;
1394
1395         return 0;
1396 }
1397
1398 int cg_pid_get_owner_uid(pid_t pid, uid_t *uid) {
1399         _cleanup_free_ char *cgroup = NULL;
1400         int r;
1401
1402         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1403         if (r < 0)
1404                 return r;
1405
1406         return cg_path_get_owner_uid(cgroup, uid);
1407 }
1408
1409 int cg_path_get_slice(const char *p, char **slice) {
1410         const char *e = NULL;
1411         size_t m = 0;
1412
1413         assert(p);
1414         assert(slice);
1415
1416         for (;;) {
1417                 size_t n;
1418
1419                 p += strspn(p, "/");
1420
1421                 n = strcspn(p, "/");
1422                 if (n <= 6 || memcmp(p + n - 6, ".slice", 6) != 0) {
1423                         char *s;
1424
1425                         if (!e)
1426                                 return -ENOENT;
1427
1428                         s = strndup(e, m);
1429                         if (!s)
1430                                 return -ENOMEM;
1431
1432                         *slice = s;
1433                         return 0;
1434                 }
1435
1436                 e = p;
1437                 m = n;
1438
1439                 p += n;
1440         }
1441 }
1442
1443 int cg_pid_get_slice(pid_t pid, char **slice) {
1444         _cleanup_free_ char *cgroup = NULL;
1445         int r;
1446
1447         assert(slice);
1448
1449         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1450         if (r < 0)
1451                 return r;
1452
1453         return cg_path_get_slice(cgroup, slice);
1454 }
1455
1456 char *cg_escape(const char *p) {
1457         bool need_prefix = false;
1458
1459         /* This implements very minimal escaping for names to be used
1460          * as file names in the cgroup tree: any name which might
1461          * conflict with a kernel name or is prefixed with '_' is
1462          * prefixed with a '_'. That way, when reading cgroup names it
1463          * is sufficient to remove a single prefixing underscore if
1464          * there is one. */
1465
1466         /* The return value of this function (unlike cg_unescape())
1467          * needs free()! */
1468
1469         if (p[0] == 0 ||
1470             p[0] == '_' ||
1471             p[0] == '.' ||
1472             streq(p, "notify_on_release") ||
1473             streq(p, "release_agent") ||
1474             streq(p, "tasks"))
1475                 need_prefix = true;
1476         else {
1477                 const char *dot;
1478
1479                 dot = strrchr(p, '.');
1480                 if (dot) {
1481
1482                         if (dot - p == 6 && memcmp(p, "cgroup", 6) == 0)
1483                                 need_prefix = true;
1484                         else {
1485                                 char *n;
1486
1487                                 n = strndupa(p, dot - p);
1488
1489                                 if (check_hierarchy(n) >= 0)
1490                                         need_prefix = true;
1491                         }
1492                 }
1493         }
1494
1495         if (need_prefix)
1496                 return strappend("_", p);
1497         else
1498                 return strdup(p);
1499 }
1500
1501 char *cg_unescape(const char *p) {
1502         assert(p);
1503
1504         /* The return value of this function (unlike cg_escape())
1505          * doesn't need free()! */
1506
1507         if (p[0] == '_')
1508                 return (char*) p+1;
1509
1510         return (char*) p;
1511 }
1512
1513 #define CONTROLLER_VALID                        \
1514         DIGITS LETTERS                          \
1515         "_"
1516
1517 bool cg_controller_is_valid(const char *p, bool allow_named) {
1518         const char *t, *s;
1519
1520         if (!p)
1521                 return false;
1522
1523         if (allow_named) {
1524                 s = startswith(p, "name=");
1525                 if (s)
1526                         p = s;
1527         }
1528
1529         if (*p == 0 || *p == '_')
1530                 return false;
1531
1532         for (t = p; *t; t++)
1533                 if (!strchr(CONTROLLER_VALID, *t))
1534                         return false;
1535
1536         if (t - p > FILENAME_MAX)
1537                 return false;
1538
1539         return true;
1540 }
1541
1542 int cg_slice_to_path(const char *unit, char **ret) {
1543         _cleanup_free_ char *p = NULL, *s = NULL, *e = NULL;
1544         const char *dash;
1545
1546         assert(unit);
1547         assert(ret);
1548
1549         if (!unit_name_is_valid(unit, false))
1550                 return -EINVAL;
1551
1552         if (!endswith(unit, ".slice"))
1553                 return -EINVAL;
1554
1555         p = unit_name_to_prefix(unit);
1556         if (!p)
1557                 return -ENOMEM;
1558
1559         dash = strchr(p, '-');
1560         while (dash) {
1561                 _cleanup_free_ char *escaped = NULL;
1562                 char n[dash - p + sizeof(".slice")];
1563
1564                 strcpy(stpncpy(n, p, dash - p), ".slice");
1565
1566                 if (!unit_name_is_valid(n, false))
1567                         return -EINVAL;
1568
1569                 escaped = cg_escape(n);
1570                 if (!escaped)
1571                         return -ENOMEM;
1572
1573                 if (!strextend(&s, escaped, "/", NULL))
1574                         return -ENOMEM;
1575
1576                 dash = strchr(dash+1, '-');
1577         }
1578
1579         e = cg_escape(unit);
1580         if (!e)
1581                 return -ENOMEM;
1582
1583         if (!strextend(&s, e, NULL))
1584                 return -ENOMEM;
1585
1586         *ret = s;
1587         s = NULL;
1588
1589         return 0;
1590 }
1591
1592 int cg_set_attribute(const char *controller, const char *path, const char *attribute, const char *value) {
1593         _cleanup_free_ char *p = NULL;
1594         int r;
1595
1596         r = cg_get_path(controller, path, attribute, &p);
1597         if (r < 0)
1598                 return r;
1599
1600         return write_string_file(p, value);
1601 }
1602
1603 static const char mask_names[] =
1604         "cpu\0"
1605         "cpuacct\0"
1606         "blkio\0"
1607         "memory\0"
1608         "devices\0";
1609
1610 int cg_create_everywhere(CGroupControllerMask supported, CGroupControllerMask mask, const char *path) {
1611         CGroupControllerMask bit = 1;
1612         const char *n;
1613         int r;
1614
1615         /* This one will create a cgroup in our private tree, but also
1616          * duplicate it in the trees specified in mask, and remove it
1617          * in all others */
1618
1619         /* First create the cgroup in our own hierarchy. */
1620         r = cg_create(SYSTEMD_CGROUP_CONTROLLER, path);
1621         if (r < 0)
1622                 return r;
1623
1624         /* Then, do the same in the other hierarchies */
1625         NULSTR_FOREACH(n, mask_names) {
1626                 if (mask & bit)
1627                         cg_create(n, path);
1628                 else if (supported & bit)
1629                         cg_trim(n, path, true);
1630
1631                 bit <<= 1;
1632         }
1633
1634         return 0;
1635 }
1636
1637 int cg_attach_everywhere(CGroupControllerMask supported, const char *path, pid_t pid) {
1638         CGroupControllerMask bit = 1;
1639         const char *n;
1640         int r;
1641
1642         r = cg_attach(SYSTEMD_CGROUP_CONTROLLER, path, pid);
1643         if (r < 0)
1644                 return r;
1645
1646         NULSTR_FOREACH(n, mask_names) {
1647                 if (supported & bit)
1648                         cg_attach_fallback(n, path, pid);
1649
1650                 bit <<= 1;
1651         }
1652
1653         return 0;
1654 }
1655
1656 int cg_attach_many_everywhere(CGroupControllerMask supported, const char *path, Set* pids) {
1657         Iterator i;
1658         void *pidp;
1659         int r = 0;
1660
1661         SET_FOREACH(pidp, pids, i) {
1662                 pid_t pid = PTR_TO_LONG(pidp);
1663                 int q;
1664
1665                 q = cg_attach_everywhere(supported, path, pid);
1666                 if (q < 0)
1667                         r = q;
1668         }
1669
1670         return r;
1671 }
1672
1673 int cg_migrate_everywhere(CGroupControllerMask supported, const char *from, const char *to) {
1674         CGroupControllerMask bit = 1;
1675         const char *n;
1676         int r;
1677
1678         if (!path_equal(from, to))  {
1679                 r = cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, from, SYSTEMD_CGROUP_CONTROLLER, to, false, true);
1680                 if (r < 0)
1681                         return r;
1682         }
1683
1684         NULSTR_FOREACH(n, mask_names) {
1685                 if (supported & bit)
1686                         cg_migrate_recursive_fallback(SYSTEMD_CGROUP_CONTROLLER, to, n, to, false, false);
1687
1688                 bit <<= 1;
1689         }
1690
1691         return 0;
1692 }
1693
1694 int cg_trim_everywhere(CGroupControllerMask supported, const char *path, bool delete_root) {
1695         CGroupControllerMask bit = 1;
1696         const char *n;
1697         int r;
1698
1699         r = cg_trim(SYSTEMD_CGROUP_CONTROLLER, path, delete_root);
1700         if (r < 0)
1701                 return r;
1702
1703         NULSTR_FOREACH(n, mask_names) {
1704                 if (supported & bit)
1705                         cg_trim(n, path, delete_root);
1706
1707                 bit <<= 1;
1708         }
1709
1710         return 0;
1711 }
1712
1713 CGroupControllerMask cg_mask_supported(void) {
1714         CGroupControllerMask bit = 1, mask = 0;
1715         const char *n;
1716
1717         NULSTR_FOREACH(n, mask_names) {
1718                 if (check_hierarchy(n) >= 0)
1719                         mask |= bit;
1720
1721                 bit <<= 1;
1722         }
1723
1724         return mask;
1725 }