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