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