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