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