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