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