]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/install.c
Merge pull request #16112 from poettering/nss-systemd-block-fix
[thirdparty/systemd.git] / src / shared / install.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include <errno.h>
4 #include <fcntl.h>
5 #include <fnmatch.h>
6 #include <limits.h>
7 #include <stddef.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <unistd.h>
11
12 #include "alloc-util.h"
13 #include "conf-files.h"
14 #include "conf-parser.h"
15 #include "def.h"
16 #include "dirent-util.h"
17 #include "extract-word.h"
18 #include "fd-util.h"
19 #include "fileio.h"
20 #include "fs-util.h"
21 #include "hashmap.h"
22 #include "install-printf.h"
23 #include "install.h"
24 #include "locale-util.h"
25 #include "log.h"
26 #include "macro.h"
27 #include "mkdir.h"
28 #include "path-lookup.h"
29 #include "path-util.h"
30 #include "rm-rf.h"
31 #include "set.h"
32 #include "special.h"
33 #include "stat-util.h"
34 #include "string-table.h"
35 #include "string-util.h"
36 #include "strv.h"
37 #include "unit-file.h"
38
39 #define UNIT_FILE_FOLLOW_SYMLINK_MAX 64
40
41 typedef enum SearchFlags {
42 SEARCH_LOAD = 1 << 0,
43 SEARCH_FOLLOW_CONFIG_SYMLINKS = 1 << 1,
44 SEARCH_DROPIN = 1 << 2,
45 } SearchFlags;
46
47 typedef struct {
48 OrderedHashmap *will_process;
49 OrderedHashmap *have_processed;
50 } InstallContext;
51
52 typedef enum {
53 PRESET_UNKNOWN,
54 PRESET_ENABLE,
55 PRESET_DISABLE,
56 } PresetAction;
57
58 struct UnitFilePresetRule {
59 char *pattern;
60 PresetAction action;
61 char **instances;
62 };
63
64 static bool unit_file_install_info_has_rules(const UnitFileInstallInfo *i) {
65 assert(i);
66
67 return !strv_isempty(i->aliases) ||
68 !strv_isempty(i->wanted_by) ||
69 !strv_isempty(i->required_by);
70 }
71
72 static bool unit_file_install_info_has_also(const UnitFileInstallInfo *i) {
73 assert(i);
74
75 return !strv_isempty(i->also);
76 }
77
78 void unit_file_presets_freep(UnitFilePresets *p) {
79 size_t i;
80
81 if (!p)
82 return;
83
84 for (i = 0; i < p->n_rules; i++) {
85 free(p->rules[i].pattern);
86 strv_free(p->rules[i].instances);
87 }
88
89 free(p->rules);
90 p->n_rules = 0;
91 }
92
93 static const char *const unit_file_type_table[_UNIT_FILE_TYPE_MAX] = {
94 [UNIT_FILE_TYPE_REGULAR] = "regular",
95 [UNIT_FILE_TYPE_SYMLINK] = "symlink",
96 [UNIT_FILE_TYPE_MASKED] = "masked",
97 };
98
99 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(unit_file_type, UnitFileType);
100
101 static int in_search_path(const LookupPaths *p, const char *path) {
102 _cleanup_free_ char *parent = NULL;
103
104 assert(path);
105
106 parent = dirname_malloc(path);
107 if (!parent)
108 return -ENOMEM;
109
110 return path_strv_contains(p->search_path, parent);
111 }
112
113 static const char* skip_root(const LookupPaths *p, const char *path) {
114 char *e;
115
116 assert(p);
117 assert(path);
118
119 if (!p->root_dir)
120 return path;
121
122 e = path_startswith(path, p->root_dir);
123 if (!e)
124 return NULL;
125
126 /* Make sure the returned path starts with a slash */
127 if (e[0] != '/') {
128 if (e == path || e[-1] != '/')
129 return NULL;
130
131 e--;
132 }
133
134 return e;
135 }
136
137 static int path_is_generator(const LookupPaths *p, const char *path) {
138 _cleanup_free_ char *parent = NULL;
139
140 assert(p);
141 assert(path);
142
143 parent = dirname_malloc(path);
144 if (!parent)
145 return -ENOMEM;
146
147 return path_equal_ptr(parent, p->generator) ||
148 path_equal_ptr(parent, p->generator_early) ||
149 path_equal_ptr(parent, p->generator_late);
150 }
151
152 static int path_is_transient(const LookupPaths *p, const char *path) {
153 _cleanup_free_ char *parent = NULL;
154
155 assert(p);
156 assert(path);
157
158 parent = dirname_malloc(path);
159 if (!parent)
160 return -ENOMEM;
161
162 return path_equal_ptr(parent, p->transient);
163 }
164
165 static int path_is_control(const LookupPaths *p, const char *path) {
166 _cleanup_free_ char *parent = NULL;
167
168 assert(p);
169 assert(path);
170
171 parent = dirname_malloc(path);
172 if (!parent)
173 return -ENOMEM;
174
175 return path_equal_ptr(parent, p->persistent_control) ||
176 path_equal_ptr(parent, p->runtime_control);
177 }
178
179 static int path_is_config(const LookupPaths *p, const char *path, bool check_parent) {
180 _cleanup_free_ char *parent = NULL;
181
182 assert(p);
183 assert(path);
184
185 /* Note that we do *not* have generic checks for /etc or /run in place, since with
186 * them we couldn't discern configuration from transient or generated units */
187
188 if (check_parent) {
189 parent = dirname_malloc(path);
190 if (!parent)
191 return -ENOMEM;
192
193 path = parent;
194 }
195
196 return path_equal_ptr(path, p->persistent_config) ||
197 path_equal_ptr(path, p->runtime_config);
198 }
199
200 static int path_is_runtime(const LookupPaths *p, const char *path, bool check_parent) {
201 _cleanup_free_ char *parent = NULL;
202 const char *rpath;
203
204 assert(p);
205 assert(path);
206
207 /* Everything in /run is considered runtime. On top of that we also add
208 * explicit checks for the various runtime directories, as safety net. */
209
210 rpath = skip_root(p, path);
211 if (rpath && path_startswith(rpath, "/run"))
212 return true;
213
214 if (check_parent) {
215 parent = dirname_malloc(path);
216 if (!parent)
217 return -ENOMEM;
218
219 path = parent;
220 }
221
222 return path_equal_ptr(path, p->runtime_config) ||
223 path_equal_ptr(path, p->generator) ||
224 path_equal_ptr(path, p->generator_early) ||
225 path_equal_ptr(path, p->generator_late) ||
226 path_equal_ptr(path, p->transient) ||
227 path_equal_ptr(path, p->runtime_control);
228 }
229
230 static int path_is_vendor_or_generator(const LookupPaths *p, const char *path) {
231 const char *rpath;
232
233 assert(p);
234 assert(path);
235
236 rpath = skip_root(p, path);
237 if (!rpath)
238 return 0;
239
240 if (path_startswith(rpath, "/usr"))
241 return true;
242
243 #if HAVE_SPLIT_USR
244 if (path_startswith(rpath, "/lib"))
245 return true;
246 #endif
247
248 if (path_is_generator(p, rpath))
249 return true;
250
251 return path_equal(rpath, SYSTEM_DATA_UNIT_PATH);
252 }
253
254 int unit_file_changes_add(
255 UnitFileChange **changes,
256 size_t *n_changes,
257 UnitFileChangeType type,
258 const char *path,
259 const char *source) {
260
261 _cleanup_free_ char *p = NULL, *s = NULL;
262 UnitFileChange *c;
263
264 assert(path);
265 assert(!changes == !n_changes);
266
267 if (!changes)
268 return 0;
269
270 c = reallocarray(*changes, *n_changes + 1, sizeof(UnitFileChange));
271 if (!c)
272 return -ENOMEM;
273 *changes = c;
274
275 p = strdup(path);
276 if (source)
277 s = strdup(source);
278
279 if (!p || (source && !s))
280 return -ENOMEM;
281
282 path_simplify(p, false);
283 if (s)
284 path_simplify(s, false);
285
286 c[*n_changes] = (UnitFileChange) { type, p, s };
287 p = s = NULL;
288 (*n_changes) ++;
289 return 0;
290 }
291
292 void unit_file_changes_free(UnitFileChange *changes, size_t n_changes) {
293 size_t i;
294
295 assert(changes || n_changes == 0);
296
297 for (i = 0; i < n_changes; i++) {
298 free(changes[i].path);
299 free(changes[i].source);
300 }
301
302 free(changes);
303 }
304
305 void unit_file_dump_changes(int r, const char *verb, const UnitFileChange *changes, size_t n_changes, bool quiet) {
306 size_t i;
307 bool logged = false;
308
309 assert(changes || n_changes == 0);
310 /* If verb is not specified, errors are not allowed! */
311 assert(verb || r >= 0);
312
313 for (i = 0; i < n_changes; i++) {
314 assert(verb || changes[i].type >= 0);
315
316 switch(changes[i].type) {
317 case UNIT_FILE_SYMLINK:
318 if (!quiet)
319 log_info("Created symlink %s %s %s.",
320 changes[i].path,
321 special_glyph(SPECIAL_GLYPH_ARROW),
322 changes[i].source);
323 break;
324 case UNIT_FILE_UNLINK:
325 if (!quiet)
326 log_info("Removed %s.", changes[i].path);
327 break;
328 case UNIT_FILE_IS_MASKED:
329 if (!quiet)
330 log_info("Unit %s is masked, ignoring.", changes[i].path);
331 break;
332 case UNIT_FILE_IS_DANGLING:
333 if (!quiet)
334 log_info("Unit %s is an alias to a unit that is not present, ignoring.",
335 changes[i].path);
336 break;
337 case -EEXIST:
338 if (changes[i].source)
339 log_error_errno(changes[i].type,
340 "Failed to %s unit, file %s already exists and is a symlink to %s.",
341 verb, changes[i].path, changes[i].source);
342 else
343 log_error_errno(changes[i].type,
344 "Failed to %s unit, file %s already exists.",
345 verb, changes[i].path);
346 logged = true;
347 break;
348 case -ERFKILL:
349 log_error_errno(changes[i].type, "Failed to %s unit, unit %s is masked.",
350 verb, changes[i].path);
351 logged = true;
352 break;
353 case -EADDRNOTAVAIL:
354 log_error_errno(changes[i].type, "Failed to %s unit, unit %s is transient or generated.",
355 verb, changes[i].path);
356 logged = true;
357 break;
358 case -EUCLEAN:
359 log_error_errno(changes[i].type,
360 "Failed to %s unit, \"%s\" is not a valid unit name.",
361 verb, changes[i].path);
362 logged = true;
363 break;
364 case -ELOOP:
365 log_error_errno(changes[i].type, "Failed to %s unit, refusing to operate on linked unit file %s",
366 verb, changes[i].path);
367 logged = true;
368 break;
369
370 case -ENOENT:
371 log_error_errno(changes[i].type, "Failed to %s unit, unit %s does not exist.", verb, changes[i].path);
372 logged = true;
373 break;
374
375 default:
376 assert(changes[i].type < 0);
377 log_error_errno(changes[i].type, "Failed to %s unit, file %s: %m.",
378 verb, changes[i].path);
379 logged = true;
380 }
381 }
382
383 if (r < 0 && !logged)
384 log_error_errno(r, "Failed to %s: %m.", verb);
385 }
386
387 /**
388 * Checks if two paths or symlinks from wd are the same, when root is the root of the filesystem.
389 * wc should be the full path in the host file system.
390 */
391 static bool chroot_symlinks_same(const char *root, const char *wd, const char *a, const char *b) {
392 assert(path_is_absolute(wd));
393
394 /* This will give incorrect results if the paths are relative and go outside
395 * of the chroot. False negatives are possible. */
396
397 if (!root)
398 root = "/";
399
400 a = strjoina(path_is_absolute(a) ? root : wd, "/", a);
401 b = strjoina(path_is_absolute(b) ? root : wd, "/", b);
402 return path_equal_or_files_same(a, b, 0);
403 }
404
405 static int create_symlink(
406 const LookupPaths *paths,
407 const char *old_path,
408 const char *new_path,
409 bool force,
410 UnitFileChange **changes,
411 size_t *n_changes) {
412
413 _cleanup_free_ char *dest = NULL, *dirname = NULL;
414 const char *rp;
415 int r;
416
417 assert(old_path);
418 assert(new_path);
419
420 rp = skip_root(paths, old_path);
421 if (rp)
422 old_path = rp;
423
424 /* Actually create a symlink, and remember that we did. Is
425 * smart enough to check if there's already a valid symlink in
426 * place.
427 *
428 * Returns 1 if a symlink was created or already exists and points to
429 * the right place, or negative on error.
430 */
431
432 mkdir_parents_label(new_path, 0755);
433
434 if (symlink(old_path, new_path) >= 0) {
435 unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
436 return 1;
437 }
438
439 if (errno != EEXIST) {
440 unit_file_changes_add(changes, n_changes, -errno, new_path, NULL);
441 return -errno;
442 }
443
444 r = readlink_malloc(new_path, &dest);
445 if (r < 0) {
446 /* translate EINVAL (non-symlink exists) to EEXIST */
447 if (r == -EINVAL)
448 r = -EEXIST;
449
450 unit_file_changes_add(changes, n_changes, r, new_path, NULL);
451 return r;
452 }
453
454 dirname = dirname_malloc(new_path);
455 if (!dirname)
456 return -ENOMEM;
457
458 if (chroot_symlinks_same(paths->root_dir, dirname, dest, old_path)) {
459 log_debug("Symlink %s → %s already exists", new_path, dest);
460 return 1;
461 }
462
463 if (!force) {
464 unit_file_changes_add(changes, n_changes, -EEXIST, new_path, dest);
465 return -EEXIST;
466 }
467
468 r = symlink_atomic(old_path, new_path);
469 if (r < 0) {
470 unit_file_changes_add(changes, n_changes, r, new_path, NULL);
471 return r;
472 }
473
474 unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL);
475 unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path);
476
477 return 1;
478 }
479
480 static int mark_symlink_for_removal(
481 Set **remove_symlinks_to,
482 const char *p) {
483
484 char *n;
485 int r;
486
487 assert(p);
488
489 r = set_ensure_allocated(remove_symlinks_to, &path_hash_ops);
490 if (r < 0)
491 return r;
492
493 n = strdup(p);
494 if (!n)
495 return -ENOMEM;
496
497 path_simplify(n, false);
498
499 r = set_consume(*remove_symlinks_to, n);
500 if (r == -EEXIST)
501 return 0;
502 if (r < 0)
503 return r;
504
505 return 1;
506 }
507
508 static int remove_marked_symlinks_fd(
509 Set *remove_symlinks_to,
510 int fd,
511 const char *path,
512 const char *config_path,
513 const LookupPaths *lp,
514 bool dry_run,
515 bool *restart,
516 UnitFileChange **changes,
517 size_t *n_changes) {
518
519 _cleanup_closedir_ DIR *d = NULL;
520 struct dirent *de;
521 int r = 0;
522
523 assert(remove_symlinks_to);
524 assert(fd >= 0);
525 assert(path);
526 assert(config_path);
527 assert(lp);
528 assert(restart);
529
530 d = fdopendir(fd);
531 if (!d) {
532 safe_close(fd);
533 return -errno;
534 }
535
536 rewinddir(d);
537
538 FOREACH_DIRENT(de, d, return -errno) {
539
540 dirent_ensure_type(d, de);
541
542 if (de->d_type == DT_DIR) {
543 _cleanup_free_ char *p = NULL;
544 int nfd, q;
545
546 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
547 if (nfd < 0) {
548 if (errno == ENOENT)
549 continue;
550
551 if (r == 0)
552 r = -errno;
553 continue;
554 }
555
556 p = path_make_absolute(de->d_name, path);
557 if (!p) {
558 safe_close(nfd);
559 return -ENOMEM;
560 }
561
562 /* This will close nfd, regardless whether it succeeds or not */
563 q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, lp, dry_run, restart, changes, n_changes);
564 if (q < 0 && r == 0)
565 r = q;
566
567 } else if (de->d_type == DT_LNK) {
568 _cleanup_free_ char *p = NULL, *dest = NULL;
569 const char *rp;
570 bool found;
571 int q;
572
573 if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
574 continue;
575
576 p = path_make_absolute(de->d_name, path);
577 if (!p)
578 return -ENOMEM;
579 path_simplify(p, false);
580
581 q = chase_symlinks(p, NULL, CHASE_NONEXISTENT, &dest, NULL);
582 if (q == -ENOENT)
583 continue;
584 if (q < 0) {
585 if (r == 0)
586 r = q;
587 continue;
588 }
589
590 /* We remove all links pointing to a file or path that is marked, as well as all files sharing
591 * the same name as a file that is marked. */
592
593 found = set_contains(remove_symlinks_to, dest) ||
594 set_contains(remove_symlinks_to, basename(dest)) ||
595 set_contains(remove_symlinks_to, de->d_name);
596
597 if (!found)
598 continue;
599
600 if (!dry_run) {
601 if (unlinkat(fd, de->d_name, 0) < 0 && errno != ENOENT) {
602 if (r == 0)
603 r = -errno;
604 unit_file_changes_add(changes, n_changes, -errno, p, NULL);
605 continue;
606 }
607
608 (void) rmdir_parents(p, config_path);
609 }
610
611 unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, p, NULL);
612
613 /* Now, remember the full path (but with the root prefix removed) of
614 * the symlink we just removed, and remove any symlinks to it, too. */
615
616 rp = skip_root(lp, p);
617 q = mark_symlink_for_removal(&remove_symlinks_to, rp ?: p);
618 if (q < 0)
619 return q;
620 if (q > 0 && !dry_run)
621 *restart = true;
622 }
623 }
624
625 return r;
626 }
627
628 static int remove_marked_symlinks(
629 Set *remove_symlinks_to,
630 const char *config_path,
631 const LookupPaths *lp,
632 bool dry_run,
633 UnitFileChange **changes,
634 size_t *n_changes) {
635
636 _cleanup_close_ int fd = -1;
637 bool restart;
638 int r = 0;
639
640 assert(config_path);
641 assert(lp);
642
643 if (set_size(remove_symlinks_to) <= 0)
644 return 0;
645
646 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC);
647 if (fd < 0)
648 return errno == ENOENT ? 0 : -errno;
649
650 do {
651 int q, cfd;
652 restart = false;
653
654 cfd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
655 if (cfd < 0)
656 return -errno;
657
658 /* This takes possession of cfd and closes it */
659 q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, lp, dry_run, &restart, changes, n_changes);
660 if (r == 0)
661 r = q;
662 } while (restart);
663
664 return r;
665 }
666
667 static int is_symlink_with_known_name(const UnitFileInstallInfo *i, const char *name) {
668 int r;
669
670 if (streq(name, i->name))
671 return true;
672
673 if (strv_contains(i->aliases, name))
674 return true;
675
676 /* Look for template symlink matching DefaultInstance */
677 if (i->default_instance && unit_name_is_valid(i->name, UNIT_NAME_TEMPLATE)) {
678 _cleanup_free_ char *s = NULL;
679
680 r = unit_name_replace_instance(i->name, i->default_instance, &s);
681 if (r < 0) {
682 if (r != -EINVAL)
683 return r;
684
685 } else if (streq(name, s))
686 return true;
687 }
688
689 return false;
690 }
691
692 static int find_symlinks_fd(
693 const char *root_dir,
694 const UnitFileInstallInfo *i,
695 bool match_aliases,
696 bool ignore_same_name,
697 int fd,
698 const char *path,
699 const char *config_path,
700 bool *same_name_link) {
701
702 _cleanup_closedir_ DIR *d = NULL;
703 struct dirent *de;
704 int r = 0;
705
706 assert(i);
707 assert(fd >= 0);
708 assert(path);
709 assert(config_path);
710 assert(same_name_link);
711
712 d = fdopendir(fd);
713 if (!d) {
714 safe_close(fd);
715 return -errno;
716 }
717
718 FOREACH_DIRENT(de, d, return -errno) {
719
720 dirent_ensure_type(d, de);
721
722 if (de->d_type == DT_DIR) {
723 _cleanup_free_ char *p = NULL;
724 int nfd, q;
725
726 nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
727 if (nfd < 0) {
728 if (errno == ENOENT)
729 continue;
730
731 if (r == 0)
732 r = -errno;
733 continue;
734 }
735
736 p = path_make_absolute(de->d_name, path);
737 if (!p) {
738 safe_close(nfd);
739 return -ENOMEM;
740 }
741
742 /* This will close nfd, regardless whether it succeeds or not */
743 q = find_symlinks_fd(root_dir, i, match_aliases, ignore_same_name, nfd,
744 p, config_path, same_name_link);
745 if (q > 0)
746 return 1;
747 if (r == 0)
748 r = q;
749
750 } else if (de->d_type == DT_LNK) {
751 _cleanup_free_ char *p = NULL, *dest = NULL;
752 bool found_path = false, found_dest, b = false;
753 int q;
754
755 /* Acquire symlink name */
756 p = path_make_absolute(de->d_name, path);
757 if (!p)
758 return -ENOMEM;
759
760 /* Acquire symlink destination */
761 q = readlink_malloc(p, &dest);
762 if (q == -ENOENT)
763 continue;
764 if (q < 0) {
765 if (r == 0)
766 r = q;
767 continue;
768 }
769
770 /* Make absolute */
771 if (!path_is_absolute(dest)) {
772 char *x;
773
774 x = path_join(root_dir, dest);
775 if (!x)
776 return -ENOMEM;
777
778 free_and_replace(dest, x);
779 }
780
781 assert(unit_name_is_valid(i->name, UNIT_NAME_ANY));
782 if (!ignore_same_name)
783 /* Check if the symlink itself matches what we are looking for.
784 *
785 * If ignore_same_name is specified, we are in one of the directories which
786 * have lower priority than the unit file, and even if a file or symlink with
787 * this name was found, we should ignore it. */
788 found_path = streq(de->d_name, i->name);
789
790 /* Check if what the symlink points to matches what we are looking for */
791 found_dest = streq(basename(dest), i->name);
792
793 if (found_path && found_dest) {
794 _cleanup_free_ char *t = NULL;
795
796 /* Filter out same name links in the main
797 * config path */
798 t = path_make_absolute(i->name, config_path);
799 if (!t)
800 return -ENOMEM;
801
802 b = path_equal(t, p);
803 }
804
805 if (b)
806 *same_name_link = true;
807 else if (found_path || found_dest) {
808 if (!match_aliases)
809 return 1;
810
811 /* Check if symlink name is in the set of names used by [Install] */
812 q = is_symlink_with_known_name(i, de->d_name);
813 if (q < 0)
814 return q;
815 if (q > 0)
816 return 1;
817 }
818 }
819 }
820
821 return r;
822 }
823
824 static int find_symlinks(
825 const char *root_dir,
826 const UnitFileInstallInfo *i,
827 bool match_name,
828 bool ignore_same_name,
829 const char *config_path,
830 bool *same_name_link) {
831
832 int fd;
833
834 assert(i);
835 assert(config_path);
836 assert(same_name_link);
837
838 fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC);
839 if (fd < 0) {
840 if (IN_SET(errno, ENOENT, ENOTDIR, EACCES))
841 return 0;
842 return -errno;
843 }
844
845 /* This takes possession of fd and closes it */
846 return find_symlinks_fd(root_dir, i, match_name, ignore_same_name, fd,
847 config_path, config_path, same_name_link);
848 }
849
850 static int find_symlinks_in_scope(
851 UnitFileScope scope,
852 const LookupPaths *paths,
853 const UnitFileInstallInfo *i,
854 bool match_name,
855 UnitFileState *state) {
856
857 bool same_name_link_runtime = false, same_name_link_config = false;
858 bool enabled_in_runtime = false, enabled_at_all = false;
859 bool ignore_same_name = false;
860 char **p;
861 int r;
862
863 assert(paths);
864 assert(i);
865
866 /* As we iterate over the list of search paths in paths->search_path, we may encounter "same name"
867 * symlinks. The ones which are "below" (i.e. have lower priority) than the unit file itself are
868 * effectively masked, so we should ignore them. */
869
870 STRV_FOREACH(p, paths->search_path) {
871 bool same_name_link = false;
872
873 r = find_symlinks(paths->root_dir, i, match_name, ignore_same_name, *p, &same_name_link);
874 if (r < 0)
875 return r;
876 if (r > 0) {
877 /* We found symlinks in this dir? Yay! Let's see where precisely it is enabled. */
878
879 if (path_equal_ptr(*p, paths->persistent_config)) {
880 /* This is the best outcome, let's return it immediately. */
881 *state = UNIT_FILE_ENABLED;
882 return 1;
883 }
884
885 /* look for global enablement of user units */
886 if (scope == UNIT_FILE_USER && path_is_user_config_dir(*p)) {
887 *state = UNIT_FILE_ENABLED;
888 return 1;
889 }
890
891 r = path_is_runtime(paths, *p, false);
892 if (r < 0)
893 return r;
894 if (r > 0)
895 enabled_in_runtime = true;
896 else
897 enabled_at_all = true;
898
899 } else if (same_name_link) {
900 if (path_equal_ptr(*p, paths->persistent_config))
901 same_name_link_config = true;
902 else {
903 r = path_is_runtime(paths, *p, false);
904 if (r < 0)
905 return r;
906 if (r > 0)
907 same_name_link_runtime = true;
908 }
909 }
910
911 /* Check if next iteration will be "below" the unit file (either a regular file
912 * or a symlink), and hence should be ignored */
913 if (!ignore_same_name && path_startswith(i->path, *p))
914 ignore_same_name = true;
915 }
916
917 if (enabled_in_runtime) {
918 *state = UNIT_FILE_ENABLED_RUNTIME;
919 return 1;
920 }
921
922 /* Here's a special rule: if the unit we are looking for is an instance, and it symlinked in the search path
923 * outside of runtime and configuration directory, then we consider it statically enabled. Note we do that only
924 * for instance, not for regular names, as those are merely aliases, while instances explicitly instantiate
925 * something, and hence are a much stronger concept. */
926 if (enabled_at_all && unit_name_is_valid(i->name, UNIT_NAME_INSTANCE)) {
927 *state = UNIT_FILE_STATIC;
928 return 1;
929 }
930
931 /* Hmm, we didn't find it, but maybe we found the same name
932 * link? */
933 if (same_name_link_config) {
934 *state = UNIT_FILE_LINKED;
935 return 1;
936 }
937 if (same_name_link_runtime) {
938 *state = UNIT_FILE_LINKED_RUNTIME;
939 return 1;
940 }
941
942 return 0;
943 }
944
945 static void install_info_free(UnitFileInstallInfo *i) {
946
947 if (!i)
948 return;
949
950 free(i->name);
951 free(i->path);
952 strv_free(i->aliases);
953 strv_free(i->wanted_by);
954 strv_free(i->required_by);
955 strv_free(i->also);
956 free(i->default_instance);
957 free(i->symlink_target);
958 free(i);
959 }
960
961 static void install_context_done(InstallContext *c) {
962 assert(c);
963
964 c->will_process = ordered_hashmap_free_with_destructor(c->will_process, install_info_free);
965 c->have_processed = ordered_hashmap_free_with_destructor(c->have_processed, install_info_free);
966 }
967
968 static UnitFileInstallInfo *install_info_find(InstallContext *c, const char *name) {
969 UnitFileInstallInfo *i;
970
971 i = ordered_hashmap_get(c->have_processed, name);
972 if (i)
973 return i;
974
975 return ordered_hashmap_get(c->will_process, name);
976 }
977
978 static int install_info_may_process(
979 const UnitFileInstallInfo *i,
980 const LookupPaths *paths,
981 UnitFileChange **changes,
982 size_t *n_changes) {
983 assert(i);
984 assert(paths);
985
986 /* Checks whether the loaded unit file is one we should process, or is masked,
987 * transient or generated and thus not subject to enable/disable operations. */
988
989 if (i->type == UNIT_FILE_TYPE_MASKED) {
990 unit_file_changes_add(changes, n_changes, -ERFKILL, i->path, NULL);
991 return -ERFKILL;
992 }
993 if (path_is_generator(paths, i->path) ||
994 path_is_transient(paths, i->path)) {
995 unit_file_changes_add(changes, n_changes, -EADDRNOTAVAIL, i->path, NULL);
996 return -EADDRNOTAVAIL;
997 }
998
999 return 0;
1000 }
1001
1002 /**
1003 * Adds a new UnitFileInstallInfo entry under name in the InstallContext.will_process
1004 * hashmap, or retrieves the existing one if already present.
1005 *
1006 * Returns negative on error, 0 if the unit was already known, 1 otherwise.
1007 */
1008 static int install_info_add(
1009 InstallContext *c,
1010 const char *name,
1011 const char *path,
1012 bool auxiliary,
1013 UnitFileInstallInfo **ret) {
1014
1015 UnitFileInstallInfo *i = NULL;
1016 int r;
1017
1018 assert(c);
1019
1020 if (!name) {
1021 /* 'name' and 'path' must not both be null. Check here 'path' using assert_se() to
1022 * workaround a bug in gcc that generates a -Wnonnull warning when calling basename(),
1023 * but this cannot be possible in any code path (See #6119). */
1024 assert_se(path);
1025 name = basename(path);
1026 }
1027
1028 if (!unit_name_is_valid(name, UNIT_NAME_ANY))
1029 return -EINVAL;
1030
1031 i = install_info_find(c, name);
1032 if (i) {
1033 i->auxiliary = i->auxiliary && auxiliary;
1034
1035 if (ret)
1036 *ret = i;
1037 return 0;
1038 }
1039
1040 r = ordered_hashmap_ensure_allocated(&c->will_process, &string_hash_ops);
1041 if (r < 0)
1042 return r;
1043
1044 i = new(UnitFileInstallInfo, 1);
1045 if (!i)
1046 return -ENOMEM;
1047
1048 *i = (UnitFileInstallInfo) {
1049 .type = _UNIT_FILE_TYPE_INVALID,
1050 .auxiliary = auxiliary,
1051 };
1052
1053 i->name = strdup(name);
1054 if (!i->name) {
1055 r = -ENOMEM;
1056 goto fail;
1057 }
1058
1059 if (path) {
1060 i->path = strdup(path);
1061 if (!i->path) {
1062 r = -ENOMEM;
1063 goto fail;
1064 }
1065 }
1066
1067 r = ordered_hashmap_put(c->will_process, i->name, i);
1068 if (r < 0)
1069 goto fail;
1070
1071 if (ret)
1072 *ret = i;
1073
1074 return 1;
1075
1076 fail:
1077 install_info_free(i);
1078 return r;
1079 }
1080
1081 static int config_parse_alias(
1082 const char *unit,
1083 const char *filename,
1084 unsigned line,
1085 const char *section,
1086 unsigned section_line,
1087 const char *lvalue,
1088 int ltype,
1089 const char *rvalue,
1090 void *data,
1091 void *userdata) {
1092
1093 UnitType type;
1094
1095 assert(unit);
1096 assert(filename);
1097 assert(lvalue);
1098 assert(rvalue);
1099
1100 type = unit_name_to_type(unit);
1101 if (!unit_type_may_alias(type))
1102 return log_syntax(unit, LOG_WARNING, filename, line, 0,
1103 "Alias= is not allowed for %s units, ignoring.",
1104 unit_type_to_string(type));
1105
1106 return config_parse_strv(unit, filename, line, section, section_line,
1107 lvalue, ltype, rvalue, data, userdata);
1108 }
1109
1110 static int config_parse_also(
1111 const char *unit,
1112 const char *filename,
1113 unsigned line,
1114 const char *section,
1115 unsigned section_line,
1116 const char *lvalue,
1117 int ltype,
1118 const char *rvalue,
1119 void *data,
1120 void *userdata) {
1121
1122 UnitFileInstallInfo *info = userdata;
1123 InstallContext *c = data;
1124 int r;
1125
1126 assert(unit);
1127 assert(filename);
1128 assert(lvalue);
1129 assert(rvalue);
1130
1131 for (;;) {
1132 _cleanup_free_ char *word = NULL, *printed = NULL;
1133
1134 r = extract_first_word(&rvalue, &word, NULL, 0);
1135 if (r < 0)
1136 return r;
1137 if (r == 0)
1138 break;
1139
1140 r = install_full_printf(info, word, &printed);
1141 if (r < 0)
1142 return r;
1143
1144 r = install_info_add(c, printed, NULL, true, NULL);
1145 if (r < 0)
1146 return r;
1147
1148 r = strv_push(&info->also, printed);
1149 if (r < 0)
1150 return r;
1151
1152 printed = NULL;
1153 }
1154
1155 return 0;
1156 }
1157
1158 static int config_parse_default_instance(
1159 const char *unit,
1160 const char *filename,
1161 unsigned line,
1162 const char *section,
1163 unsigned section_line,
1164 const char *lvalue,
1165 int ltype,
1166 const char *rvalue,
1167 void *data,
1168 void *userdata) {
1169
1170 UnitFileInstallInfo *i = data;
1171 _cleanup_free_ char *printed = NULL;
1172 int r;
1173
1174 assert(unit);
1175 assert(filename);
1176 assert(lvalue);
1177 assert(rvalue);
1178
1179 if (unit_name_is_valid(unit, UNIT_NAME_INSTANCE))
1180 /* When enabling an instance, we might be using a template unit file,
1181 * but we should ignore DefaultInstance silently. */
1182 return 0;
1183 if (!unit_name_is_valid(unit, UNIT_NAME_TEMPLATE))
1184 return log_syntax(unit, LOG_WARNING, filename, line, 0,
1185 "DefaultInstance= only makes sense for template units, ignoring.");
1186
1187 r = install_full_printf(i, rvalue, &printed);
1188 if (r < 0)
1189 return r;
1190
1191 if (isempty(printed)) {
1192 i->default_instance = mfree(i->default_instance);
1193 return 0;
1194 }
1195
1196 if (!unit_instance_is_valid(printed))
1197 return log_syntax(unit, LOG_WARNING, filename, line, SYNTHETIC_ERRNO(EINVAL),
1198 "Invalid DefaultInstance= value \"%s\".", printed);
1199
1200 return free_and_replace(i->default_instance, printed);
1201 }
1202
1203 static int unit_file_load(
1204 InstallContext *c,
1205 UnitFileInstallInfo *info,
1206 const char *path,
1207 const char *root_dir,
1208 SearchFlags flags) {
1209
1210 const ConfigTableItem items[] = {
1211 { "Install", "Alias", config_parse_alias, 0, &info->aliases },
1212 { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by },
1213 { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by },
1214 { "Install", "DefaultInstance", config_parse_default_instance, 0, info },
1215 { "Install", "Also", config_parse_also, 0, c },
1216 {}
1217 };
1218
1219 UnitType type;
1220 _cleanup_fclose_ FILE *f = NULL;
1221 _cleanup_close_ int fd = -1;
1222 struct stat st;
1223 int r;
1224
1225 assert(info);
1226 assert(path);
1227
1228 if (!(flags & SEARCH_DROPIN)) {
1229 /* Loading or checking for the main unit file… */
1230
1231 type = unit_name_to_type(info->name);
1232 if (type < 0)
1233 return -EINVAL;
1234 if (unit_name_is_valid(info->name, UNIT_NAME_TEMPLATE|UNIT_NAME_INSTANCE) && !unit_type_may_template(type))
1235 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1236 "%s: unit type %s cannot be templated, ignoring.", path, unit_type_to_string(type));
1237
1238 if (!(flags & SEARCH_LOAD)) {
1239 r = lstat(path, &st);
1240 if (r < 0)
1241 return -errno;
1242
1243 if (null_or_empty(&st))
1244 info->type = UNIT_FILE_TYPE_MASKED;
1245 else if (S_ISREG(st.st_mode))
1246 info->type = UNIT_FILE_TYPE_REGULAR;
1247 else if (S_ISLNK(st.st_mode))
1248 return -ELOOP;
1249 else if (S_ISDIR(st.st_mode))
1250 return -EISDIR;
1251 else
1252 return -ENOTTY;
1253
1254 return 0;
1255 }
1256
1257 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
1258 if (fd < 0)
1259 return -errno;
1260 } else {
1261 /* Operating on a drop-in file. If we aren't supposed to load the unit file drop-ins don't matter, let's hence shortcut this. */
1262
1263 if (!(flags & SEARCH_LOAD))
1264 return 0;
1265
1266 fd = chase_symlinks_and_open(path, root_dir, 0, O_RDONLY|O_CLOEXEC|O_NOCTTY, NULL);
1267 if (fd < 0)
1268 return fd;
1269 }
1270
1271 if (fstat(fd, &st) < 0)
1272 return -errno;
1273
1274 if (null_or_empty(&st)) {
1275 if ((flags & SEARCH_DROPIN) == 0)
1276 info->type = UNIT_FILE_TYPE_MASKED;
1277
1278 return 0;
1279 }
1280
1281 r = stat_verify_regular(&st);
1282 if (r < 0)
1283 return r;
1284
1285 f = take_fdopen(&fd, "r");
1286 if (!f)
1287 return -errno;
1288
1289 /* c is only needed if we actually load the file (it's referenced from items[] btw, in case you wonder.) */
1290 assert(c);
1291
1292 r = config_parse(info->name, path, f,
1293 "Install\0"
1294 "-Unit\0"
1295 "-Automount\0"
1296 "-Device\0"
1297 "-Mount\0"
1298 "-Path\0"
1299 "-Scope\0"
1300 "-Service\0"
1301 "-Slice\0"
1302 "-Socket\0"
1303 "-Swap\0"
1304 "-Target\0"
1305 "-Timer\0",
1306 config_item_table_lookup, items,
1307 0, info,
1308 NULL);
1309 if (r < 0)
1310 return log_debug_errno(r, "Failed to parse %s: %m", info->name);
1311
1312 if ((flags & SEARCH_DROPIN) == 0)
1313 info->type = UNIT_FILE_TYPE_REGULAR;
1314
1315 return
1316 (int) strv_length(info->aliases) +
1317 (int) strv_length(info->wanted_by) +
1318 (int) strv_length(info->required_by);
1319 }
1320
1321 static int unit_file_load_or_readlink(
1322 InstallContext *c,
1323 UnitFileInstallInfo *info,
1324 const char *path,
1325 const char *root_dir,
1326 SearchFlags flags) {
1327
1328 _cleanup_free_ char *target = NULL;
1329 int r;
1330
1331 r = unit_file_load(c, info, path, root_dir, flags);
1332 if (r != -ELOOP || (flags & SEARCH_DROPIN))
1333 return r;
1334
1335 /* This is a symlink, let's read it. */
1336
1337 r = readlink_malloc(path, &target);
1338 if (r < 0)
1339 return r;
1340
1341 if (path_equal(target, "/dev/null"))
1342 info->type = UNIT_FILE_TYPE_MASKED;
1343 else {
1344 const char *bn;
1345 UnitType a, b;
1346
1347 bn = basename(target);
1348
1349 if (unit_name_is_valid(info->name, UNIT_NAME_PLAIN)) {
1350
1351 if (!unit_name_is_valid(bn, UNIT_NAME_PLAIN))
1352 return -EINVAL;
1353
1354 } else if (unit_name_is_valid(info->name, UNIT_NAME_INSTANCE)) {
1355
1356 if (!unit_name_is_valid(bn, UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE))
1357 return -EINVAL;
1358
1359 } else if (unit_name_is_valid(info->name, UNIT_NAME_TEMPLATE)) {
1360
1361 if (!unit_name_is_valid(bn, UNIT_NAME_TEMPLATE))
1362 return -EINVAL;
1363 } else
1364 return -EINVAL;
1365
1366 /* Enforce that the symlink destination does not
1367 * change the unit file type. */
1368
1369 a = unit_name_to_type(info->name);
1370 b = unit_name_to_type(bn);
1371 if (a < 0 || b < 0 || a != b)
1372 return -EINVAL;
1373
1374 if (path_is_absolute(target))
1375 /* This is an absolute path, prefix the root so that we always deal with fully qualified paths */
1376 info->symlink_target = path_join(root_dir, target);
1377 else
1378 /* This is a relative path, take it relative to the dir the symlink is located in. */
1379 info->symlink_target = file_in_same_dir(path, target);
1380 if (!info->symlink_target)
1381 return -ENOMEM;
1382
1383 info->type = UNIT_FILE_TYPE_SYMLINK;
1384 }
1385
1386 return 0;
1387 }
1388
1389 static int unit_file_search(
1390 InstallContext *c,
1391 UnitFileInstallInfo *info,
1392 const LookupPaths *paths,
1393 SearchFlags flags) {
1394
1395 const char *dropin_dir_name = NULL, *dropin_template_dir_name = NULL;
1396 _cleanup_strv_free_ char **dirs = NULL, **files = NULL;
1397 _cleanup_free_ char *template = NULL;
1398 bool found_unit = false;
1399 int r, result;
1400 char **p;
1401
1402 assert(info);
1403 assert(paths);
1404
1405 /* Was this unit already loaded? */
1406 if (info->type != _UNIT_FILE_TYPE_INVALID)
1407 return 0;
1408
1409 if (info->path)
1410 return unit_file_load_or_readlink(c, info, info->path, paths->root_dir, flags);
1411
1412 assert(info->name);
1413
1414 if (unit_name_is_valid(info->name, UNIT_NAME_INSTANCE)) {
1415 r = unit_name_template(info->name, &template);
1416 if (r < 0)
1417 return r;
1418 }
1419
1420 STRV_FOREACH(p, paths->search_path) {
1421 _cleanup_free_ char *path = NULL;
1422
1423 path = path_join(*p, info->name);
1424 if (!path)
1425 return -ENOMEM;
1426
1427 r = unit_file_load_or_readlink(c, info, path, paths->root_dir, flags);
1428 if (r >= 0) {
1429 info->path = TAKE_PTR(path);
1430 result = r;
1431 found_unit = true;
1432 break;
1433 } else if (!IN_SET(r, -ENOENT, -ENOTDIR, -EACCES))
1434 return r;
1435 }
1436
1437 if (!found_unit && template) {
1438
1439 /* Unit file doesn't exist, however instance
1440 * enablement was requested. We will check if it is
1441 * possible to load template unit file. */
1442
1443 STRV_FOREACH(p, paths->search_path) {
1444 _cleanup_free_ char *path = NULL;
1445
1446 path = path_join(*p, template);
1447 if (!path)
1448 return -ENOMEM;
1449
1450 r = unit_file_load_or_readlink(c, info, path, paths->root_dir, flags);
1451 if (r >= 0) {
1452 info->path = TAKE_PTR(path);
1453 result = r;
1454 found_unit = true;
1455 break;
1456 } else if (!IN_SET(r, -ENOENT, -ENOTDIR, -EACCES))
1457 return r;
1458 }
1459 }
1460
1461 if (!found_unit)
1462 return log_debug_errno(SYNTHETIC_ERRNO(ENOENT),
1463 "Cannot find unit %s%s%s.",
1464 info->name, template ? " or " : "", strempty(template));
1465
1466 if (info->type == UNIT_FILE_TYPE_MASKED)
1467 return result;
1468
1469 /* Search for drop-in directories */
1470
1471 dropin_dir_name = strjoina(info->name, ".d");
1472 STRV_FOREACH(p, paths->search_path) {
1473 char *path;
1474
1475 path = path_join(*p, dropin_dir_name);
1476 if (!path)
1477 return -ENOMEM;
1478
1479 r = strv_consume(&dirs, path);
1480 if (r < 0)
1481 return r;
1482 }
1483
1484 if (template) {
1485 dropin_template_dir_name = strjoina(template, ".d");
1486 STRV_FOREACH(p, paths->search_path) {
1487 char *path;
1488
1489 path = path_join(*p, dropin_template_dir_name);
1490 if (!path)
1491 return -ENOMEM;
1492
1493 r = strv_consume(&dirs, path);
1494 if (r < 0)
1495 return r;
1496 }
1497 }
1498
1499 /* Load drop-in conf files */
1500
1501 r = conf_files_list_strv(&files, ".conf", NULL, 0, (const char**) dirs);
1502 if (r < 0)
1503 return log_debug_errno(r, "Failed to get list of conf files: %m");
1504
1505 STRV_FOREACH(p, files) {
1506 r = unit_file_load_or_readlink(c, info, *p, paths->root_dir, flags | SEARCH_DROPIN);
1507 if (r < 0)
1508 return log_debug_errno(r, "Failed to load conf file %s: %m", *p);
1509 }
1510
1511 return result;
1512 }
1513
1514 static int install_info_follow(
1515 InstallContext *c,
1516 UnitFileInstallInfo *i,
1517 const char *root_dir,
1518 SearchFlags flags,
1519 bool ignore_different_name) {
1520
1521 assert(c);
1522 assert(i);
1523
1524 if (i->type != UNIT_FILE_TYPE_SYMLINK)
1525 return -EINVAL;
1526 if (!i->symlink_target)
1527 return -EINVAL;
1528
1529 /* If the basename doesn't match, the caller should add a
1530 * complete new entry for this. */
1531
1532 if (!ignore_different_name && !streq(basename(i->symlink_target), i->name))
1533 return -EXDEV;
1534
1535 free_and_replace(i->path, i->symlink_target);
1536 i->type = _UNIT_FILE_TYPE_INVALID;
1537
1538 return unit_file_load_or_readlink(c, i, i->path, root_dir, flags);
1539 }
1540
1541 /**
1542 * Search for the unit file. If the unit name is a symlink, follow the symlink to the
1543 * target, maybe more than once. Propagate the instance name if present.
1544 */
1545 static int install_info_traverse(
1546 UnitFileScope scope,
1547 InstallContext *c,
1548 const LookupPaths *paths,
1549 UnitFileInstallInfo *start,
1550 SearchFlags flags,
1551 UnitFileInstallInfo **ret) {
1552
1553 UnitFileInstallInfo *i;
1554 unsigned k = 0;
1555 int r;
1556
1557 assert(paths);
1558 assert(start);
1559 assert(c);
1560
1561 r = unit_file_search(c, start, paths, flags);
1562 if (r < 0)
1563 return r;
1564
1565 i = start;
1566 while (i->type == UNIT_FILE_TYPE_SYMLINK) {
1567 /* Follow the symlink */
1568
1569 if (++k > UNIT_FILE_FOLLOW_SYMLINK_MAX)
1570 return -ELOOP;
1571
1572 if (!(flags & SEARCH_FOLLOW_CONFIG_SYMLINKS)) {
1573 r = path_is_config(paths, i->path, true);
1574 if (r < 0)
1575 return r;
1576 if (r > 0)
1577 return -ELOOP;
1578 }
1579
1580 r = install_info_follow(c, i, paths->root_dir, flags, false);
1581 if (r == -EXDEV) {
1582 _cleanup_free_ char *buffer = NULL;
1583 const char *bn;
1584
1585 /* Target has a different name, create a new
1586 * install info object for that, and continue
1587 * with that. */
1588
1589 bn = basename(i->symlink_target);
1590
1591 if (unit_name_is_valid(i->name, UNIT_NAME_INSTANCE) &&
1592 unit_name_is_valid(bn, UNIT_NAME_TEMPLATE)) {
1593
1594 _cleanup_free_ char *instance = NULL;
1595
1596 r = unit_name_to_instance(i->name, &instance);
1597 if (r < 0)
1598 return r;
1599
1600 r = unit_name_replace_instance(bn, instance, &buffer);
1601 if (r < 0)
1602 return r;
1603
1604 if (streq(buffer, i->name)) {
1605
1606 /* We filled in the instance, and the target stayed the same? If so, then let's
1607 * honour the link as it is. */
1608
1609 r = install_info_follow(c, i, paths->root_dir, flags, true);
1610 if (r < 0)
1611 return r;
1612
1613 continue;
1614 }
1615
1616 bn = buffer;
1617 }
1618
1619 r = install_info_add(c, bn, NULL, false, &i);
1620 if (r < 0)
1621 return r;
1622
1623 /* Try again, with the new target we found. */
1624 r = unit_file_search(c, i, paths, flags);
1625 if (r == -ENOENT)
1626 /* Translate error code to highlight this specific case */
1627 return -ENOLINK;
1628 }
1629
1630 if (r < 0)
1631 return r;
1632 }
1633
1634 if (ret)
1635 *ret = i;
1636
1637 return 0;
1638 }
1639
1640 /**
1641 * Call install_info_add() with name_or_path as the path (if name_or_path starts with "/")
1642 * or the name (otherwise). root_dir is prepended to the path.
1643 */
1644 static int install_info_add_auto(
1645 InstallContext *c,
1646 const LookupPaths *paths,
1647 const char *name_or_path,
1648 UnitFileInstallInfo **ret) {
1649
1650 assert(c);
1651 assert(name_or_path);
1652
1653 if (path_is_absolute(name_or_path)) {
1654 const char *pp;
1655
1656 pp = prefix_roota(paths->root_dir, name_or_path);
1657
1658 return install_info_add(c, NULL, pp, false, ret);
1659 } else
1660 return install_info_add(c, name_or_path, NULL, false, ret);
1661 }
1662
1663 static int install_info_discover(
1664 UnitFileScope scope,
1665 InstallContext *c,
1666 const LookupPaths *paths,
1667 const char *name,
1668 SearchFlags flags,
1669 UnitFileInstallInfo **ret,
1670 UnitFileChange **changes,
1671 size_t *n_changes) {
1672
1673 UnitFileInstallInfo *i;
1674 int r;
1675
1676 assert(c);
1677 assert(paths);
1678 assert(name);
1679
1680 r = install_info_add_auto(c, paths, name, &i);
1681 if (r >= 0)
1682 r = install_info_traverse(scope, c, paths, i, flags, ret);
1683
1684 if (r < 0)
1685 unit_file_changes_add(changes, n_changes, r, name, NULL);
1686 return r;
1687 }
1688
1689 static int install_info_discover_and_check(
1690 UnitFileScope scope,
1691 InstallContext *c,
1692 const LookupPaths *paths,
1693 const char *name,
1694 SearchFlags flags,
1695 UnitFileInstallInfo **ret,
1696 UnitFileChange **changes,
1697 size_t *n_changes) {
1698
1699 int r;
1700
1701 r = install_info_discover(scope, c, paths, name, flags, ret, changes, n_changes);
1702 if (r < 0)
1703 return r;
1704
1705 return install_info_may_process(ret ? *ret : NULL, paths, changes, n_changes);
1706 }
1707
1708 int unit_file_verify_alias(const UnitFileInstallInfo *i, const char *dst, char **ret_dst) {
1709 _cleanup_free_ char *dst_updated = NULL;
1710 int r;
1711
1712 /* Verify that dst is a valid either a valid alias or a valid .wants/.requires symlink for the target
1713 * unit *i. Return negative on error or if not compatible, zero on success.
1714 *
1715 * ret_dst is set in cases where "instance propagation" happens, i.e. when the instance part is
1716 * inserted into dst. It is not normally set, even on success, so that the caller can easily
1717 * distinguish the case where instance propagation occurred.
1718 */
1719
1720 const char *path_alias = strrchr(dst, '/');
1721 if (path_alias) {
1722 /* This branch covers legacy Alias= function of creating .wants and .requires symlinks. */
1723 _cleanup_free_ char *dir = NULL;
1724 char *p;
1725
1726 path_alias ++; /* skip over slash */
1727
1728 dir = dirname_malloc(dst);
1729 if (!dir)
1730 return log_oom();
1731
1732 p = endswith(dir, ".wants");
1733 if (!p)
1734 p = endswith(dir, ".requires");
1735 if (!p)
1736 return log_warning_errno(SYNTHETIC_ERRNO(EXDEV),
1737 "Invalid path \"%s\" in alias.", dir);
1738 *p = '\0'; /* dir should now be a unit name */
1739
1740 r = unit_name_classify(dir);
1741 if (r < 0)
1742 return log_warning_errno(SYNTHETIC_ERRNO(EXDEV),
1743 "Invalid unit name component \"%s\" in alias.", dir);
1744
1745 const bool instance_propagation = r == UNIT_NAME_TEMPLATE;
1746
1747 /* That's the name we want to use for verification. */
1748 r = unit_symlink_name_compatible(path_alias, i->name, instance_propagation);
1749 if (r < 0)
1750 return log_error_errno(r, "Failed to verify alias validity: %m");
1751 if (r == 0)
1752 return log_warning_errno(SYNTHETIC_ERRNO(EXDEV),
1753 "Invalid unit %s symlink %s.",
1754 i->name, dst);
1755
1756 } else {
1757 /* If the symlink target has an instance set and the symlink source doesn't, we "propagate
1758 * the instance", i.e. instantiate the symlink source with the target instance. */
1759 if (unit_name_is_valid(dst, UNIT_NAME_TEMPLATE)) {
1760 _cleanup_free_ char *inst = NULL;
1761
1762 r = unit_name_to_instance(i->name, &inst);
1763 if (r < 0)
1764 return log_error_errno(r, "Failed to extract instance name from %s: %m", i->name);
1765
1766 if (r == UNIT_NAME_INSTANCE) {
1767 r = unit_name_replace_instance(dst, inst, &dst_updated);
1768 if (r < 0)
1769 return log_error_errno(r, "Failed to build unit name from %s+%s: %m",
1770 dst, inst);
1771 }
1772 }
1773
1774 r = unit_validate_alias_symlink_and_warn(dst_updated ?: dst, i->name);
1775 if (r < 0)
1776 return r;
1777
1778 }
1779
1780 *ret_dst = TAKE_PTR(dst_updated);
1781 return 0;
1782 }
1783
1784 static int install_info_symlink_alias(
1785 UnitFileInstallInfo *i,
1786 const LookupPaths *paths,
1787 const char *config_path,
1788 bool force,
1789 UnitFileChange **changes,
1790 size_t *n_changes) {
1791
1792 char **s;
1793 int r = 0, q;
1794
1795 assert(i);
1796 assert(paths);
1797 assert(config_path);
1798
1799 STRV_FOREACH(s, i->aliases) {
1800 _cleanup_free_ char *alias_path = NULL, *dst = NULL, *dst_updated = NULL;
1801
1802 q = install_full_printf(i, *s, &dst);
1803 if (q < 0)
1804 return q;
1805
1806 q = unit_file_verify_alias(i, dst, &dst_updated);
1807 if (q < 0)
1808 continue;
1809
1810 alias_path = path_make_absolute(dst_updated ?: dst, config_path);
1811 if (!alias_path)
1812 return -ENOMEM;
1813
1814 q = create_symlink(paths, i->path, alias_path, force, changes, n_changes);
1815 if (r == 0)
1816 r = q;
1817 }
1818
1819 return r;
1820 }
1821
1822 static int install_info_symlink_wants(
1823 UnitFileInstallInfo *i,
1824 const LookupPaths *paths,
1825 const char *config_path,
1826 char **list,
1827 const char *suffix,
1828 UnitFileChange **changes,
1829 size_t *n_changes) {
1830
1831 _cleanup_free_ char *buf = NULL;
1832 const char *n;
1833 char **s;
1834 int r = 0, q;
1835
1836 assert(i);
1837 assert(paths);
1838 assert(config_path);
1839
1840 if (strv_isempty(list))
1841 return 0;
1842
1843 if (unit_name_is_valid(i->name, UNIT_NAME_TEMPLATE)) {
1844 UnitFileInstallInfo instance = {
1845 .type = _UNIT_FILE_TYPE_INVALID,
1846 };
1847 _cleanup_free_ char *path = NULL;
1848
1849 /* If this is a template, and we have no instance, don't do anything */
1850 if (!i->default_instance)
1851 return 1;
1852
1853 r = unit_name_replace_instance(i->name, i->default_instance, &buf);
1854 if (r < 0)
1855 return r;
1856
1857 instance.name = buf;
1858 r = unit_file_search(NULL, &instance, paths, SEARCH_FOLLOW_CONFIG_SYMLINKS);
1859 if (r < 0)
1860 return r;
1861
1862 path = TAKE_PTR(instance.path);
1863
1864 if (instance.type == UNIT_FILE_TYPE_MASKED) {
1865 unit_file_changes_add(changes, n_changes, -ERFKILL, path, NULL);
1866 return -ERFKILL;
1867 }
1868
1869 n = buf;
1870 } else
1871 n = i->name;
1872
1873 STRV_FOREACH(s, list) {
1874 _cleanup_free_ char *path = NULL, *dst = NULL;
1875
1876 q = install_full_printf(i, *s, &dst);
1877 if (q < 0)
1878 return q;
1879
1880 if (!unit_name_is_valid(dst, UNIT_NAME_ANY)) {
1881 unit_file_changes_add(changes, n_changes, -EUCLEAN, dst, NULL);
1882 r = -EUCLEAN;
1883 continue;
1884 }
1885
1886 path = strjoin(config_path, "/", dst, suffix, n);
1887 if (!path)
1888 return -ENOMEM;
1889
1890 q = create_symlink(paths, i->path, path, true, changes, n_changes);
1891 if (r == 0)
1892 r = q;
1893 }
1894
1895 return r;
1896 }
1897
1898 static int install_info_symlink_link(
1899 UnitFileInstallInfo *i,
1900 const LookupPaths *paths,
1901 const char *config_path,
1902 bool force,
1903 UnitFileChange **changes,
1904 size_t *n_changes) {
1905
1906 _cleanup_free_ char *path = NULL;
1907 int r;
1908
1909 assert(i);
1910 assert(paths);
1911 assert(config_path);
1912 assert(i->path);
1913
1914 r = in_search_path(paths, i->path);
1915 if (r < 0)
1916 return r;
1917 if (r > 0)
1918 return 0;
1919
1920 path = path_join(config_path, i->name);
1921 if (!path)
1922 return -ENOMEM;
1923
1924 return create_symlink(paths, i->path, path, force, changes, n_changes);
1925 }
1926
1927 static int install_info_apply(
1928 UnitFileInstallInfo *i,
1929 const LookupPaths *paths,
1930 const char *config_path,
1931 bool force,
1932 UnitFileChange **changes,
1933 size_t *n_changes) {
1934
1935 int r, q;
1936
1937 assert(i);
1938 assert(paths);
1939 assert(config_path);
1940
1941 if (i->type != UNIT_FILE_TYPE_REGULAR)
1942 return 0;
1943
1944 r = install_info_symlink_alias(i, paths, config_path, force, changes, n_changes);
1945
1946 q = install_info_symlink_wants(i, paths, config_path, i->wanted_by, ".wants/", changes, n_changes);
1947 if (r == 0)
1948 r = q;
1949
1950 q = install_info_symlink_wants(i, paths, config_path, i->required_by, ".requires/", changes, n_changes);
1951 if (r == 0)
1952 r = q;
1953
1954 q = install_info_symlink_link(i, paths, config_path, force, changes, n_changes);
1955 /* Do not count links to the unit file towards the "carries_install_info" count */
1956 if (r == 0 && q < 0)
1957 r = q;
1958
1959 return r;
1960 }
1961
1962 static int install_context_apply(
1963 UnitFileScope scope,
1964 InstallContext *c,
1965 const LookupPaths *paths,
1966 const char *config_path,
1967 bool force,
1968 SearchFlags flags,
1969 UnitFileChange **changes,
1970 size_t *n_changes) {
1971
1972 UnitFileInstallInfo *i;
1973 int r;
1974
1975 assert(c);
1976 assert(paths);
1977 assert(config_path);
1978
1979 if (ordered_hashmap_isempty(c->will_process))
1980 return 0;
1981
1982 r = ordered_hashmap_ensure_allocated(&c->have_processed, &string_hash_ops);
1983 if (r < 0)
1984 return r;
1985
1986 r = 0;
1987 while ((i = ordered_hashmap_first(c->will_process))) {
1988 int q;
1989
1990 q = ordered_hashmap_move_one(c->have_processed, c->will_process, i->name);
1991 if (q < 0)
1992 return q;
1993
1994 q = install_info_traverse(scope, c, paths, i, flags, NULL);
1995 if (q < 0) {
1996 unit_file_changes_add(changes, n_changes, q, i->name, NULL);
1997 return q;
1998 }
1999
2000 /* We can attempt to process a masked unit when a different unit
2001 * that we were processing specifies it in Also=. */
2002 if (i->type == UNIT_FILE_TYPE_MASKED) {
2003 unit_file_changes_add(changes, n_changes, UNIT_FILE_IS_MASKED, i->path, NULL);
2004 if (r >= 0)
2005 /* Assume that something *could* have been enabled here,
2006 * avoid "empty [Install] section" warning. */
2007 r += 1;
2008 continue;
2009 }
2010
2011 if (i->type != UNIT_FILE_TYPE_REGULAR)
2012 continue;
2013
2014 q = install_info_apply(i, paths, config_path, force, changes, n_changes);
2015 if (r >= 0) {
2016 if (q < 0)
2017 r = q;
2018 else
2019 r += q;
2020 }
2021 }
2022
2023 return r;
2024 }
2025
2026 static int install_context_mark_for_removal(
2027 UnitFileScope scope,
2028 InstallContext *c,
2029 const LookupPaths *paths,
2030 Set **remove_symlinks_to,
2031 const char *config_path,
2032 UnitFileChange **changes,
2033 size_t *n_changes) {
2034
2035 UnitFileInstallInfo *i;
2036 int r;
2037
2038 assert(c);
2039 assert(paths);
2040 assert(config_path);
2041
2042 /* Marks all items for removal */
2043
2044 if (ordered_hashmap_isempty(c->will_process))
2045 return 0;
2046
2047 r = ordered_hashmap_ensure_allocated(&c->have_processed, &string_hash_ops);
2048 if (r < 0)
2049 return r;
2050
2051 while ((i = ordered_hashmap_first(c->will_process))) {
2052
2053 r = ordered_hashmap_move_one(c->have_processed, c->will_process, i->name);
2054 if (r < 0)
2055 return r;
2056
2057 r = install_info_traverse(scope, c, paths, i, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, NULL);
2058 if (r == -ENOLINK) {
2059 log_debug_errno(r, "Name %s leads to a dangling symlink, removing name.", i->name);
2060 unit_file_changes_add(changes, n_changes, UNIT_FILE_IS_DANGLING, i->path ?: i->name, NULL);
2061 } else if (r == -ENOENT) {
2062
2063 if (i->auxiliary) /* some unit specified in Also= or similar is missing */
2064 log_debug_errno(r, "Auxiliary unit of %s not found, removing name.", i->name);
2065 else {
2066 log_debug_errno(r, "Unit %s not found, removing name.", i->name);
2067 unit_file_changes_add(changes, n_changes, r, i->path ?: i->name, NULL);
2068 }
2069
2070 } else if (r < 0) {
2071 log_debug_errno(r, "Failed to find unit %s, removing name: %m", i->name);
2072 unit_file_changes_add(changes, n_changes, r, i->path ?: i->name, NULL);
2073 } else if (i->type == UNIT_FILE_TYPE_MASKED) {
2074 log_debug("Unit file %s is masked, ignoring.", i->name);
2075 unit_file_changes_add(changes, n_changes, UNIT_FILE_IS_MASKED, i->path ?: i->name, NULL);
2076 continue;
2077 } else if (i->type != UNIT_FILE_TYPE_REGULAR) {
2078 log_debug("Unit %s has type %s, ignoring.", i->name, unit_file_type_to_string(i->type) ?: "invalid");
2079 continue;
2080 }
2081
2082 r = mark_symlink_for_removal(remove_symlinks_to, i->name);
2083 if (r < 0)
2084 return r;
2085 }
2086
2087 return 0;
2088 }
2089
2090 int unit_file_mask(
2091 UnitFileScope scope,
2092 UnitFileFlags flags,
2093 const char *root_dir,
2094 char **files,
2095 UnitFileChange **changes,
2096 size_t *n_changes) {
2097
2098 _cleanup_(lookup_paths_free) LookupPaths paths = {};
2099 const char *config_path;
2100 char **i;
2101 int r;
2102
2103 assert(scope >= 0);
2104 assert(scope < _UNIT_FILE_SCOPE_MAX);
2105
2106 r = lookup_paths_init(&paths, scope, 0, root_dir);
2107 if (r < 0)
2108 return r;
2109
2110 config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config;
2111 if (!config_path)
2112 return -ENXIO;
2113
2114 STRV_FOREACH(i, files) {
2115 _cleanup_free_ char *path = NULL;
2116 int q;
2117
2118 if (!unit_name_is_valid(*i, UNIT_NAME_ANY)) {
2119 if (r == 0)
2120 r = -EINVAL;
2121 continue;
2122 }
2123
2124 path = path_make_absolute(*i, config_path);
2125 if (!path)
2126 return -ENOMEM;
2127
2128 q = create_symlink(&paths, "/dev/null", path, !!(flags & UNIT_FILE_FORCE), changes, n_changes);
2129 if (q < 0 && r >= 0)
2130 r = q;
2131 }
2132
2133 return r;
2134 }
2135
2136 int unit_file_unmask(
2137 UnitFileScope scope,
2138 UnitFileFlags flags,
2139 const char *root_dir,
2140 char **files,
2141 UnitFileChange **changes,
2142 size_t *n_changes) {
2143
2144 _cleanup_(lookup_paths_free) LookupPaths paths = {};
2145 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
2146 _cleanup_strv_free_ char **todo = NULL;
2147 size_t n_todo = 0, n_allocated = 0;
2148 const char *config_path;
2149 char **i;
2150 bool dry_run;
2151 int r, q;
2152
2153 assert(scope >= 0);
2154 assert(scope < _UNIT_FILE_SCOPE_MAX);
2155
2156 r = lookup_paths_init(&paths, scope, 0, root_dir);
2157 if (r < 0)
2158 return r;
2159
2160 config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config;
2161 if (!config_path)
2162 return -ENXIO;
2163
2164 dry_run = !!(flags & UNIT_FILE_DRY_RUN);
2165
2166 STRV_FOREACH(i, files) {
2167 _cleanup_free_ char *path = NULL;
2168
2169 if (!unit_name_is_valid(*i, UNIT_NAME_ANY))
2170 return -EINVAL;
2171
2172 path = path_make_absolute(*i, config_path);
2173 if (!path)
2174 return -ENOMEM;
2175
2176 r = null_or_empty_path(path);
2177 if (r == -ENOENT)
2178 continue;
2179 if (r < 0)
2180 return r;
2181 if (r == 0)
2182 continue;
2183
2184 if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2))
2185 return -ENOMEM;
2186
2187 todo[n_todo] = strdup(*i);
2188 if (!todo[n_todo])
2189 return -ENOMEM;
2190
2191 n_todo++;
2192 }
2193
2194 strv_uniq(todo);
2195
2196 r = 0;
2197 STRV_FOREACH(i, todo) {
2198 _cleanup_free_ char *path = NULL;
2199 const char *rp;
2200
2201 path = path_make_absolute(*i, config_path);
2202 if (!path)
2203 return -ENOMEM;
2204
2205 if (!dry_run && unlink(path) < 0) {
2206 if (errno != ENOENT) {
2207 if (r >= 0)
2208 r = -errno;
2209 unit_file_changes_add(changes, n_changes, -errno, path, NULL);
2210 }
2211
2212 continue;
2213 }
2214
2215 unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
2216
2217 rp = skip_root(&paths, path);
2218 q = mark_symlink_for_removal(&remove_symlinks_to, rp ?: path);
2219 if (q < 0)
2220 return q;
2221 }
2222
2223 q = remove_marked_symlinks(remove_symlinks_to, config_path, &paths, dry_run, changes, n_changes);
2224 if (r >= 0)
2225 r = q;
2226
2227 return r;
2228 }
2229
2230 int unit_file_link(
2231 UnitFileScope scope,
2232 UnitFileFlags flags,
2233 const char *root_dir,
2234 char **files,
2235 UnitFileChange **changes,
2236 size_t *n_changes) {
2237
2238 _cleanup_(lookup_paths_free) LookupPaths paths = {};
2239 _cleanup_strv_free_ char **todo = NULL;
2240 size_t n_todo = 0, n_allocated = 0;
2241 const char *config_path;
2242 char **i;
2243 int r, q;
2244
2245 assert(scope >= 0);
2246 assert(scope < _UNIT_FILE_SCOPE_MAX);
2247
2248 r = lookup_paths_init(&paths, scope, 0, root_dir);
2249 if (r < 0)
2250 return r;
2251
2252 config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config;
2253 if (!config_path)
2254 return -ENXIO;
2255
2256 STRV_FOREACH(i, files) {
2257 _cleanup_free_ char *full = NULL;
2258 struct stat st;
2259 char *fn;
2260
2261 if (!path_is_absolute(*i))
2262 return -EINVAL;
2263
2264 fn = basename(*i);
2265 if (!unit_name_is_valid(fn, UNIT_NAME_ANY))
2266 return -EINVAL;
2267
2268 full = path_join(paths.root_dir, *i);
2269 if (!full)
2270 return -ENOMEM;
2271
2272 if (lstat(full, &st) < 0)
2273 return -errno;
2274 r = stat_verify_regular(&st);
2275 if (r < 0)
2276 return r;
2277
2278 q = in_search_path(&paths, *i);
2279 if (q < 0)
2280 return q;
2281 if (q > 0)
2282 continue;
2283
2284 if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2))
2285 return -ENOMEM;
2286
2287 todo[n_todo] = strdup(*i);
2288 if (!todo[n_todo])
2289 return -ENOMEM;
2290
2291 n_todo++;
2292 }
2293
2294 strv_uniq(todo);
2295
2296 r = 0;
2297 STRV_FOREACH(i, todo) {
2298 _cleanup_free_ char *new_path = NULL;
2299
2300 new_path = path_make_absolute(basename(*i), config_path);
2301 if (!new_path)
2302 return -ENOMEM;
2303
2304 q = create_symlink(&paths, *i, new_path, !!(flags & UNIT_FILE_FORCE), changes, n_changes);
2305 if (q < 0 && r >= 0)
2306 r = q;
2307 }
2308
2309 return r;
2310 }
2311
2312 static int path_shall_revert(const LookupPaths *paths, const char *path) {
2313 int r;
2314
2315 assert(paths);
2316 assert(path);
2317
2318 /* Checks whether the path is one where the drop-in directories shall be removed. */
2319
2320 r = path_is_config(paths, path, true);
2321 if (r != 0)
2322 return r;
2323
2324 r = path_is_control(paths, path);
2325 if (r != 0)
2326 return r;
2327
2328 return path_is_transient(paths, path);
2329 }
2330
2331 int unit_file_revert(
2332 UnitFileScope scope,
2333 const char *root_dir,
2334 char **files,
2335 UnitFileChange **changes,
2336 size_t *n_changes) {
2337
2338 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
2339 _cleanup_(lookup_paths_free) LookupPaths paths = {};
2340 _cleanup_strv_free_ char **todo = NULL;
2341 size_t n_todo = 0, n_allocated = 0;
2342 char **i;
2343 int r, q;
2344
2345 /* Puts a unit file back into vendor state. This means:
2346 *
2347 * a) we remove all drop-in snippets added by the user ("config"), add to transient units ("transient"), and
2348 * added via "systemctl set-property" ("control"), but not if the drop-in is generated ("generated").
2349 *
2350 * c) if there's a vendor unit file (i.e. one in /usr) we remove any configured overriding unit files (i.e. in
2351 * "config", but not in "transient" or "control" or even "generated").
2352 *
2353 * We remove all that in both the runtime and the persistent directories, if that applies.
2354 */
2355
2356 r = lookup_paths_init(&paths, scope, 0, root_dir);
2357 if (r < 0)
2358 return r;
2359
2360 STRV_FOREACH(i, files) {
2361 bool has_vendor = false;
2362 char **p;
2363
2364 if (!unit_name_is_valid(*i, UNIT_NAME_ANY))
2365 return -EINVAL;
2366
2367 STRV_FOREACH(p, paths.search_path) {
2368 _cleanup_free_ char *path = NULL, *dropin = NULL;
2369 struct stat st;
2370
2371 path = path_make_absolute(*i, *p);
2372 if (!path)
2373 return -ENOMEM;
2374
2375 r = lstat(path, &st);
2376 if (r < 0) {
2377 if (errno != ENOENT)
2378 return -errno;
2379 } else if (S_ISREG(st.st_mode)) {
2380 /* Check if there's a vendor version */
2381 r = path_is_vendor_or_generator(&paths, path);
2382 if (r < 0)
2383 return r;
2384 if (r > 0)
2385 has_vendor = true;
2386 }
2387
2388 dropin = strjoin(path, ".d");
2389 if (!dropin)
2390 return -ENOMEM;
2391
2392 r = lstat(dropin, &st);
2393 if (r < 0) {
2394 if (errno != ENOENT)
2395 return -errno;
2396 } else if (S_ISDIR(st.st_mode)) {
2397 /* Remove the drop-ins */
2398 r = path_shall_revert(&paths, dropin);
2399 if (r < 0)
2400 return r;
2401 if (r > 0) {
2402 if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2))
2403 return -ENOMEM;
2404
2405 todo[n_todo++] = TAKE_PTR(dropin);
2406 }
2407 }
2408 }
2409
2410 if (!has_vendor)
2411 continue;
2412
2413 /* OK, there's a vendor version, hence drop all configuration versions */
2414 STRV_FOREACH(p, paths.search_path) {
2415 _cleanup_free_ char *path = NULL;
2416 struct stat st;
2417
2418 path = path_make_absolute(*i, *p);
2419 if (!path)
2420 return -ENOMEM;
2421
2422 r = lstat(path, &st);
2423 if (r < 0) {
2424 if (errno != ENOENT)
2425 return -errno;
2426 } else if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
2427 r = path_is_config(&paths, path, true);
2428 if (r < 0)
2429 return r;
2430 if (r > 0) {
2431 if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2))
2432 return -ENOMEM;
2433
2434 todo[n_todo++] = TAKE_PTR(path);
2435 }
2436 }
2437 }
2438 }
2439
2440 strv_uniq(todo);
2441
2442 r = 0;
2443 STRV_FOREACH(i, todo) {
2444 _cleanup_strv_free_ char **fs = NULL;
2445 const char *rp;
2446 char **j;
2447
2448 (void) get_files_in_directory(*i, &fs);
2449
2450 q = rm_rf(*i, REMOVE_ROOT|REMOVE_PHYSICAL);
2451 if (q < 0 && q != -ENOENT && r >= 0) {
2452 r = q;
2453 continue;
2454 }
2455
2456 STRV_FOREACH(j, fs) {
2457 _cleanup_free_ char *t = NULL;
2458
2459 t = path_join(*i, *j);
2460 if (!t)
2461 return -ENOMEM;
2462
2463 unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, t, NULL);
2464 }
2465
2466 unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, *i, NULL);
2467
2468 rp = skip_root(&paths, *i);
2469 q = mark_symlink_for_removal(&remove_symlinks_to, rp ?: *i);
2470 if (q < 0)
2471 return q;
2472 }
2473
2474 q = remove_marked_symlinks(remove_symlinks_to, paths.runtime_config, &paths, false, changes, n_changes);
2475 if (r >= 0)
2476 r = q;
2477
2478 q = remove_marked_symlinks(remove_symlinks_to, paths.persistent_config, &paths, false, changes, n_changes);
2479 if (r >= 0)
2480 r = q;
2481
2482 return r;
2483 }
2484
2485 int unit_file_add_dependency(
2486 UnitFileScope scope,
2487 UnitFileFlags flags,
2488 const char *root_dir,
2489 char **files,
2490 const char *target,
2491 UnitDependency dep,
2492 UnitFileChange **changes,
2493 size_t *n_changes) {
2494
2495 _cleanup_(lookup_paths_free) LookupPaths paths = {};
2496 _cleanup_(install_context_done) InstallContext c = {};
2497 UnitFileInstallInfo *i, *target_info;
2498 const char *config_path;
2499 char **f;
2500 int r;
2501
2502 assert(scope >= 0);
2503 assert(scope < _UNIT_FILE_SCOPE_MAX);
2504 assert(target);
2505
2506 if (!IN_SET(dep, UNIT_WANTS, UNIT_REQUIRES))
2507 return -EINVAL;
2508
2509 if (!unit_name_is_valid(target, UNIT_NAME_ANY))
2510 return -EINVAL;
2511
2512 r = lookup_paths_init(&paths, scope, 0, root_dir);
2513 if (r < 0)
2514 return r;
2515
2516 config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config;
2517 if (!config_path)
2518 return -ENXIO;
2519
2520 r = install_info_discover_and_check(scope, &c, &paths, target, SEARCH_FOLLOW_CONFIG_SYMLINKS,
2521 &target_info, changes, n_changes);
2522 if (r < 0)
2523 return r;
2524
2525 assert(target_info->type == UNIT_FILE_TYPE_REGULAR);
2526
2527 STRV_FOREACH(f, files) {
2528 char ***l;
2529
2530 r = install_info_discover_and_check(scope, &c, &paths, *f, SEARCH_FOLLOW_CONFIG_SYMLINKS,
2531 &i, changes, n_changes);
2532 if (r < 0)
2533 return r;
2534
2535 assert(i->type == UNIT_FILE_TYPE_REGULAR);
2536
2537 /* We didn't actually load anything from the unit
2538 * file, but instead just add in our new symlink to
2539 * create. */
2540
2541 if (dep == UNIT_WANTS)
2542 l = &i->wanted_by;
2543 else
2544 l = &i->required_by;
2545
2546 strv_free(*l);
2547 *l = strv_new(target_info->name);
2548 if (!*l)
2549 return -ENOMEM;
2550 }
2551
2552 return install_context_apply(scope, &c, &paths, config_path, !!(flags & UNIT_FILE_FORCE), SEARCH_FOLLOW_CONFIG_SYMLINKS, changes, n_changes);
2553 }
2554
2555 int unit_file_enable(
2556 UnitFileScope scope,
2557 UnitFileFlags flags,
2558 const char *root_dir,
2559 char **files,
2560 UnitFileChange **changes,
2561 size_t *n_changes) {
2562
2563 _cleanup_(lookup_paths_free) LookupPaths paths = {};
2564 _cleanup_(install_context_done) InstallContext c = {};
2565 const char *config_path;
2566 UnitFileInstallInfo *i;
2567 char **f;
2568 int r;
2569
2570 assert(scope >= 0);
2571 assert(scope < _UNIT_FILE_SCOPE_MAX);
2572
2573 r = lookup_paths_init(&paths, scope, 0, root_dir);
2574 if (r < 0)
2575 return r;
2576
2577 config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config;
2578 if (!config_path)
2579 return -ENXIO;
2580
2581 STRV_FOREACH(f, files) {
2582 r = install_info_discover_and_check(scope, &c, &paths, *f, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS,
2583 &i, changes, n_changes);
2584 if (r < 0)
2585 return r;
2586
2587 assert(i->type == UNIT_FILE_TYPE_REGULAR);
2588 }
2589
2590 /* This will return the number of symlink rules that were
2591 supposed to be created, not the ones actually created. This
2592 is useful to determine whether the passed files had any
2593 installation data at all. */
2594
2595 return install_context_apply(scope, &c, &paths, config_path, !!(flags & UNIT_FILE_FORCE), SEARCH_LOAD, changes, n_changes);
2596 }
2597
2598 int unit_file_disable(
2599 UnitFileScope scope,
2600 UnitFileFlags flags,
2601 const char *root_dir,
2602 char **files,
2603 UnitFileChange **changes,
2604 size_t *n_changes) {
2605
2606 _cleanup_(lookup_paths_free) LookupPaths paths = {};
2607 _cleanup_(install_context_done) InstallContext c = {};
2608 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
2609 const char *config_path;
2610 char **i;
2611 int r;
2612
2613 assert(scope >= 0);
2614 assert(scope < _UNIT_FILE_SCOPE_MAX);
2615
2616 r = lookup_paths_init(&paths, scope, 0, root_dir);
2617 if (r < 0)
2618 return r;
2619
2620 config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config;
2621 if (!config_path)
2622 return -ENXIO;
2623
2624 STRV_FOREACH(i, files) {
2625 if (!unit_name_is_valid(*i, UNIT_NAME_ANY))
2626 return -EINVAL;
2627
2628 r = install_info_add(&c, *i, NULL, false, NULL);
2629 if (r < 0)
2630 return r;
2631 }
2632
2633 r = install_context_mark_for_removal(scope, &c, &paths, &remove_symlinks_to, config_path, changes, n_changes);
2634 if (r < 0)
2635 return r;
2636
2637 return remove_marked_symlinks(remove_symlinks_to, config_path, &paths, !!(flags & UNIT_FILE_DRY_RUN), changes, n_changes);
2638 }
2639
2640 int unit_file_reenable(
2641 UnitFileScope scope,
2642 UnitFileFlags flags,
2643 const char *root_dir,
2644 char **files,
2645 UnitFileChange **changes,
2646 size_t *n_changes) {
2647
2648 char **n;
2649 int r;
2650 size_t l, i;
2651
2652 /* First, we invoke the disable command with only the basename... */
2653 l = strv_length(files);
2654 n = newa(char*, l+1);
2655 for (i = 0; i < l; i++)
2656 n[i] = basename(files[i]);
2657 n[i] = NULL;
2658
2659 r = unit_file_disable(scope, flags, root_dir, n, changes, n_changes);
2660 if (r < 0)
2661 return r;
2662
2663 /* But the enable command with the full name */
2664 return unit_file_enable(scope, flags, root_dir, files, changes, n_changes);
2665 }
2666
2667 int unit_file_set_default(
2668 UnitFileScope scope,
2669 UnitFileFlags flags,
2670 const char *root_dir,
2671 const char *name,
2672 UnitFileChange **changes,
2673 size_t *n_changes) {
2674
2675 _cleanup_(lookup_paths_free) LookupPaths paths = {};
2676 _cleanup_(install_context_done) InstallContext c = {};
2677 UnitFileInstallInfo *i;
2678 const char *new_path;
2679 int r;
2680
2681 assert(scope >= 0);
2682 assert(scope < _UNIT_FILE_SCOPE_MAX);
2683 assert(name);
2684
2685 if (unit_name_to_type(name) != UNIT_TARGET) /* this also validates the name */
2686 return -EINVAL;
2687 if (streq(name, SPECIAL_DEFAULT_TARGET))
2688 return -EINVAL;
2689
2690 r = lookup_paths_init(&paths, scope, 0, root_dir);
2691 if (r < 0)
2692 return r;
2693
2694 r = install_info_discover_and_check(scope, &c, &paths, name, 0, &i, changes, n_changes);
2695 if (r < 0)
2696 return r;
2697
2698 new_path = strjoina(paths.persistent_config, "/" SPECIAL_DEFAULT_TARGET);
2699 return create_symlink(&paths, i->path, new_path, !!(flags & UNIT_FILE_FORCE), changes, n_changes);
2700 }
2701
2702 int unit_file_get_default(
2703 UnitFileScope scope,
2704 const char *root_dir,
2705 char **name) {
2706
2707 _cleanup_(lookup_paths_free) LookupPaths paths = {};
2708 _cleanup_(install_context_done) InstallContext c = {};
2709 UnitFileInstallInfo *i;
2710 char *n;
2711 int r;
2712
2713 assert(scope >= 0);
2714 assert(scope < _UNIT_FILE_SCOPE_MAX);
2715 assert(name);
2716
2717 r = lookup_paths_init(&paths, scope, 0, root_dir);
2718 if (r < 0)
2719 return r;
2720
2721 r = install_info_discover(scope, &c, &paths, SPECIAL_DEFAULT_TARGET, SEARCH_FOLLOW_CONFIG_SYMLINKS,
2722 &i, NULL, NULL);
2723 if (r < 0)
2724 return r;
2725 r = install_info_may_process(i, &paths, NULL, 0);
2726 if (r < 0)
2727 return r;
2728
2729 n = strdup(i->name);
2730 if (!n)
2731 return -ENOMEM;
2732
2733 *name = n;
2734 return 0;
2735 }
2736
2737 int unit_file_lookup_state(
2738 UnitFileScope scope,
2739 const LookupPaths *paths,
2740 const char *name,
2741 UnitFileState *ret) {
2742
2743 _cleanup_(install_context_done) InstallContext c = {};
2744 UnitFileInstallInfo *i;
2745 UnitFileState state;
2746 int r;
2747
2748 assert(paths);
2749 assert(name);
2750
2751 if (!unit_name_is_valid(name, UNIT_NAME_ANY))
2752 return -EINVAL;
2753
2754 r = install_info_discover(scope, &c, paths, name, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS,
2755 &i, NULL, NULL);
2756 if (r < 0)
2757 return log_debug_errno(r, "Failed to discover unit %s: %m", name);
2758
2759 assert(IN_SET(i->type, UNIT_FILE_TYPE_REGULAR, UNIT_FILE_TYPE_MASKED));
2760 log_debug("Found unit %s at %s (%s)", name, strna(i->path),
2761 i->type == UNIT_FILE_TYPE_REGULAR ? "regular file" : "mask");
2762
2763 /* Shortcut things, if the caller just wants to know if this unit exists. */
2764 if (!ret)
2765 return 0;
2766
2767 switch (i->type) {
2768
2769 case UNIT_FILE_TYPE_MASKED:
2770 r = path_is_runtime(paths, i->path, true);
2771 if (r < 0)
2772 return r;
2773
2774 state = r > 0 ? UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
2775 break;
2776
2777 case UNIT_FILE_TYPE_REGULAR:
2778 /* Check if the name we were querying is actually an alias */
2779 if (!streq(name, basename(i->path)) && !unit_name_is_valid(i->name, UNIT_NAME_INSTANCE)) {
2780 state = UNIT_FILE_ALIAS;
2781 break;
2782 }
2783
2784 r = path_is_generator(paths, i->path);
2785 if (r < 0)
2786 return r;
2787 if (r > 0) {
2788 state = UNIT_FILE_GENERATED;
2789 break;
2790 }
2791
2792 r = path_is_transient(paths, i->path);
2793 if (r < 0)
2794 return r;
2795 if (r > 0) {
2796 state = UNIT_FILE_TRANSIENT;
2797 break;
2798 }
2799
2800 /* Check if any of the Alias= symlinks have been created.
2801 * We ignore other aliases, and only check those that would
2802 * be created by systemctl enable for this unit. */
2803 r = find_symlinks_in_scope(scope, paths, i, true, &state);
2804 if (r < 0)
2805 return r;
2806 if (r > 0)
2807 break;
2808
2809 /* Check if the file is known under other names. If it is,
2810 * it might be in use. Report that as UNIT_FILE_INDIRECT. */
2811 r = find_symlinks_in_scope(scope, paths, i, false, &state);
2812 if (r < 0)
2813 return r;
2814 if (r > 0)
2815 state = UNIT_FILE_INDIRECT;
2816 else {
2817 if (unit_file_install_info_has_rules(i))
2818 state = UNIT_FILE_DISABLED;
2819 else if (unit_file_install_info_has_also(i))
2820 state = UNIT_FILE_INDIRECT;
2821 else
2822 state = UNIT_FILE_STATIC;
2823 }
2824
2825 break;
2826
2827 default:
2828 assert_not_reached("Unexpected unit file type.");
2829 }
2830
2831 *ret = state;
2832 return 0;
2833 }
2834
2835 int unit_file_get_state(
2836 UnitFileScope scope,
2837 const char *root_dir,
2838 const char *name,
2839 UnitFileState *ret) {
2840
2841 _cleanup_(lookup_paths_free) LookupPaths paths = {};
2842 int r;
2843
2844 assert(scope >= 0);
2845 assert(scope < _UNIT_FILE_SCOPE_MAX);
2846 assert(name);
2847
2848 r = lookup_paths_init(&paths, scope, 0, root_dir);
2849 if (r < 0)
2850 return r;
2851
2852 return unit_file_lookup_state(scope, &paths, name, ret);
2853 }
2854
2855 int unit_file_exists(UnitFileScope scope, const LookupPaths *paths, const char *name) {
2856 _cleanup_(install_context_done) InstallContext c = {};
2857 int r;
2858
2859 assert(paths);
2860 assert(name);
2861
2862 if (!unit_name_is_valid(name, UNIT_NAME_ANY))
2863 return -EINVAL;
2864
2865 r = install_info_discover(scope, &c, paths, name, 0, NULL, NULL, NULL);
2866 if (r == -ENOENT)
2867 return 0;
2868 if (r < 0)
2869 return r;
2870
2871 return 1;
2872 }
2873
2874 static int split_pattern_into_name_and_instances(const char *pattern, char **out_unit_name, char ***out_instances) {
2875 _cleanup_strv_free_ char **instances = NULL;
2876 _cleanup_free_ char *unit_name = NULL;
2877 int r;
2878
2879 assert(pattern);
2880 assert(out_instances);
2881 assert(out_unit_name);
2882
2883 r = extract_first_word(&pattern, &unit_name, NULL, EXTRACT_RETAIN_ESCAPE);
2884 if (r < 0)
2885 return r;
2886
2887 /* We handle the instances logic when unit name is extracted */
2888 if (pattern) {
2889 /* We only create instances when a rule of templated unit
2890 * is seen. A rule like enable foo@.service a b c will
2891 * result in an array of (a, b, c) as instance names */
2892 if (!unit_name_is_valid(unit_name, UNIT_NAME_TEMPLATE))
2893 return -EINVAL;
2894
2895 instances = strv_split(pattern, WHITESPACE);
2896 if (!instances)
2897 return -ENOMEM;
2898
2899 *out_instances = TAKE_PTR(instances);
2900 }
2901
2902 *out_unit_name = TAKE_PTR(unit_name);
2903
2904 return 0;
2905 }
2906
2907 static int presets_find_config(UnitFileScope scope, const char *root_dir, char ***files) {
2908 static const char* const system_dirs[] = {CONF_PATHS("systemd/system-preset"), NULL};
2909 static const char* const user_dirs[] = {CONF_PATHS_USR("systemd/user-preset"), NULL};
2910 const char* const* dirs;
2911
2912 assert(scope >= 0);
2913 assert(scope < _UNIT_FILE_SCOPE_MAX);
2914
2915 if (scope == UNIT_FILE_SYSTEM)
2916 dirs = system_dirs;
2917 else if (IN_SET(scope, UNIT_FILE_GLOBAL, UNIT_FILE_USER))
2918 dirs = user_dirs;
2919 else
2920 assert_not_reached("Invalid unit file scope");
2921
2922 return conf_files_list_strv(files, ".preset", root_dir, 0, dirs);
2923 }
2924
2925 static int read_presets(UnitFileScope scope, const char *root_dir, UnitFilePresets *presets) {
2926 _cleanup_(unit_file_presets_freep) UnitFilePresets ps = {};
2927 size_t n_allocated = 0;
2928 _cleanup_strv_free_ char **files = NULL;
2929 char **p;
2930 int r;
2931
2932 assert(scope >= 0);
2933 assert(scope < _UNIT_FILE_SCOPE_MAX);
2934 assert(presets);
2935
2936 r = presets_find_config(scope, root_dir, &files);
2937 if (r < 0)
2938 return r;
2939
2940 STRV_FOREACH(p, files) {
2941 _cleanup_fclose_ FILE *f;
2942 int n = 0;
2943
2944 f = fopen(*p, "re");
2945 if (!f) {
2946 if (errno == ENOENT)
2947 continue;
2948
2949 return -errno;
2950 }
2951
2952 for (;;) {
2953 _cleanup_free_ char *line = NULL;
2954 UnitFilePresetRule rule = {};
2955 const char *parameter;
2956 char *l;
2957
2958 r = read_line(f, LONG_LINE_MAX, &line);
2959 if (r < 0)
2960 return r;
2961 if (r == 0)
2962 break;
2963
2964 l = strstrip(line);
2965 n++;
2966
2967 if (isempty(l))
2968 continue;
2969 if (strchr(COMMENTS, *l))
2970 continue;
2971
2972 parameter = first_word(l, "enable");
2973 if (parameter) {
2974 char *unit_name;
2975 char **instances = NULL;
2976
2977 /* Unit_name will remain the same as parameter when no instances are specified */
2978 r = split_pattern_into_name_and_instances(parameter, &unit_name, &instances);
2979 if (r < 0) {
2980 log_syntax(NULL, LOG_WARNING, *p, n, r, "Couldn't parse line '%s'. Ignoring.", line);
2981 continue;
2982 }
2983
2984 rule = (UnitFilePresetRule) {
2985 .pattern = unit_name,
2986 .action = PRESET_ENABLE,
2987 .instances = instances,
2988 };
2989 }
2990
2991 parameter = first_word(l, "disable");
2992 if (parameter) {
2993 char *pattern;
2994
2995 pattern = strdup(parameter);
2996 if (!pattern)
2997 return -ENOMEM;
2998
2999 rule = (UnitFilePresetRule) {
3000 .pattern = pattern,
3001 .action = PRESET_DISABLE,
3002 };
3003 }
3004
3005 if (rule.action) {
3006 if (!GREEDY_REALLOC(ps.rules, n_allocated, ps.n_rules + 1))
3007 return -ENOMEM;
3008
3009 ps.rules[ps.n_rules++] = rule;
3010 continue;
3011 }
3012
3013 log_syntax(NULL, LOG_WARNING, *p, n, 0, "Couldn't parse line '%s'. Ignoring.", line);
3014 }
3015 }
3016
3017 ps.initialized = true;
3018 *presets = ps;
3019 ps = (UnitFilePresets){};
3020
3021 return 0;
3022 }
3023
3024 static int pattern_match_multiple_instances(
3025 const UnitFilePresetRule rule,
3026 const char *unit_name,
3027 char ***ret) {
3028
3029 _cleanup_free_ char *templated_name = NULL;
3030 int r;
3031
3032 /* If no ret is needed or the rule itself does not have instances
3033 * initialized, we return not matching */
3034 if (!ret || !rule.instances)
3035 return 0;
3036
3037 r = unit_name_template(unit_name, &templated_name);
3038 if (r < 0)
3039 return r;
3040 if (!streq(rule.pattern, templated_name))
3041 return 0;
3042
3043 /* Compose a list of specified instances when unit name is a template */
3044 if (unit_name_is_valid(unit_name, UNIT_NAME_TEMPLATE)) {
3045 _cleanup_free_ char *prefix = NULL;
3046 _cleanup_strv_free_ char **out_strv = NULL;
3047 char **iter;
3048
3049 r = unit_name_to_prefix(unit_name, &prefix);
3050 if (r < 0)
3051 return r;
3052
3053 STRV_FOREACH(iter, rule.instances) {
3054 _cleanup_free_ char *name = NULL;
3055 r = unit_name_build(prefix, *iter, ".service", &name);
3056 if (r < 0)
3057 return r;
3058 r = strv_extend(&out_strv, name);
3059 if (r < 0)
3060 return r;
3061 }
3062
3063 *ret = TAKE_PTR(out_strv);
3064 return 1;
3065 } else {
3066 /* We now know the input unit name is an instance name */
3067 _cleanup_free_ char *instance_name = NULL;
3068
3069 r = unit_name_to_instance(unit_name, &instance_name);
3070 if (r < 0)
3071 return r;
3072
3073 if (strv_find(rule.instances, instance_name))
3074 return 1;
3075 }
3076 return 0;
3077 }
3078
3079 static int query_presets(const char *name, const UnitFilePresets *presets, char ***instance_name_list) {
3080 PresetAction action = PRESET_UNKNOWN;
3081 size_t i;
3082 char **s;
3083 if (!unit_name_is_valid(name, UNIT_NAME_ANY))
3084 return -EINVAL;
3085
3086 for (i = 0; i < presets->n_rules; i++)
3087 if (pattern_match_multiple_instances(presets->rules[i], name, instance_name_list) > 0 ||
3088 fnmatch(presets->rules[i].pattern, name, FNM_NOESCAPE) == 0) {
3089 action = presets->rules[i].action;
3090 break;
3091 }
3092
3093 switch (action) {
3094 case PRESET_UNKNOWN:
3095 log_debug("Preset files don't specify rule for %s. Enabling.", name);
3096 return 1;
3097 case PRESET_ENABLE:
3098 if (instance_name_list && *instance_name_list)
3099 STRV_FOREACH(s, *instance_name_list)
3100 log_debug("Preset files say enable %s.", *s);
3101 else
3102 log_debug("Preset files say enable %s.", name);
3103 return 1;
3104 case PRESET_DISABLE:
3105 log_debug("Preset files say disable %s.", name);
3106 return 0;
3107 default:
3108 assert_not_reached("invalid preset action");
3109 }
3110 }
3111
3112 int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name, UnitFilePresets *cached) {
3113 _cleanup_(unit_file_presets_freep) UnitFilePresets tmp = {};
3114 int r;
3115
3116 if (!cached)
3117 cached = &tmp;
3118 if (!cached->initialized) {
3119 r = read_presets(scope, root_dir, cached);
3120 if (r < 0)
3121 return r;
3122 }
3123
3124 return query_presets(name, cached, NULL);
3125 }
3126
3127 static int execute_preset(
3128 UnitFileScope scope,
3129 InstallContext *plus,
3130 InstallContext *minus,
3131 const LookupPaths *paths,
3132 const char *config_path,
3133 char **files,
3134 UnitFilePresetMode mode,
3135 bool force,
3136 UnitFileChange **changes,
3137 size_t *n_changes) {
3138
3139 int r;
3140
3141 assert(plus);
3142 assert(minus);
3143 assert(paths);
3144 assert(config_path);
3145
3146 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
3147 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
3148
3149 r = install_context_mark_for_removal(scope, minus, paths, &remove_symlinks_to, config_path, changes, n_changes);
3150 if (r < 0)
3151 return r;
3152
3153 r = remove_marked_symlinks(remove_symlinks_to, config_path, paths, false, changes, n_changes);
3154 } else
3155 r = 0;
3156
3157 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
3158 int q;
3159
3160 /* Returns number of symlinks that where supposed to be installed. */
3161 q = install_context_apply(scope, plus, paths, config_path, force, SEARCH_LOAD, changes, n_changes);
3162 if (r >= 0) {
3163 if (q < 0)
3164 r = q;
3165 else
3166 r += q;
3167 }
3168 }
3169
3170 return r;
3171 }
3172
3173 static int preset_prepare_one(
3174 UnitFileScope scope,
3175 InstallContext *plus,
3176 InstallContext *minus,
3177 LookupPaths *paths,
3178 const char *name,
3179 const UnitFilePresets *presets,
3180 UnitFileChange **changes,
3181 size_t *n_changes) {
3182
3183 _cleanup_(install_context_done) InstallContext tmp = {};
3184 _cleanup_strv_free_ char **instance_name_list = NULL;
3185 UnitFileInstallInfo *i;
3186 int r;
3187
3188 if (install_info_find(plus, name) || install_info_find(minus, name))
3189 return 0;
3190
3191 r = install_info_discover(scope, &tmp, paths, name, SEARCH_FOLLOW_CONFIG_SYMLINKS,
3192 &i, changes, n_changes);
3193 if (r < 0)
3194 return r;
3195 if (!streq(name, i->name)) {
3196 log_debug("Skipping %s because it is an alias for %s.", name, i->name);
3197 return 0;
3198 }
3199
3200 r = query_presets(name, presets, &instance_name_list);
3201 if (r < 0)
3202 return r;
3203
3204 if (r > 0) {
3205 if (instance_name_list) {
3206 char **s;
3207 STRV_FOREACH(s, instance_name_list) {
3208 r = install_info_discover_and_check(scope, plus, paths, *s, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS,
3209 &i, changes, n_changes);
3210 if (r < 0)
3211 return r;
3212 }
3213 } else {
3214 r = install_info_discover_and_check(scope, plus, paths, name, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS,
3215 &i, changes, n_changes);
3216 if (r < 0)
3217 return r;
3218 }
3219
3220 } else
3221 r = install_info_discover(scope, minus, paths, name, SEARCH_FOLLOW_CONFIG_SYMLINKS,
3222 &i, changes, n_changes);
3223
3224 return r;
3225 }
3226
3227 int unit_file_preset(
3228 UnitFileScope scope,
3229 UnitFileFlags flags,
3230 const char *root_dir,
3231 char **files,
3232 UnitFilePresetMode mode,
3233 UnitFileChange **changes,
3234 size_t *n_changes) {
3235
3236 _cleanup_(install_context_done) InstallContext plus = {}, minus = {};
3237 _cleanup_(lookup_paths_free) LookupPaths paths = {};
3238 _cleanup_(unit_file_presets_freep) UnitFilePresets presets = {};
3239 const char *config_path;
3240 char **i;
3241 int r;
3242
3243 assert(scope >= 0);
3244 assert(scope < _UNIT_FILE_SCOPE_MAX);
3245 assert(mode < _UNIT_FILE_PRESET_MAX);
3246
3247 r = lookup_paths_init(&paths, scope, 0, root_dir);
3248 if (r < 0)
3249 return r;
3250
3251 config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config;
3252 if (!config_path)
3253 return -ENXIO;
3254
3255 r = read_presets(scope, root_dir, &presets);
3256 if (r < 0)
3257 return r;
3258
3259 STRV_FOREACH(i, files) {
3260 r = preset_prepare_one(scope, &plus, &minus, &paths, *i, &presets, changes, n_changes);
3261 if (r < 0)
3262 return r;
3263 }
3264
3265 return execute_preset(scope, &plus, &minus, &paths, config_path, files, mode, !!(flags & UNIT_FILE_FORCE), changes, n_changes);
3266 }
3267
3268 int unit_file_preset_all(
3269 UnitFileScope scope,
3270 UnitFileFlags flags,
3271 const char *root_dir,
3272 UnitFilePresetMode mode,
3273 UnitFileChange **changes,
3274 size_t *n_changes) {
3275
3276 _cleanup_(install_context_done) InstallContext plus = {}, minus = {};
3277 _cleanup_(lookup_paths_free) LookupPaths paths = {};
3278 _cleanup_(unit_file_presets_freep) UnitFilePresets presets = {};
3279 const char *config_path = NULL;
3280 char **i;
3281 int r;
3282
3283 assert(scope >= 0);
3284 assert(scope < _UNIT_FILE_SCOPE_MAX);
3285 assert(mode < _UNIT_FILE_PRESET_MAX);
3286
3287 r = lookup_paths_init(&paths, scope, 0, root_dir);
3288 if (r < 0)
3289 return r;
3290
3291 config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config;
3292 if (!config_path)
3293 return -ENXIO;
3294
3295 r = read_presets(scope, root_dir, &presets);
3296 if (r < 0)
3297 return r;
3298
3299 STRV_FOREACH(i, paths.search_path) {
3300 _cleanup_closedir_ DIR *d = NULL;
3301 struct dirent *de;
3302
3303 d = opendir(*i);
3304 if (!d) {
3305 if (errno == ENOENT)
3306 continue;
3307
3308 return -errno;
3309 }
3310
3311 FOREACH_DIRENT(de, d, return -errno) {
3312
3313 if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
3314 continue;
3315
3316 dirent_ensure_type(d, de);
3317
3318 if (!IN_SET(de->d_type, DT_LNK, DT_REG))
3319 continue;
3320
3321 /* we don't pass changes[] in, because we want to handle errors on our own */
3322 r = preset_prepare_one(scope, &plus, &minus, &paths, de->d_name, &presets, NULL, 0);
3323 if (r == -ERFKILL)
3324 r = unit_file_changes_add(changes, n_changes,
3325 UNIT_FILE_IS_MASKED, de->d_name, NULL);
3326 else if (r == -ENOLINK)
3327 r = unit_file_changes_add(changes, n_changes,
3328 UNIT_FILE_IS_DANGLING, de->d_name, NULL);
3329 else if (r == -EADDRNOTAVAIL) /* Ignore generated/transient units when applying preset */
3330 continue;
3331 if (r < 0)
3332 return r;
3333 }
3334 }
3335
3336 return execute_preset(scope, &plus, &minus, &paths, config_path, NULL, mode, !!(flags & UNIT_FILE_FORCE), changes, n_changes);
3337 }
3338
3339 static void unit_file_list_free_one(UnitFileList *f) {
3340 if (!f)
3341 return;
3342
3343 free(f->path);
3344 free(f);
3345 }
3346
3347 Hashmap* unit_file_list_free(Hashmap *h) {
3348 return hashmap_free_with_destructor(h, unit_file_list_free_one);
3349 }
3350
3351 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitFileList*, unit_file_list_free_one);
3352
3353 int unit_file_get_list(
3354 UnitFileScope scope,
3355 const char *root_dir,
3356 Hashmap *h,
3357 char **states,
3358 char **patterns) {
3359
3360 _cleanup_(lookup_paths_free) LookupPaths paths = {};
3361 char **dirname;
3362 int r;
3363
3364 assert(scope >= 0);
3365 assert(scope < _UNIT_FILE_SCOPE_MAX);
3366 assert(h);
3367
3368 r = lookup_paths_init(&paths, scope, 0, root_dir);
3369 if (r < 0)
3370 return r;
3371
3372 STRV_FOREACH(dirname, paths.search_path) {
3373 _cleanup_closedir_ DIR *d = NULL;
3374 struct dirent *de;
3375
3376 d = opendir(*dirname);
3377 if (!d) {
3378 if (errno == ENOENT)
3379 continue;
3380 if (IN_SET(errno, ENOTDIR, EACCES)) {
3381 log_debug_errno(errno, "Failed to open \"%s\": %m", *dirname);
3382 continue;
3383 }
3384
3385 return -errno;
3386 }
3387
3388 FOREACH_DIRENT(de, d, return -errno) {
3389 _cleanup_(unit_file_list_free_onep) UnitFileList *f = NULL;
3390
3391 if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
3392 continue;
3393
3394 if (!strv_fnmatch_or_empty(patterns, de->d_name, FNM_NOESCAPE))
3395 continue;
3396
3397 if (hashmap_get(h, de->d_name))
3398 continue;
3399
3400 dirent_ensure_type(d, de);
3401
3402 if (!IN_SET(de->d_type, DT_LNK, DT_REG))
3403 continue;
3404
3405 f = new0(UnitFileList, 1);
3406 if (!f)
3407 return -ENOMEM;
3408
3409 f->path = path_make_absolute(de->d_name, *dirname);
3410 if (!f->path)
3411 return -ENOMEM;
3412
3413 r = unit_file_lookup_state(scope, &paths, de->d_name, &f->state);
3414 if (r < 0)
3415 f->state = UNIT_FILE_BAD;
3416
3417 if (!strv_isempty(states) &&
3418 !strv_contains(states, unit_file_state_to_string(f->state)))
3419 continue;
3420
3421 r = hashmap_put(h, basename(f->path), f);
3422 if (r < 0)
3423 return r;
3424
3425 f = NULL; /* prevent cleanup */
3426 }
3427 }
3428
3429 return 0;
3430 }
3431
3432 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
3433 [UNIT_FILE_ENABLED] = "enabled",
3434 [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
3435 [UNIT_FILE_LINKED] = "linked",
3436 [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
3437 [UNIT_FILE_ALIAS] = "alias",
3438 [UNIT_FILE_MASKED] = "masked",
3439 [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
3440 [UNIT_FILE_STATIC] = "static",
3441 [UNIT_FILE_DISABLED] = "disabled",
3442 [UNIT_FILE_INDIRECT] = "indirect",
3443 [UNIT_FILE_GENERATED] = "generated",
3444 [UNIT_FILE_TRANSIENT] = "transient",
3445 [UNIT_FILE_BAD] = "bad",
3446 };
3447
3448 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
3449
3450 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
3451 [UNIT_FILE_SYMLINK] = "symlink",
3452 [UNIT_FILE_UNLINK] = "unlink",
3453 [UNIT_FILE_IS_MASKED] = "masked",
3454 [UNIT_FILE_IS_DANGLING] = "dangling",
3455 };
3456
3457 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);
3458
3459 static const char* const unit_file_preset_mode_table[_UNIT_FILE_PRESET_MAX] = {
3460 [UNIT_FILE_PRESET_FULL] = "full",
3461 [UNIT_FILE_PRESET_ENABLE_ONLY] = "enable-only",
3462 [UNIT_FILE_PRESET_DISABLE_ONLY] = "disable-only",
3463 };
3464
3465 DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode, UnitFilePresetMode);