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