chiark / gitweb /
bus: properly serialize unit file change list
[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 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, char **root, char **cgroup) {
1086         _cleanup_free_ char *cg_root = NULL;
1087         char *cg_process, *p;
1088         int r;
1089
1090         r = cg_get_root_path(&cg_root);
1091         if (r < 0)
1092                 return r;
1093
1094         r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cg_process);
1095         if (r < 0)
1096                 return r;
1097
1098         p = path_startswith(cg_process, cg_root);
1099         if (p)
1100                 p--;
1101         else
1102                 p = cg_process;
1103
1104         if (cgroup) {
1105                 char* c;
1106
1107                 c = strdup(p);
1108                 if (!c) {
1109                         free(cg_process);
1110                         return -ENOMEM;
1111                 }
1112
1113                 *cgroup = c;
1114         }
1115
1116         if (root) {
1117                 cg_process[p-cg_process] = 0;
1118                 *root = cg_process;
1119         } else
1120                 free(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 static const char *skip_session(const char *p) {
1187         size_t n;
1188
1189         assert(p);
1190
1191         p += strspn(p, "/");
1192
1193         n = strcspn(p, "/");
1194         if (n <= 12 || memcmp(p, "session-", 8) != 0 || memcmp(p + n - 6, ".scope", 6) != 0)
1195                 return NULL;
1196
1197         p += n;
1198         p += strspn(p, "/");
1199
1200         return p;
1201 }
1202
1203 int cg_path_get_user_unit(const char *path, char **unit) {
1204         const char *e;
1205
1206         assert(path);
1207         assert(unit);
1208
1209         /* We always have to parse the path from the beginning as unit
1210          * cgroups might have arbitrary child cgroups and we shouldn't get
1211          * confused by those */
1212
1213         /* Skip slices, if there are any */
1214         e = skip_slices(path);
1215
1216         /* Skip the session scope, require that there is one */
1217         e = skip_session(e);
1218         if (!e)
1219                 return -ENOENT;
1220
1221         /* And skip more slices */
1222         e = skip_slices(e);
1223
1224         return cg_path_decode_unit(e, unit);
1225 }
1226
1227 int cg_pid_get_user_unit(pid_t pid, char **unit) {
1228         _cleanup_free_ char *cgroup = NULL;
1229         int r;
1230
1231         assert(unit);
1232
1233         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1234         if (r < 0)
1235                 return r;
1236
1237         return cg_path_get_user_unit(cgroup, unit);
1238 }
1239
1240 int cg_path_get_machine_name(const char *path, char **machine) {
1241         const char *e, *n, *x;
1242         char *s, *r;
1243         size_t l;
1244
1245         assert(path);
1246         assert(machine);
1247
1248         /* Skip slices, if there are any */
1249         e = skip_slices(path);
1250
1251         n = strchrnul(e, '/');
1252         if (e == n)
1253                 return -ENOENT;
1254
1255         s = strndupa(e, n - e);
1256         s = cg_unescape(s);
1257
1258         x = startswith(s, "machine-");
1259         if (!x)
1260                 return -ENOENT;
1261         if (!endswith(x, ".scope"))
1262                 return -ENOENT;
1263
1264         l = strlen(x);
1265         if (l <= 6)
1266                 return -ENOENT;
1267
1268         r = strndup(x, l - 6);
1269         if (!r)
1270                 return -ENOMEM;
1271
1272         *machine = r;
1273         return 0;
1274 }
1275
1276 int cg_pid_get_machine_name(pid_t pid, char **machine) {
1277         _cleanup_free_ char *cgroup = NULL;
1278         int r;
1279
1280         assert(machine);
1281
1282         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1283         if (r < 0)
1284                 return r;
1285
1286         return cg_path_get_machine_name(cgroup, machine);
1287 }
1288
1289 int cg_path_get_session(const char *path, char **session) {
1290         const char *e, *n, *x;
1291         char *s, *r;
1292         size_t l;
1293
1294         assert(path);
1295         assert(session);
1296
1297         /* Skip slices, if there are any */
1298         e = skip_slices(path);
1299
1300         n = strchrnul(e, '/');
1301         if (e == n)
1302                 return -ENOENT;
1303
1304         s = strndupa(e, n - e);
1305         s = cg_unescape(s);
1306
1307         x = startswith(s, "session-");
1308         if (!x)
1309                 return -ENOENT;
1310         if (!endswith(x, ".scope"))
1311                 return -ENOENT;
1312
1313         l = strlen(x);
1314         if (l <= 6)
1315                 return -ENOENT;
1316
1317         r = strndup(x, l - 6);
1318         if (!r)
1319                 return -ENOMEM;
1320
1321         *session = r;
1322         return 0;
1323 }
1324
1325 int cg_pid_get_session(pid_t pid, char **session) {
1326         _cleanup_free_ char *cgroup = NULL;
1327         int r;
1328
1329         assert(session);
1330
1331         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1332         if (r < 0)
1333                 return r;
1334
1335         return cg_path_get_session(cgroup, session);
1336 }
1337
1338 int cg_path_get_owner_uid(const char *path, uid_t *uid) {
1339         _cleanup_free_ char *slice = NULL;
1340         const char *e;
1341         char *s;
1342         int r;
1343
1344         assert(path);
1345         assert(uid);
1346
1347         r = cg_path_get_slice(path, &slice);
1348         if (r < 0)
1349                 return r;
1350
1351         e = startswith(slice, "user-");
1352         if (!e)
1353                 return -ENOENT;
1354         if (!endswith(slice, ".slice"))
1355                 return -ENOENT;
1356
1357         s = strndupa(e, strlen(e) - 6);
1358         if (!s)
1359                 return -ENOMEM;
1360
1361         return parse_uid(s, uid);
1362 }
1363
1364 int cg_pid_get_owner_uid(pid_t pid, uid_t *uid) {
1365         _cleanup_free_ char *cgroup = NULL;
1366         int r;
1367
1368         assert(uid);
1369
1370         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1371         if (r < 0)
1372                 return r;
1373
1374         return cg_path_get_owner_uid(cgroup, uid);
1375 }
1376
1377 int cg_path_get_slice(const char *p, char **slice) {
1378         const char *e = NULL;
1379         size_t m = 0;
1380
1381         assert(p);
1382         assert(slice);
1383
1384         for (;;) {
1385                 size_t n;
1386
1387                 p += strspn(p, "/");
1388
1389                 n = strcspn(p, "/");
1390                 if (n <= 6 || memcmp(p + n - 6, ".slice", 6) != 0) {
1391                         char *s;
1392
1393                         if (!e)
1394                                 return -ENOENT;
1395
1396                         s = strndup(e, m);
1397                         if (!s)
1398                                 return -ENOMEM;
1399
1400                         *slice = s;
1401                         return 0;
1402                 }
1403
1404                 e = p;
1405                 m = n;
1406
1407                 p += n;
1408         }
1409 }
1410
1411 int cg_pid_get_slice(pid_t pid, char **slice) {
1412         _cleanup_free_ char *cgroup = NULL;
1413         int r;
1414
1415         assert(slice);
1416
1417         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1418         if (r < 0)
1419                 return r;
1420
1421         return cg_path_get_slice(cgroup, slice);
1422 }
1423
1424 char *cg_escape(const char *p) {
1425         bool need_prefix = false;
1426
1427         /* This implements very minimal escaping for names to be used
1428          * as file names in the cgroup tree: any name which might
1429          * conflict with a kernel name or is prefixed with '_' is
1430          * prefixed with a '_'. That way, when reading cgroup names it
1431          * is sufficient to remove a single prefixing underscore if
1432          * there is one. */
1433
1434         /* The return value of this function (unlike cg_unescape())
1435          * needs free()! */
1436
1437         if (p[0] == 0 ||
1438             p[0] == '_' ||
1439             p[0] == '.' ||
1440             streq(p, "notify_on_release") ||
1441             streq(p, "release_agent") ||
1442             streq(p, "tasks"))
1443                 need_prefix = true;
1444         else {
1445                 const char *dot;
1446
1447                 dot = strrchr(p, '.');
1448                 if (dot) {
1449
1450                         if (dot - p == 6 && memcmp(p, "cgroup", 6) == 0)
1451                                 need_prefix = true;
1452                         else {
1453                                 char *n;
1454
1455                                 n = strndupa(p, dot - p);
1456
1457                                 if (check_hierarchy(n) >= 0)
1458                                         need_prefix = true;
1459                         }
1460                 }
1461         }
1462
1463         if (need_prefix)
1464                 return strappend("_", p);
1465         else
1466                 return strdup(p);
1467 }
1468
1469 char *cg_unescape(const char *p) {
1470         assert(p);
1471
1472         /* The return value of this function (unlike cg_escape())
1473          * doesn't need free()! */
1474
1475         if (p[0] == '_')
1476                 return (char*) p+1;
1477
1478         return (char*) p;
1479 }
1480
1481 #define CONTROLLER_VALID                        \
1482         DIGITS LETTERS                          \
1483         "_"
1484
1485 bool cg_controller_is_valid(const char *p, bool allow_named) {
1486         const char *t, *s;
1487
1488         if (!p)
1489                 return false;
1490
1491         if (allow_named) {
1492                 s = startswith(p, "name=");
1493                 if (s)
1494                         p = s;
1495         }
1496
1497         if (*p == 0 || *p == '_')
1498                 return false;
1499
1500         for (t = p; *t; t++)
1501                 if (!strchr(CONTROLLER_VALID, *t))
1502                         return false;
1503
1504         if (t - p > FILENAME_MAX)
1505                 return false;
1506
1507         return true;
1508 }
1509
1510 int cg_slice_to_path(const char *unit, char **ret) {
1511         _cleanup_free_ char *p = NULL, *s = NULL, *e = NULL;
1512         const char *dash;
1513
1514         assert(unit);
1515         assert(ret);
1516
1517         if (!unit_name_is_valid(unit, false))
1518                 return -EINVAL;
1519
1520         if (!endswith(unit, ".slice"))
1521                 return -EINVAL;
1522
1523         p = unit_name_to_prefix(unit);
1524         if (!p)
1525                 return -ENOMEM;
1526
1527         dash = strchr(p, '-');
1528         while (dash) {
1529                 _cleanup_free_ char *escaped = NULL;
1530                 char n[dash - p + sizeof(".slice")];
1531
1532                 strcpy(stpncpy(n, p, dash - p), ".slice");
1533
1534                 if (!unit_name_is_valid(n, false))
1535                         return -EINVAL;
1536
1537                 escaped = cg_escape(n);
1538                 if (!escaped)
1539                         return -ENOMEM;
1540
1541                 if (!strextend(&s, escaped, "/", NULL))
1542                         return -ENOMEM;
1543
1544                 dash = strchr(dash+1, '-');
1545         }
1546
1547         e = cg_escape(unit);
1548         if (!e)
1549                 return -ENOMEM;
1550
1551         if (!strextend(&s, e, NULL))
1552                 return -ENOMEM;
1553
1554         *ret = s;
1555         s = NULL;
1556
1557         return 0;
1558 }
1559
1560 int cg_set_attribute(const char *controller, const char *path, const char *attribute, const char *value) {
1561         _cleanup_free_ char *p = NULL;
1562         int r;
1563
1564         r = cg_get_path(controller, path, attribute, &p);
1565         if (r < 0)
1566                 return r;
1567
1568         return write_string_file(p, value);
1569 }
1570
1571 static const char mask_names[] =
1572         "cpu\0"
1573         "cpuacct\0"
1574         "blkio\0"
1575         "memory\0"
1576         "devices\0";
1577
1578 int cg_create_everywhere(CGroupControllerMask supported, CGroupControllerMask mask, const char *path) {
1579         CGroupControllerMask bit = 1;
1580         const char *n;
1581         int r;
1582
1583         /* This one will create a cgroup in our private tree, but also
1584          * duplicate it in the trees specified in mask, and remove it
1585          * in all others */
1586
1587         /* First create the cgroup in our own hierarchy. */
1588         r = cg_create(SYSTEMD_CGROUP_CONTROLLER, path);
1589         if (r < 0)
1590                 return r;
1591
1592         /* Then, do the same in the other hierarchies */
1593         NULSTR_FOREACH(n, mask_names) {
1594                 if (mask & bit)
1595                         cg_create(n, path);
1596                 else if (supported & bit)
1597                         cg_trim(n, path, true);
1598
1599                 bit <<= 1;
1600         }
1601
1602         return 0;
1603 }
1604
1605 int cg_attach_everywhere(CGroupControllerMask supported, const char *path, pid_t pid) {
1606         CGroupControllerMask bit = 1;
1607         const char *n;
1608         int r;
1609
1610         r = cg_attach(SYSTEMD_CGROUP_CONTROLLER, path, pid);
1611         if (r < 0)
1612                 return r;
1613
1614         NULSTR_FOREACH(n, mask_names) {
1615                 if (supported & bit)
1616                         cg_attach_fallback(n, path, pid);
1617
1618                 bit <<= 1;
1619         }
1620
1621         return 0;
1622 }
1623
1624 int cg_attach_many_everywhere(CGroupControllerMask supported, const char *path, Set* pids) {
1625         Iterator i;
1626         void *pidp;
1627         int r = 0;
1628
1629         SET_FOREACH(pidp, pids, i) {
1630                 pid_t pid = PTR_TO_LONG(pidp);
1631                 int q;
1632
1633                 q = cg_attach_everywhere(supported, path, pid);
1634                 if (q < 0)
1635                         r = q;
1636         }
1637
1638         return r;
1639 }
1640
1641 int cg_migrate_everywhere(CGroupControllerMask supported, const char *from, const char *to) {
1642         CGroupControllerMask bit = 1;
1643         const char *n;
1644         int r;
1645
1646         if (!path_equal(from, to))  {
1647                 r = cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, from, SYSTEMD_CGROUP_CONTROLLER, to, false, true);
1648                 if (r < 0)
1649                         return r;
1650         }
1651
1652         NULSTR_FOREACH(n, mask_names) {
1653                 if (supported & bit)
1654                         cg_migrate_recursive_fallback(SYSTEMD_CGROUP_CONTROLLER, to, n, to, false, false);
1655
1656                 bit <<= 1;
1657         }
1658
1659         return 0;
1660 }
1661
1662 int cg_trim_everywhere(CGroupControllerMask supported, const char *path, bool delete_root) {
1663         CGroupControllerMask bit = 1;
1664         const char *n;
1665         int r;
1666
1667         r = cg_trim(SYSTEMD_CGROUP_CONTROLLER, path, delete_root);
1668         if (r < 0)
1669                 return r;
1670
1671         NULSTR_FOREACH(n, mask_names) {
1672                 if (supported & bit)
1673                         cg_trim(n, path, delete_root);
1674
1675                 bit <<= 1;
1676         }
1677
1678         return 0;
1679 }
1680
1681 CGroupControllerMask cg_mask_supported(void) {
1682         CGroupControllerMask bit = 1, mask = 0;
1683         const char *n;
1684
1685         NULSTR_FOREACH(n, mask_names) {
1686                 if (check_hierarchy(n) >= 0)
1687                         mask |= bit;
1688
1689                 bit <<= 1;
1690         }
1691
1692         return mask;
1693 }