]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/install.c
eb9a5fc0b5d51af6a44b1beb09397b3c86f25f3c
[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
971 assert(filename);
972 assert(lvalue);
973 assert(rvalue);
974
975 printed = install_full_printf(i, rvalue);
976 if (!printed)
977 return -ENOMEM;
978
979 free(i->user);
980 i->user = printed;
981
982 return 0;
983 }
984
985 static int unit_file_load(
986 InstallContext *c,
987 InstallInfo *info,
988 const char *path,
989 bool allow_symlink) {
990
991 const ConfigTableItem items[] = {
992 { "Install", "Alias", config_parse_strv, 0, &info->aliases },
993 { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
994 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
995 { "Install", "Also", config_parse_also, 0, c },
996 { "Exec", "User", config_parse_user, 0, info },
997 { NULL, NULL, NULL, 0, NULL }
998 };
999
1000 int fd;
1001 _cleanup_fclose_ FILE *f = NULL;
1002 int r;
1003
1004 assert(c);
1005 assert(info);
1006 assert(path);
1007
1008 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|(allow_symlink ? 0 : O_NOFOLLOW));
1009 if (fd < 0)
1010 return -errno;
1011
1012 f = fdopen(fd, "re");
1013 if (!f) {
1014 close_nointr_nofail(fd);
1015 return -ENOMEM;
1016 }
1017
1018 r = config_parse(NULL, path, f, NULL,
1019 config_item_table_lookup, (void*) items, true, true, info);
1020 if (r < 0)
1021 return r;
1022
1023 return
1024 strv_length(info->aliases) +
1025 strv_length(info->wanted_by) +
1026 strv_length(info->required_by);
1027 }
1028
1029 static int unit_file_search(
1030 InstallContext *c,
1031 InstallInfo *info,
1032 LookupPaths *paths,
1033 const char *root_dir,
1034 bool allow_symlink) {
1035
1036 char **p;
1037 int r;
1038
1039 assert(c);
1040 assert(info);
1041 assert(paths);
1042
1043 if (info->path)
1044 return unit_file_load(c, info, info->path, allow_symlink);
1045
1046 assert(info->name);
1047
1048 STRV_FOREACH(p, paths->unit_path) {
1049 char *path = NULL;
1050
1051 if (isempty(root_dir))
1052 asprintf(&path, "%s/%s", *p, info->name);
1053 else
1054 asprintf(&path, "%s/%s/%s", root_dir, *p, info->name);
1055
1056 if (!path)
1057 return -ENOMEM;
1058
1059 r = unit_file_load(c, info, path, allow_symlink);
1060
1061 if (r >= 0)
1062 info->path = path;
1063 else {
1064 if (r == -ENOENT && unit_name_is_instance(info->name)) {
1065 /* unit file doesn't exist, however instance enablement was request */
1066 /* we will check if it is possible to load template unit file */
1067 char *template = NULL,
1068 *template_path = NULL,
1069 *template_dir = NULL;
1070
1071 template = unit_name_template(info->name);
1072 if (!template) {
1073 free(path);
1074 return -ENOMEM;
1075 }
1076
1077 /* we will reuse path variable since we don't need it anymore */
1078 template_dir = path;
1079 *(strrchr(path, '/') + 1) = '\0';
1080
1081 template_path = strjoin(template_dir, template, NULL);
1082 if (!template_path) {
1083 free(path);
1084 free(template);
1085 return -ENOMEM;
1086 }
1087
1088 /* let's try to load template unit */
1089 r = unit_file_load(c, info, template_path, allow_symlink);
1090 if (r >= 0) {
1091 info->path = strdup(template_path);
1092 if (!info->path) {
1093 free(path);
1094 free(template);
1095 free(template_path);
1096 return -ENOMEM;
1097 }
1098 }
1099
1100 free(template);
1101 free(template_path);
1102 }
1103 free(path);
1104 }
1105
1106 if (r != -ENOENT && r != -ELOOP)
1107 return r;
1108 }
1109
1110 return -ENOENT;
1111 }
1112
1113 static int unit_file_can_install(
1114 LookupPaths *paths,
1115 const char *root_dir,
1116 const char *name,
1117 bool allow_symlink) {
1118
1119 _cleanup_install_context_done_ InstallContext c = {};
1120 InstallInfo *i;
1121 int r;
1122
1123 assert(paths);
1124 assert(name);
1125
1126 r = install_info_add_auto(&c, name);
1127 if (r < 0)
1128 return r;
1129
1130 assert_se(i = hashmap_first(c.will_install));
1131
1132 r = unit_file_search(&c, i, paths, root_dir, allow_symlink);
1133
1134 if (r >= 0)
1135 r =
1136 strv_length(i->aliases) +
1137 strv_length(i->wanted_by) +
1138 strv_length(i->required_by);
1139
1140 return r;
1141 }
1142
1143 static int create_symlink(
1144 const char *old_path,
1145 const char *new_path,
1146 bool force,
1147 UnitFileChange **changes,
1148 unsigned *n_changes) {
1149
1150 _cleanup_free_ char *dest = NULL;
1151 int r;
1152
1153 assert(old_path);
1154 assert(new_path);
1155
1156 mkdir_parents_label(new_path, 0755);
1157
1158 if (symlink(old_path, new_path) >= 0) {
1159 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1160 return 0;
1161 }
1162
1163 if (errno != EEXIST)
1164 return -errno;
1165
1166 r = readlink_and_make_absolute(new_path, &dest);
1167 if (r < 0)
1168 return r;
1169
1170 if (path_equal(dest, old_path))
1171 return 0;
1172
1173 if (!force)
1174 return -EEXIST;
1175
1176 unlink(new_path);
1177
1178 if (symlink(old_path, new_path) >= 0) {
1179 add_file_change(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
1180 add_file_change(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
1181 return 0;
1182 }
1183
1184 return -errno;
1185 }
1186
1187 static int install_info_symlink_alias(
1188 InstallInfo *i,
1189 const char *config_path,
1190 bool force,
1191 UnitFileChange **changes,
1192 unsigned *n_changes) {
1193
1194 char **s;
1195 int r = 0, q;
1196
1197 assert(i);
1198 assert(config_path);
1199
1200 STRV_FOREACH(s, i->aliases) {
1201 _cleanup_free_ char *alias_path = NULL, *dst = NULL;
1202
1203 dst = install_full_printf(i, *s);
1204 if (!dst)
1205 return -ENOMEM;
1206
1207 alias_path = path_make_absolute(dst, config_path);
1208 if (!alias_path)
1209 return -ENOMEM;
1210
1211 q = create_symlink(i->path, alias_path, force, changes, n_changes);
1212 if (r == 0)
1213 r = q;
1214 }
1215
1216 return r;
1217 }
1218
1219 static int install_info_symlink_wants(
1220 InstallInfo *i,
1221 const char *config_path,
1222 bool force,
1223 UnitFileChange **changes,
1224 unsigned *n_changes) {
1225
1226 char **s;
1227 int r = 0, q;
1228
1229 assert(i);
1230 assert(config_path);
1231
1232 STRV_FOREACH(s, i->wanted_by) {
1233 _cleanup_free_ char *path = NULL, *dst = NULL;
1234
1235 dst = install_full_printf(i, *s);
1236 if (!dst)
1237 return -ENOMEM;
1238
1239 if (!unit_name_is_valid(dst, true)) {
1240 r = -EINVAL;
1241 continue;
1242 }
1243
1244 if (asprintf(&path, "%s/%s.wants/%s", config_path, dst, i->name) < 0)
1245 return -ENOMEM;
1246
1247 q = create_symlink(i->path, path, force, changes, n_changes);
1248
1249 if (r == 0)
1250 r = q;
1251 }
1252
1253 return r;
1254 }
1255
1256 static int install_info_symlink_requires(
1257 InstallInfo *i,
1258 const char *config_path,
1259 bool force,
1260 UnitFileChange **changes,
1261 unsigned *n_changes) {
1262
1263 char **s;
1264 int r = 0, q;
1265
1266 assert(i);
1267 assert(config_path);
1268
1269 STRV_FOREACH(s, i->required_by) {
1270 _cleanup_free_ char *path = NULL, *dst = NULL;
1271
1272 dst = install_full_printf(i, *s);
1273 if (!dst)
1274 return -ENOMEM;
1275
1276 if (!unit_name_is_valid(dst, true)) {
1277 r = -EINVAL;
1278 continue;
1279 }
1280
1281 if (asprintf(&path, "%s/%s.requires/%s", config_path, dst, i->name) < 0)
1282 return -ENOMEM;
1283
1284 q = create_symlink(i->path, path, force, changes, n_changes);
1285
1286 if (r == 0)
1287 r = q;
1288 }
1289
1290 return r;
1291 }
1292
1293 static int install_info_symlink_link(
1294 InstallInfo *i,
1295 LookupPaths *paths,
1296 const char *config_path,
1297 bool force,
1298 UnitFileChange **changes,
1299 unsigned *n_changes) {
1300
1301 int r;
1302 _cleanup_free_ char *path = NULL;
1303
1304 assert(i);
1305 assert(paths);
1306 assert(config_path);
1307 assert(i->path);
1308
1309 r = in_search_path(i->path, paths->unit_path);
1310 if (r != 0)
1311 return r;
1312
1313 if (asprintf(&path, "%s/%s", config_path, i->name) < 0)
1314 return -ENOMEM;
1315
1316 r = create_symlink(i->path, path, force, changes, n_changes);
1317 return r;
1318 }
1319
1320 static int install_info_apply(
1321 InstallInfo *i,
1322 LookupPaths *paths,
1323 const char *config_path,
1324 bool force,
1325 UnitFileChange **changes,
1326 unsigned *n_changes) {
1327
1328 int r, q;
1329
1330 assert(i);
1331 assert(paths);
1332 assert(config_path);
1333
1334 r = install_info_symlink_alias(i, config_path, force, changes, n_changes);
1335
1336 q = install_info_symlink_wants(i, config_path, force, changes, n_changes);
1337 if (r == 0)
1338 r = q;
1339
1340 q = install_info_symlink_requires(i, config_path, force, changes, n_changes);
1341 if (r == 0)
1342 r = q;
1343
1344 q = install_info_symlink_link(i, paths, config_path, force, changes, n_changes);
1345 if (r == 0)
1346 r = q;
1347
1348 return r;
1349 }
1350
1351 static int install_context_apply(
1352 InstallContext *c,
1353 LookupPaths *paths,
1354 const char *config_path,
1355 const char *root_dir,
1356 bool force,
1357 UnitFileChange **changes,
1358 unsigned *n_changes) {
1359
1360 InstallInfo *i;
1361 int r = 0, q;
1362
1363 assert(c);
1364 assert(paths);
1365 assert(config_path);
1366
1367 while ((i = hashmap_first(c->will_install))) {
1368
1369 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1370 if (q < 0)
1371 return q;
1372
1373 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1374
1375 q = unit_file_search(c, i, paths, root_dir, false);
1376 if (q < 0) {
1377 if (r >= 0)
1378 r = q;
1379
1380 return r;
1381 } else if (r >= 0)
1382 r += q;
1383
1384 q = install_info_apply(i, paths, config_path, force, changes, n_changes);
1385 if (r >= 0 && q < 0)
1386 r = q;
1387 }
1388
1389 return r;
1390 }
1391
1392 static int install_context_mark_for_removal(
1393 InstallContext *c,
1394 LookupPaths *paths,
1395 Set **remove_symlinks_to,
1396 const char *config_path,
1397 const char *root_dir) {
1398
1399 InstallInfo *i;
1400 int r = 0, q;
1401
1402 assert(c);
1403 assert(paths);
1404 assert(config_path);
1405
1406 /* Marks all items for removal */
1407
1408 while ((i = hashmap_first(c->will_install))) {
1409
1410 q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func);
1411 if (q < 0)
1412 return q;
1413
1414 assert_se(hashmap_move_one(c->have_installed, c->will_install, i->name) == 0);
1415
1416 q = unit_file_search(c, i, paths, root_dir, false);
1417 if (q == -ENOENT) {
1418 /* do nothing */
1419 } else if (q < 0) {
1420 if (r >= 0)
1421 r = q;
1422
1423 return r;
1424 } else if (r >= 0)
1425 r += q;
1426
1427 if (unit_name_is_instance(i->name)) {
1428 char *unit_file = NULL;
1429
1430 unit_file = path_get_file_name(i->path);
1431
1432 if (unit_name_is_instance(unit_file))
1433 /* unit file named as instance exists, thus all symlinks pointing to it, will be removed */
1434 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1435 else
1436 /* does not exist, thus we will mark for removal symlinks to template unit file */
1437 q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
1438 } else
1439 q = mark_symlink_for_removal(remove_symlinks_to, i->name);
1440
1441 if (r >= 0 && q < 0)
1442 r = q;
1443 }
1444
1445 return r;
1446 }
1447
1448 int unit_file_enable(
1449 UnitFileScope scope,
1450 bool runtime,
1451 const char *root_dir,
1452 char *files[],
1453 bool force,
1454 UnitFileChange **changes,
1455 unsigned *n_changes) {
1456
1457 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1458 _cleanup_install_context_done_ InstallContext c = {};
1459 char **i;
1460 _cleanup_free_ char *config_path = NULL;
1461 int r;
1462
1463 assert(scope >= 0);
1464 assert(scope < _UNIT_FILE_SCOPE_MAX);
1465
1466 r = lookup_paths_init_from_scope(&paths, scope);
1467 if (r < 0)
1468 return r;
1469
1470 r = get_config_path(scope, runtime, root_dir, &config_path);
1471 if (r < 0)
1472 return r;
1473
1474 STRV_FOREACH(i, files) {
1475 r = install_info_add_auto(&c, *i);
1476 if (r < 0)
1477 return r;
1478 }
1479
1480 /* This will return the number of symlink rules that were
1481 supposed to be created, not the ones actually created. This is
1482 useful to determine whether the passed files had any
1483 installation data at all. */
1484 r = install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1485 return r;
1486 }
1487
1488 int unit_file_disable(
1489 UnitFileScope scope,
1490 bool runtime,
1491 const char *root_dir,
1492 char *files[],
1493 UnitFileChange **changes,
1494 unsigned *n_changes) {
1495
1496 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1497 _cleanup_install_context_done_ InstallContext c = {};
1498 char **i;
1499 _cleanup_free_ char *config_path = NULL;
1500 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1501 int r, q;
1502
1503 assert(scope >= 0);
1504 assert(scope < _UNIT_FILE_SCOPE_MAX);
1505
1506 r = lookup_paths_init_from_scope(&paths, scope);
1507 if (r < 0)
1508 return r;
1509
1510 r = get_config_path(scope, runtime, root_dir, &config_path);
1511 if (r < 0)
1512 return r;
1513
1514 STRV_FOREACH(i, files) {
1515 r = install_info_add_auto(&c, *i);
1516 if (r < 0)
1517 return r;
1518 }
1519
1520 r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
1521
1522 q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1523 if (r == 0)
1524 r = q;
1525
1526 return r;
1527 }
1528
1529 int unit_file_reenable(
1530 UnitFileScope scope,
1531 bool runtime,
1532 const char *root_dir,
1533 char *files[],
1534 bool force,
1535 UnitFileChange **changes,
1536 unsigned *n_changes) {
1537
1538 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1539 _cleanup_install_context_done_ InstallContext c = {};
1540 char **i;
1541 _cleanup_free_ char *config_path = NULL;
1542 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1543 int r, q;
1544
1545 assert(scope >= 0);
1546 assert(scope < _UNIT_FILE_SCOPE_MAX);
1547
1548 r = lookup_paths_init_from_scope(&paths, scope);
1549 if (r < 0)
1550 return r;
1551
1552 r = get_config_path(scope, runtime, root_dir, &config_path);
1553 if (r < 0)
1554 return r;
1555
1556 STRV_FOREACH(i, files) {
1557 r = mark_symlink_for_removal(&remove_symlinks_to, *i);
1558 if (r < 0)
1559 return r;
1560
1561 r = install_info_add_auto(&c, *i);
1562 if (r < 0)
1563 return r;
1564 }
1565
1566 r = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
1567
1568 /* Returns number of symlinks that where supposed to be installed. */
1569 q = install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
1570 if (r == 0)
1571 r = q;
1572
1573 return r;
1574 }
1575
1576 int unit_file_set_default(
1577 UnitFileScope scope,
1578 const char *root_dir,
1579 char *file,
1580 UnitFileChange **changes,
1581 unsigned *n_changes) {
1582
1583 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1584 _cleanup_install_context_done_ InstallContext c = {};
1585 _cleanup_free_ char *config_path = NULL;
1586 char *path;
1587 int r;
1588 InstallInfo *i = NULL;
1589
1590 assert(scope >= 0);
1591 assert(scope < _UNIT_FILE_SCOPE_MAX);
1592
1593 if (unit_name_to_type(file) != UNIT_TARGET)
1594 return -EINVAL;
1595
1596 r = lookup_paths_init_from_scope(&paths, scope);
1597 if (r < 0)
1598 return r;
1599
1600 r = get_config_path(scope, false, root_dir, &config_path);
1601 if (r < 0)
1602 return r;
1603
1604 r = install_info_add_auto(&c, file);
1605 if (r < 0)
1606 return r;
1607
1608 i = (InstallInfo*)hashmap_first(c.will_install);
1609
1610 r = unit_file_search(&c, i, &paths, root_dir, false);
1611 if (r < 0)
1612 return r;
1613
1614 path = strappenda(config_path, "/default.target");
1615 r = create_symlink(i->path, path, true, changes, n_changes);
1616 if (r < 0)
1617 return r;
1618
1619 return 0;
1620 }
1621
1622 int unit_file_get_default(
1623 UnitFileScope scope,
1624 const char *root_dir,
1625 char **name) {
1626
1627 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1628 char **p;
1629 int r;
1630
1631 r = lookup_paths_init_from_scope(&paths, scope);
1632 if (r < 0)
1633 return r;
1634
1635 STRV_FOREACH(p, paths.unit_path) {
1636 _cleanup_free_ char *path = NULL, *tmp = NULL;
1637
1638 if (isempty(root_dir))
1639 path = strappend(*p, "/default.target");
1640 else
1641 path = strjoin(root_dir, "/", *p, "/default.target", NULL);
1642
1643 if (!path)
1644 return -ENOMEM;
1645
1646 r = readlink_malloc(path, &tmp);
1647 if (r == -ENOENT)
1648 continue;
1649 else if (r < 0)
1650 return r;
1651
1652 *name = strdup(path_get_file_name(tmp));
1653 if (!*name)
1654 return -ENOMEM;
1655
1656 return 0;
1657 }
1658
1659 return -ENOENT;
1660 }
1661
1662 UnitFileState unit_file_get_state(
1663 UnitFileScope scope,
1664 const char *root_dir,
1665 const char *name) {
1666
1667 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1668 UnitFileState state = _UNIT_FILE_STATE_INVALID;
1669 char **i;
1670 _cleanup_free_ char *path = NULL;
1671 int r;
1672
1673 assert(scope >= 0);
1674 assert(scope < _UNIT_FILE_SCOPE_MAX);
1675 assert(name);
1676
1677 if (root_dir && scope != UNIT_FILE_SYSTEM)
1678 return -EINVAL;
1679
1680 if (!unit_name_is_valid(name, true))
1681 return -EINVAL;
1682
1683 r = lookup_paths_init_from_scope(&paths, scope);
1684 if (r < 0)
1685 return r;
1686
1687 STRV_FOREACH(i, paths.unit_path) {
1688 struct stat st;
1689
1690 free(path);
1691 path = NULL;
1692
1693 if (root_dir)
1694 asprintf(&path, "%s/%s/%s", root_dir, *i, name);
1695 else
1696 asprintf(&path, "%s/%s", *i, name);
1697
1698 if (!path)
1699 return -ENOMEM;
1700
1701 /*
1702 * Search for a unit file in our default paths, to
1703 * be sure, that there are no broken symlinks.
1704 */
1705 if (lstat(path, &st) < 0) {
1706 r = -errno;
1707 if (errno != ENOENT)
1708 return r;
1709
1710 if (!unit_name_is_instance(name))
1711 continue;
1712 } else {
1713 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
1714 return -ENOENT;
1715
1716 r = null_or_empty_path(path);
1717 if (r < 0 && r != -ENOENT)
1718 return r;
1719 else if (r > 0) {
1720 state = path_startswith(*i, "/run") ?
1721 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1722 return state;
1723 }
1724 }
1725
1726 r = find_symlinks_in_scope(scope, root_dir, name, &state);
1727 if (r < 0)
1728 return r;
1729 else if (r > 0)
1730 return state;
1731
1732 r = unit_file_can_install(&paths, root_dir, path, true);
1733 if (r < 0 && errno != ENOENT)
1734 return r;
1735 else if (r > 0)
1736 return UNIT_FILE_DISABLED;
1737 else if (r == 0)
1738 return UNIT_FILE_STATIC;
1739 }
1740
1741 return r < 0 ? r : state;
1742 }
1743
1744 int unit_file_query_preset(UnitFileScope scope, const char *name) {
1745 _cleanup_strv_free_ char **files = NULL;
1746 char **i;
1747 int r;
1748
1749 assert(scope >= 0);
1750 assert(scope < _UNIT_FILE_SCOPE_MAX);
1751 assert(name);
1752
1753 if (scope == UNIT_FILE_SYSTEM)
1754 r = conf_files_list(&files, ".preset", NULL,
1755 "/etc/systemd/system-preset",
1756 "/usr/local/lib/systemd/system-preset",
1757 "/usr/lib/systemd/system-preset",
1758 #ifdef HAVE_SPLIT_USR
1759 "/lib/systemd/system-preset",
1760 #endif
1761 NULL);
1762 else if (scope == UNIT_FILE_GLOBAL)
1763 r = conf_files_list(&files, ".preset", NULL,
1764 "/etc/systemd/user-preset",
1765 "/usr/local/lib/systemd/user-preset",
1766 "/usr/lib/systemd/user-preset",
1767 NULL);
1768 else
1769 return 1;
1770
1771 if (r < 0)
1772 return r;
1773
1774 STRV_FOREACH(i, files) {
1775 _cleanup_fclose_ FILE *f;
1776
1777 f = fopen(*i, "re");
1778 if (!f) {
1779 if (errno == ENOENT)
1780 continue;
1781
1782 return -errno;
1783 }
1784
1785 for (;;) {
1786 char line[LINE_MAX], *l;
1787
1788 if (!fgets(line, sizeof(line), f))
1789 break;
1790
1791 l = strstrip(line);
1792 if (!*l)
1793 continue;
1794
1795 if (strchr(COMMENTS "\n", *l))
1796 continue;
1797
1798 if (first_word(l, "enable")) {
1799 l += 6;
1800 l += strspn(l, WHITESPACE);
1801
1802 if (fnmatch(l, name, FNM_NOESCAPE) == 0)
1803 return 1;
1804
1805 } else if (first_word(l, "disable")) {
1806 l += 7;
1807 l += strspn(l, WHITESPACE);
1808
1809 if (fnmatch(l, name, FNM_NOESCAPE) == 0)
1810 return 0;
1811
1812 } else
1813 log_debug("Couldn't parse line '%s'", l);
1814 }
1815 }
1816
1817 /* Default is "enable" */
1818 return 1;
1819 }
1820
1821 int unit_file_preset(
1822 UnitFileScope scope,
1823 bool runtime,
1824 const char *root_dir,
1825 char *files[],
1826 bool force,
1827 UnitFileChange **changes,
1828 unsigned *n_changes) {
1829
1830 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1831 _cleanup_install_context_done_ InstallContext plus = {}, minus = {};
1832 char **i;
1833 _cleanup_free_ char *config_path = NULL;
1834 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
1835 int r, q;
1836
1837 assert(scope >= 0);
1838 assert(scope < _UNIT_FILE_SCOPE_MAX);
1839
1840 r = lookup_paths_init_from_scope(&paths, scope);
1841 if (r < 0)
1842 return r;
1843
1844 r = get_config_path(scope, runtime, root_dir, &config_path);
1845 if (r < 0)
1846 return r;
1847
1848 STRV_FOREACH(i, files) {
1849
1850 if (!unit_name_is_valid(*i, true))
1851 return -EINVAL;
1852
1853 r = unit_file_query_preset(scope, *i);
1854 if (r < 0)
1855 return r;
1856
1857 if (r)
1858 r = install_info_add_auto(&plus, *i);
1859 else
1860 r = install_info_add_auto(&minus, *i);
1861
1862 if (r < 0)
1863 return r;
1864 }
1865
1866 r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to,
1867 config_path, root_dir);
1868
1869 q = remove_marked_symlinks(remove_symlinks_to, config_path,
1870 changes, n_changes, files);
1871 if (r == 0)
1872 r = q;
1873
1874 /* Returns number of symlinks that where supposed to be installed. */
1875 q = install_context_apply(&plus, &paths, config_path, root_dir, force,
1876 changes, n_changes);
1877 if (r == 0)
1878 r = q;
1879
1880 return r;
1881 }
1882
1883 static void unitfilelist_free(UnitFileList **f) {
1884 if (!*f)
1885 return;
1886
1887 free((*f)->path);
1888 free(*f);
1889 }
1890
1891 int unit_file_get_list(
1892 UnitFileScope scope,
1893 const char *root_dir,
1894 Hashmap *h) {
1895
1896 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1897 char **i;
1898 _cleanup_free_ char *buf = NULL;
1899 _cleanup_closedir_ DIR *d = NULL;
1900 int r;
1901
1902 assert(scope >= 0);
1903 assert(scope < _UNIT_FILE_SCOPE_MAX);
1904 assert(h);
1905
1906 if (root_dir && scope != UNIT_FILE_SYSTEM)
1907 return -EINVAL;
1908
1909 r = lookup_paths_init_from_scope(&paths, scope);
1910 if (r < 0)
1911 return r;
1912
1913 STRV_FOREACH(i, paths.unit_path) {
1914 const char *units_dir;
1915
1916 free(buf);
1917 buf = NULL;
1918
1919 if (root_dir) {
1920 if (asprintf(&buf, "%s/%s", root_dir, *i) < 0)
1921 return -ENOMEM;
1922
1923 units_dir = buf;
1924 } else
1925 units_dir = *i;
1926
1927 if (d)
1928 closedir(d);
1929
1930 d = opendir(units_dir);
1931 if (!d) {
1932 if (errno == ENOENT)
1933 continue;
1934
1935 return -errno;
1936 }
1937
1938 for (;;) {
1939 struct dirent *de;
1940 union dirent_storage buffer;
1941 UnitFileList __attribute__((cleanup(unitfilelist_free)))
1942 *f = NULL;
1943
1944 r = readdir_r(d, &buffer.de, &de);
1945 if (r != 0)
1946 return -r;
1947
1948 if (!de)
1949 break;
1950
1951 if (ignore_file(de->d_name))
1952 continue;
1953
1954 if (!unit_name_is_valid(de->d_name, true))
1955 continue;
1956
1957 if (hashmap_get(h, de->d_name))
1958 continue;
1959
1960 r = dirent_ensure_type(d, de);
1961 if (r < 0) {
1962 if (r == -ENOENT)
1963 continue;
1964
1965 return r;
1966 }
1967
1968 if (de->d_type != DT_LNK && de->d_type != DT_REG)
1969 continue;
1970
1971 f = new0(UnitFileList, 1);
1972 if (!f)
1973 return -ENOMEM;
1974
1975 f->path = path_make_absolute(de->d_name, units_dir);
1976 if (!f->path)
1977 return -ENOMEM;
1978
1979 r = null_or_empty_path(f->path);
1980 if (r < 0 && r != -ENOENT)
1981 return r;
1982 else if (r > 0) {
1983 f->state =
1984 path_startswith(*i, "/run") ?
1985 UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
1986 goto found;
1987 }
1988
1989 r = find_symlinks_in_scope(scope, root_dir, de->d_name, &f->state);
1990 if (r < 0)
1991 return r;
1992 else if (r > 0) {
1993 f->state = UNIT_FILE_ENABLED;
1994 goto found;
1995 }
1996
1997 r = unit_file_can_install(&paths, root_dir, f->path, true);
1998 if (r == -EINVAL || /* Invalid setting? */
1999 r == -EBADMSG || /* Invalid format? */
2000 r == -ENOENT /* Included file not found? */)
2001 f->state = UNIT_FILE_INVALID;
2002 else if (r < 0)
2003 return r;
2004 else if (r > 0)
2005 f->state = UNIT_FILE_DISABLED;
2006 else
2007 f->state = UNIT_FILE_STATIC;
2008
2009 found:
2010 r = hashmap_put(h, path_get_file_name(f->path), f);
2011 if (r < 0)
2012 return r;
2013 f = NULL; /* prevent cleanup */
2014 }
2015 }
2016
2017 return r;
2018 }
2019
2020 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
2021 [UNIT_FILE_ENABLED] = "enabled",
2022 [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
2023 [UNIT_FILE_LINKED] = "linked",
2024 [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
2025 [UNIT_FILE_MASKED] = "masked",
2026 [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
2027 [UNIT_FILE_STATIC] = "static",
2028 [UNIT_FILE_DISABLED] = "disabled",
2029 [UNIT_FILE_INVALID] = "invalid",
2030 };
2031
2032 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
2033
2034 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
2035 [UNIT_FILE_SYMLINK] = "symlink",
2036 [UNIT_FILE_UNLINK] = "unlink",
2037 };
2038
2039 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);