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