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