]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/install.c
codespell: fix spelling errors
[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 *const 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 * effectively 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, EXTRACT_RETAIN_ESCAPE);
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 static const char* const system_dirs[] = {CONF_PATHS("systemd/system-preset"), NULL};
2826 static const char* const user_dirs[] = {CONF_PATHS_USR("systemd/user-preset"), NULL};
2827 const char* const* dirs;
2828
2829 assert(scope >= 0);
2830 assert(scope < _UNIT_FILE_SCOPE_MAX);
2831
2832 if (scope == UNIT_FILE_SYSTEM)
2833 dirs = system_dirs;
2834 else if (IN_SET(scope, UNIT_FILE_GLOBAL, UNIT_FILE_USER))
2835 dirs = user_dirs;
2836 else
2837 assert_not_reached("Invalid unit file scope");
2838
2839 return conf_files_list_strv(files, ".preset", root_dir, 0, dirs);
2840 }
2841
2842 static int read_presets(UnitFileScope scope, const char *root_dir, Presets *presets) {
2843 _cleanup_(presets_freep) Presets ps = {};
2844 size_t n_allocated = 0;
2845 _cleanup_strv_free_ char **files = NULL;
2846 char **p;
2847 int r;
2848
2849 assert(scope >= 0);
2850 assert(scope < _UNIT_FILE_SCOPE_MAX);
2851 assert(presets);
2852
2853 r = presets_find_config(scope, root_dir, &files);
2854 if (r < 0)
2855 return r;
2856
2857 STRV_FOREACH(p, files) {
2858 _cleanup_fclose_ FILE *f;
2859 int n = 0;
2860
2861 f = fopen(*p, "re");
2862 if (!f) {
2863 if (errno == ENOENT)
2864 continue;
2865
2866 return -errno;
2867 }
2868
2869 for (;;) {
2870 _cleanup_free_ char *line = NULL;
2871 PresetRule rule = {};
2872 const char *parameter;
2873 char *l;
2874
2875 r = read_line(f, LONG_LINE_MAX, &line);
2876 if (r < 0)
2877 return r;
2878 if (r == 0)
2879 break;
2880
2881 l = strstrip(line);
2882 n++;
2883
2884 if (isempty(l))
2885 continue;
2886 if (strchr(COMMENTS, *l))
2887 continue;
2888
2889 parameter = first_word(l, "enable");
2890 if (parameter) {
2891 char *unit_name;
2892 char **instances = NULL;
2893
2894 /* Unit_name will remain the same as parameter when no instances are specified */
2895 r = split_pattern_into_name_and_instances(parameter, &unit_name, &instances);
2896 if (r < 0) {
2897 log_syntax(NULL, LOG_WARNING, *p, n, r, "Couldn't parse line '%s'. Ignoring.", line);
2898 continue;
2899 }
2900
2901 rule = (PresetRule) {
2902 .pattern = unit_name,
2903 .action = PRESET_ENABLE,
2904 .instances = instances,
2905 };
2906 }
2907
2908 parameter = first_word(l, "disable");
2909 if (parameter) {
2910 char *pattern;
2911
2912 pattern = strdup(parameter);
2913 if (!pattern)
2914 return -ENOMEM;
2915
2916 rule = (PresetRule) {
2917 .pattern = pattern,
2918 .action = PRESET_DISABLE,
2919 };
2920 }
2921
2922 if (rule.action) {
2923 if (!GREEDY_REALLOC(ps.rules, n_allocated, ps.n_rules + 1))
2924 return -ENOMEM;
2925
2926 ps.rules[ps.n_rules++] = rule;
2927 continue;
2928 }
2929
2930 log_syntax(NULL, LOG_WARNING, *p, n, 0, "Couldn't parse line '%s'. Ignoring.", line);
2931 }
2932 }
2933
2934 *presets = ps;
2935 ps = (Presets){};
2936
2937 return 0;
2938 }
2939
2940 static int pattern_match_multiple_instances(
2941 const PresetRule rule,
2942 const char *unit_name,
2943 char ***ret) {
2944
2945 _cleanup_free_ char *templated_name = NULL;
2946 int r;
2947
2948 /* If no ret is needed or the rule itself does not have instances
2949 * initialized, we return not matching */
2950 if (!ret || !rule.instances)
2951 return 0;
2952
2953 r = unit_name_template(unit_name, &templated_name);
2954 if (r < 0)
2955 return r;
2956 if (!streq(rule.pattern, templated_name))
2957 return 0;
2958
2959 /* Compose a list of specified instances when unit name is a template */
2960 if (unit_name_is_valid(unit_name, UNIT_NAME_TEMPLATE)) {
2961 _cleanup_free_ char *prefix = NULL;
2962 _cleanup_strv_free_ char **out_strv = NULL;
2963 char **iter;
2964
2965 r = unit_name_to_prefix(unit_name, &prefix);
2966 if (r < 0)
2967 return r;
2968
2969 STRV_FOREACH(iter, rule.instances) {
2970 _cleanup_free_ char *name = NULL;
2971 r = unit_name_build(prefix, *iter, ".service", &name);
2972 if (r < 0)
2973 return r;
2974 r = strv_extend(&out_strv, name);
2975 if (r < 0)
2976 return r;
2977 }
2978
2979 *ret = TAKE_PTR(out_strv);
2980 return 1;
2981 } else {
2982 /* We now know the input unit name is an instance name */
2983 _cleanup_free_ char *instance_name = NULL;
2984
2985 r = unit_name_to_instance(unit_name, &instance_name);
2986 if (r < 0)
2987 return r;
2988
2989 if (strv_find(rule.instances, instance_name))
2990 return 1;
2991 }
2992 return 0;
2993 }
2994
2995 static int query_presets(const char *name, const Presets presets, char ***instance_name_list) {
2996 PresetAction action = PRESET_UNKNOWN;
2997 size_t i;
2998 char **s;
2999 if (!unit_name_is_valid(name, UNIT_NAME_ANY))
3000 return -EINVAL;
3001
3002 for (i = 0; i < presets.n_rules; i++)
3003 if (pattern_match_multiple_instances(presets.rules[i], name, instance_name_list) > 0 ||
3004 fnmatch(presets.rules[i].pattern, name, FNM_NOESCAPE) == 0) {
3005 action = presets.rules[i].action;
3006 break;
3007 }
3008
3009 switch (action) {
3010 case PRESET_UNKNOWN:
3011 log_debug("Preset files don't specify rule for %s. Enabling.", name);
3012 return 1;
3013 case PRESET_ENABLE:
3014 if (instance_name_list && *instance_name_list)
3015 STRV_FOREACH(s, *instance_name_list)
3016 log_debug("Preset files say enable %s.", *s);
3017 else
3018 log_debug("Preset files say enable %s.", name);
3019 return 1;
3020 case PRESET_DISABLE:
3021 log_debug("Preset files say disable %s.", name);
3022 return 0;
3023 default:
3024 assert_not_reached("invalid preset action");
3025 }
3026 }
3027
3028 int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name) {
3029 _cleanup_(presets_freep) Presets presets = {};
3030 int r;
3031
3032 r = read_presets(scope, root_dir, &presets);
3033 if (r < 0)
3034 return r;
3035
3036 return query_presets(name, presets, NULL);
3037 }
3038
3039 static int execute_preset(
3040 UnitFileScope scope,
3041 InstallContext *plus,
3042 InstallContext *minus,
3043 const LookupPaths *paths,
3044 const char *config_path,
3045 char **files,
3046 UnitFilePresetMode mode,
3047 bool force,
3048 UnitFileChange **changes,
3049 size_t *n_changes) {
3050
3051 int r;
3052
3053 assert(plus);
3054 assert(minus);
3055 assert(paths);
3056 assert(config_path);
3057
3058 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
3059 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
3060
3061 r = install_context_mark_for_removal(scope, minus, paths, &remove_symlinks_to, config_path, changes, n_changes);
3062 if (r < 0)
3063 return r;
3064
3065 r = remove_marked_symlinks(remove_symlinks_to, config_path, paths, false, changes, n_changes);
3066 } else
3067 r = 0;
3068
3069 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
3070 int q;
3071
3072 /* Returns number of symlinks that where supposed to be installed. */
3073 q = install_context_apply(scope, plus, paths, config_path, force, SEARCH_LOAD, changes, n_changes);
3074 if (r >= 0) {
3075 if (q < 0)
3076 r = q;
3077 else
3078 r += q;
3079 }
3080 }
3081
3082 return r;
3083 }
3084
3085 static int preset_prepare_one(
3086 UnitFileScope scope,
3087 InstallContext *plus,
3088 InstallContext *minus,
3089 LookupPaths *paths,
3090 const char *name,
3091 Presets presets,
3092 UnitFileChange **changes,
3093 size_t *n_changes) {
3094
3095 _cleanup_(install_context_done) InstallContext tmp = {};
3096 _cleanup_strv_free_ char **instance_name_list = NULL;
3097 UnitFileInstallInfo *i;
3098 int r;
3099
3100 if (install_info_find(plus, name) || install_info_find(minus, name))
3101 return 0;
3102
3103 r = install_info_discover(scope, &tmp, paths, name, SEARCH_FOLLOW_CONFIG_SYMLINKS,
3104 &i, changes, n_changes);
3105 if (r < 0)
3106 return r;
3107 if (!streq(name, i->name)) {
3108 log_debug("Skipping %s because it is an alias for %s.", name, i->name);
3109 return 0;
3110 }
3111
3112 r = query_presets(name, presets, &instance_name_list);
3113 if (r < 0)
3114 return r;
3115
3116 if (r > 0) {
3117 if (instance_name_list) {
3118 char **s;
3119 STRV_FOREACH(s, instance_name_list) {
3120 r = install_info_discover_and_check(scope, plus, paths, *s, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS,
3121 &i, changes, n_changes);
3122 if (r < 0)
3123 return r;
3124 }
3125 } else {
3126 r = install_info_discover_and_check(scope, plus, paths, name, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS,
3127 &i, changes, n_changes);
3128 if (r < 0)
3129 return r;
3130 }
3131
3132 } else
3133 r = install_info_discover(scope, minus, paths, name, SEARCH_FOLLOW_CONFIG_SYMLINKS,
3134 &i, changes, n_changes);
3135
3136 return r;
3137 }
3138
3139 int unit_file_preset(
3140 UnitFileScope scope,
3141 UnitFileFlags flags,
3142 const char *root_dir,
3143 char **files,
3144 UnitFilePresetMode mode,
3145 UnitFileChange **changes,
3146 size_t *n_changes) {
3147
3148 _cleanup_(install_context_done) InstallContext plus = {}, minus = {};
3149 _cleanup_(lookup_paths_free) LookupPaths paths = {};
3150 _cleanup_(presets_freep) Presets presets = {};
3151 const char *config_path;
3152 char **i;
3153 int r;
3154
3155 assert(scope >= 0);
3156 assert(scope < _UNIT_FILE_SCOPE_MAX);
3157 assert(mode < _UNIT_FILE_PRESET_MAX);
3158
3159 r = lookup_paths_init(&paths, scope, 0, root_dir);
3160 if (r < 0)
3161 return r;
3162
3163 config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config;
3164 if (!config_path)
3165 return -ENXIO;
3166
3167 r = read_presets(scope, root_dir, &presets);
3168 if (r < 0)
3169 return r;
3170
3171 STRV_FOREACH(i, files) {
3172 r = preset_prepare_one(scope, &plus, &minus, &paths, *i, presets, changes, n_changes);
3173 if (r < 0)
3174 return r;
3175 }
3176
3177 return execute_preset(scope, &plus, &minus, &paths, config_path, files, mode, !!(flags & UNIT_FILE_FORCE), changes, n_changes);
3178 }
3179
3180 int unit_file_preset_all(
3181 UnitFileScope scope,
3182 UnitFileFlags flags,
3183 const char *root_dir,
3184 UnitFilePresetMode mode,
3185 UnitFileChange **changes,
3186 size_t *n_changes) {
3187
3188 _cleanup_(install_context_done) InstallContext plus = {}, minus = {};
3189 _cleanup_(lookup_paths_free) LookupPaths paths = {};
3190 _cleanup_(presets_freep) Presets presets = {};
3191 const char *config_path = NULL;
3192 char **i;
3193 int r;
3194
3195 assert(scope >= 0);
3196 assert(scope < _UNIT_FILE_SCOPE_MAX);
3197 assert(mode < _UNIT_FILE_PRESET_MAX);
3198
3199 r = lookup_paths_init(&paths, scope, 0, root_dir);
3200 if (r < 0)
3201 return r;
3202
3203 config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config;
3204 if (!config_path)
3205 return -ENXIO;
3206
3207 r = read_presets(scope, root_dir, &presets);
3208 if (r < 0)
3209 return r;
3210
3211 STRV_FOREACH(i, paths.search_path) {
3212 _cleanup_closedir_ DIR *d = NULL;
3213 struct dirent *de;
3214
3215 d = opendir(*i);
3216 if (!d) {
3217 if (errno == ENOENT)
3218 continue;
3219
3220 return -errno;
3221 }
3222
3223 FOREACH_DIRENT(de, d, return -errno) {
3224
3225 if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
3226 continue;
3227
3228 dirent_ensure_type(d, de);
3229
3230 if (!IN_SET(de->d_type, DT_LNK, DT_REG))
3231 continue;
3232
3233 /* we don't pass changes[] in, because we want to handle errors on our own */
3234 r = preset_prepare_one(scope, &plus, &minus, &paths, de->d_name, presets, NULL, 0);
3235 if (r == -ERFKILL)
3236 r = unit_file_changes_add(changes, n_changes,
3237 UNIT_FILE_IS_MASKED, de->d_name, NULL);
3238 else if (r == -ENOLINK)
3239 r = unit_file_changes_add(changes, n_changes,
3240 UNIT_FILE_IS_DANGLING, de->d_name, NULL);
3241 else if (r == -EADDRNOTAVAIL) /* Ignore generated/transient units when applying preset */
3242 continue;
3243 if (r < 0)
3244 return r;
3245 }
3246 }
3247
3248 return execute_preset(scope, &plus, &minus, &paths, config_path, NULL, mode, !!(flags & UNIT_FILE_FORCE), changes, n_changes);
3249 }
3250
3251 static void unit_file_list_free_one(UnitFileList *f) {
3252 if (!f)
3253 return;
3254
3255 free(f->path);
3256 free(f);
3257 }
3258
3259 Hashmap* unit_file_list_free(Hashmap *h) {
3260 return hashmap_free_with_destructor(h, unit_file_list_free_one);
3261 }
3262
3263 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitFileList*, unit_file_list_free_one);
3264
3265 int unit_file_get_list(
3266 UnitFileScope scope,
3267 const char *root_dir,
3268 Hashmap *h,
3269 char **states,
3270 char **patterns) {
3271
3272 _cleanup_(lookup_paths_free) LookupPaths paths = {};
3273 char **i;
3274 int r;
3275
3276 assert(scope >= 0);
3277 assert(scope < _UNIT_FILE_SCOPE_MAX);
3278 assert(h);
3279
3280 r = lookup_paths_init(&paths, scope, 0, root_dir);
3281 if (r < 0)
3282 return r;
3283
3284 STRV_FOREACH(i, paths.search_path) {
3285 _cleanup_closedir_ DIR *d = NULL;
3286 struct dirent *de;
3287
3288 d = opendir(*i);
3289 if (!d) {
3290 if (errno == ENOENT)
3291 continue;
3292 if (IN_SET(errno, ENOTDIR, EACCES)) {
3293 log_debug_errno(errno, "Failed to open \"%s\": %m", *i);
3294 continue;
3295 }
3296
3297 return -errno;
3298 }
3299
3300 FOREACH_DIRENT(de, d, return -errno) {
3301 _cleanup_(unit_file_list_free_onep) UnitFileList *f = NULL;
3302
3303 if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
3304 continue;
3305
3306 if (!strv_fnmatch_or_empty(patterns, de->d_name, FNM_NOESCAPE))
3307 continue;
3308
3309 if (hashmap_get(h, de->d_name))
3310 continue;
3311
3312 dirent_ensure_type(d, de);
3313
3314 if (!IN_SET(de->d_type, DT_LNK, DT_REG))
3315 continue;
3316
3317 f = new0(UnitFileList, 1);
3318 if (!f)
3319 return -ENOMEM;
3320
3321 f->path = path_make_absolute(de->d_name, *i);
3322 if (!f->path)
3323 return -ENOMEM;
3324
3325 r = unit_file_lookup_state(scope, &paths, de->d_name, &f->state);
3326 if (r < 0)
3327 f->state = UNIT_FILE_BAD;
3328
3329 if (!strv_isempty(states) &&
3330 !strv_contains(states, unit_file_state_to_string(f->state)))
3331 continue;
3332
3333 r = hashmap_put(h, basename(f->path), f);
3334 if (r < 0)
3335 return r;
3336
3337 f = NULL; /* prevent cleanup */
3338 }
3339 }
3340
3341 return 0;
3342 }
3343
3344 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
3345 [UNIT_FILE_ENABLED] = "enabled",
3346 [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
3347 [UNIT_FILE_LINKED] = "linked",
3348 [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
3349 [UNIT_FILE_MASKED] = "masked",
3350 [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
3351 [UNIT_FILE_STATIC] = "static",
3352 [UNIT_FILE_DISABLED] = "disabled",
3353 [UNIT_FILE_INDIRECT] = "indirect",
3354 [UNIT_FILE_GENERATED] = "generated",
3355 [UNIT_FILE_TRANSIENT] = "transient",
3356 [UNIT_FILE_BAD] = "bad",
3357 };
3358
3359 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
3360
3361 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
3362 [UNIT_FILE_SYMLINK] = "symlink",
3363 [UNIT_FILE_UNLINK] = "unlink",
3364 [UNIT_FILE_IS_MASKED] = "masked",
3365 [UNIT_FILE_IS_DANGLING] = "dangling",
3366 };
3367
3368 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);
3369
3370 static const char* const unit_file_preset_mode_table[_UNIT_FILE_PRESET_MAX] = {
3371 [UNIT_FILE_PRESET_FULL] = "full",
3372 [UNIT_FILE_PRESET_ENABLE_ONLY] = "enable-only",
3373 [UNIT_FILE_PRESET_DISABLE_ONLY] = "disable-only",
3374 };
3375
3376 DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode, UnitFilePresetMode);