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