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