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