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