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