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