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