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