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