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