]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/install.c
install, cgtop: adjust hashmap_move_one() callers for -ENOMEM possibility
[thirdparty/systemd.git] / src / shared / install.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2011 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 <fcntl.h>
24 #include <unistd.h>
25 #include <string.h>
26 #include <fnmatch.h>
27
28 #include "util.h"
29 #include "mkdir.h"
30 #include "hashmap.h"
31 #include "set.h"
32 #include "path-util.h"
33 #include "path-lookup.h"
34 #include "strv.h"
35 #include "unit-name.h"
36 #include "install.h"
37 #include "conf-parser.h"
38 #include "conf-files.h"
39 #include "specifier.h"
40 #include "install-printf.h"
41 #include "special.h"
42
43 typedef struct {
44 OrderedHashmap *will_install;
45 OrderedHashmap *have_installed;
46 } InstallContext;
47
48 static int in_search_path(const char *path, char **search) {
49 _cleanup_free_ char *parent = NULL;
50 int r;
51
52 assert(path);
53
54 r = path_get_parent(path, &parent);
55 if (r < 0)
56 return r;
57
58 return strv_contains(search, parent);
59 }
60
61 static int lookup_paths_init_from_scope(LookupPaths *paths,
62 UnitFileScope scope,
63 const char *root_dir) {
64 assert(paths);
65 assert(scope >= 0);
66 assert(scope < _UNIT_FILE_SCOPE_MAX);
67
68 zero(*paths);
69
70 return lookup_paths_init(paths,
71 scope == UNIT_FILE_SYSTEM ? SYSTEMD_SYSTEM : SYSTEMD_USER,
72 scope == UNIT_FILE_USER,
73 root_dir,
74 NULL, NULL, NULL);
75 }
76
77 static int get_config_path(UnitFileScope scope, bool runtime, const char *root_dir, char **ret) {
78 char *p = NULL;
79 int r;
80
81 assert(scope >= 0);
82 assert(scope < _UNIT_FILE_SCOPE_MAX);
83 assert(ret);
84
85 switch (scope) {
86
87 case UNIT_FILE_SYSTEM:
88
89 if (runtime)
90 p = path_join(root_dir, "/run/systemd/system", NULL);
91 else
92 p = path_join(root_dir, SYSTEM_CONFIG_UNIT_PATH, NULL);
93 break;
94
95 case UNIT_FILE_GLOBAL:
96
97 if (root_dir)
98 return -EINVAL;
99
100 if (runtime)
101 p = strdup("/run/systemd/user");
102 else
103 p = strdup(USER_CONFIG_UNIT_PATH);
104 break;
105
106 case UNIT_FILE_USER:
107
108 if (root_dir)
109 return -EINVAL;
110
111 if (runtime)
112 r = user_runtime_dir(&p);
113 else
114 r = user_config_home(&p);
115
116 if (r <= 0)
117 return r < 0 ? r : -ENOENT;
118
119 break;
120
121 default:
122 assert_not_reached("Bad scope");
123 }
124
125 if (!p)
126 return -ENOMEM;
127
128 *ret = p;
129 return 0;
130 }
131
132 static int add_file_change(
133 UnitFileChange **changes,
134 unsigned *n_changes,
135 UnitFileChangeType type,
136 const char *path,
137 const char *source) {
138
139 UnitFileChange *c;
140 unsigned i;
141
142 assert(path);
143 assert(!changes == !n_changes);
144
145 if (!changes)
146 return 0;
147
148 c = realloc(*changes, (*n_changes + 1) * sizeof(UnitFileChange));
149 if (!c)
150 return -ENOMEM;
151
152 *changes = c;
153 i = *n_changes;
154
155 c[i].type = type;
156 c[i].path = strdup(path);
157 if (!c[i].path)
158 return -ENOMEM;
159
160 path_kill_slashes(c[i].path);
161
162 if (source) {
163 c[i].source = strdup(source);
164 if (!c[i].source) {
165 free(c[i].path);
166 return -ENOMEM;
167 }
168
169 path_kill_slashes(c[i].path);
170 } else
171 c[i].source = NULL;
172
173 *n_changes = i+1;
174 return 0;
175 }
176
177 static int mark_symlink_for_removal(
178 Set **remove_symlinks_to,
179 const char *p) {
180
181 char *n;
182 int r;
183
184 assert(p);
185
186 r = set_ensure_allocated(remove_symlinks_to, &string_hash_ops);
187 if (r < 0)
188 return r;
189
190 n = strdup(p);
191 if (!n)
192 return -ENOMEM;
193
194 path_kill_slashes(n);
195
196 r = set_consume(*remove_symlinks_to, n);
197 if (r < 0)
198 return r == -EEXIST ? 0 : r;
199
200 return 0;
201 }
202
203 static int remove_marked_symlinks_fd(
204 Set *remove_symlinks_to,
205 int fd,
206 const char *path,
207 const char *config_path,
208 bool *deleted,
209 UnitFileChange **changes,
210 unsigned *n_changes,
211 char** instance_whitelist) {
212
213 _cleanup_closedir_ DIR *d = NULL;
214 int r = 0;
215
216 assert(remove_symlinks_to);
217 assert(fd >= 0);
218 assert(path);
219 assert(config_path);
220 assert(deleted);
221
222 d = fdopendir(fd);
223 if (!d) {
224 safe_close(fd);
225 return -errno;
226 }
227
228 rewinddir(d);
229
230 for (;;) {
231 struct dirent *de;
232
233 errno = 0;
234 de = readdir(d);
235 if (!de && errno != 0) {
236 r = -errno;
237 break;
238 }
239
240 if (!de)
241 break;
242
243 if (ignore_file(de->d_name))
244 continue;
245
246 dirent_ensure_type(d, de);
247
248 if (de->d_type == DT_DIR) {
249 int nfd, q;
250 _cleanup_free_ char *p = NULL;
251
252 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
253 if (nfd < 0) {
254 if (errno == ENOENT)
255 continue;
256
257 if (r == 0)
258 r = -errno;
259 continue;
260 }
261
262 p = path_make_absolute(de->d_name, path);
263 if (!p) {
264 safe_close(nfd);
265 return -ENOMEM;
266 }
267
268 /* This will close nfd, regardless whether it succeeds or not */
269 q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, deleted, changes, n_changes, instance_whitelist);
270 if (q < 0 && r == 0)
271 r = q;
272
273 } else if (de->d_type == DT_LNK) {
274 _cleanup_free_ char *p = NULL, *dest = NULL;
275 int q;
276 bool found;
277
278 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
279 continue;
280
281 if (unit_name_is_instance(de->d_name) &&
282 instance_whitelist &&
283 !strv_contains(instance_whitelist, de->d_name)) {
284
285 _cleanup_free_ char *w;
286
287 /* OK, the file is not listed directly
288 * in the whitelist, so let's check if
289 * the template of it might be
290 * listed. */
291
292 w = unit_name_template(de->d_name);
293 if (!w)
294 return -ENOMEM;
295
296 if (!strv_contains(instance_whitelist, w))
297 continue;
298 }
299
300 p = path_make_absolute(de->d_name, path);
301 if (!p)
302 return -ENOMEM;
303
304 q = readlink_and_canonicalize(p, &dest);
305 if (q < 0) {
306 if (q == -ENOENT)
307 continue;
308
309 if (r == 0)
310 r = q;
311 continue;
312 }
313
314 found =
315 set_get(remove_symlinks_to, dest) ||
316 set_get(remove_symlinks_to, basename(dest));
317
318 if (!found)
319 continue;
320
321 if (unlink(p) < 0 && errno != ENOENT) {
322 if (r == 0)
323 r = -errno;
324 continue;
325 }
326
327 path_kill_slashes(p);
328 rmdir_parents(p, config_path);
329 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, p, NULL);
330
331 if (!set_get(remove_symlinks_to, p)) {
332
333 q = mark_symlink_for_removal(&remove_symlinks_to, p);
334 if (q < 0) {
335 if (r == 0)
336 r = q;
337 } else
338 *deleted = true;
339 }
340 }
341 }
342
343 return r;
344 }
345
346 static int remove_marked_symlinks(
347 Set *remove_symlinks_to,
348 const char *config_path,
349 UnitFileChange **changes,
350 unsigned *n_changes,
351 char** instance_whitelist) {
352
353 _cleanup_close_ int fd = -1;
354 int r = 0;
355 bool deleted;
356
357 assert(config_path);
358
359 if (set_size(remove_symlinks_to) <= 0)
360 return 0;
361
362 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
363 if (fd < 0)
364 return -errno;
365
366 do {
367 int q, cfd;
368 deleted = false;
369
370 cfd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
371 if (cfd < 0) {
372 r = -errno;
373 break;
374 }
375
376 /* This takes possession of cfd and closes it */
377 q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, &deleted, changes, n_changes, instance_whitelist);
378 if (r == 0)
379 r = q;
380 } while (deleted);
381
382 return r;
383 }
384
385 static int find_symlinks_fd(
386 const char *name,
387 int fd,
388 const char *path,
389 const char *config_path,
390 bool *same_name_link) {
391
392 int r = 0;
393 _cleanup_closedir_ DIR *d = NULL;
394
395 assert(name);
396 assert(fd >= 0);
397 assert(path);
398 assert(config_path);
399 assert(same_name_link);
400
401 d = fdopendir(fd);
402 if (!d) {
403 safe_close(fd);
404 return -errno;
405 }
406
407 for (;;) {
408 struct dirent *de;
409
410 errno = 0;
411 de = readdir(d);
412 if (!de && errno != 0)
413 return -errno;
414
415 if (!de)
416 return r;
417
418 if (ignore_file(de->d_name))
419 continue;
420
421 dirent_ensure_type(d, de);
422
423 if (de->d_type == DT_DIR) {
424 int nfd, q;
425 _cleanup_free_ char *p = NULL;
426
427 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
428 if (nfd < 0) {
429 if (errno == ENOENT)
430 continue;
431
432 if (r == 0)
433 r = -errno;
434 continue;
435 }
436
437 p = path_make_absolute(de->d_name, path);
438 if (!p) {
439 safe_close(nfd);
440 return -ENOMEM;
441 }
442
443 /* This will close nfd, regardless whether it succeeds or not */
444 q = find_symlinks_fd(name, nfd, p, config_path, same_name_link);
445 if (q > 0)
446 return 1;
447 if (r == 0)
448 r = q;
449
450 } else if (de->d_type == DT_LNK) {
451 _cleanup_free_ char *p = NULL, *dest = NULL;
452 bool found_path, found_dest, b = false;
453 int q;
454
455 /* Acquire symlink name */
456 p = path_make_absolute(de->d_name, path);
457 if (!p)
458 return -ENOMEM;
459
460 /* Acquire symlink destination */
461 q = readlink_and_canonicalize(p, &dest);
462 if (q < 0) {
463 if (q == -ENOENT)
464 continue;
465
466 if (r == 0)
467 r = q;
468 continue;
469 }
470
471 /* Check if the symlink itself matches what we
472 * are looking for */
473 if (path_is_absolute(name))
474 found_path = path_equal(p, name);
475 else
476 found_path = streq(de->d_name, name);
477
478 /* Check if what the symlink points to
479 * matches what we are looking for */
480 if (path_is_absolute(name))
481 found_dest = path_equal(dest, name);
482 else
483 found_dest = streq(basename(dest), name);
484
485 if (found_path && found_dest) {
486 _cleanup_free_ char *t = NULL;
487
488 /* Filter out same name links in the main
489 * config path */
490 t = path_make_absolute(name, config_path);
491 if (!t)
492 return -ENOMEM;
493
494 b = path_equal(t, p);
495 }
496
497 if (b)
498 *same_name_link = true;
499 else if (found_path || found_dest)
500 return 1;
501 }
502 }
503 }
504
505 static int find_symlinks(
506 const char *name,
507 const char *config_path,
508 bool *same_name_link) {
509
510 int fd;
511
512 assert(name);
513 assert(config_path);
514 assert(same_name_link);
515
516 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
517 if (fd < 0) {
518 if (errno == ENOENT)
519 return 0;
520 return -errno;
521 }
522
523 /* This takes possession of fd and closes it */
524 return find_symlinks_fd(name, fd, config_path, config_path, same_name_link);
525 }
526
527 static int find_symlinks_in_scope(
528 UnitFileScope scope,
529 const char *root_dir,
530 const char *name,
531 UnitFileState *state) {
532
533 int r;
534 _cleanup_free_ char *path = NULL;
535 bool same_name_link_runtime = false, same_name_link = false;
536
537 assert(scope >= 0);
538 assert(scope < _UNIT_FILE_SCOPE_MAX);
539 assert(name);
540
541
542 /* First look in runtime config path */
543 r = get_config_path(scope, true, root_dir, &path);
544 if (r < 0)
545 return r;
546
547 r = find_symlinks(name, path, &same_name_link_runtime);
548 if (r < 0)
549 return r;
550 else if (r > 0) {
551 *state = UNIT_FILE_ENABLED_RUNTIME;
552 return r;
553 }
554
555 /* Then look in the normal config path */
556 r = get_config_path(scope, false, root_dir, &path);
557 if (r < 0)
558 return r;
559
560 r = find_symlinks(name, path, &same_name_link);
561 if (r < 0)
562 return r;
563 else if (r > 0) {
564 *state = UNIT_FILE_ENABLED;
565 return r;
566 }
567
568 /* Hmm, we didn't find it, but maybe we found the same name
569 * link? */
570 if (same_name_link_runtime) {
571 *state = UNIT_FILE_LINKED_RUNTIME;
572 return 1;
573 } else if (same_name_link) {
574 *state = UNIT_FILE_LINKED;
575 return 1;
576 }
577
578 return 0;
579 }
580
581 int unit_file_mask(
582 UnitFileScope scope,
583 bool runtime,
584 const char *root_dir,
585 char **files,
586 bool force,
587 UnitFileChange **changes,
588 unsigned *n_changes) {
589
590 char **i;
591 _cleanup_free_ char *prefix = NULL;
592 int r;
593
594 assert(scope >= 0);
595 assert(scope < _UNIT_FILE_SCOPE_MAX);
596
597 r = get_config_path(scope, runtime, root_dir, &prefix);
598 if (r < 0)
599 return r;
600
601 STRV_FOREACH(i, files) {
602 _cleanup_free_ char *path = NULL;
603
604 if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
605 if (r == 0)
606 r = -EINVAL;
607 continue;
608 }
609
610 path = path_make_absolute(*i, prefix);
611 if (!path) {
612 r = -ENOMEM;
613 break;
614 }
615
616 if (symlink("/dev/null", path) >= 0) {
617 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
618 continue;
619 }
620
621 if (errno == EEXIST) {
622
623 if (null_or_empty_path(path) > 0)
624 continue;
625
626 if (force) {
627 if (symlink_atomic("/dev/null", path) >= 0) {
628 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
629 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, "/dev/null");
630 continue;
631 }
632 }
633
634 if (r == 0)
635 r = -EEXIST;
636 } else {
637 if (r == 0)
638 r = -errno;
639 }
640 }
641
642 return r;
643 }
644
645 int unit_file_unmask(
646 UnitFileScope scope,
647 bool runtime,
648 const char *root_dir,
649 char **files,
650 UnitFileChange **changes,
651 unsigned *n_changes) {
652
653 char **i, *config_path = NULL;
654 int r, q;
655 Set *remove_symlinks_to = NULL;
656
657 assert(scope >= 0);
658 assert(scope < _UNIT_FILE_SCOPE_MAX);
659
660 r = get_config_path(scope, runtime, root_dir, &config_path);
661 if (r < 0)
662 goto finish;
663
664 STRV_FOREACH(i, files) {
665 char *path;
666
667 if (!unit_name_is_valid(*i, TEMPLATE_VALID)) {
668 if (r == 0)
669 r = -EINVAL;
670 continue;
671 }
672
673 path = path_make_absolute(*i, config_path);
674 if (!path) {
675 r = -ENOMEM;
676 break;
677 }
678
679 q = null_or_empty_path(path);
680 if (q > 0) {
681 if (unlink(path) >= 0) {
682 mark_symlink_for_removal(&remove_symlinks_to, path);
683 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
684
685 free(path);
686 continue;
687 }
688
689 q = -errno;
690 }
691
692 if (q != -ENOENT && r == 0)
693 r = q;
694
695 free(path);
696 }
697
698
699 finish:
700 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
701 if (r == 0)
702 r = q;
703
704 set_free_free(remove_symlinks_to);
705 free(config_path);
706
707 return r;
708 }
709
710 int unit_file_link(
711 UnitFileScope scope,
712 bool runtime,
713 const char *root_dir,
714 char **files,
715 bool force,
716 UnitFileChange **changes,
717 unsigned *n_changes) {
718
719 _cleanup_lookup_paths_free_ LookupPaths paths = {};
720 char **i;
721 _cleanup_free_ char *config_path = NULL;
722 int r, q;
723
724 assert(scope >= 0);
725 assert(scope < _UNIT_FILE_SCOPE_MAX);
726
727 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
728 if (r < 0)
729 return r;
730
731 r = get_config_path(scope, runtime, root_dir, &config_path);
732 if (r < 0)
733 return r;
734
735 STRV_FOREACH(i, files) {
736 _cleanup_free_ char *path = NULL;
737 char *fn;
738 struct stat st;
739
740 fn = basename(*i);
741
742 if (!path_is_absolute(*i) ||
743 !unit_name_is_valid(fn, TEMPLATE_VALID)) {
744 if (r == 0)
745 r = -EINVAL;
746 continue;
747 }
748
749 if (lstat(*i, &st) < 0) {
750 if (r == 0)
751 r = -errno;
752 continue;
753 }
754
755 if (!S_ISREG(st.st_mode)) {
756 r = -ENOENT;
757 continue;
758 }
759
760 q = in_search_path(*i, paths.unit_path);
761 if (q < 0)
762 return q;
763
764 if (q > 0)
765 continue;
766
767 path = path_make_absolute(fn, config_path);
768 if (!path)
769 return -ENOMEM;
770
771 if (symlink(*i, path) >= 0) {
772 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
773 continue;
774 }
775
776 if (errno == EEXIST) {
777 _cleanup_free_ char *dest = NULL;
778
779 q = readlink_and_make_absolute(path, &dest);
780 if (q < 0 && errno != ENOENT) {
781 if (r == 0)
782 r = q;
783 continue;
784 }
785
786 if (q >= 0 && path_equal(dest, *i))
787 continue;
788
789 if (force) {
790 if (symlink_atomic(*i, path) >= 0) {
791 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
792 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, path, *i);
793 continue;
794 }
795 }
796
797 if (r == 0)
798 r = -EEXIST;
799 } else {
800 if (r == 0)
801 r = -errno;
802 }
803 }
804
805 return r;
806 }
807
808 void unit_file_list_free(Hashmap *h) {
809 UnitFileList *i;
810
811 while ((i = hashmap_steal_first(h))) {
812 free(i->path);
813 free(i);
814 }
815
816 hashmap_free(h);
817 }
818
819 void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) {
820 unsigned i;
821
822 assert(changes || n_changes == 0);
823
824 if (!changes)
825 return;
826
827 for (i = 0; i < n_changes; i++) {
828 free(changes[i].path);
829 free(changes[i].source);
830 }
831
832 free(changes);
833 }
834
835 static void install_info_free(InstallInfo *i) {
836 assert(i);
837
838 free(i->name);
839 free(i->path);
840 strv_free(i->aliases);
841 strv_free(i->wanted_by);
842 strv_free(i->required_by);
843 free(i->default_instance);
844 free(i);
845 }
846
847 static void install_info_hashmap_free(OrderedHashmap *m) {
848 InstallInfo *i;
849
850 if (!m)
851 return;
852
853 while ((i = ordered_hashmap_steal_first(m)))
854 install_info_free(i);
855
856 ordered_hashmap_free(m);
857 }
858
859 static void install_context_done(InstallContext *c) {
860 assert(c);
861
862 install_info_hashmap_free(c->will_install);
863 install_info_hashmap_free(c->have_installed);
864
865 c->will_install = c->have_installed = NULL;
866 }
867
868 static int install_info_add(
869 InstallContext *c,
870 const char *name,
871 const char *path) {
872 InstallInfo *i = NULL;
873 int r;
874
875 assert(c);
876 assert(name || path);
877
878 if (!name)
879 name = basename(path);
880
881 if (!unit_name_is_valid(name, TEMPLATE_VALID))
882 return -EINVAL;
883
884 if (ordered_hashmap_get(c->have_installed, name) ||
885 ordered_hashmap_get(c->will_install, name))
886 return 0;
887
888 r = ordered_hashmap_ensure_allocated(&c->will_install, &string_hash_ops);
889 if (r < 0)
890 return r;
891
892 i = new0(InstallInfo, 1);
893 if (!i)
894 return -ENOMEM;
895
896 i->name = strdup(name);
897 if (!i->name) {
898 r = -ENOMEM;
899 goto fail;
900 }
901
902 if (path) {
903 i->path = strdup(path);
904 if (!i->path) {
905 r = -ENOMEM;
906 goto fail;
907 }
908 }
909
910 r = ordered_hashmap_put(c->will_install, i->name, i);
911 if (r < 0)
912 goto fail;
913
914 return 0;
915
916 fail:
917 if (i)
918 install_info_free(i);
919
920 return r;
921 }
922
923 static int install_info_add_auto(
924 InstallContext *c,
925 const char *name_or_path) {
926
927 assert(c);
928 assert(name_or_path);
929
930 if (path_is_absolute(name_or_path))
931 return install_info_add(c, NULL, name_or_path);
932 else
933 return install_info_add(c, name_or_path, NULL);
934 }
935
936 static int config_parse_also(
937 const char *unit,
938 const char *filename,
939 unsigned line,
940 const char *section,
941 unsigned section_line,
942 const char *lvalue,
943 int ltype,
944 const char *rvalue,
945 void *data,
946 void *userdata) {
947
948 size_t l;
949 const char *word, *state;
950 InstallContext *c = data;
951
952 assert(filename);
953 assert(lvalue);
954 assert(rvalue);
955
956 FOREACH_WORD_QUOTED(word, l, rvalue, state) {
957 _cleanup_free_ char *n;
958 int r;
959
960 n = strndup(word, l);
961 if (!n)
962 return -ENOMEM;
963
964 r = install_info_add(c, n, NULL);
965 if (r < 0)
966 return r;
967 }
968 if (!isempty(state))
969 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
970 "Trailing garbage, ignoring.");
971
972 return 0;
973 }
974
975 static int config_parse_user(
976 const char *unit,
977 const char *filename,
978 unsigned line,
979 const char *section,
980 unsigned section_line,
981 const char *lvalue,
982 int ltype,
983 const char *rvalue,
984 void *data,
985 void *userdata) {
986
987 InstallInfo *i = data;
988 char *printed;
989 int r;
990
991 assert(filename);
992 assert(lvalue);
993 assert(rvalue);
994
995 r = install_full_printf(i, rvalue, &printed);
996 if (r < 0)
997 return r;
998
999 free(i->user);
1000 i->user = printed;
1001
1002 return 0;
1003 }
1004
1005 static int config_parse_default_instance(
1006 const char *unit,
1007 const char *filename,
1008 unsigned line,
1009 const char *section,
1010 unsigned section_line,
1011 const char *lvalue,
1012 int ltype,
1013 const char *rvalue,
1014 void *data,
1015 void *userdata) {
1016
1017 InstallInfo *i = data;
1018 char *printed;
1019 int r;
1020
1021 assert(filename);
1022 assert(lvalue);
1023 assert(rvalue);
1024
1025 r = install_full_printf(i, rvalue, &printed);
1026 if (r < 0)
1027 return r;
1028
1029 if (!unit_instance_is_valid(printed)) {
1030 free(printed);
1031 return -EINVAL;
1032 }
1033
1034 free(i->default_instance);
1035 i->default_instance = printed;
1036
1037 return 0;
1038 }
1039
1040 static int unit_file_load(
1041 InstallContext *c,
1042 InstallInfo *info,
1043 const char *path,
1044 const char *root_dir,
1045 bool allow_symlink,
1046 bool load) {
1047
1048 const ConfigTableItem items[] = {
1049 { "Install", "Alias", config_parse_strv, 0, &info->aliases },
1050 { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
1051 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
1052 { "Install", "DefaultInstance", config_parse_default_instance, 0, info },
1053 { "Install", "Also", config_parse_also, 0, c },
1054 { "Exec", "User", config_parse_user, 0, info },
1055 {}
1056 };
1057
1058 _cleanup_fclose_ FILE *f = NULL;
1059 int fd, r;
1060
1061 assert(c);
1062 assert(info);
1063 assert(path);
1064
1065 if (!isempty(root_dir))
1066 path = strappenda(root_dir, "/", path);
1067
1068 if (!load) {
1069 r = access(path, F_OK) ? -errno : 0;
1070 return r;
1071 }
1072
1073 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW));
1074 if (fd < 0)
1075 return -errno;
1076
1077 f = fdopen(fd, "re");
1078 if (!f) {
1079 safe_close(fd);
1080 return -ENOMEM;
1081 }
1082
1083 r = config_parse(NULL, path, f,
1084 NULL,
1085 config_item_table_lookup, items,
1086 true, true, false, info);
1087 if (r < 0)
1088 return r;
1089
1090 return
1091 (int) strv_length(info->aliases) +
1092 (int) strv_length(info->wanted_by) +
1093 (int) strv_length(info->required_by);
1094 }
1095
1096 static int unit_file_search(
1097 InstallContext *c,
1098 InstallInfo *info,
1099 LookupPaths *paths,
1100 const char *root_dir,
1101 bool allow_symlink,
1102 bool load) {
1103
1104 char **p;
1105 int r;
1106
1107 assert(c);
1108 assert(info);
1109 assert(paths);
1110
1111 if (info->path)
1112 return unit_file_load(c, info, info->path, root_dir, allow_symlink, load);
1113
1114 assert(info->name);
1115
1116 STRV_FOREACH(p, paths->unit_path) {
1117 _cleanup_free_ char *path = NULL;
1118
1119 path = strjoin(*p, "/", info->name, NULL);
1120 if (!path)
1121 return -ENOMEM;
1122
1123 r = unit_file_load(c, info, path, root_dir, allow_symlink, load);
1124 if (r >= 0) {
1125 info->path = path;
1126 path = NULL;
1127 return r;
1128 }
1129 if (r != -ENOENT && r != -ELOOP)
1130 return r;
1131 }
1132
1133 if (unit_name_is_instance(info->name)) {
1134
1135 /* Unit file doesn't exist, however instance
1136 * enablement was requested. We will check if it is
1137 * possible to load template unit file. */
1138
1139 _cleanup_free_ char *template = NULL;
1140
1141 template = unit_name_template(info->name);
1142 if (!template)
1143 return -ENOMEM;
1144
1145 STRV_FOREACH(p, paths->unit_path) {
1146 _cleanup_free_ char *path = NULL;
1147
1148 path = strjoin(*p, "/", template, NULL);
1149 if (!path)
1150 return -ENOMEM;
1151
1152 r = unit_file_load(c, info, path, root_dir, allow_symlink, load);
1153 if (r >= 0) {
1154 info->path = path;
1155 path = NULL;
1156 return r;
1157 }
1158 if (r != -ENOENT && r != -ELOOP)
1159 return r;
1160 }
1161 }
1162
1163 return -ENOENT;
1164 }
1165
1166 static int unit_file_can_install(
1167 LookupPaths *paths,
1168 const char *root_dir,
1169 const char *name,
1170 bool allow_symlink) {
1171
1172 _cleanup_(install_context_done) InstallContext c = {};
1173 InstallInfo *i;
1174 int r;
1175
1176 assert(paths);
1177 assert(name);
1178
1179 r = install_info_add_auto(&c, name);
1180 if (r < 0)
1181 return r;
1182
1183 assert_se(i = ordered_hashmap_first(c.will_install));
1184
1185 r = unit_file_search(&c, i, paths, root_dir, allow_symlink, true);
1186
1187 if (r >= 0)
1188 r =
1189 (int) strv_length(i->aliases) +
1190 (int) strv_length(i->wanted_by) +
1191 (int) strv_length(i->required_by);
1192
1193 return r;
1194 }
1195
1196 static int create_symlink(
1197 const char *old_path,
1198 const char *new_path,
1199 bool force,
1200 UnitFileChange **changes,
1201 unsigned *n_changes) {
1202
1203 _cleanup_free_ char *dest = NULL;
1204 int r;
1205
1206 assert(old_path);
1207 assert(new_path);
1208
1209 mkdir_parents_label(new_path, 0755);
1210
1211 if (symlink(old_path, new_path) >= 0) {
1212 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1213 return 0;
1214 }
1215
1216 if (errno != EEXIST)
1217 return -errno;
1218
1219 r = readlink_and_make_absolute(new_path, &dest);
1220 if (r < 0)
1221 return r;
1222
1223 if (path_equal(dest, old_path))
1224 return 0;
1225
1226 if (!force)
1227 return -EEXIST;
1228
1229 r = symlink_atomic(old_path, new_path);
1230 if (r < 0)
1231 return r;
1232
1233 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
1234 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1235
1236 return 0;
1237 }
1238
1239 static int install_info_symlink_alias(
1240 InstallInfo *i,
1241 const char *config_path,
1242 bool force,
1243 UnitFileChange **changes,
1244 unsigned *n_changes) {
1245
1246 char **s;
1247 int r = 0, q;
1248
1249 assert(i);
1250 assert(config_path);
1251
1252 STRV_FOREACH(s, i->aliases) {
1253 _cleanup_free_ char *alias_path = NULL, *dst = NULL;
1254
1255 q = install_full_printf(i, *s, &dst);
1256 if (q < 0)
1257 return q;
1258
1259 alias_path = path_make_absolute(dst, config_path);
1260 if (!alias_path)
1261 return -ENOMEM;
1262
1263 q = create_symlink(i->path, alias_path, force, changes, n_changes);
1264 if (r == 0)
1265 r = q;
1266 }
1267
1268 return r;
1269 }
1270
1271 static int install_info_symlink_wants(
1272 InstallInfo *i,
1273 const char *config_path,
1274 char **list,
1275 const char *suffix,
1276 bool force,
1277 UnitFileChange **changes,
1278 unsigned *n_changes) {
1279
1280 _cleanup_free_ char *buf = NULL;
1281 const char *n;
1282 char **s;
1283 int r = 0, q;
1284
1285 assert(i);
1286 assert(config_path);
1287
1288 if (unit_name_is_template(i->name)) {
1289
1290 /* Don't install any symlink if there's no default
1291 * instance configured */
1292
1293 if (!i->default_instance)
1294 return 0;
1295
1296 buf = unit_name_replace_instance(i->name, i->default_instance);
1297 if (!buf)
1298 return -ENOMEM;
1299
1300 n = buf;
1301 } else
1302 n = i->name;
1303
1304 STRV_FOREACH(s, list) {
1305 _cleanup_free_ char *path = NULL, *dst = NULL;
1306
1307 q = install_full_printf(i, *s, &dst);
1308 if (q < 0)
1309 return q;
1310
1311 if (!unit_name_is_valid(dst, TEMPLATE_VALID)) {
1312 r = -EINVAL;
1313 continue;
1314 }
1315
1316 path = strjoin(config_path, "/", dst, suffix, n, NULL);
1317 if (!path)
1318 return -ENOMEM;
1319
1320 q = create_symlink(i->path, path, force, changes, n_changes);
1321 if (r == 0)
1322 r = q;
1323 }
1324
1325 return r;
1326 }
1327
1328 static int install_info_symlink_link(
1329 InstallInfo *i,
1330 LookupPaths *paths,
1331 const char *config_path,
1332 const char *root_dir,
1333 bool force,
1334 UnitFileChange **changes,
1335 unsigned *n_changes) {
1336
1337 _cleanup_free_ char *path = NULL;
1338 int r;
1339
1340 assert(i);
1341 assert(paths);
1342 assert(config_path);
1343 assert(i->path);
1344
1345 r = in_search_path(i->path, paths->unit_path);
1346 if (r != 0)
1347 return r;
1348
1349 path = strjoin(config_path, "/", i->name, NULL);
1350 if (!path)
1351 return -ENOMEM;
1352
1353 return create_symlink(i->path, path, force, changes, n_changes);
1354 }
1355
1356 static int install_info_apply(
1357 InstallInfo *i,
1358 LookupPaths *paths,
1359 const char *config_path,
1360 const char *root_dir,
1361 bool force,
1362 UnitFileChange **changes,
1363 unsigned *n_changes) {
1364
1365 int r, q;
1366
1367 assert(i);
1368 assert(paths);
1369 assert(config_path);
1370
1371 r = install_info_symlink_alias(i, config_path, force, changes, n_changes);
1372
1373 q = install_info_symlink_wants(i, config_path, i->wanted_by, ".wants/", force, changes, n_changes);
1374 if (r == 0)
1375 r = q;
1376
1377 q = install_info_symlink_wants(i, config_path, i->required_by, ".requires/", force, changes, n_changes);
1378 if (r == 0)
1379 r = q;
1380
1381 q = install_info_symlink_link(i, paths, config_path, root_dir, force, changes, n_changes);
1382 if (r == 0)
1383 r = q;
1384
1385 return r;
1386 }
1387
1388 static int install_context_apply(
1389 InstallContext *c,
1390 LookupPaths *paths,
1391 const char *config_path,
1392 const char *root_dir,
1393 bool force,
1394 UnitFileChange **changes,
1395 unsigned *n_changes) {
1396
1397 InstallInfo *i;
1398 int r, q;
1399
1400 assert(c);
1401 assert(paths);
1402 assert(config_path);
1403
1404 if (!ordered_hashmap_isempty(c->will_install)) {
1405 r = ordered_hashmap_ensure_allocated(&c->have_installed, &string_hash_ops);
1406 if (r < 0)
1407 return r;
1408
1409 r = ordered_hashmap_reserve(c->have_installed, ordered_hashmap_size(c->will_install));
1410 if (r < 0)
1411 return r;
1412 }
1413
1414 r = 0;
1415 while ((i = ordered_hashmap_first(c->will_install))) {
1416 assert_se(ordered_hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1417
1418 q = unit_file_search(c, i, paths, root_dir, false, true);
1419 if (q < 0) {
1420 if (r >= 0)
1421 r = q;
1422
1423 return r;
1424 } else if (r >= 0)
1425 r += q;
1426
1427 q = install_info_apply(i, paths, config_path, root_dir, force, changes, n_changes);
1428 if (r >= 0 && q < 0)
1429 r = q;
1430 }
1431
1432 return r;
1433 }
1434
1435 static int install_context_mark_for_removal(
1436 InstallContext *c,
1437 LookupPaths *paths,
1438 Set **remove_symlinks_to,
1439 const char *config_path,
1440 const char *root_dir) {
1441
1442 InstallInfo *i;
1443 int r, q;
1444
1445 assert(c);
1446 assert(paths);
1447 assert(config_path);
1448
1449 /* Marks all items for removal */
1450
1451 if (!ordered_hashmap_isempty(c->will_install)) {
1452 r = ordered_hashmap_ensure_allocated(&c->have_installed, &string_hash_ops);
1453 if (r < 0)
1454 return r;
1455
1456 r = ordered_hashmap_reserve(c->have_installed, ordered_hashmap_size(c->will_install));
1457 if (r < 0)
1458 return r;
1459 }
1460
1461 r = 0;
1462 while ((i = ordered_hashmap_first(c->will_install))) {
1463 assert_se(ordered_hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1464
1465 q = unit_file_search(c, i, paths, root_dir, false, true);
1466 if (q == -ENOENT) {
1467 /* do nothing */
1468 } else if (q < 0) {
1469 if (r >= 0)
1470 r = q;
1471
1472 return r;
1473 } else if (r >= 0)
1474 r += q;
1475
1476 if (unit_name_is_instance(i->name)) {
1477 char *unit_file;
1478
1479 if (i->path) {
1480 unit_file = basename(i->path);
1481
1482 if (unit_name_is_instance(unit_file))
1483 /* unit file named as instance exists, thus all symlinks
1484 * pointing to it will be removed */
1485 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1486 else
1487 /* does not exist, thus we will mark for removal symlinks
1488 * to template unit file */
1489 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1490 } else {
1491 /* If i->path is not set, it means that we didn't actually find
1492 * the unit file. But we can still remove symlinks to the
1493 * nonexistent template. */
1494 unit_file = unit_name_template(i->name);
1495 if (!unit_file)
1496 return log_oom();
1497
1498 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1499 free(unit_file);
1500 }
1501 } else
1502 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1503
1504 if (r >= 0 && q < 0)
1505 r = q;
1506 }
1507
1508 return r;
1509 }
1510
1511 int unit_file_add_dependency(
1512 UnitFileScope scope,
1513 bool runtime,
1514 const char *root_dir,
1515 char **files,
1516 char *target,
1517 UnitDependency dep,
1518 bool force,
1519 UnitFileChange **changes,
1520 unsigned *n_changes) {
1521
1522 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1523 _cleanup_(install_context_done) InstallContext c = {};
1524 _cleanup_free_ char *config_path = NULL;
1525 char **i;
1526 int r;
1527 InstallInfo *info;
1528
1529 assert(scope >= 0);
1530 assert(scope < _UNIT_FILE_SCOPE_MAX);
1531
1532 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1533 if (r < 0)
1534 return r;
1535
1536 r = get_config_path(scope, runtime, root_dir, &config_path);
1537 if (r < 0)
1538 return r;
1539
1540 STRV_FOREACH(i, files) {
1541 UnitFileState state;
1542
1543 state = unit_file_get_state(scope, root_dir, *i);
1544 if (state < 0) {
1545 log_error("Failed to get unit file state for %s: %s", *i, strerror(-state));
1546 return state;
1547 }
1548
1549 if (state == UNIT_FILE_MASKED || state == UNIT_FILE_MASKED_RUNTIME) {
1550 log_error("Failed to enable unit: Unit %s is masked", *i);
1551 return -ENOTSUP;
1552 }
1553
1554 r = install_info_add_auto(&c, *i);
1555 if (r < 0)
1556 return r;
1557 }
1558
1559 if (!ordered_hashmap_isempty(c.will_install)) {
1560 r = ordered_hashmap_ensure_allocated(&c.have_installed, &string_hash_ops);
1561 if (r < 0)
1562 return r;
1563
1564 r = ordered_hashmap_reserve(c.have_installed, ordered_hashmap_size(c.will_install));
1565 if (r < 0)
1566 return r;
1567 }
1568
1569 while ((info = ordered_hashmap_first(c.will_install))) {
1570 assert_se(ordered_hashmap_move_one(c.have_installed, c.will_install, info->name) == 0);
1571
1572 r = unit_file_search(&c, info, &paths, root_dir, false, false);
1573 if (r < 0)
1574 return r;
1575
1576 if (dep == UNIT_WANTS)
1577 r = strv_extend(&info->wanted_by, target);
1578 else if (dep == UNIT_REQUIRES)
1579 r = strv_extend(&info->required_by, target);
1580 else
1581 r = -EINVAL;
1582
1583 if (r < 0)
1584 return r;
1585
1586 r = install_info_apply(info, &paths, config_path, root_dir, force, changes, n_changes);
1587 if (r < 0)
1588 return r;
1589 }
1590
1591 return 0;
1592 }
1593
1594 int unit_file_enable(
1595 UnitFileScope scope,
1596 bool runtime,
1597 const char *root_dir,
1598 char **files,
1599 bool force,
1600 UnitFileChange **changes,
1601 unsigned *n_changes) {
1602
1603 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1604 _cleanup_(install_context_done) InstallContext c = {};
1605 char **i;
1606 _cleanup_free_ char *config_path = NULL;
1607 int r;
1608
1609 assert(scope >= 0);
1610 assert(scope < _UNIT_FILE_SCOPE_MAX);
1611
1612 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1613 if (r < 0)
1614 return r;
1615
1616 r = get_config_path(scope, runtime, root_dir, &config_path);
1617 if (r < 0)
1618 return r;
1619
1620 STRV_FOREACH(i, files) {
1621 UnitFileState state;
1622
1623 state = unit_file_get_state(scope, root_dir, *i);
1624 if (state < 0) {
1625 log_error("Failed to get unit file state for %s: %s", *i, strerror(-state));
1626 return state;
1627 }
1628
1629 if (state == UNIT_FILE_MASKED || state == UNIT_FILE_MASKED_RUNTIME) {
1630 log_error("Failed to enable unit: Unit %s is masked", *i);
1631 return -ENOTSUP;
1632 }
1633
1634 r = install_info_add_auto(&c, *i);
1635 if (r < 0)
1636 return r;
1637 }
1638
1639 /* This will return the number of symlink rules that were
1640 supposed to be created, not the ones actually created. This is
1641 useful to determine whether the passed files had any
1642 installation data at all. */
1643
1644 return install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1645 }
1646
1647 int unit_file_disable(
1648 UnitFileScope scope,
1649 bool runtime,
1650 const char *root_dir,
1651 char **files,
1652 UnitFileChange **changes,
1653 unsigned *n_changes) {
1654
1655 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1656 _cleanup_(install_context_done) InstallContext c = {};
1657 char **i;
1658 _cleanup_free_ char *config_path = NULL;
1659 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1660 int r, q;
1661
1662 assert(scope >= 0);
1663 assert(scope < _UNIT_FILE_SCOPE_MAX);
1664
1665 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1666 if (r < 0)
1667 return r;
1668
1669 r = get_config_path(scope, runtime, root_dir, &config_path);
1670 if (r < 0)
1671 return r;
1672
1673 STRV_FOREACH(i, files) {
1674 r = install_info_add_auto(&c, *i);
1675 if (r < 0)
1676 return r;
1677 }
1678
1679 r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
1680
1681 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1682 if (r == 0)
1683 r = q;
1684
1685 return r;
1686 }
1687
1688 int unit_file_reenable(
1689 UnitFileScope scope,
1690 bool runtime,
1691 const char *root_dir,
1692 char **files,
1693 bool force,
1694 UnitFileChange **changes,
1695 unsigned *n_changes) {
1696 int r;
1697
1698 r = unit_file_disable(scope, runtime, root_dir, files,
1699 changes, n_changes);
1700 if (r < 0)
1701 return r;
1702
1703 return unit_file_enable(scope, runtime, root_dir, files, force,
1704 changes, n_changes);
1705 }
1706
1707 int unit_file_set_default(
1708 UnitFileScope scope,
1709 const char *root_dir,
1710 const char *file,
1711 bool force,
1712 UnitFileChange **changes,
1713 unsigned *n_changes) {
1714
1715 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1716 _cleanup_(install_context_done) InstallContext c = {};
1717 _cleanup_free_ char *config_path = NULL;
1718 char *path;
1719 int r;
1720 InstallInfo *i = NULL;
1721
1722 assert(scope >= 0);
1723 assert(scope < _UNIT_FILE_SCOPE_MAX);
1724 assert(file);
1725
1726 if (unit_name_to_type(file) != UNIT_TARGET)
1727 return -EINVAL;
1728
1729 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1730 if (r < 0)
1731 return r;
1732
1733 r = get_config_path(scope, false, root_dir, &config_path);
1734 if (r < 0)
1735 return r;
1736
1737 r = install_info_add_auto(&c, file);
1738 if (r < 0)
1739 return r;
1740
1741 assert_se(i = ordered_hashmap_first(c.will_install));
1742
1743 r = unit_file_search(&c, i, &paths, root_dir, false, true);
1744 if (r < 0)
1745 return r;
1746
1747 path = strappenda(config_path, "/" SPECIAL_DEFAULT_TARGET);
1748
1749 r = create_symlink(i->path, path, force, changes, n_changes);
1750 if (r < 0)
1751 return r;
1752
1753 return 0;
1754 }
1755
1756 int unit_file_get_default(
1757 UnitFileScope scope,
1758 const char *root_dir,
1759 char **name) {
1760
1761 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1762 char **p;
1763 int r;
1764
1765 assert(scope >= 0);
1766 assert(scope < _UNIT_FILE_SCOPE_MAX);
1767 assert(name);
1768
1769 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1770 if (r < 0)
1771 return r;
1772
1773 STRV_FOREACH(p, paths.unit_path) {
1774 _cleanup_free_ char *path = NULL, *tmp = NULL;
1775 char *n;
1776
1777 path = path_join(root_dir, *p, SPECIAL_DEFAULT_TARGET);
1778 if (!path)
1779 return -ENOMEM;
1780
1781 r = readlink_malloc(path, &tmp);
1782 if (r == -ENOENT)
1783 continue;
1784 else if (r == -EINVAL)
1785 /* not a symlink */
1786 n = strdup(SPECIAL_DEFAULT_TARGET);
1787 else if (r < 0)
1788 return r;
1789 else
1790 n = strdup(basename(tmp));
1791
1792 if (!n)
1793 return -ENOMEM;
1794
1795 *name = n;
1796 return 0;
1797 }
1798
1799 return -ENOENT;
1800 }
1801
1802 UnitFileState unit_file_get_state(
1803 UnitFileScope scope,
1804 const char *root_dir,
1805 const char *name) {
1806
1807 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1808 UnitFileState state = _UNIT_FILE_STATE_INVALID;
1809 char **i;
1810 _cleanup_free_ char *path = NULL;
1811 int r;
1812
1813 assert(scope >= 0);
1814 assert(scope < _UNIT_FILE_SCOPE_MAX);
1815 assert(name);
1816
1817 if (root_dir && scope != UNIT_FILE_SYSTEM)
1818 return -EINVAL;
1819
1820 if (!unit_name_is_valid(name, TEMPLATE_VALID))
1821 return -EINVAL;
1822
1823 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1824 if (r < 0)
1825 return r;
1826
1827 STRV_FOREACH(i, paths.unit_path) {
1828 struct stat st;
1829 char *partial;
1830
1831 free(path);
1832 path = NULL;
1833
1834 path = path_join(root_dir, *i, name);
1835 if (!path)
1836 return -ENOMEM;
1837
1838 if (root_dir)
1839 partial = path + strlen(root_dir);
1840 else
1841 partial = path;
1842
1843 /*
1844 * Search for a unit file in our default paths, to
1845 * be sure, that there are no broken symlinks.
1846 */
1847 if (lstat(path, &st) < 0) {
1848 r = -errno;
1849 if (errno != ENOENT)
1850 return r;
1851
1852 if (!unit_name_is_instance(name))
1853 continue;
1854 } else {
1855 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
1856 return -ENOENT;
1857
1858 r = null_or_empty_path(path);
1859 if (r < 0 && r != -ENOENT)
1860 return r;
1861 else if (r > 0) {
1862 state = path_startswith(*i, "/run") ?
1863 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1864 return state;
1865 }
1866 }
1867
1868 r = find_symlinks_in_scope(scope, root_dir, name, &state);
1869 if (r < 0)
1870 return r;
1871 else if (r > 0)
1872 return state;
1873
1874 r = unit_file_can_install(&paths, root_dir, partial, true);
1875 if (r < 0 && errno != ENOENT)
1876 return r;
1877 else if (r > 0)
1878 return UNIT_FILE_DISABLED;
1879 else if (r == 0)
1880 return UNIT_FILE_STATIC;
1881 }
1882
1883 return r < 0 ? r : state;
1884 }
1885
1886 int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name) {
1887 _cleanup_strv_free_ char **files = NULL;
1888 char **p;
1889 int r;
1890
1891 assert(scope >= 0);
1892 assert(scope < _UNIT_FILE_SCOPE_MAX);
1893 assert(name);
1894
1895 if (scope == UNIT_FILE_SYSTEM)
1896 r = conf_files_list(&files, ".preset", root_dir,
1897 "/etc/systemd/system-preset",
1898 "/usr/local/lib/systemd/system-preset",
1899 "/usr/lib/systemd/system-preset",
1900 #ifdef HAVE_SPLIT_USR
1901 "/lib/systemd/system-preset",
1902 #endif
1903 NULL);
1904 else if (scope == UNIT_FILE_GLOBAL)
1905 r = conf_files_list(&files, ".preset", root_dir,
1906 "/etc/systemd/user-preset",
1907 "/usr/local/lib/systemd/user-preset",
1908 "/usr/lib/systemd/user-preset",
1909 NULL);
1910 else
1911 return 1;
1912
1913 if (r < 0)
1914 return r;
1915
1916 STRV_FOREACH(p, files) {
1917 _cleanup_fclose_ FILE *f;
1918
1919 f = fopen(*p, "re");
1920 if (!f) {
1921 if (errno == ENOENT)
1922 continue;
1923
1924 return -errno;
1925 }
1926
1927 for (;;) {
1928 char line[LINE_MAX], *l;
1929
1930 if (!fgets(line, sizeof(line), f))
1931 break;
1932
1933 l = strstrip(line);
1934 if (!*l)
1935 continue;
1936
1937 if (strchr(COMMENTS "\n", *l))
1938 continue;
1939
1940 if (first_word(l, "enable")) {
1941 l += 6;
1942 l += strspn(l, WHITESPACE);
1943
1944 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1945 log_debug("Preset file says enable %s.", name);
1946 return 1;
1947 }
1948
1949 } else if (first_word(l, "disable")) {
1950 l += 7;
1951 l += strspn(l, WHITESPACE);
1952
1953 if (fnmatch(l, name, FNM_NOESCAPE) == 0) {
1954 log_debug("Preset file says disable %s.", name);
1955 return 0;
1956 }
1957
1958 } else
1959 log_debug("Couldn't parse line '%s'", l);
1960 }
1961 }
1962
1963 /* Default is "enable" */
1964 log_debug("Preset file doesn't say anything about %s, enabling.", name);
1965 return 1;
1966 }
1967
1968 int unit_file_preset(
1969 UnitFileScope scope,
1970 bool runtime,
1971 const char *root_dir,
1972 char **files,
1973 UnitFilePresetMode mode,
1974 bool force,
1975 UnitFileChange **changes,
1976 unsigned *n_changes) {
1977
1978 _cleanup_(install_context_done) InstallContext plus = {}, minus = {};
1979 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1980 _cleanup_free_ char *config_path = NULL;
1981 char **i;
1982 int r, q;
1983
1984 assert(scope >= 0);
1985 assert(scope < _UNIT_FILE_SCOPE_MAX);
1986 assert(mode < _UNIT_FILE_PRESET_MAX);
1987
1988 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
1989 if (r < 0)
1990 return r;
1991
1992 r = get_config_path(scope, runtime, root_dir, &config_path);
1993 if (r < 0)
1994 return r;
1995
1996 STRV_FOREACH(i, files) {
1997
1998 if (!unit_name_is_valid(*i, TEMPLATE_VALID))
1999 return -EINVAL;
2000
2001 r = unit_file_query_preset(scope, root_dir, *i);
2002 if (r < 0)
2003 return r;
2004
2005 if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
2006 r = install_info_add_auto(&plus, *i);
2007 else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
2008 r = install_info_add_auto(&minus, *i);
2009 else
2010 r = 0;
2011 if (r < 0)
2012 return r;
2013 }
2014
2015 r = 0;
2016
2017 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
2018 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
2019
2020 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
2021
2022 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
2023 if (r == 0)
2024 r = q;
2025 }
2026
2027 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
2028 /* Returns number of symlinks that where supposed to be installed. */
2029 q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
2030 if (r == 0)
2031 r = q;
2032 }
2033
2034 return r;
2035 }
2036
2037 int unit_file_preset_all(
2038 UnitFileScope scope,
2039 bool runtime,
2040 const char *root_dir,
2041 UnitFilePresetMode mode,
2042 bool force,
2043 UnitFileChange **changes,
2044 unsigned *n_changes) {
2045
2046 _cleanup_(install_context_done) InstallContext plus = {}, minus = {};
2047 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2048 _cleanup_free_ char *config_path = NULL;
2049 char **i;
2050 int r, q;
2051
2052 assert(scope >= 0);
2053 assert(scope < _UNIT_FILE_SCOPE_MAX);
2054 assert(mode < _UNIT_FILE_PRESET_MAX);
2055
2056 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
2057 if (r < 0)
2058 return r;
2059
2060 r = get_config_path(scope, runtime, root_dir, &config_path);
2061 if (r < 0)
2062 return r;
2063
2064 STRV_FOREACH(i, paths.unit_path) {
2065 _cleanup_closedir_ DIR *d = NULL;
2066 _cleanup_free_ char *units_dir;
2067
2068 units_dir = path_join(root_dir, *i, NULL);
2069 if (!units_dir)
2070 return -ENOMEM;
2071
2072 d = opendir(units_dir);
2073 if (!d) {
2074 if (errno == ENOENT)
2075 continue;
2076
2077 return -errno;
2078 }
2079
2080 for (;;) {
2081 struct dirent *de;
2082
2083 errno = 0;
2084 de = readdir(d);
2085 if (!de && errno != 0)
2086 return -errno;
2087
2088 if (!de)
2089 break;
2090
2091 if (ignore_file(de->d_name))
2092 continue;
2093
2094 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
2095 continue;
2096
2097 dirent_ensure_type(d, de);
2098
2099 if (de->d_type != DT_REG)
2100 continue;
2101
2102 r = unit_file_query_preset(scope, root_dir, de->d_name);
2103 if (r < 0)
2104 return r;
2105
2106 if (r && mode != UNIT_FILE_PRESET_DISABLE_ONLY)
2107 r = install_info_add_auto(&plus, de->d_name);
2108 else if (!r && mode != UNIT_FILE_PRESET_ENABLE_ONLY)
2109 r = install_info_add_auto(&minus, de->d_name);
2110 else
2111 r = 0;
2112 if (r < 0)
2113 return r;
2114 }
2115 }
2116
2117 r = 0;
2118
2119 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
2120 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
2121
2122 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
2123
2124 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, NULL);
2125 if (r == 0)
2126 r = q;
2127 }
2128
2129 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
2130 q = install_context_apply(&plus, &paths, config_path, root_dir, force, changes, n_changes);
2131 if (r == 0)
2132 r = q;
2133 }
2134
2135 return r;
2136 }
2137
2138 static void unit_file_list_free_one(UnitFileList *f) {
2139 if (!f)
2140 return;
2141
2142 free(f->path);
2143 free(f);
2144 }
2145
2146 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitFileList*, unit_file_list_free_one);
2147
2148 int unit_file_get_list(
2149 UnitFileScope scope,
2150 const char *root_dir,
2151 Hashmap *h) {
2152
2153 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2154 char **i;
2155 int r;
2156
2157 assert(scope >= 0);
2158 assert(scope < _UNIT_FILE_SCOPE_MAX);
2159 assert(h);
2160
2161 if (root_dir && scope != UNIT_FILE_SYSTEM)
2162 return -EINVAL;
2163
2164 if (root_dir) {
2165 r = access(root_dir, F_OK);
2166 if (r < 0)
2167 return -errno;
2168 }
2169
2170 r = lookup_paths_init_from_scope(&paths, scope, root_dir);
2171 if (r < 0)
2172 return r;
2173
2174 STRV_FOREACH(i, paths.unit_path) {
2175 _cleanup_closedir_ DIR *d = NULL;
2176 _cleanup_free_ char *units_dir;
2177
2178 units_dir = path_join(root_dir, *i, NULL);
2179 if (!units_dir)
2180 return -ENOMEM;
2181
2182 d = opendir(units_dir);
2183 if (!d) {
2184 if (errno == ENOENT)
2185 continue;
2186
2187 return -errno;
2188 }
2189
2190 for (;;) {
2191 _cleanup_(unit_file_list_free_onep) UnitFileList *f = NULL;
2192 struct dirent *de;
2193 _cleanup_free_ char *path = NULL;
2194
2195 errno = 0;
2196 de = readdir(d);
2197 if (!de && errno != 0)
2198 return -errno;
2199
2200 if (!de)
2201 break;
2202
2203 if (ignore_file(de->d_name))
2204 continue;
2205
2206 if (!unit_name_is_valid(de->d_name, TEMPLATE_VALID))
2207 continue;
2208
2209 if (hashmap_get(h, de->d_name))
2210 continue;
2211
2212 dirent_ensure_type(d, de);
2213
2214 if (!IN_SET(de->d_type, DT_LNK, DT_REG))
2215 continue;
2216
2217 f = new0(UnitFileList, 1);
2218 if (!f)
2219 return -ENOMEM;
2220
2221 f->path = path_make_absolute(de->d_name, units_dir);
2222 if (!f->path)
2223 return -ENOMEM;
2224
2225 r = null_or_empty_path(f->path);
2226 if (r < 0 && r != -ENOENT)
2227 return r;
2228 else if (r > 0) {
2229 f->state =
2230 path_startswith(*i, "/run") ?
2231 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
2232 goto found;
2233 }
2234
2235 r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
2236 if (r < 0)
2237 return r;
2238 else if (r > 0) {
2239 f->state = UNIT_FILE_ENABLED;
2240 goto found;
2241 }
2242
2243 path = path_make_absolute(de->d_name, *i);
2244 if (!path)
2245 return -ENOMEM;
2246
2247 r = unit_file_can_install(&paths, root_dir, path, true);
2248 if (r == -EINVAL || /* Invalid setting? */
2249 r == -EBADMSG || /* Invalid format? */
2250 r == -ENOENT /* Included file not found? */)
2251 f->state = UNIT_FILE_INVALID;
2252 else if (r < 0)
2253 return r;
2254 else if (r > 0)
2255 f->state = UNIT_FILE_DISABLED;
2256 else
2257 f->state = UNIT_FILE_STATIC;
2258
2259 found:
2260 r = hashmap_put(h, basename(f->path), f);
2261 if (r < 0)
2262 return r;
2263 f = NULL; /* prevent cleanup */
2264 }
2265 }
2266
2267 return r;
2268 }
2269
2270 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
2271 [UNIT_FILE_ENABLED] = "enabled",
2272 [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
2273 [UNIT_FILE_LINKED] = "linked",
2274 [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
2275 [UNIT_FILE_MASKED] = "masked",
2276 [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
2277 [UNIT_FILE_STATIC] = "static",
2278 [UNIT_FILE_DISABLED] = "disabled",
2279 [UNIT_FILE_INVALID] = "invalid",
2280 };
2281
2282 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
2283
2284 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
2285 [UNIT_FILE_SYMLINK] = "symlink",
2286 [UNIT_FILE_UNLINK] = "unlink",
2287 };
2288
2289 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);
2290
2291 static const char* const unit_file_preset_mode_table[_UNIT_FILE_PRESET_MAX] = {
2292 [UNIT_FILE_PRESET_FULL] = "full",
2293 [UNIT_FILE_PRESET_ENABLE_ONLY] = "enable-only",
2294 [UNIT_FILE_PRESET_DISABLE_ONLY] = "disable-only",
2295 };
2296
2297 DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode, UnitFilePresetMode);