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