]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/install.c
01e2ebf672a9877b5983107b66a07fd845c5c4bf
[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 /* Search for drop-in directories */
1465
1466 dropin_dir_name = strjoina(info->name, ".d");
1467 STRV_FOREACH(p, paths->search_path) {
1468 char *path;
1469
1470 path = path_join(NULL, *p, dropin_dir_name);
1471 if (!path)
1472 return -ENOMEM;
1473
1474 r = strv_consume(&dirs, path);
1475 if (r < 0)
1476 return r;
1477 }
1478
1479 if (template) {
1480 dropin_template_dir_name = strjoina(template, ".d");
1481 STRV_FOREACH(p, paths->search_path) {
1482 char *path;
1483
1484 path = path_join(NULL, *p, dropin_template_dir_name);
1485 if (!path)
1486 return -ENOMEM;
1487
1488 r = strv_consume(&dirs, path);
1489 if (r < 0)
1490 return r;
1491 }
1492 }
1493
1494 /* Load drop-in conf files */
1495
1496 r = conf_files_list_strv(&files, ".conf", NULL, 0, (const char**) dirs);
1497 if (r < 0)
1498 return log_debug_errno(r, "Failed to get list of conf files: %m");
1499
1500 STRV_FOREACH(p, files) {
1501 r = unit_file_load_or_readlink(c, info, *p, paths->root_dir, flags);
1502 if (r < 0)
1503 return log_debug_errno(r, "Failed to load conf file %s: %m", *p);
1504 }
1505
1506 return result;
1507 }
1508
1509 static int install_info_follow(
1510 InstallContext *c,
1511 UnitFileInstallInfo *i,
1512 const char *root_dir,
1513 SearchFlags flags,
1514 bool ignore_different_name) {
1515
1516 assert(c);
1517 assert(i);
1518
1519 if (i->type != UNIT_FILE_TYPE_SYMLINK)
1520 return -EINVAL;
1521 if (!i->symlink_target)
1522 return -EINVAL;
1523
1524 /* If the basename doesn't match, the caller should add a
1525 * complete new entry for this. */
1526
1527 if (!ignore_different_name && !streq(basename(i->symlink_target), i->name))
1528 return -EXDEV;
1529
1530 free_and_replace(i->path, i->symlink_target);
1531 i->type = _UNIT_FILE_TYPE_INVALID;
1532
1533 return unit_file_load_or_readlink(c, i, i->path, root_dir, flags);
1534 }
1535
1536 /**
1537 * Search for the unit file. If the unit name is a symlink, follow the symlink to the
1538 * target, maybe more than once. Propagate the instance name if present.
1539 */
1540 static int install_info_traverse(
1541 UnitFileScope scope,
1542 InstallContext *c,
1543 const LookupPaths *paths,
1544 UnitFileInstallInfo *start,
1545 SearchFlags flags,
1546 UnitFileInstallInfo **ret) {
1547
1548 UnitFileInstallInfo *i;
1549 unsigned k = 0;
1550 int r;
1551
1552 assert(paths);
1553 assert(start);
1554 assert(c);
1555
1556 r = unit_file_search(c, start, paths, flags);
1557 if (r < 0)
1558 return r;
1559
1560 i = start;
1561 while (i->type == UNIT_FILE_TYPE_SYMLINK) {
1562 /* Follow the symlink */
1563
1564 if (++k > UNIT_FILE_FOLLOW_SYMLINK_MAX)
1565 return -ELOOP;
1566
1567 if (!(flags & SEARCH_FOLLOW_CONFIG_SYMLINKS)) {
1568 r = path_is_config(paths, i->path, true);
1569 if (r < 0)
1570 return r;
1571 if (r > 0)
1572 return -ELOOP;
1573 }
1574
1575 r = install_info_follow(c, i, paths->root_dir, flags, false);
1576 if (r == -EXDEV) {
1577 _cleanup_free_ char *buffer = NULL;
1578 const char *bn;
1579
1580 /* Target has a different name, create a new
1581 * install info object for that, and continue
1582 * with that. */
1583
1584 bn = basename(i->symlink_target);
1585
1586 if (unit_name_is_valid(i->name, UNIT_NAME_INSTANCE) &&
1587 unit_name_is_valid(bn, UNIT_NAME_TEMPLATE)) {
1588
1589 _cleanup_free_ char *instance = NULL;
1590
1591 r = unit_name_to_instance(i->name, &instance);
1592 if (r < 0)
1593 return r;
1594
1595 r = unit_name_replace_instance(bn, instance, &buffer);
1596 if (r < 0)
1597 return r;
1598
1599 if (streq(buffer, i->name)) {
1600
1601 /* We filled in the instance, and the target stayed the same? If so, then let's
1602 * honour the link as it is. */
1603
1604 r = install_info_follow(c, i, paths->root_dir, flags, true);
1605 if (r < 0)
1606 return r;
1607
1608 continue;
1609 }
1610
1611 bn = buffer;
1612 }
1613
1614 r = install_info_add(c, bn, NULL, false, &i);
1615 if (r < 0)
1616 return r;
1617
1618 /* Try again, with the new target we found. */
1619 r = unit_file_search(c, i, paths, flags);
1620 if (r == -ENOENT)
1621 /* Translate error code to highlight this specific case */
1622 return -ENOLINK;
1623 }
1624
1625 if (r < 0)
1626 return r;
1627 }
1628
1629 if (ret)
1630 *ret = i;
1631
1632 return 0;
1633 }
1634
1635 /**
1636 * Call install_info_add() with name_or_path as the path (if name_or_path starts with "/")
1637 * or the name (otherwise). root_dir is prepended to the path.
1638 */
1639 static int install_info_add_auto(
1640 InstallContext *c,
1641 const LookupPaths *paths,
1642 const char *name_or_path,
1643 UnitFileInstallInfo **ret) {
1644
1645 assert(c);
1646 assert(name_or_path);
1647
1648 if (path_is_absolute(name_or_path)) {
1649 const char *pp;
1650
1651 pp = prefix_roota(paths->root_dir, name_or_path);
1652
1653 return install_info_add(c, NULL, pp, false, ret);
1654 } else
1655 return install_info_add(c, name_or_path, NULL, false, ret);
1656 }
1657
1658 static int install_info_discover(
1659 UnitFileScope scope,
1660 InstallContext *c,
1661 const LookupPaths *paths,
1662 const char *name,
1663 SearchFlags flags,
1664 UnitFileInstallInfo **ret,
1665 UnitFileChange **changes,
1666 unsigned *n_changes) {
1667
1668 UnitFileInstallInfo *i;
1669 int r;
1670
1671 assert(c);
1672 assert(paths);
1673 assert(name);
1674
1675 r = install_info_add_auto(c, paths, name, &i);
1676 if (r >= 0)
1677 r = install_info_traverse(scope, c, paths, i, flags, ret);
1678
1679 if (r < 0)
1680 unit_file_changes_add(changes, n_changes, r, name, NULL);
1681 return r;
1682 }
1683
1684 static int install_info_symlink_alias(
1685 UnitFileInstallInfo *i,
1686 const LookupPaths *paths,
1687 const char *config_path,
1688 bool force,
1689 UnitFileChange **changes,
1690 unsigned *n_changes) {
1691
1692 char **s;
1693 int r = 0, q;
1694
1695 assert(i);
1696 assert(paths);
1697 assert(config_path);
1698
1699 STRV_FOREACH(s, i->aliases) {
1700 _cleanup_free_ char *alias_path = NULL, *dst = NULL;
1701
1702 q = install_full_printf(i, *s, &dst);
1703 if (q < 0)
1704 return q;
1705
1706 alias_path = path_make_absolute(dst, config_path);
1707 if (!alias_path)
1708 return -ENOMEM;
1709
1710 q = create_symlink(paths, i->path, alias_path, force, changes, n_changes);
1711 if (r == 0)
1712 r = q;
1713 }
1714
1715 return r;
1716 }
1717
1718 static int install_info_symlink_wants(
1719 UnitFileInstallInfo *i,
1720 const LookupPaths *paths,
1721 const char *config_path,
1722 char **list,
1723 const char *suffix,
1724 UnitFileChange **changes,
1725 unsigned *n_changes) {
1726
1727 _cleanup_free_ char *buf = NULL;
1728 const char *n;
1729 char **s;
1730 int r = 0, q;
1731
1732 assert(i);
1733 assert(paths);
1734 assert(config_path);
1735
1736 if (strv_isempty(list))
1737 return 0;
1738
1739 if (unit_name_is_valid(i->name, UNIT_NAME_TEMPLATE) && i->default_instance) {
1740 UnitFileInstallInfo instance = {
1741 .type = _UNIT_FILE_TYPE_INVALID,
1742 };
1743 _cleanup_free_ char *path = NULL;
1744
1745 r = unit_name_replace_instance(i->name, i->default_instance, &buf);
1746 if (r < 0)
1747 return r;
1748
1749 instance.name = buf;
1750 r = unit_file_search(NULL, &instance, paths, SEARCH_FOLLOW_CONFIG_SYMLINKS);
1751 if (r < 0)
1752 return r;
1753
1754 path = instance.path;
1755 instance.path = NULL;
1756
1757 if (instance.type == UNIT_FILE_TYPE_MASKED) {
1758 unit_file_changes_add(changes, n_changes, -ERFKILL, path, NULL);
1759 return -ERFKILL;
1760 }
1761
1762 n = buf;
1763 } else
1764 n = i->name;
1765
1766 STRV_FOREACH(s, list) {
1767 _cleanup_free_ char *path = NULL, *dst = NULL;
1768
1769 q = install_full_printf(i, *s, &dst);
1770 if (q < 0)
1771 return q;
1772
1773 if (!unit_name_is_valid(dst, UNIT_NAME_ANY)) {
1774 r = -EINVAL;
1775 continue;
1776 }
1777
1778 path = strjoin(config_path, "/", dst, suffix, n);
1779 if (!path)
1780 return -ENOMEM;
1781
1782 q = create_symlink(paths, i->path, path, true, changes, n_changes);
1783 if (r == 0)
1784 r = q;
1785 }
1786
1787 return r;
1788 }
1789
1790 static int install_info_symlink_link(
1791 UnitFileInstallInfo *i,
1792 const LookupPaths *paths,
1793 const char *config_path,
1794 bool force,
1795 UnitFileChange **changes,
1796 unsigned *n_changes) {
1797
1798 _cleanup_free_ char *path = NULL;
1799 int r;
1800
1801 assert(i);
1802 assert(paths);
1803 assert(config_path);
1804 assert(i->path);
1805
1806 r = in_search_path(paths, i->path);
1807 if (r < 0)
1808 return r;
1809 if (r > 0)
1810 return 0;
1811
1812 path = strjoin(config_path, "/", i->name);
1813 if (!path)
1814 return -ENOMEM;
1815
1816 return create_symlink(paths, i->path, path, force, changes, n_changes);
1817 }
1818
1819 static int install_info_apply(
1820 UnitFileInstallInfo *i,
1821 const LookupPaths *paths,
1822 const char *config_path,
1823 bool force,
1824 UnitFileChange **changes,
1825 unsigned *n_changes) {
1826
1827 int r, q;
1828
1829 assert(i);
1830 assert(paths);
1831 assert(config_path);
1832
1833 if (i->type != UNIT_FILE_TYPE_REGULAR)
1834 return 0;
1835
1836 r = install_info_symlink_alias(i, paths, config_path, force, changes, n_changes);
1837
1838 q = install_info_symlink_wants(i, paths, config_path, i->wanted_by, ".wants/", changes, n_changes);
1839 if (r == 0)
1840 r = q;
1841
1842 q = install_info_symlink_wants(i, paths, config_path, i->required_by, ".requires/", changes, n_changes);
1843 if (r == 0)
1844 r = q;
1845
1846 q = install_info_symlink_link(i, paths, config_path, force, changes, n_changes);
1847 /* Do not count links to the unit file towards the "carries_install_info" count */
1848 if (r == 0 && q < 0)
1849 r = q;
1850
1851 return r;
1852 }
1853
1854 static int install_context_apply(
1855 UnitFileScope scope,
1856 InstallContext *c,
1857 const LookupPaths *paths,
1858 const char *config_path,
1859 bool force,
1860 SearchFlags flags,
1861 UnitFileChange **changes,
1862 unsigned *n_changes) {
1863
1864 UnitFileInstallInfo *i;
1865 int r;
1866
1867 assert(c);
1868 assert(paths);
1869 assert(config_path);
1870
1871 if (ordered_hashmap_isempty(c->will_process))
1872 return 0;
1873
1874 r = ordered_hashmap_ensure_allocated(&c->have_processed, &string_hash_ops);
1875 if (r < 0)
1876 return r;
1877
1878 r = 0;
1879 while ((i = ordered_hashmap_first(c->will_process))) {
1880 int q;
1881
1882 q = ordered_hashmap_move_one(c->have_processed, c->will_process, i->name);
1883 if (q < 0)
1884 return q;
1885
1886 r = install_info_traverse(scope, c, paths, i, flags, NULL);
1887 if (r < 0) {
1888 unit_file_changes_add(changes, n_changes, r, i->name, NULL);
1889 return r;
1890 }
1891
1892 /* We can attempt to process a masked unit when a different unit
1893 * that we were processing specifies it in Also=. */
1894 if (i->type == UNIT_FILE_TYPE_MASKED) {
1895 unit_file_changes_add(changes, n_changes, UNIT_FILE_IS_MASKED, i->path, NULL);
1896 if (r >= 0)
1897 /* Assume that something *could* have been enabled here,
1898 * avoid "empty [Install] section" warning. */
1899 r += 1;
1900 continue;
1901 }
1902
1903 if (i->type != UNIT_FILE_TYPE_REGULAR)
1904 continue;
1905
1906 q = install_info_apply(i, paths, config_path, force, changes, n_changes);
1907 if (r >= 0) {
1908 if (q < 0)
1909 r = q;
1910 else
1911 r += q;
1912 }
1913 }
1914
1915 return r;
1916 }
1917
1918 static int install_context_mark_for_removal(
1919 UnitFileScope scope,
1920 InstallContext *c,
1921 const LookupPaths *paths,
1922 Set **remove_symlinks_to,
1923 const char *config_path,
1924 UnitFileChange **changes,
1925 unsigned *n_changes) {
1926
1927 UnitFileInstallInfo *i;
1928 int r;
1929
1930 assert(c);
1931 assert(paths);
1932 assert(config_path);
1933
1934 /* Marks all items for removal */
1935
1936 if (ordered_hashmap_isempty(c->will_process))
1937 return 0;
1938
1939 r = ordered_hashmap_ensure_allocated(&c->have_processed, &string_hash_ops);
1940 if (r < 0)
1941 return r;
1942
1943 while ((i = ordered_hashmap_first(c->will_process))) {
1944
1945 r = ordered_hashmap_move_one(c->have_processed, c->will_process, i->name);
1946 if (r < 0)
1947 return r;
1948
1949 r = install_info_traverse(scope, c, paths, i, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, NULL);
1950 if (r == -ENOLINK) {
1951 log_debug_errno(r, "Name %s leads to a dangling symlink, removing name.", i->name);
1952 unit_file_changes_add(changes, n_changes, UNIT_FILE_IS_DANGLING, i->path ?: i->name, NULL);
1953 } else if (r == -ENOENT) {
1954
1955 if (i->auxiliary) /* some unit specified in Also= or similar is missing */
1956 log_debug_errno(r, "Auxiliary unit of %s not found, removing name.", i->name);
1957 else {
1958 log_debug_errno(r, "Unit %s not found, removing name.", i->name);
1959 unit_file_changes_add(changes, n_changes, r, i->path ?: i->name, NULL);
1960 }
1961
1962 } else if (r < 0) {
1963 log_debug_errno(r, "Failed to find unit %s, removing name: %m", i->name);
1964 unit_file_changes_add(changes, n_changes, r, i->path ?: i->name, NULL);
1965 } else if (i->type == UNIT_FILE_TYPE_MASKED) {
1966 log_debug("Unit file %s is masked, ignoring.", i->name);
1967 unit_file_changes_add(changes, n_changes, UNIT_FILE_IS_MASKED, i->path ?: i->name, NULL);
1968 continue;
1969 } else if (i->type != UNIT_FILE_TYPE_REGULAR) {
1970 log_debug("Unit %s has type %s, ignoring.", i->name, unit_file_type_to_string(i->type) ?: "invalid");
1971 continue;
1972 }
1973
1974 r = mark_symlink_for_removal(remove_symlinks_to, i->name);
1975 if (r < 0)
1976 return r;
1977 }
1978
1979 return 0;
1980 }
1981
1982 int unit_file_mask(
1983 UnitFileScope scope,
1984 UnitFileFlags flags,
1985 const char *root_dir,
1986 char **files,
1987 UnitFileChange **changes,
1988 unsigned *n_changes) {
1989
1990 _cleanup_lookup_paths_free_ LookupPaths paths = {};
1991 const char *config_path;
1992 char **i;
1993 int r;
1994
1995 assert(scope >= 0);
1996 assert(scope < _UNIT_FILE_SCOPE_MAX);
1997
1998 r = lookup_paths_init(&paths, scope, 0, root_dir);
1999 if (r < 0)
2000 return r;
2001
2002 config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config;
2003 if (!config_path)
2004 return -ENXIO;
2005
2006 STRV_FOREACH(i, files) {
2007 _cleanup_free_ char *path = NULL;
2008 int q;
2009
2010 if (!unit_name_is_valid(*i, UNIT_NAME_ANY)) {
2011 if (r == 0)
2012 r = -EINVAL;
2013 continue;
2014 }
2015
2016 path = path_make_absolute(*i, config_path);
2017 if (!path)
2018 return -ENOMEM;
2019
2020 q = create_symlink(&paths, "/dev/null", path, !!(flags & UNIT_FILE_FORCE), changes, n_changes);
2021 if (q < 0 && r >= 0)
2022 r = q;
2023 }
2024
2025 return r;
2026 }
2027
2028 int unit_file_unmask(
2029 UnitFileScope scope,
2030 UnitFileFlags flags,
2031 const char *root_dir,
2032 char **files,
2033 UnitFileChange **changes,
2034 unsigned *n_changes) {
2035
2036 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2037 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
2038 _cleanup_strv_free_ char **todo = NULL;
2039 size_t n_todo = 0, n_allocated = 0;
2040 const char *config_path;
2041 char **i;
2042 bool dry_run;
2043 int r, q;
2044
2045 assert(scope >= 0);
2046 assert(scope < _UNIT_FILE_SCOPE_MAX);
2047
2048 r = lookup_paths_init(&paths, scope, 0, root_dir);
2049 if (r < 0)
2050 return r;
2051
2052 config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config;
2053 if (!config_path)
2054 return -ENXIO;
2055
2056 dry_run = !!(flags & UNIT_FILE_DRY_RUN);
2057
2058 STRV_FOREACH(i, files) {
2059 _cleanup_free_ char *path = NULL;
2060
2061 if (!unit_name_is_valid(*i, UNIT_NAME_ANY))
2062 return -EINVAL;
2063
2064 path = path_make_absolute(*i, config_path);
2065 if (!path)
2066 return -ENOMEM;
2067
2068 r = null_or_empty_path(path);
2069 if (r == -ENOENT)
2070 continue;
2071 if (r < 0)
2072 return r;
2073 if (r == 0)
2074 continue;
2075
2076 if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2))
2077 return -ENOMEM;
2078
2079 todo[n_todo] = strdup(*i);
2080 if (!todo[n_todo])
2081 return -ENOMEM;
2082
2083 n_todo++;
2084 }
2085
2086 strv_uniq(todo);
2087
2088 r = 0;
2089 STRV_FOREACH(i, todo) {
2090 _cleanup_free_ char *path = NULL;
2091 const char *rp;
2092
2093 path = path_make_absolute(*i, config_path);
2094 if (!path)
2095 return -ENOMEM;
2096
2097 if (!dry_run && unlink(path) < 0) {
2098 if (errno != ENOENT) {
2099 if (r >= 0)
2100 r = -errno;
2101 unit_file_changes_add(changes, n_changes, -errno, path, NULL);
2102 }
2103
2104 continue;
2105 }
2106
2107 unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
2108
2109 rp = skip_root(&paths, path);
2110 q = mark_symlink_for_removal(&remove_symlinks_to, rp ?: path);
2111 if (q < 0)
2112 return q;
2113 }
2114
2115 q = remove_marked_symlinks(remove_symlinks_to, config_path, &paths, dry_run, changes, n_changes);
2116 if (r >= 0)
2117 r = q;
2118
2119 return r;
2120 }
2121
2122 int unit_file_link(
2123 UnitFileScope scope,
2124 UnitFileFlags flags,
2125 const char *root_dir,
2126 char **files,
2127 UnitFileChange **changes,
2128 unsigned *n_changes) {
2129
2130 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2131 _cleanup_strv_free_ char **todo = NULL;
2132 size_t n_todo = 0, n_allocated = 0;
2133 const char *config_path;
2134 char **i;
2135 int r, q;
2136
2137 assert(scope >= 0);
2138 assert(scope < _UNIT_FILE_SCOPE_MAX);
2139
2140 r = lookup_paths_init(&paths, scope, 0, root_dir);
2141 if (r < 0)
2142 return r;
2143
2144 config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config;
2145 if (!config_path)
2146 return -ENXIO;
2147
2148 STRV_FOREACH(i, files) {
2149 _cleanup_free_ char *full = NULL;
2150 struct stat st;
2151 char *fn;
2152
2153 if (!path_is_absolute(*i))
2154 return -EINVAL;
2155
2156 fn = basename(*i);
2157 if (!unit_name_is_valid(fn, UNIT_NAME_ANY))
2158 return -EINVAL;
2159
2160 full = prefix_root(paths.root_dir, *i);
2161 if (!full)
2162 return -ENOMEM;
2163
2164 if (lstat(full, &st) < 0)
2165 return -errno;
2166 r = stat_verify_regular(&st);
2167 if (r < 0)
2168 return r;
2169
2170 q = in_search_path(&paths, *i);
2171 if (q < 0)
2172 return q;
2173 if (q > 0)
2174 continue;
2175
2176 if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2))
2177 return -ENOMEM;
2178
2179 todo[n_todo] = strdup(*i);
2180 if (!todo[n_todo])
2181 return -ENOMEM;
2182
2183 n_todo++;
2184 }
2185
2186 strv_uniq(todo);
2187
2188 r = 0;
2189 STRV_FOREACH(i, todo) {
2190 _cleanup_free_ char *new_path = NULL;
2191
2192 new_path = path_make_absolute(basename(*i), config_path);
2193 if (!new_path)
2194 return -ENOMEM;
2195
2196 q = create_symlink(&paths, *i, new_path, !!(flags & UNIT_FILE_FORCE), changes, n_changes);
2197 if (q < 0 && r >= 0)
2198 r = q;
2199 }
2200
2201 return r;
2202 }
2203
2204 static int path_shall_revert(const LookupPaths *paths, const char *path) {
2205 int r;
2206
2207 assert(paths);
2208 assert(path);
2209
2210 /* Checks whether the path is one where the drop-in directories shall be removed. */
2211
2212 r = path_is_config(paths, path, true);
2213 if (r != 0)
2214 return r;
2215
2216 r = path_is_control(paths, path);
2217 if (r != 0)
2218 return r;
2219
2220 return path_is_transient(paths, path);
2221 }
2222
2223 int unit_file_revert(
2224 UnitFileScope scope,
2225 const char *root_dir,
2226 char **files,
2227 UnitFileChange **changes,
2228 unsigned *n_changes) {
2229
2230 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
2231 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2232 _cleanup_strv_free_ char **todo = NULL;
2233 size_t n_todo = 0, n_allocated = 0;
2234 char **i;
2235 int r, q;
2236
2237 /* Puts a unit file back into vendor state. This means:
2238 *
2239 * a) we remove all drop-in snippets added by the user ("config"), add to transient units ("transient"), and
2240 * added via "systemctl set-property" ("control"), but not if the drop-in is generated ("generated").
2241 *
2242 * c) if there's a vendor unit file (i.e. one in /usr) we remove any configured overriding unit files (i.e. in
2243 * "config", but not in "transient" or "control" or even "generated").
2244 *
2245 * We remove all that in both the runtime and the persistent directories, if that applies.
2246 */
2247
2248 r = lookup_paths_init(&paths, scope, 0, root_dir);
2249 if (r < 0)
2250 return r;
2251
2252 STRV_FOREACH(i, files) {
2253 bool has_vendor = false;
2254 char **p;
2255
2256 if (!unit_name_is_valid(*i, UNIT_NAME_ANY))
2257 return -EINVAL;
2258
2259 STRV_FOREACH(p, paths.search_path) {
2260 _cleanup_free_ char *path = NULL, *dropin = NULL;
2261 struct stat st;
2262
2263 path = path_make_absolute(*i, *p);
2264 if (!path)
2265 return -ENOMEM;
2266
2267 r = lstat(path, &st);
2268 if (r < 0) {
2269 if (errno != ENOENT)
2270 return -errno;
2271 } else if (S_ISREG(st.st_mode)) {
2272 /* Check if there's a vendor version */
2273 r = path_is_vendor(&paths, path);
2274 if (r < 0)
2275 return r;
2276 if (r > 0)
2277 has_vendor = true;
2278 }
2279
2280 dropin = strappend(path, ".d");
2281 if (!dropin)
2282 return -ENOMEM;
2283
2284 r = lstat(dropin, &st);
2285 if (r < 0) {
2286 if (errno != ENOENT)
2287 return -errno;
2288 } else if (S_ISDIR(st.st_mode)) {
2289 /* Remove the drop-ins */
2290 r = path_shall_revert(&paths, dropin);
2291 if (r < 0)
2292 return r;
2293 if (r > 0) {
2294 if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2))
2295 return -ENOMEM;
2296
2297 todo[n_todo++] = dropin;
2298 dropin = NULL;
2299 }
2300 }
2301 }
2302
2303 if (!has_vendor)
2304 continue;
2305
2306 /* OK, there's a vendor version, hence drop all configuration versions */
2307 STRV_FOREACH(p, paths.search_path) {
2308 _cleanup_free_ char *path = NULL;
2309 struct stat st;
2310
2311 path = path_make_absolute(*i, *p);
2312 if (!path)
2313 return -ENOMEM;
2314
2315 r = lstat(path, &st);
2316 if (r < 0) {
2317 if (errno != ENOENT)
2318 return -errno;
2319 } else if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
2320 r = path_is_config(&paths, path, true);
2321 if (r < 0)
2322 return r;
2323 if (r > 0) {
2324 if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2))
2325 return -ENOMEM;
2326
2327 todo[n_todo++] = path;
2328 path = NULL;
2329 }
2330 }
2331 }
2332 }
2333
2334 strv_uniq(todo);
2335
2336 r = 0;
2337 STRV_FOREACH(i, todo) {
2338 _cleanup_strv_free_ char **fs = NULL;
2339 const char *rp;
2340 char **j;
2341
2342 (void) get_files_in_directory(*i, &fs);
2343
2344 q = rm_rf(*i, REMOVE_ROOT|REMOVE_PHYSICAL);
2345 if (q < 0 && q != -ENOENT && r >= 0) {
2346 r = q;
2347 continue;
2348 }
2349
2350 STRV_FOREACH(j, fs) {
2351 _cleanup_free_ char *t = NULL;
2352
2353 t = strjoin(*i, "/", *j);
2354 if (!t)
2355 return -ENOMEM;
2356
2357 unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, t, NULL);
2358 }
2359
2360 unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, *i, NULL);
2361
2362 rp = skip_root(&paths, *i);
2363 q = mark_symlink_for_removal(&remove_symlinks_to, rp ?: *i);
2364 if (q < 0)
2365 return q;
2366 }
2367
2368 q = remove_marked_symlinks(remove_symlinks_to, paths.runtime_config, &paths, false, changes, n_changes);
2369 if (r >= 0)
2370 r = q;
2371
2372 q = remove_marked_symlinks(remove_symlinks_to, paths.persistent_config, &paths, false, changes, n_changes);
2373 if (r >= 0)
2374 r = q;
2375
2376 return r;
2377 }
2378
2379 int unit_file_add_dependency(
2380 UnitFileScope scope,
2381 UnitFileFlags flags,
2382 const char *root_dir,
2383 char **files,
2384 const char *target,
2385 UnitDependency dep,
2386 UnitFileChange **changes,
2387 unsigned *n_changes) {
2388
2389 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2390 _cleanup_(install_context_done) InstallContext c = {};
2391 UnitFileInstallInfo *i, *target_info;
2392 const char *config_path;
2393 char **f;
2394 int r;
2395
2396 assert(scope >= 0);
2397 assert(scope < _UNIT_FILE_SCOPE_MAX);
2398 assert(target);
2399
2400 if (!IN_SET(dep, UNIT_WANTS, UNIT_REQUIRES))
2401 return -EINVAL;
2402
2403 if (!unit_name_is_valid(target, UNIT_NAME_ANY))
2404 return -EINVAL;
2405
2406 r = lookup_paths_init(&paths, scope, 0, root_dir);
2407 if (r < 0)
2408 return r;
2409
2410 config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config;
2411 if (!config_path)
2412 return -ENXIO;
2413
2414 r = install_info_discover(scope, &c, &paths, target, SEARCH_FOLLOW_CONFIG_SYMLINKS,
2415 &target_info, changes, n_changes);
2416 if (r < 0)
2417 return r;
2418 r = install_info_may_process(target_info, &paths, changes, n_changes);
2419 if (r < 0)
2420 return r;
2421
2422 assert(target_info->type == UNIT_FILE_TYPE_REGULAR);
2423
2424 STRV_FOREACH(f, files) {
2425 char ***l;
2426
2427 r = install_info_discover(scope, &c, &paths, *f, SEARCH_FOLLOW_CONFIG_SYMLINKS,
2428 &i, changes, n_changes);
2429 if (r < 0)
2430 return r;
2431 r = install_info_may_process(i, &paths, changes, n_changes);
2432 if (r < 0)
2433 return r;
2434
2435 assert(i->type == UNIT_FILE_TYPE_REGULAR);
2436
2437 /* We didn't actually load anything from the unit
2438 * file, but instead just add in our new symlink to
2439 * create. */
2440
2441 if (dep == UNIT_WANTS)
2442 l = &i->wanted_by;
2443 else
2444 l = &i->required_by;
2445
2446 strv_free(*l);
2447 *l = strv_new(target_info->name, NULL);
2448 if (!*l)
2449 return -ENOMEM;
2450 }
2451
2452 return install_context_apply(scope, &c, &paths, config_path, !!(flags & UNIT_FILE_FORCE), SEARCH_FOLLOW_CONFIG_SYMLINKS, changes, n_changes);
2453 }
2454
2455 int unit_file_enable(
2456 UnitFileScope scope,
2457 UnitFileFlags flags,
2458 const char *root_dir,
2459 char **files,
2460 UnitFileChange **changes,
2461 unsigned *n_changes) {
2462
2463 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2464 _cleanup_(install_context_done) InstallContext c = {};
2465 const char *config_path;
2466 UnitFileInstallInfo *i;
2467 char **f;
2468 int r;
2469
2470 assert(scope >= 0);
2471 assert(scope < _UNIT_FILE_SCOPE_MAX);
2472
2473 r = lookup_paths_init(&paths, scope, 0, root_dir);
2474 if (r < 0)
2475 return r;
2476
2477 config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config;
2478 if (!config_path)
2479 return -ENXIO;
2480
2481 STRV_FOREACH(f, files) {
2482 r = install_info_discover(scope, &c, &paths, *f, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS,
2483 &i, changes, n_changes);
2484 if (r < 0)
2485 return r;
2486 r = install_info_may_process(i, &paths, changes, n_changes);
2487 if (r < 0)
2488 return r;
2489
2490 assert(i->type == UNIT_FILE_TYPE_REGULAR);
2491 }
2492
2493 /* This will return the number of symlink rules that were
2494 supposed to be created, not the ones actually created. This
2495 is useful to determine whether the passed files had any
2496 installation data at all. */
2497
2498 return install_context_apply(scope, &c, &paths, config_path, !!(flags & UNIT_FILE_FORCE), SEARCH_LOAD, changes, n_changes);
2499 }
2500
2501 int unit_file_disable(
2502 UnitFileScope scope,
2503 UnitFileFlags flags,
2504 const char *root_dir,
2505 char **files,
2506 UnitFileChange **changes,
2507 unsigned *n_changes) {
2508
2509 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2510 _cleanup_(install_context_done) InstallContext c = {};
2511 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
2512 const char *config_path;
2513 char **i;
2514 int r;
2515
2516 assert(scope >= 0);
2517 assert(scope < _UNIT_FILE_SCOPE_MAX);
2518
2519 r = lookup_paths_init(&paths, scope, 0, root_dir);
2520 if (r < 0)
2521 return r;
2522
2523 config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config;
2524 if (!config_path)
2525 return -ENXIO;
2526
2527 STRV_FOREACH(i, files) {
2528 if (!unit_name_is_valid(*i, UNIT_NAME_ANY))
2529 return -EINVAL;
2530
2531 r = install_info_add(&c, *i, NULL, false, NULL);
2532 if (r < 0)
2533 return r;
2534 }
2535
2536 r = install_context_mark_for_removal(scope, &c, &paths, &remove_symlinks_to, config_path, changes, n_changes);
2537 if (r < 0)
2538 return r;
2539
2540 return remove_marked_symlinks(remove_symlinks_to, config_path, &paths, !!(flags & UNIT_FILE_DRY_RUN), changes, n_changes);
2541 }
2542
2543 int unit_file_reenable(
2544 UnitFileScope scope,
2545 UnitFileFlags flags,
2546 const char *root_dir,
2547 char **files,
2548 UnitFileChange **changes,
2549 unsigned *n_changes) {
2550
2551 char **n;
2552 int r;
2553 size_t l, i;
2554
2555 /* First, we invoke the disable command with only the basename... */
2556 l = strv_length(files);
2557 n = newa(char*, l+1);
2558 for (i = 0; i < l; i++)
2559 n[i] = basename(files[i]);
2560 n[i] = NULL;
2561
2562 r = unit_file_disable(scope, flags, root_dir, n, changes, n_changes);
2563 if (r < 0)
2564 return r;
2565
2566 /* But the enable command with the full name */
2567 return unit_file_enable(scope, flags, root_dir, files, changes, n_changes);
2568 }
2569
2570 int unit_file_set_default(
2571 UnitFileScope scope,
2572 UnitFileFlags flags,
2573 const char *root_dir,
2574 const char *name,
2575 UnitFileChange **changes,
2576 unsigned *n_changes) {
2577
2578 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2579 _cleanup_(install_context_done) InstallContext c = {};
2580 UnitFileInstallInfo *i;
2581 const char *new_path;
2582 int r;
2583
2584 assert(scope >= 0);
2585 assert(scope < _UNIT_FILE_SCOPE_MAX);
2586 assert(name);
2587
2588 if (unit_name_to_type(name) != UNIT_TARGET) /* this also validates the name */
2589 return -EINVAL;
2590 if (streq(name, SPECIAL_DEFAULT_TARGET))
2591 return -EINVAL;
2592
2593 r = lookup_paths_init(&paths, scope, 0, root_dir);
2594 if (r < 0)
2595 return r;
2596
2597 r = install_info_discover(scope, &c, &paths, name, 0, &i, changes, n_changes);
2598 if (r < 0)
2599 return r;
2600 r = install_info_may_process(i, &paths, changes, n_changes);
2601 if (r < 0)
2602 return r;
2603
2604 new_path = strjoina(paths.persistent_config, "/" SPECIAL_DEFAULT_TARGET);
2605 return create_symlink(&paths, i->path, new_path, !!(flags & UNIT_FILE_FORCE), changes, n_changes);
2606 }
2607
2608 int unit_file_get_default(
2609 UnitFileScope scope,
2610 const char *root_dir,
2611 char **name) {
2612
2613 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2614 _cleanup_(install_context_done) InstallContext c = {};
2615 UnitFileInstallInfo *i;
2616 char *n;
2617 int r;
2618
2619 assert(scope >= 0);
2620 assert(scope < _UNIT_FILE_SCOPE_MAX);
2621 assert(name);
2622
2623 r = lookup_paths_init(&paths, scope, 0, root_dir);
2624 if (r < 0)
2625 return r;
2626
2627 r = install_info_discover(scope, &c, &paths, SPECIAL_DEFAULT_TARGET, SEARCH_FOLLOW_CONFIG_SYMLINKS,
2628 &i, NULL, NULL);
2629 if (r < 0)
2630 return r;
2631 r = install_info_may_process(i, &paths, NULL, 0);
2632 if (r < 0)
2633 return r;
2634
2635 n = strdup(i->name);
2636 if (!n)
2637 return -ENOMEM;
2638
2639 *name = n;
2640 return 0;
2641 }
2642
2643 static int unit_file_lookup_state(
2644 UnitFileScope scope,
2645 const LookupPaths *paths,
2646 const char *name,
2647 UnitFileState *ret) {
2648
2649 _cleanup_(install_context_done) InstallContext c = {};
2650 UnitFileInstallInfo *i;
2651 UnitFileState state;
2652 int r;
2653
2654 assert(paths);
2655 assert(name);
2656
2657 if (!unit_name_is_valid(name, UNIT_NAME_ANY))
2658 return -EINVAL;
2659
2660 r = install_info_discover(scope, &c, paths, name, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS,
2661 &i, NULL, NULL);
2662 if (r < 0)
2663 return r;
2664
2665 /* Shortcut things, if the caller just wants to know if this unit exists. */
2666 if (!ret)
2667 return 0;
2668
2669 switch (i->type) {
2670
2671 case UNIT_FILE_TYPE_MASKED:
2672 r = path_is_runtime(paths, i->path, true);
2673 if (r < 0)
2674 return r;
2675
2676 state = r > 0 ? UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
2677 break;
2678
2679 case UNIT_FILE_TYPE_REGULAR:
2680 r = path_is_generator(paths, i->path);
2681 if (r < 0)
2682 return r;
2683 if (r > 0) {
2684 state = UNIT_FILE_GENERATED;
2685 break;
2686 }
2687
2688 r = path_is_transient(paths, i->path);
2689 if (r < 0)
2690 return r;
2691 if (r > 0) {
2692 state = UNIT_FILE_TRANSIENT;
2693 break;
2694 }
2695
2696 /* Check if any of the Alias= symlinks have been created.
2697 * We ignore other aliases, and only check those that would
2698 * be created by systemctl enable for this unit. */
2699 r = find_symlinks_in_scope(scope, paths, i, true, &state);
2700 if (r < 0)
2701 return r;
2702 if (r > 0)
2703 break;
2704
2705 /* Check if the file is known under other names. If it is,
2706 * it might be in use. Report that as UNIT_FILE_INDIRECT. */
2707 r = find_symlinks_in_scope(scope, paths, i, false, &state);
2708 if (r < 0)
2709 return r;
2710 if (r > 0)
2711 state = UNIT_FILE_INDIRECT;
2712 else {
2713 if (unit_file_install_info_has_rules(i))
2714 state = UNIT_FILE_DISABLED;
2715 else if (unit_file_install_info_has_also(i))
2716 state = UNIT_FILE_INDIRECT;
2717 else
2718 state = UNIT_FILE_STATIC;
2719 }
2720
2721 break;
2722
2723 default:
2724 assert_not_reached("Unexpect unit file type.");
2725 }
2726
2727 *ret = state;
2728 return 0;
2729 }
2730
2731 int unit_file_get_state(
2732 UnitFileScope scope,
2733 const char *root_dir,
2734 const char *name,
2735 UnitFileState *ret) {
2736
2737 _cleanup_lookup_paths_free_ LookupPaths paths = {};
2738 int r;
2739
2740 assert(scope >= 0);
2741 assert(scope < _UNIT_FILE_SCOPE_MAX);
2742 assert(name);
2743
2744 r = lookup_paths_init(&paths, scope, 0, root_dir);
2745 if (r < 0)
2746 return r;
2747
2748 return unit_file_lookup_state(scope, &paths, name, ret);
2749 }
2750
2751 int unit_file_exists(UnitFileScope scope, const LookupPaths *paths, const char *name) {
2752 _cleanup_(install_context_done) InstallContext c = {};
2753 int r;
2754
2755 assert(paths);
2756 assert(name);
2757
2758 if (!unit_name_is_valid(name, UNIT_NAME_ANY))
2759 return -EINVAL;
2760
2761 r = install_info_discover(scope, &c, paths, name, 0, NULL, NULL, NULL);
2762 if (r == -ENOENT)
2763 return 0;
2764 if (r < 0)
2765 return r;
2766
2767 return 1;
2768 }
2769
2770 static int read_presets(UnitFileScope scope, const char *root_dir, Presets *presets) {
2771 _cleanup_(presets_freep) Presets ps = {};
2772 size_t n_allocated = 0;
2773 _cleanup_strv_free_ char **files = NULL;
2774 char **p;
2775 int r;
2776
2777 assert(scope >= 0);
2778 assert(scope < _UNIT_FILE_SCOPE_MAX);
2779 assert(presets);
2780
2781 if (scope == UNIT_FILE_SYSTEM)
2782 r = conf_files_list(&files, ".preset", root_dir, 0,
2783 "/etc/systemd/system-preset",
2784 "/run/systemd/system-preset",
2785 "/usr/local/lib/systemd/system-preset",
2786 "/usr/lib/systemd/system-preset",
2787 #if HAVE_SPLIT_USR
2788 "/lib/systemd/system-preset",
2789 #endif
2790 NULL);
2791 else if (scope == UNIT_FILE_GLOBAL)
2792 r = conf_files_list(&files, ".preset", root_dir, 0,
2793 "/etc/systemd/user-preset",
2794 "/run/systemd/user-preset",
2795 "/usr/local/lib/systemd/user-preset",
2796 "/usr/lib/systemd/user-preset",
2797 NULL);
2798 else {
2799 *presets = (Presets){};
2800
2801 return 0;
2802 }
2803
2804 if (r < 0)
2805 return r;
2806
2807 STRV_FOREACH(p, files) {
2808 _cleanup_fclose_ FILE *f;
2809 char line[LINE_MAX];
2810 int n = 0;
2811
2812 f = fopen(*p, "re");
2813 if (!f) {
2814 if (errno == ENOENT)
2815 continue;
2816
2817 return -errno;
2818 }
2819
2820 FOREACH_LINE(line, f, return -errno) {
2821 PresetRule rule = {};
2822 const char *parameter;
2823 char *l;
2824
2825 l = strstrip(line);
2826 n++;
2827
2828 if (isempty(l))
2829 continue;
2830 if (strchr(COMMENTS, *l))
2831 continue;
2832
2833 parameter = first_word(l, "enable");
2834 if (parameter) {
2835 char *pattern;
2836
2837 pattern = strdup(parameter);
2838 if (!pattern)
2839 return -ENOMEM;
2840
2841 rule = (PresetRule) {
2842 .pattern = pattern,
2843 .action = PRESET_ENABLE,
2844 };
2845 }
2846
2847 parameter = first_word(l, "disable");
2848 if (parameter) {
2849 char *pattern;
2850
2851 pattern = strdup(parameter);
2852 if (!pattern)
2853 return -ENOMEM;
2854
2855 rule = (PresetRule) {
2856 .pattern = pattern,
2857 .action = PRESET_DISABLE,
2858 };
2859 }
2860
2861 if (rule.action) {
2862 if (!GREEDY_REALLOC(ps.rules, n_allocated, ps.n_rules + 1))
2863 return -ENOMEM;
2864
2865 ps.rules[ps.n_rules++] = rule;
2866 continue;
2867 }
2868
2869 log_syntax(NULL, LOG_WARNING, *p, n, 0, "Couldn't parse line '%s'. Ignoring.", line);
2870 }
2871 }
2872
2873 *presets = ps;
2874 ps = (Presets){};
2875
2876 return 0;
2877 }
2878
2879 static int query_presets(const char *name, const Presets presets) {
2880 PresetAction action = PRESET_UNKNOWN;
2881 size_t i;
2882
2883 if (!unit_name_is_valid(name, UNIT_NAME_ANY))
2884 return -EINVAL;
2885
2886 for (i = 0; i < presets.n_rules; i++)
2887 if (fnmatch(presets.rules[i].pattern, name, FNM_NOESCAPE) == 0) {
2888 action = presets.rules[i].action;
2889 break;
2890 }
2891
2892 switch (action) {
2893 case PRESET_UNKNOWN:
2894 log_debug("Preset files don't specify rule for %s. Enabling.", name);
2895 return 1;
2896 case PRESET_ENABLE:
2897 log_debug("Preset files say enable %s.", name);
2898 return 1;
2899 case PRESET_DISABLE:
2900 log_debug("Preset files say disable %s.", name);
2901 return 0;
2902 default:
2903 assert_not_reached("invalid preset action");
2904 }
2905 }
2906
2907 int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name) {
2908 _cleanup_(presets_freep) Presets presets = {};
2909 int r;
2910
2911 r = read_presets(scope, root_dir, &presets);
2912 if (r < 0)
2913 return r;
2914
2915 return query_presets(name, presets);
2916 }
2917
2918 static int execute_preset(
2919 UnitFileScope scope,
2920 InstallContext *plus,
2921 InstallContext *minus,
2922 const LookupPaths *paths,
2923 const char *config_path,
2924 char **files,
2925 UnitFilePresetMode mode,
2926 bool force,
2927 UnitFileChange **changes,
2928 unsigned *n_changes) {
2929
2930 int r;
2931
2932 assert(plus);
2933 assert(minus);
2934 assert(paths);
2935 assert(config_path);
2936
2937 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
2938 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
2939
2940 r = install_context_mark_for_removal(scope, minus, paths, &remove_symlinks_to, config_path, changes, n_changes);
2941 if (r < 0)
2942 return r;
2943
2944 r = remove_marked_symlinks(remove_symlinks_to, config_path, paths, false, changes, n_changes);
2945 } else
2946 r = 0;
2947
2948 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
2949 int q;
2950
2951 /* Returns number of symlinks that where supposed to be installed. */
2952 q = install_context_apply(scope, plus, paths, config_path, force, SEARCH_LOAD, changes, n_changes);
2953 if (r >= 0) {
2954 if (q < 0)
2955 r = q;
2956 else
2957 r += q;
2958 }
2959 }
2960
2961 return r;
2962 }
2963
2964 static int preset_prepare_one(
2965 UnitFileScope scope,
2966 InstallContext *plus,
2967 InstallContext *minus,
2968 LookupPaths *paths,
2969 const char *name,
2970 Presets presets,
2971 UnitFileChange **changes,
2972 unsigned *n_changes) {
2973
2974 _cleanup_(install_context_done) InstallContext tmp = {};
2975 UnitFileInstallInfo *i;
2976 int r;
2977
2978 if (install_info_find(plus, name) || install_info_find(minus, name))
2979 return 0;
2980
2981 r = install_info_discover(scope, &tmp, paths, name, SEARCH_FOLLOW_CONFIG_SYMLINKS,
2982 &i, changes, n_changes);
2983 if (r < 0)
2984 return r;
2985 if (!streq(name, i->name)) {
2986 log_debug("Skipping %s because it is an alias for %s.", name, i->name);
2987 return 0;
2988 }
2989
2990 r = query_presets(name, presets);
2991 if (r < 0)
2992 return r;
2993
2994 if (r > 0) {
2995 r = install_info_discover(scope, plus, paths, name, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS,
2996 &i, changes, n_changes);
2997 if (r < 0)
2998 return r;
2999
3000 r = install_info_may_process(i, paths, changes, n_changes);
3001 if (r < 0)
3002 return r;
3003 } else
3004 r = install_info_discover(scope, minus, paths, name, SEARCH_FOLLOW_CONFIG_SYMLINKS,
3005 &i, changes, n_changes);
3006
3007 return r;
3008 }
3009
3010 int unit_file_preset(
3011 UnitFileScope scope,
3012 UnitFileFlags flags,
3013 const char *root_dir,
3014 char **files,
3015 UnitFilePresetMode mode,
3016 UnitFileChange **changes,
3017 unsigned *n_changes) {
3018
3019 _cleanup_(install_context_done) InstallContext plus = {}, minus = {};
3020 _cleanup_lookup_paths_free_ LookupPaths paths = {};
3021 _cleanup_(presets_freep) Presets presets = {};
3022 const char *config_path;
3023 char **i;
3024 int r;
3025
3026 assert(scope >= 0);
3027 assert(scope < _UNIT_FILE_SCOPE_MAX);
3028 assert(mode < _UNIT_FILE_PRESET_MAX);
3029
3030 r = lookup_paths_init(&paths, scope, 0, root_dir);
3031 if (r < 0)
3032 return r;
3033
3034 config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config;
3035 if (!config_path)
3036 return -ENXIO;
3037
3038 r = read_presets(scope, root_dir, &presets);
3039 if (r < 0)
3040 return r;
3041
3042 STRV_FOREACH(i, files) {
3043 r = preset_prepare_one(scope, &plus, &minus, &paths, *i, presets, changes, n_changes);
3044 if (r < 0)
3045 return r;
3046 }
3047
3048 return execute_preset(scope, &plus, &minus, &paths, config_path, files, mode, !!(flags & UNIT_FILE_FORCE), changes, n_changes);
3049 }
3050
3051 int unit_file_preset_all(
3052 UnitFileScope scope,
3053 UnitFileFlags flags,
3054 const char *root_dir,
3055 UnitFilePresetMode mode,
3056 UnitFileChange **changes,
3057 unsigned *n_changes) {
3058
3059 _cleanup_(install_context_done) InstallContext plus = {}, minus = {};
3060 _cleanup_lookup_paths_free_ LookupPaths paths = {};
3061 _cleanup_(presets_freep) Presets presets = {};
3062 const char *config_path = NULL;
3063 char **i;
3064 int r;
3065
3066 assert(scope >= 0);
3067 assert(scope < _UNIT_FILE_SCOPE_MAX);
3068 assert(mode < _UNIT_FILE_PRESET_MAX);
3069
3070 r = lookup_paths_init(&paths, scope, 0, root_dir);
3071 if (r < 0)
3072 return r;
3073
3074 config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config;
3075 if (!config_path)
3076 return -ENXIO;
3077
3078 r = read_presets(scope, root_dir, &presets);
3079 if (r < 0)
3080 return r;
3081
3082 STRV_FOREACH(i, paths.search_path) {
3083 _cleanup_closedir_ DIR *d = NULL;
3084 struct dirent *de;
3085
3086 d = opendir(*i);
3087 if (!d) {
3088 if (errno == ENOENT)
3089 continue;
3090
3091 return -errno;
3092 }
3093
3094 FOREACH_DIRENT(de, d, return -errno) {
3095
3096 if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
3097 continue;
3098
3099 dirent_ensure_type(d, de);
3100
3101 if (!IN_SET(de->d_type, DT_LNK, DT_REG))
3102 continue;
3103
3104 /* we don't pass changes[] in, because we want to handle errors on our own */
3105 r = preset_prepare_one(scope, &plus, &minus, &paths, de->d_name, presets, NULL, 0);
3106 if (r == -ERFKILL)
3107 r = unit_file_changes_add(changes, n_changes,
3108 UNIT_FILE_IS_MASKED, de->d_name, NULL);
3109 else if (r == -ENOLINK)
3110 r = unit_file_changes_add(changes, n_changes,
3111 UNIT_FILE_IS_DANGLING, de->d_name, NULL);
3112 else if (r == -EADDRNOTAVAIL) /* Ignore generated/transient units when applying preset */
3113 continue;
3114 if (r < 0)
3115 return r;
3116 }
3117 }
3118
3119 return execute_preset(scope, &plus, &minus, &paths, config_path, NULL, mode, !!(flags & UNIT_FILE_FORCE), changes, n_changes);
3120 }
3121
3122 static void unit_file_list_free_one(UnitFileList *f) {
3123 if (!f)
3124 return;
3125
3126 free(f->path);
3127 free(f);
3128 }
3129
3130 Hashmap* unit_file_list_free(Hashmap *h) {
3131 return hashmap_free_with_destructor(h, unit_file_list_free_one);
3132 }
3133
3134 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitFileList*, unit_file_list_free_one);
3135
3136 int unit_file_get_list(
3137 UnitFileScope scope,
3138 const char *root_dir,
3139 Hashmap *h,
3140 char **states,
3141 char **patterns) {
3142
3143 _cleanup_lookup_paths_free_ LookupPaths paths = {};
3144 char **i;
3145 int r;
3146
3147 assert(scope >= 0);
3148 assert(scope < _UNIT_FILE_SCOPE_MAX);
3149 assert(h);
3150
3151 r = lookup_paths_init(&paths, scope, 0, root_dir);
3152 if (r < 0)
3153 return r;
3154
3155 STRV_FOREACH(i, paths.search_path) {
3156 _cleanup_closedir_ DIR *d = NULL;
3157 struct dirent *de;
3158
3159 d = opendir(*i);
3160 if (!d) {
3161 if (errno == ENOENT)
3162 continue;
3163 if (IN_SET(errno, ENOTDIR, EACCES)) {
3164 log_debug_errno(errno, "Failed to open \"%s\": %m", *i);
3165 continue;
3166 }
3167
3168 return -errno;
3169 }
3170
3171 FOREACH_DIRENT(de, d, return -errno) {
3172 _cleanup_(unit_file_list_free_onep) UnitFileList *f = NULL;
3173
3174 if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
3175 continue;
3176
3177 if (!strv_fnmatch_or_empty(patterns, de->d_name, FNM_NOESCAPE))
3178 continue;
3179
3180 if (hashmap_get(h, de->d_name))
3181 continue;
3182
3183 dirent_ensure_type(d, de);
3184
3185 if (!IN_SET(de->d_type, DT_LNK, DT_REG))
3186 continue;
3187
3188 f = new0(UnitFileList, 1);
3189 if (!f)
3190 return -ENOMEM;
3191
3192 f->path = path_make_absolute(de->d_name, *i);
3193 if (!f->path)
3194 return -ENOMEM;
3195
3196 r = unit_file_lookup_state(scope, &paths, de->d_name, &f->state);
3197 if (r < 0)
3198 f->state = UNIT_FILE_BAD;
3199
3200 if (!strv_isempty(states) &&
3201 !strv_contains(states, unit_file_state_to_string(f->state)))
3202 continue;
3203
3204 r = hashmap_put(h, basename(f->path), f);
3205 if (r < 0)
3206 return r;
3207
3208 f = NULL; /* prevent cleanup */
3209 }
3210 }
3211
3212 return 0;
3213 }
3214
3215 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
3216 [UNIT_FILE_ENABLED] = "enabled",
3217 [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
3218 [UNIT_FILE_LINKED] = "linked",
3219 [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
3220 [UNIT_FILE_MASKED] = "masked",
3221 [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
3222 [UNIT_FILE_STATIC] = "static",
3223 [UNIT_FILE_DISABLED] = "disabled",
3224 [UNIT_FILE_INDIRECT] = "indirect",
3225 [UNIT_FILE_GENERATED] = "generated",
3226 [UNIT_FILE_TRANSIENT] = "transient",
3227 [UNIT_FILE_BAD] = "bad",
3228 };
3229
3230 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
3231
3232 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
3233 [UNIT_FILE_SYMLINK] = "symlink",
3234 [UNIT_FILE_UNLINK] = "unlink",
3235 [UNIT_FILE_IS_MASKED] = "masked",
3236 [UNIT_FILE_IS_DANGLING] = "dangling",
3237 };
3238
3239 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);
3240
3241 static const char* const unit_file_preset_mode_table[_UNIT_FILE_PRESET_MAX] = {
3242 [UNIT_FILE_PRESET_FULL] = "full",
3243 [UNIT_FILE_PRESET_ENABLE_ONLY] = "enable-only",
3244 [UNIT_FILE_PRESET_DISABLE_ONLY] = "disable-only",
3245 };
3246
3247 DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode, UnitFilePresetMode);