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