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