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