chiark / gitweb /
sysusers: add a new RPM macro for creating users directly from data passed in via...
[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 {
198                                 if (sigcont)
199                                         kill(pid, SIGCONT);
200
201                                 if (ret == 0)
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         *fs = path_kill_slashes(t);
476         return 0;
477 }
478
479 int cg_get_path(const char *controller, const char *path, const char *suffix, char **fs) {
480         const char *p;
481         static thread_local bool good = false;
482
483         assert(fs);
484
485         if (controller && !cg_controller_is_valid(controller, true))
486                 return -EINVAL;
487
488         if (_unlikely_(!good)) {
489                 int r;
490
491                 r = path_is_mount_point("/sys/fs/cgroup", false);
492                 if (r <= 0)
493                         return r < 0 ? r : -ENOENT;
494
495                 /* Cache this to save a few stat()s */
496                 good = true;
497         }
498
499         p = controller ? normalize_controller(controller) : NULL;
500
501         return join_path(p, path, suffix, fs);
502 }
503
504 static int check_hierarchy(const char *p) {
505         char *cc;
506
507         assert(p);
508
509         /* Check if this controller actually really exists */
510         cc = alloca(strlen("/sys/fs/cgroup/") + strlen(p) + 1);
511         strcpy(stpcpy(cc, "/sys/fs/cgroup/"), p);
512         if (access(cc, F_OK) < 0)
513                 return -errno;
514
515         return 0;
516 }
517
518 int cg_get_path_and_check(const char *controller, const char *path, const char *suffix, char **fs) {
519         const char *p;
520         int r;
521
522         assert(fs);
523
524         if (!cg_controller_is_valid(controller, true))
525                 return -EINVAL;
526
527         /* Normalize the controller syntax */
528         p = normalize_controller(controller);
529
530         /* Check if this controller actually really exists */
531         r = check_hierarchy(p);
532         if (r < 0)
533                 return r;
534
535         return join_path(p, path, suffix, fs);
536 }
537
538 static int trim_cb(const char *path, const struct stat *sb, int typeflag, struct FTW *ftwbuf) {
539         assert(path);
540         assert(sb);
541         assert(ftwbuf);
542
543         if (typeflag != FTW_DP)
544                 return 0;
545
546         if (ftwbuf->level < 1)
547                 return 0;
548
549         rmdir(path);
550         return 0;
551 }
552
553 int cg_trim(const char *controller, const char *path, bool delete_root) {
554         _cleanup_free_ char *fs = NULL;
555         int r = 0;
556
557         assert(path);
558
559         r = cg_get_path(controller, path, NULL, &fs);
560         if (r < 0)
561                 return r;
562
563         errno = 0;
564         if (nftw(fs, trim_cb, 64, FTW_DEPTH|FTW_MOUNT|FTW_PHYS) != 0)
565                 r = errno ? -errno : -EIO;
566
567         if (delete_root) {
568                 if (rmdir(fs) < 0 && errno != ENOENT)
569                         return -errno;
570         }
571
572         return r;
573 }
574
575 int cg_delete(const char *controller, const char *path) {
576         _cleanup_free_ char *parent = NULL;
577         int r;
578
579         assert(path);
580
581         r = path_get_parent(path, &parent);
582         if (r < 0)
583                 return r;
584
585         r = cg_migrate_recursive(controller, path, controller, parent, false, true);
586         return r == -ENOENT ? 0 : r;
587 }
588
589 int cg_create(const char *controller, const char *path) {
590         _cleanup_free_ char *fs = NULL;
591         int r;
592
593         r = cg_get_path_and_check(controller, path, NULL, &fs);
594         if (r < 0)
595                 return r;
596
597         r = mkdir_parents(fs, 0755);
598         if (r < 0)
599                 return r;
600
601         if (mkdir(fs, 0755) < 0) {
602
603                 if (errno == EEXIST)
604                         return 0;
605
606                 return -errno;
607         }
608
609         return 1;
610 }
611
612 int cg_create_and_attach(const char *controller, const char *path, pid_t pid) {
613         int r, q;
614
615         assert(pid >= 0);
616
617         r = cg_create(controller, path);
618         if (r < 0)
619                 return r;
620
621         q = cg_attach(controller, path, pid);
622         if (q < 0)
623                 return q;
624
625         /* This does not remove the cgroup on failure */
626         return r;
627 }
628
629 int cg_attach(const char *controller, const char *path, pid_t pid) {
630         _cleanup_free_ char *fs = NULL;
631         char c[DECIMAL_STR_MAX(pid_t) + 2];
632         int r;
633
634         assert(path);
635         assert(pid >= 0);
636
637         r = cg_get_path_and_check(controller, path, "cgroup.procs", &fs);
638         if (r < 0)
639                 return r;
640
641         if (pid == 0)
642                 pid = getpid();
643
644         snprintf(c, sizeof(c), PID_FMT"\n", pid);
645
646         return write_string_file_no_create(fs, c);
647 }
648
649 int cg_attach_fallback(const char *controller, const char *path, pid_t pid) {
650         int r;
651
652         assert(controller);
653         assert(path);
654         assert(pid >= 0);
655
656         r = cg_attach(controller, path, pid);
657         if (r < 0) {
658                 char prefix[strlen(path) + 1];
659
660                 /* This didn't work? Then let's try all prefixes of
661                  * the destination */
662
663                 PATH_FOREACH_PREFIX(prefix, path) {
664                         r = cg_attach(controller, prefix, pid);
665                         if (r >= 0)
666                                 break;
667                 }
668         }
669
670         return 0;
671 }
672
673 int cg_set_group_access(
674                 const char *controller,
675                 const char *path,
676                 mode_t mode,
677                 uid_t uid,
678                 gid_t gid) {
679
680         _cleanup_free_ char *fs = NULL;
681         int r;
682
683         assert(path);
684
685         if (mode != (mode_t) -1)
686                 mode &= 0777;
687
688         r = cg_get_path(controller, path, NULL, &fs);
689         if (r < 0)
690                 return r;
691
692         return chmod_and_chown(fs, mode, uid, gid);
693 }
694
695 int cg_set_task_access(
696                 const char *controller,
697                 const char *path,
698                 mode_t mode,
699                 uid_t uid,
700                 gid_t gid) {
701
702         _cleanup_free_ char *fs = NULL, *procs = NULL;
703         int r;
704
705         assert(path);
706
707         if (mode == (mode_t) -1 && uid == (uid_t) -1 && gid == (gid_t) -1)
708                 return 0;
709
710         if (mode != (mode_t) -1)
711                 mode &= 0666;
712
713         r = cg_get_path(controller, path, "cgroup.procs", &fs);
714         if (r < 0)
715                 return r;
716
717         r = chmod_and_chown(fs, mode, uid, gid);
718         if (r < 0)
719                 return r;
720
721         /* Compatibility, Always keep values for "tasks" in sync with
722          * "cgroup.procs" */
723         r = cg_get_path(controller, path, "tasks", &procs);
724         if (r < 0)
725                 return r;
726
727         return chmod_and_chown(procs, mode, uid, gid);
728 }
729
730 int cg_pid_get_path(const char *controller, pid_t pid, char **path) {
731         _cleanup_fclose_ FILE *f = NULL;
732         char line[LINE_MAX];
733         const char *fs;
734         size_t cs;
735
736         assert(path);
737         assert(pid >= 0);
738
739         if (controller) {
740                 if (!cg_controller_is_valid(controller, true))
741                         return -EINVAL;
742
743                 controller = normalize_controller(controller);
744         } else
745                 controller = SYSTEMD_CGROUP_CONTROLLER;
746
747         fs = procfs_file_alloca(pid, "cgroup");
748
749         f = fopen(fs, "re");
750         if (!f)
751                 return errno == ENOENT ? -ESRCH : -errno;
752
753         cs = strlen(controller);
754
755         FOREACH_LINE(line, f, return -errno) {
756                 char *l, *p, *e;
757                 size_t k;
758                 const char *word, *state;
759                 bool found = false;
760
761                 truncate_nl(line);
762
763                 l = strchr(line, ':');
764                 if (!l)
765                         continue;
766
767                 l++;
768                 e = strchr(l, ':');
769                 if (!e)
770                         continue;
771
772                 *e = 0;
773
774                 FOREACH_WORD_SEPARATOR(word, k, l, ",", state) {
775
776                         if (k == cs && memcmp(word, controller, cs) == 0) {
777                                 found = true;
778                                 break;
779                         }
780
781                         if (k == 5 + cs &&
782                             memcmp(word, "name=", 5) == 0 &&
783                             memcmp(word+5, controller, cs) == 0) {
784                                 found = true;
785                                 break;
786                         }
787                 }
788
789                 if (!found)
790                         continue;
791
792                 p = strdup(e + 1);
793                 if (!p)
794                         return -ENOMEM;
795
796                 *path = p;
797                 return 0;
798         }
799
800         return -ENOENT;
801 }
802
803 int cg_install_release_agent(const char *controller, const char *agent) {
804         _cleanup_free_ char *fs = NULL, *contents = NULL;
805         char *sc;
806         int r;
807
808         assert(agent);
809
810         r = cg_get_path(controller, NULL, "release_agent", &fs);
811         if (r < 0)
812                 return r;
813
814         r = read_one_line_file(fs, &contents);
815         if (r < 0)
816                 return r;
817
818         sc = strstrip(contents);
819         if (sc[0] == 0) {
820                 r = write_string_file_no_create(fs, agent);
821                 if (r < 0)
822                         return r;
823         } else if (!streq(sc, agent))
824                 return -EEXIST;
825
826         free(fs);
827         fs = NULL;
828         r = cg_get_path(controller, NULL, "notify_on_release", &fs);
829         if (r < 0)
830                 return r;
831
832         free(contents);
833         contents = NULL;
834         r = read_one_line_file(fs, &contents);
835         if (r < 0)
836                 return r;
837
838         sc = strstrip(contents);
839         if (streq(sc, "0")) {
840                 r = write_string_file_no_create(fs, "1");
841                 if (r < 0)
842                         return r;
843
844                 return 1;
845         }
846
847         if (!streq(sc, "1"))
848                 return -EIO;
849
850         return 0;
851 }
852
853 int cg_uninstall_release_agent(const char *controller) {
854         _cleanup_free_ char *fs = NULL;
855         int r;
856
857         r = cg_get_path(controller, NULL, "notify_on_release", &fs);
858         if (r < 0)
859                 return r;
860
861         r = write_string_file_no_create(fs, "0");
862         if (r < 0)
863                 return r;
864
865         free(fs);
866         fs = NULL;
867
868         r = cg_get_path(controller, NULL, "release_agent", &fs);
869         if (r < 0)
870                 return r;
871
872         r = write_string_file_no_create(fs, "");
873         if (r < 0)
874                 return r;
875
876         return 0;
877 }
878
879 int cg_is_empty(const char *controller, const char *path, bool ignore_self) {
880         _cleanup_fclose_ FILE *f = NULL;
881         pid_t pid = 0, self_pid;
882         bool found = false;
883         int r;
884
885         assert(path);
886
887         r = cg_enumerate_processes(controller, path, &f);
888         if (r < 0)
889                 return r == -ENOENT ? 1 : r;
890
891         self_pid = getpid();
892
893         while ((r = cg_read_pid(f, &pid)) > 0) {
894
895                 if (ignore_self && pid == self_pid)
896                         continue;
897
898                 found = true;
899                 break;
900         }
901
902         if (r < 0)
903                 return r;
904
905         return !found;
906 }
907
908 int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_self) {
909         _cleanup_closedir_ DIR *d = NULL;
910         char *fn;
911         int r;
912
913         assert(path);
914
915         r = cg_is_empty(controller, path, ignore_self);
916         if (r <= 0)
917                 return r;
918
919         r = cg_enumerate_subgroups(controller, path, &d);
920         if (r < 0)
921                 return r == -ENOENT ? 1 : r;
922
923         while ((r = cg_read_subgroup(d, &fn)) > 0) {
924                 _cleanup_free_ char *p = NULL;
925
926                 p = strjoin(path, "/", fn, NULL);
927                 free(fn);
928                 if (!p)
929                         return -ENOMEM;
930
931                 r = cg_is_empty_recursive(controller, p, ignore_self);
932                 if (r <= 0)
933                         return r;
934         }
935
936         if (r < 0)
937                 return r;
938
939         return 1;
940 }
941
942 int cg_split_spec(const char *spec, char **controller, char **path) {
943         const char *e;
944         char *t = NULL, *u = NULL;
945         _cleanup_free_ char *v = NULL;
946
947         assert(spec);
948
949         if (*spec == '/') {
950                 if (!path_is_safe(spec))
951                         return -EINVAL;
952
953                 if (path) {
954                         t = strdup(spec);
955                         if (!t)
956                                 return -ENOMEM;
957
958                         *path = path_kill_slashes(t);
959                 }
960
961                 if (controller)
962                         *controller = NULL;
963
964                 return 0;
965         }
966
967         e = strchr(spec, ':');
968         if (!e) {
969                 if (!cg_controller_is_valid(spec, true))
970                         return -EINVAL;
971
972                 if (controller) {
973                         t = strdup(normalize_controller(spec));
974                         if (!t)
975                                 return -ENOMEM;
976
977                         *controller = t;
978                 }
979
980                 if (path)
981                         *path = NULL;
982
983                 return 0;
984         }
985
986         v = strndup(spec, e-spec);
987         if (!v)
988                 return -ENOMEM;
989         t = strdup(normalize_controller(v));
990         if (!t)
991                 return -ENOMEM;
992         if (!cg_controller_is_valid(t, true)) {
993                 free(t);
994                 return -EINVAL;
995         }
996
997         if (streq(e+1, "")) {
998                 u = strdup("/");
999                 if (!u) {
1000                         free(t);
1001                         return -ENOMEM;
1002                 }
1003         } else {
1004                 u = strdup(e+1);
1005                 if (!u) {
1006                         free(t);
1007                         return -ENOMEM;
1008                 }
1009
1010                 if (!path_is_safe(u) ||
1011                     !path_is_absolute(u)) {
1012                         free(t);
1013                         free(u);
1014                         return -EINVAL;
1015                 }
1016
1017                 path_kill_slashes(u);
1018         }
1019
1020         if (controller)
1021                 *controller = t;
1022         else
1023                 free(t);
1024
1025         if (path)
1026                 *path = u;
1027         else
1028                 free(u);
1029
1030         return 0;
1031 }
1032
1033 int cg_mangle_path(const char *path, char **result) {
1034         _cleanup_free_ char *c = NULL, *p = NULL;
1035         char *t;
1036         int r;
1037
1038         assert(path);
1039         assert(result);
1040
1041         /* First, check if it already is a filesystem path */
1042         if (path_startswith(path, "/sys/fs/cgroup")) {
1043
1044                 t = strdup(path);
1045                 if (!t)
1046                         return -ENOMEM;
1047
1048                 *result = path_kill_slashes(t);
1049                 return 0;
1050         }
1051
1052         /* Otherwise, treat it as cg spec */
1053         r = cg_split_spec(path, &c, &p);
1054         if (r < 0)
1055                 return r;
1056
1057         return cg_get_path(c ? c : SYSTEMD_CGROUP_CONTROLLER, p ? p : "/", NULL, result);
1058 }
1059
1060 int cg_get_root_path(char **path) {
1061         char *p, *e;
1062         int r;
1063
1064         assert(path);
1065
1066         r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 1, &p);
1067         if (r < 0)
1068                 return r;
1069
1070         e = endswith(p, "/" SPECIAL_SYSTEM_SLICE);
1071         if (e)
1072                 *e = 0;
1073
1074         *path = p;
1075         return 0;
1076 }
1077
1078 int cg_shift_path(const char *cgroup, const char *root, const char **shifted) {
1079         _cleanup_free_ char *rt = NULL;
1080         char *p;
1081         int r;
1082
1083         assert(cgroup);
1084         assert(shifted);
1085
1086         if (!root) {
1087                 /* If the root was specified let's use that, otherwise
1088                  * let's determine it from PID 1 */
1089
1090                 r = cg_get_root_path(&rt);
1091                 if (r < 0)
1092                         return r;
1093
1094                 root = rt;
1095         }
1096
1097         p = path_startswith(cgroup, root);
1098         if (p)
1099                 *shifted = p - 1;
1100         else
1101                 *shifted = cgroup;
1102
1103         return 0;
1104 }
1105
1106 int cg_pid_get_path_shifted(pid_t pid, const char *root, char **cgroup) {
1107         _cleanup_free_ char *raw = NULL;
1108         const char *c;
1109         int r;
1110
1111         assert(pid >= 0);
1112         assert(cgroup);
1113
1114         r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &raw);
1115         if (r < 0)
1116                 return r;
1117
1118         r = cg_shift_path(raw, root, &c);
1119         if (r < 0)
1120                 return r;
1121
1122         if (c == raw) {
1123                 *cgroup = raw;
1124                 raw = NULL;
1125         } else {
1126                 char *n;
1127
1128                 n = strdup(c);
1129                 if (!n)
1130                         return -ENOMEM;
1131
1132                 *cgroup = n;
1133         }
1134
1135         return 0;
1136 }
1137
1138 int cg_path_decode_unit(const char *cgroup, char **unit){
1139         char *e, *c, *s;
1140
1141         assert(cgroup);
1142         assert(unit);
1143
1144         e = strchrnul(cgroup, '/');
1145         c = strndupa(cgroup, e - cgroup);
1146         c = cg_unescape(c);
1147
1148         if (!unit_name_is_valid(c, TEMPLATE_INVALID))
1149                 return -EINVAL;
1150
1151         s = strdup(c);
1152         if (!s)
1153                 return -ENOMEM;
1154
1155         *unit = s;
1156         return 0;
1157 }
1158
1159 static const char *skip_slices(const char *p) {
1160         /* Skips over all slice assignments */
1161
1162         for (;;) {
1163                 size_t n;
1164
1165                 p += strspn(p, "/");
1166
1167                 n = strcspn(p, "/");
1168                 if (n <= 6 || memcmp(p + n - 6, ".slice", 6) != 0)
1169                         return p;
1170
1171                 p += n;
1172         }
1173 }
1174
1175 int cg_path_get_unit(const char *path, char **unit) {
1176         const char *e;
1177
1178         assert(path);
1179         assert(unit);
1180
1181         e = skip_slices(path);
1182
1183         return cg_path_decode_unit(e, unit);
1184 }
1185
1186 int cg_pid_get_unit(pid_t pid, char **unit) {
1187         _cleanup_free_ char *cgroup = NULL;
1188         int r;
1189
1190         assert(unit);
1191
1192         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1193         if (r < 0)
1194                 return r;
1195
1196         return cg_path_get_unit(cgroup, unit);
1197 }
1198
1199 /**
1200  * Skip session-*.scope, but require it to be there.
1201  */
1202 static const char *skip_session(const char *p) {
1203         size_t n;
1204
1205         assert(p);
1206
1207         p += strspn(p, "/");
1208
1209         n = strcspn(p, "/");
1210         if (n < strlen("session-x.scope") || memcmp(p, "session-", 8) != 0 || memcmp(p + n - 6, ".scope", 6) != 0)
1211                 return NULL;
1212
1213         p += n;
1214         p += strspn(p, "/");
1215
1216         return p;
1217 }
1218
1219 /**
1220  * Skip user@*.service, but require it to be there.
1221  */
1222 static const char *skip_user_manager(const char *p) {
1223         size_t n;
1224
1225         assert(p);
1226
1227         p += strspn(p, "/");
1228
1229         n = strcspn(p, "/");
1230         if (n < strlen("user@x.service") || memcmp(p, "user@", 5) != 0 || memcmp(p + n - 8, ".service", 8) != 0)
1231                 return NULL;
1232
1233         p += n;
1234         p += strspn(p, "/");
1235
1236         return p;
1237 }
1238
1239 int cg_path_get_user_unit(const char *path, char **unit) {
1240         const char *e, *t;
1241
1242         assert(path);
1243         assert(unit);
1244
1245         /* We always have to parse the path from the beginning as unit
1246          * cgroups might have arbitrary child cgroups and we shouldn't get
1247          * confused by those */
1248
1249         /* Skip slices, if there are any */
1250         e = skip_slices(path);
1251
1252         /* Skip the session scope... */
1253         t = skip_session(e);
1254         if (t)
1255                 /* ... and skip more slices if there's one */
1256                 e = skip_slices(t);
1257         else {
1258                 /* ... or require a user manager unit to be there */
1259                 e = skip_user_manager(e);
1260                 if (!e)
1261                         return -ENOENT;
1262         }
1263
1264         return cg_path_decode_unit(e, unit);
1265 }
1266
1267 int cg_pid_get_user_unit(pid_t pid, char **unit) {
1268         _cleanup_free_ char *cgroup = NULL;
1269         int r;
1270
1271         assert(unit);
1272
1273         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1274         if (r < 0)
1275                 return r;
1276
1277         return cg_path_get_user_unit(cgroup, unit);
1278 }
1279
1280 int cg_path_get_machine_name(const char *path, char **machine) {
1281         _cleanup_free_ char *u = NULL, *sl = NULL;
1282         int r;
1283
1284         r = cg_path_get_unit(path, &u);
1285         if (r < 0)
1286                 return r;
1287
1288         sl = strjoin("/run/systemd/machines/unit:", u, NULL);
1289         if (!sl)
1290                 return -ENOMEM;
1291
1292         return readlink_malloc(sl, machine);
1293 }
1294
1295 int cg_pid_get_machine_name(pid_t pid, char **machine) {
1296         _cleanup_free_ char *cgroup = NULL;
1297         int r;
1298
1299         assert(machine);
1300
1301         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1302         if (r < 0)
1303                 return r;
1304
1305         return cg_path_get_machine_name(cgroup, machine);
1306 }
1307
1308 int cg_path_get_session(const char *path, char **session) {
1309         const char *e, *n, *x;
1310         char *s;
1311         size_t l;
1312
1313         assert(path);
1314
1315         /* Skip slices, if there are any */
1316         e = skip_slices(path);
1317
1318         n = strchrnul(e, '/');
1319         if (e == n)
1320                 return -ENOENT;
1321
1322         s = strndupa(e, n - e);
1323         s = cg_unescape(s);
1324
1325         x = startswith(s, "session-");
1326         if (!x)
1327                 return -ENOENT;
1328         if (!endswith(x, ".scope"))
1329                 return -ENOENT;
1330
1331         l = strlen(x);
1332         if (l <= 6)
1333                 return -ENOENT;
1334
1335         if (session) {
1336                 char *r;
1337
1338                 r = strndup(x, l - 6);
1339                 if (!r)
1340                         return -ENOMEM;
1341
1342                 *session = r;
1343         }
1344
1345         return 0;
1346 }
1347
1348 int cg_pid_get_session(pid_t pid, char **session) {
1349         _cleanup_free_ char *cgroup = NULL;
1350         int r;
1351
1352         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1353         if (r < 0)
1354                 return r;
1355
1356         return cg_path_get_session(cgroup, session);
1357 }
1358
1359 int cg_path_get_owner_uid(const char *path, uid_t *uid) {
1360         _cleanup_free_ char *slice = NULL;
1361         const char *start, *end;
1362         char *s;
1363         uid_t u;
1364         int r;
1365
1366         assert(path);
1367
1368         r = cg_path_get_slice(path, &slice);
1369         if (r < 0)
1370                 return r;
1371
1372         start = startswith(slice, "user-");
1373         if (!start)
1374                 return -ENOENT;
1375         end = endswith(slice, ".slice");
1376         if (!end)
1377                 return -ENOENT;
1378
1379         s = strndupa(start, end - start);
1380         if (!s)
1381                 return -ENOENT;
1382
1383         if (parse_uid(s, &u) < 0)
1384                 return -EIO;
1385
1386         if (uid)
1387                 *uid = u;
1388
1389         return 0;
1390 }
1391
1392 int cg_pid_get_owner_uid(pid_t pid, uid_t *uid) {
1393         _cleanup_free_ char *cgroup = NULL;
1394         int r;
1395
1396         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1397         if (r < 0)
1398                 return r;
1399
1400         return cg_path_get_owner_uid(cgroup, uid);
1401 }
1402
1403 int cg_path_get_slice(const char *p, char **slice) {
1404         const char *e = NULL;
1405         size_t m = 0;
1406
1407         assert(p);
1408         assert(slice);
1409
1410         for (;;) {
1411                 size_t n;
1412
1413                 p += strspn(p, "/");
1414
1415                 n = strcspn(p, "/");
1416                 if (n <= 6 || memcmp(p + n - 6, ".slice", 6) != 0) {
1417                         char *s;
1418
1419                         if (!e)
1420                                 return -ENOENT;
1421
1422                         s = strndup(e, m);
1423                         if (!s)
1424                                 return -ENOMEM;
1425
1426                         *slice = s;
1427                         return 0;
1428                 }
1429
1430                 e = p;
1431                 m = n;
1432
1433                 p += n;
1434         }
1435 }
1436
1437 int cg_pid_get_slice(pid_t pid, char **slice) {
1438         _cleanup_free_ char *cgroup = NULL;
1439         int r;
1440
1441         assert(slice);
1442
1443         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1444         if (r < 0)
1445                 return r;
1446
1447         return cg_path_get_slice(cgroup, slice);
1448 }
1449
1450 char *cg_escape(const char *p) {
1451         bool need_prefix = false;
1452
1453         /* This implements very minimal escaping for names to be used
1454          * as file names in the cgroup tree: any name which might
1455          * conflict with a kernel name or is prefixed with '_' is
1456          * prefixed with a '_'. That way, when reading cgroup names it
1457          * is sufficient to remove a single prefixing underscore if
1458          * there is one. */
1459
1460         /* The return value of this function (unlike cg_unescape())
1461          * needs free()! */
1462
1463         if (p[0] == 0 ||
1464             p[0] == '_' ||
1465             p[0] == '.' ||
1466             streq(p, "notify_on_release") ||
1467             streq(p, "release_agent") ||
1468             streq(p, "tasks"))
1469                 need_prefix = true;
1470         else {
1471                 const char *dot;
1472
1473                 dot = strrchr(p, '.');
1474                 if (dot) {
1475
1476                         if (dot - p == 6 && memcmp(p, "cgroup", 6) == 0)
1477                                 need_prefix = true;
1478                         else {
1479                                 char *n;
1480
1481                                 n = strndupa(p, dot - p);
1482
1483                                 if (check_hierarchy(n) >= 0)
1484                                         need_prefix = true;
1485                         }
1486                 }
1487         }
1488
1489         if (need_prefix)
1490                 return strappend("_", p);
1491         else
1492                 return strdup(p);
1493 }
1494
1495 char *cg_unescape(const char *p) {
1496         assert(p);
1497
1498         /* The return value of this function (unlike cg_escape())
1499          * doesn't need free()! */
1500
1501         if (p[0] == '_')
1502                 return (char*) p+1;
1503
1504         return (char*) p;
1505 }
1506
1507 #define CONTROLLER_VALID                        \
1508         DIGITS LETTERS                          \
1509         "_"
1510
1511 bool cg_controller_is_valid(const char *p, bool allow_named) {
1512         const char *t, *s;
1513
1514         if (!p)
1515                 return false;
1516
1517         if (allow_named) {
1518                 s = startswith(p, "name=");
1519                 if (s)
1520                         p = s;
1521         }
1522
1523         if (*p == 0 || *p == '_')
1524                 return false;
1525
1526         for (t = p; *t; t++)
1527                 if (!strchr(CONTROLLER_VALID, *t))
1528                         return false;
1529
1530         if (t - p > FILENAME_MAX)
1531                 return false;
1532
1533         return true;
1534 }
1535
1536 int cg_slice_to_path(const char *unit, char **ret) {
1537         _cleanup_free_ char *p = NULL, *s = NULL, *e = NULL;
1538         const char *dash;
1539
1540         assert(unit);
1541         assert(ret);
1542
1543         if (!unit_name_is_valid(unit, TEMPLATE_INVALID))
1544                 return -EINVAL;
1545
1546         if (!endswith(unit, ".slice"))
1547                 return -EINVAL;
1548
1549         p = unit_name_to_prefix(unit);
1550         if (!p)
1551                 return -ENOMEM;
1552
1553         dash = strchr(p, '-');
1554         while (dash) {
1555                 _cleanup_free_ char *escaped = NULL;
1556                 char n[dash - p + sizeof(".slice")];
1557
1558                 strcpy(stpncpy(n, p, dash - p), ".slice");
1559
1560                 if (!unit_name_is_valid(n, TEMPLATE_INVALID))
1561                         return -EINVAL;
1562
1563                 escaped = cg_escape(n);
1564                 if (!escaped)
1565                         return -ENOMEM;
1566
1567                 if (!strextend(&s, escaped, "/", NULL))
1568                         return -ENOMEM;
1569
1570                 dash = strchr(dash+1, '-');
1571         }
1572
1573         e = cg_escape(unit);
1574         if (!e)
1575                 return -ENOMEM;
1576
1577         if (!strextend(&s, e, NULL))
1578                 return -ENOMEM;
1579
1580         *ret = s;
1581         s = NULL;
1582
1583         return 0;
1584 }
1585
1586 int cg_set_attribute(const char *controller, const char *path, const char *attribute, const char *value) {
1587         _cleanup_free_ char *p = NULL;
1588         int r;
1589
1590         r = cg_get_path(controller, path, attribute, &p);
1591         if (r < 0)
1592                 return r;
1593
1594         return write_string_file_no_create(p, value);
1595 }
1596
1597 static const char mask_names[] =
1598         "cpu\0"
1599         "cpuacct\0"
1600         "blkio\0"
1601         "memory\0"
1602         "devices\0";
1603
1604 int cg_create_everywhere(CGroupControllerMask supported, CGroupControllerMask mask, const char *path) {
1605         CGroupControllerMask bit = 1;
1606         const char *n;
1607         int r;
1608
1609         /* This one will create a cgroup in our private tree, but also
1610          * duplicate it in the trees specified in mask, and remove it
1611          * in all others */
1612
1613         /* First create the cgroup in our own hierarchy. */
1614         r = cg_create(SYSTEMD_CGROUP_CONTROLLER, path);
1615         if (r < 0)
1616                 return r;
1617
1618         /* Then, do the same in the other hierarchies */
1619         NULSTR_FOREACH(n, mask_names) {
1620                 if (mask & bit)
1621                         cg_create(n, path);
1622                 else if (supported & bit)
1623                         cg_trim(n, path, true);
1624
1625                 bit <<= 1;
1626         }
1627
1628         return 0;
1629 }
1630
1631 int cg_attach_everywhere(CGroupControllerMask supported, const char *path, pid_t pid) {
1632         CGroupControllerMask bit = 1;
1633         const char *n;
1634         int r;
1635
1636         r = cg_attach(SYSTEMD_CGROUP_CONTROLLER, path, pid);
1637         if (r < 0)
1638                 return r;
1639
1640         NULSTR_FOREACH(n, mask_names) {
1641                 if (supported & bit)
1642                         cg_attach_fallback(n, path, pid);
1643
1644                 bit <<= 1;
1645         }
1646
1647         return 0;
1648 }
1649
1650 int cg_attach_many_everywhere(CGroupControllerMask supported, const char *path, Set* pids) {
1651         Iterator i;
1652         void *pidp;
1653         int r = 0;
1654
1655         SET_FOREACH(pidp, pids, i) {
1656                 pid_t pid = PTR_TO_LONG(pidp);
1657                 int q;
1658
1659                 q = cg_attach_everywhere(supported, path, pid);
1660                 if (q < 0)
1661                         r = q;
1662         }
1663
1664         return r;
1665 }
1666
1667 int cg_migrate_everywhere(CGroupControllerMask supported, const char *from, const char *to, cg_migrate_callback_t to_callback, void *userdata) {
1668         CGroupControllerMask bit = 1;
1669         const char *n;
1670         int r;
1671
1672         if (!path_equal(from, to))  {
1673                 r = cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, from, SYSTEMD_CGROUP_CONTROLLER, to, false, true);
1674                 if (r < 0)
1675                         return r;
1676         }
1677
1678         NULSTR_FOREACH(n, mask_names) {
1679                 if (supported & bit) {
1680                         const char *p = NULL;
1681
1682                         if (to_callback)
1683                                 p = to_callback(bit, userdata);
1684
1685                         if (!p)
1686                                 p = to;
1687
1688                         cg_migrate_recursive_fallback(SYSTEMD_CGROUP_CONTROLLER, to, n, p, false, false);
1689                 }
1690
1691                 bit <<= 1;
1692         }
1693
1694         return 0;
1695 }
1696
1697 int cg_trim_everywhere(CGroupControllerMask supported, const char *path, bool delete_root) {
1698         CGroupControllerMask bit = 1;
1699         const char *n;
1700         int r;
1701
1702         r = cg_trim(SYSTEMD_CGROUP_CONTROLLER, path, delete_root);
1703         if (r < 0)
1704                 return r;
1705
1706         NULSTR_FOREACH(n, mask_names) {
1707                 if (supported & bit)
1708                         cg_trim(n, path, delete_root);
1709
1710                 bit <<= 1;
1711         }
1712
1713         return 0;
1714 }
1715
1716 CGroupControllerMask cg_mask_supported(void) {
1717         CGroupControllerMask bit = 1, mask = 0;
1718         const char *n;
1719
1720         NULSTR_FOREACH(n, mask_names) {
1721                 if (check_hierarchy(n) >= 0)
1722                         mask |= bit;
1723
1724                 bit <<= 1;
1725         }
1726
1727         return mask;
1728 }