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