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