]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/install.c
pkgconfig: define variables relative to ${prefix}/${rootprefix}/${sysconfdir}
[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 log_error("Unit type %s cannot be templated.", unit_type_to_string(type));
1237 return -EINVAL;
1238 }
1239
1240 if (!(flags & SEARCH_LOAD)) {
1241 r = lstat(path, &st);
1242 if (r < 0)
1243 return -errno;
1244
1245 if (null_or_empty(&st))
1246 info->type = UNIT_FILE_TYPE_MASKED;
1247 else if (S_ISREG(st.st_mode))
1248 info->type = UNIT_FILE_TYPE_REGULAR;
1249 else if (S_ISLNK(st.st_mode))
1250 return -ELOOP;
1251 else if (S_ISDIR(st.st_mode))
1252 return -EISDIR;
1253 else
1254 return -ENOTTY;
1255
1256 return 0;
1257 }
1258
1259 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
1260 if (fd < 0)
1261 return -errno;
1262 } else {
1263 /* 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. */
1264
1265 if (!(flags & SEARCH_LOAD))
1266 return 0;
1267
1268 fd = chase_symlinks_and_open(path, root_dir, 0, O_RDONLY|O_CLOEXEC|O_NOCTTY, NULL);
1269 if (fd < 0)
1270 return fd;
1271 }
1272
1273 if (fstat(fd, &st) < 0)
1274 return -errno;
1275
1276 if (null_or_empty(&st)) {
1277 if ((flags & SEARCH_DROPIN) == 0)
1278 info->type = UNIT_FILE_TYPE_MASKED;
1279
1280 return 0;
1281 }
1282
1283 r = stat_verify_regular(&st);
1284 if (r < 0)
1285 return r;
1286
1287 f = fdopen(fd, "re");
1288 if (!f)
1289 return -errno;
1290 fd = -1;
1291
1292 /* c is only needed if we actually load the file (it's referenced from items[] btw, in case you wonder.) */
1293 assert(c);
1294
1295 r = config_parse(info->name, path, f,
1296 NULL,
1297 config_item_table_lookup, items,
1298 CONFIG_PARSE_RELAXED|CONFIG_PARSE_ALLOW_INCLUDE, info);
1299 if (r < 0)
1300 return log_debug_errno(r, "Failed to parse %s: %m", info->name);
1301
1302 if ((flags & SEARCH_DROPIN) == 0)
1303 info->type = UNIT_FILE_TYPE_REGULAR;
1304
1305 return
1306 (int) strv_length(info->aliases) +
1307 (int) strv_length(info->wanted_by) +
1308 (int) strv_length(info->required_by);
1309 }
1310
1311 static int unit_file_load_or_readlink(
1312 InstallContext *c,
1313 UnitFileInstallInfo *info,
1314 const char *path,
1315 const char *root_dir,
1316 SearchFlags flags) {
1317
1318 _cleanup_free_ char *target = NULL;
1319 int r;
1320
1321 r = unit_file_load(c, info, path, root_dir, flags);
1322 if (r != -ELOOP || (flags & SEARCH_DROPIN))
1323 return r;
1324
1325 /* This is a symlink, let's read it. */
1326
1327 r = readlink_malloc(path, &target);
1328 if (r < 0)
1329 return r;
1330
1331 if (path_equal(target, "/dev/null"))
1332 info->type = UNIT_FILE_TYPE_MASKED;
1333 else {
1334 const char *bn;
1335 UnitType a, b;
1336
1337 bn = basename(target);
1338
1339 if (unit_name_is_valid(info->name, UNIT_NAME_PLAIN)) {
1340
1341 if (!unit_name_is_valid(bn, UNIT_NAME_PLAIN))
1342 return -EINVAL;
1343
1344 } else if (unit_name_is_valid(info->name, UNIT_NAME_INSTANCE)) {
1345
1346 if (!unit_name_is_valid(bn, UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE))
1347 return -EINVAL;
1348
1349 } else if (unit_name_is_valid(info->name, UNIT_NAME_TEMPLATE)) {
1350
1351 if (!unit_name_is_valid(bn, UNIT_NAME_TEMPLATE))
1352 return -EINVAL;
1353 } else
1354 return -EINVAL;
1355
1356 /* Enforce that the symlink destination does not
1357 * change the unit file type. */
1358
1359 a = unit_name_to_type(info->name);
1360 b = unit_name_to_type(bn);
1361 if (a < 0 || b < 0 || a != b)
1362 return -EINVAL;
1363
1364 if (path_is_absolute(target))
1365 /* This is an absolute path, prefix the root so that we always deal with fully qualified paths */
1366 info->symlink_target = prefix_root(root_dir, target);
1367 else
1368 /* This is a relative path, take it relative to the dir the symlink is located in. */
1369 info->symlink_target = file_in_same_dir(path, target);
1370 if (!info->symlink_target)
1371 return -ENOMEM;
1372
1373 info->type = UNIT_FILE_TYPE_SYMLINK;
1374 }
1375
1376 return 0;
1377 }
1378
1379 static int unit_file_search(
1380 InstallContext *c,
1381 UnitFileInstallInfo *info,
1382 const LookupPaths *paths,
1383 SearchFlags flags) {
1384
1385 const char *dropin_dir_name = NULL, *dropin_template_dir_name = NULL;
1386 _cleanup_strv_free_ char **dirs = NULL, **files = NULL;
1387 _cleanup_free_ char *template = NULL;
1388 bool found_unit = false;
1389 int r, result;
1390 char **p;
1391
1392 assert(info);
1393 assert(paths);
1394
1395 /* Was this unit already loaded? */
1396 if (info->type != _UNIT_FILE_TYPE_INVALID)
1397 return 0;
1398
1399 if (info->path)
1400 return unit_file_load_or_readlink(c, info, info->path, paths->root_dir, flags);
1401
1402 assert(info->name);
1403
1404 if (unit_name_is_valid(info->name, UNIT_NAME_INSTANCE)) {
1405 r = unit_name_template(info->name, &template);
1406 if (r < 0)
1407 return r;
1408 }
1409
1410 STRV_FOREACH(p, paths->search_path) {
1411 _cleanup_free_ char *path = NULL;
1412
1413 path = strjoin(*p, "/", info->name);
1414 if (!path)
1415 return -ENOMEM;
1416
1417 r = unit_file_load_or_readlink(c, info, path, paths->root_dir, flags);
1418 if (r >= 0) {
1419 info->path = TAKE_PTR(path);
1420 result = r;
1421 found_unit = true;
1422 break;
1423 } else if (!IN_SET(r, -ENOENT, -ENOTDIR, -EACCES))
1424 return r;
1425 }
1426
1427 if (!found_unit && template) {
1428
1429 /* Unit file doesn't exist, however instance
1430 * enablement was requested. We will check if it is
1431 * possible to load template unit file. */
1432
1433 STRV_FOREACH(p, paths->search_path) {
1434 _cleanup_free_ char *path = NULL;
1435
1436 path = strjoin(*p, "/", template);
1437 if (!path)
1438 return -ENOMEM;
1439
1440 r = unit_file_load_or_readlink(c, info, path, paths->root_dir, flags);
1441 if (r >= 0) {
1442 info->path = TAKE_PTR(path);
1443 result = r;
1444 found_unit = true;
1445 break;
1446 } else if (!IN_SET(r, -ENOENT, -ENOTDIR, -EACCES))
1447 return r;
1448 }
1449 }
1450
1451 if (!found_unit) {
1452 log_debug("Cannot find unit %s%s%s.", info->name, template ? " or " : "", strempty(template));
1453 return -ENOENT;
1454 }
1455
1456 if (info->type == UNIT_FILE_TYPE_MASKED)
1457 return result;
1458
1459 /* Search for drop-in directories */
1460
1461 dropin_dir_name = strjoina(info->name, ".d");
1462 STRV_FOREACH(p, paths->search_path) {
1463 char *path;
1464
1465 path = path_join(NULL, *p, dropin_dir_name);
1466 if (!path)
1467 return -ENOMEM;
1468
1469 r = strv_consume(&dirs, path);
1470 if (r < 0)
1471 return r;
1472 }
1473
1474 if (template) {
1475 dropin_template_dir_name = strjoina(template, ".d");
1476 STRV_FOREACH(p, paths->search_path) {
1477 char *path;
1478
1479 path = path_join(NULL, *p, dropin_template_dir_name);
1480 if (!path)
1481 return -ENOMEM;
1482
1483 r = strv_consume(&dirs, path);
1484 if (r < 0)
1485 return r;
1486 }
1487 }
1488
1489 /* Load drop-in conf files */
1490
1491 r = conf_files_list_strv(&files, ".conf", NULL, 0, (const char**) dirs);
1492 if (r < 0)
1493 return log_debug_errno(r, "Failed to get list of conf files: %m");
1494
1495 STRV_FOREACH(p, files) {
1496 r = unit_file_load_or_readlink(c, info, *p, paths->root_dir, flags | SEARCH_DROPIN);
1497 if (r < 0)
1498 return log_debug_errno(r, "Failed to load conf file %s: %m", *p);
1499 }
1500
1501 return result;
1502 }
1503
1504 static int install_info_follow(
1505 InstallContext *c,
1506 UnitFileInstallInfo *i,
1507 const char *root_dir,
1508 SearchFlags flags,
1509 bool ignore_different_name) {
1510
1511 assert(c);
1512 assert(i);
1513
1514 if (i->type != UNIT_FILE_TYPE_SYMLINK)
1515 return -EINVAL;
1516 if (!i->symlink_target)
1517 return -EINVAL;
1518
1519 /* If the basename doesn't match, the caller should add a
1520 * complete new entry for this. */
1521
1522 if (!ignore_different_name && !streq(basename(i->symlink_target), i->name))
1523 return -EXDEV;
1524
1525 free_and_replace(i->path, i->symlink_target);
1526 i->type = _UNIT_FILE_TYPE_INVALID;
1527
1528 return unit_file_load_or_readlink(c, i, i->path, root_dir, flags);
1529 }
1530
1531 /**
1532 * Search for the unit file. If the unit name is a symlink, follow the symlink to the
1533 * target, maybe more than once. Propagate the instance name if present.
1534 */
1535 static int install_info_traverse(
1536 UnitFileScope scope,
1537 InstallContext *c,
1538 const LookupPaths *paths,
1539 UnitFileInstallInfo *start,
1540 SearchFlags flags,
1541 UnitFileInstallInfo **ret) {
1542
1543 UnitFileInstallInfo *i;
1544 unsigned k = 0;
1545 int r;
1546
1547 assert(paths);
1548 assert(start);
1549 assert(c);
1550
1551 r = unit_file_search(c, start, paths, flags);
1552 if (r < 0)
1553 return r;
1554
1555 i = start;
1556 while (i->type == UNIT_FILE_TYPE_SYMLINK) {
1557 /* Follow the symlink */
1558
1559 if (++k > UNIT_FILE_FOLLOW_SYMLINK_MAX)
1560 return -ELOOP;
1561
1562 if (!(flags & SEARCH_FOLLOW_CONFIG_SYMLINKS)) {
1563 r = path_is_config(paths, i->path, true);
1564 if (r < 0)
1565 return r;
1566 if (r > 0)
1567 return -ELOOP;
1568 }
1569
1570 r = install_info_follow(c, i, paths->root_dir, flags, false);
1571 if (r == -EXDEV) {
1572 _cleanup_free_ char *buffer = NULL;
1573 const char *bn;
1574
1575 /* Target has a different name, create a new
1576 * install info object for that, and continue
1577 * with that. */
1578
1579 bn = basename(i->symlink_target);
1580
1581 if (unit_name_is_valid(i->name, UNIT_NAME_INSTANCE) &&
1582 unit_name_is_valid(bn, UNIT_NAME_TEMPLATE)) {
1583
1584 _cleanup_free_ char *instance = NULL;
1585
1586 r = unit_name_to_instance(i->name, &instance);
1587 if (r < 0)
1588 return r;
1589
1590 r = unit_name_replace_instance(bn, instance, &buffer);
1591 if (r < 0)
1592 return r;
1593
1594 if (streq(buffer, i->name)) {
1595
1596 /* We filled in the instance, and the target stayed the same? If so, then let's
1597 * honour the link as it is. */
1598
1599 r = install_info_follow(c, i, paths->root_dir, flags, true);
1600 if (r < 0)
1601 return r;
1602
1603 continue;
1604 }
1605
1606 bn = buffer;
1607 }
1608
1609 r = install_info_add(c, bn, NULL, false, &i);
1610 if (r < 0)
1611 return r;
1612
1613 /* Try again, with the new target we found. */
1614 r = unit_file_search(c, i, paths, flags);
1615 if (r == -ENOENT)
1616 /* Translate error code to highlight this specific case */
1617 return -ENOLINK;
1618 }
1619
1620 if (r < 0)
1621 return r;
1622 }
1623
1624 if (ret)
1625 *ret = i;
1626
1627 return 0;
1628 }
1629
1630 /**
1631 * Call install_info_add() with name_or_path as the path (if name_or_path starts with "/")
1632 * or the name (otherwise). root_dir is prepended to the path.
1633 */
1634 static int install_info_add_auto(
1635 InstallContext *c,
1636 const LookupPaths *paths,
1637 const char *name_or_path,
1638 UnitFileInstallInfo **ret) {
1639
1640 assert(c);
1641 assert(name_or_path);
1642
1643 if (path_is_absolute(name_or_path)) {
1644 const char *pp;
1645
1646 pp = prefix_roota(paths->root_dir, name_or_path);
1647
1648 return install_info_add(c, NULL, pp, false, ret);
1649 } else
1650 return install_info_add(c, name_or_path, NULL, false, ret);
1651 }
1652
1653 static int install_info_discover(
1654 UnitFileScope scope,
1655 InstallContext *c,
1656 const LookupPaths *paths,
1657 const char *name,
1658 SearchFlags flags,
1659 UnitFileInstallInfo **ret,
1660 UnitFileChange **changes,
1661 size_t *n_changes) {
1662
1663 UnitFileInstallInfo *i;
1664 int r;
1665
1666 assert(c);
1667 assert(paths);
1668 assert(name);
1669
1670 r = install_info_add_auto(c, paths, name, &i);
1671 if (r >= 0)
1672 r = install_info_traverse(scope, c, paths, i, flags, ret);
1673
1674 if (r < 0)
1675 unit_file_changes_add(changes, n_changes, r, name, NULL);
1676 return r;
1677 }
1678
1679 static int install_info_discover_and_check(
1680 UnitFileScope scope,
1681 InstallContext *c,
1682 const LookupPaths *paths,
1683 const char *name,
1684 SearchFlags flags,
1685 UnitFileInstallInfo **ret,
1686 UnitFileChange **changes,
1687 size_t *n_changes) {
1688
1689 int r;
1690
1691 r = install_info_discover(scope, c, paths, name, flags, ret, changes, n_changes);
1692 if (r < 0)
1693 return r;
1694
1695 return install_info_may_process(ret ? *ret : NULL, paths, changes, n_changes);
1696 }
1697
1698 static int install_info_symlink_alias(
1699 UnitFileInstallInfo *i,
1700 const LookupPaths *paths,
1701 const char *config_path,
1702 bool force,
1703 UnitFileChange **changes,
1704 size_t *n_changes) {
1705
1706 char **s;
1707 int r = 0, q;
1708
1709 assert(i);
1710 assert(paths);
1711 assert(config_path);
1712
1713 STRV_FOREACH(s, i->aliases) {
1714 _cleanup_free_ char *alias_path = NULL, *dst = NULL;
1715
1716 q = install_full_printf(i, *s, &dst);
1717 if (q < 0)
1718 return q;
1719
1720 alias_path = path_make_absolute(dst, config_path);
1721 if (!alias_path)
1722 return -ENOMEM;
1723
1724 q = create_symlink(paths, i->path, alias_path, force, changes, n_changes);
1725 if (r == 0)
1726 r = q;
1727 }
1728
1729 return r;
1730 }
1731
1732 static int install_info_symlink_wants(
1733 UnitFileInstallInfo *i,
1734 const LookupPaths *paths,
1735 const char *config_path,
1736 char **list,
1737 const char *suffix,
1738 UnitFileChange **changes,
1739 size_t *n_changes) {
1740
1741 _cleanup_free_ char *buf = NULL;
1742 const char *n;
1743 char **s;
1744 int r = 0, q;
1745
1746 assert(i);
1747 assert(paths);
1748 assert(config_path);
1749
1750 if (strv_isempty(list))
1751 return 0;
1752
1753 if (unit_name_is_valid(i->name, UNIT_NAME_TEMPLATE) && i->default_instance) {
1754 UnitFileInstallInfo instance = {
1755 .type = _UNIT_FILE_TYPE_INVALID,
1756 };
1757 _cleanup_free_ char *path = NULL;
1758
1759 r = unit_name_replace_instance(i->name, i->default_instance, &buf);
1760 if (r < 0)
1761 return r;
1762
1763 instance.name = buf;
1764 r = unit_file_search(NULL, &instance, paths, SEARCH_FOLLOW_CONFIG_SYMLINKS);
1765 if (r < 0)
1766 return r;
1767
1768 path = TAKE_PTR(instance.path);
1769
1770 if (instance.type == UNIT_FILE_TYPE_MASKED) {
1771 unit_file_changes_add(changes, n_changes, -ERFKILL, path, NULL);
1772 return -ERFKILL;
1773 }
1774
1775 n = buf;
1776 } else
1777 n = i->name;
1778
1779 STRV_FOREACH(s, list) {
1780 _cleanup_free_ char *path = NULL, *dst = NULL;
1781
1782 q = install_full_printf(i, *s, &dst);
1783 if (q < 0)
1784 return q;
1785
1786 if (!unit_name_is_valid(dst, UNIT_NAME_ANY)) {
1787 r = -EINVAL;
1788 continue;
1789 }
1790
1791 path = strjoin(config_path, "/", dst, suffix, n);
1792 if (!path)
1793 return -ENOMEM;
1794
1795 q = create_symlink(paths, i->path, path, true, changes, n_changes);
1796 if (r == 0)
1797 r = q;
1798 }
1799
1800 return r;
1801 }
1802
1803 static int install_info_symlink_link(
1804 UnitFileInstallInfo *i,
1805 const LookupPaths *paths,
1806 const char *config_path,
1807 bool force,
1808 UnitFileChange **changes,
1809 size_t *n_changes) {
1810
1811 _cleanup_free_ char *path = NULL;
1812 int r;
1813
1814 assert(i);
1815 assert(paths);
1816 assert(config_path);
1817 assert(i->path);
1818
1819 r = in_search_path(paths, i->path);
1820 if (r < 0)
1821 return r;
1822 if (r > 0)
1823 return 0;
1824
1825 path = strjoin(config_path, "/", i->name);
1826 if (!path)
1827 return -ENOMEM;
1828
1829 return create_symlink(paths, i->path, path, force, changes, n_changes);
1830 }
1831
1832 static int install_info_apply(
1833 UnitFileInstallInfo *i,
1834 const LookupPaths *paths,
1835 const char *config_path,
1836 bool force,
1837 UnitFileChange **changes,
1838 size_t *n_changes) {
1839
1840 int r, q;
1841
1842 assert(i);
1843 assert(paths);
1844 assert(config_path);
1845
1846 if (i->type != UNIT_FILE_TYPE_REGULAR)
1847 return 0;
1848
1849 r = install_info_symlink_alias(i, paths, config_path, force, changes, n_changes);
1850
1851 q = install_info_symlink_wants(i, paths, config_path, i->wanted_by, ".wants/", changes, n_changes);
1852 if (r == 0)
1853 r = q;
1854
1855 q = install_info_symlink_wants(i, paths, config_path, i->required_by, ".requires/", changes, n_changes);
1856 if (r == 0)
1857 r = q;
1858
1859 q = install_info_symlink_link(i, paths, config_path, force, changes, n_changes);
1860 /* Do not count links to the unit file towards the "carries_install_info" count */
1861 if (r == 0 && q < 0)
1862 r = q;
1863
1864 return r;
1865 }
1866
1867 static int install_context_apply(
1868 UnitFileScope scope,
1869 InstallContext *c,
1870 const LookupPaths *paths,
1871 const char *config_path,
1872 bool force,
1873 SearchFlags flags,
1874 UnitFileChange **changes,
1875 size_t *n_changes) {
1876
1877 UnitFileInstallInfo *i;
1878 int r;
1879
1880 assert(c);
1881 assert(paths);
1882 assert(config_path);
1883
1884 if (ordered_hashmap_isempty(c->will_process))
1885 return 0;
1886
1887 r = ordered_hashmap_ensure_allocated(&c->have_processed, &string_hash_ops);
1888 if (r < 0)
1889 return r;
1890
1891 r = 0;
1892 while ((i = ordered_hashmap_first(c->will_process))) {
1893 int q;
1894
1895 q = ordered_hashmap_move_one(c->have_processed, c->will_process, i->name);
1896 if (q < 0)
1897 return q;
1898
1899 q = install_info_traverse(scope, c, paths, i, flags, NULL);
1900 if (q < 0) {
1901 unit_file_changes_add(changes, n_changes, r, i->name, NULL);
1902 return q;
1903 }
1904
1905 /* We can attempt to process a masked unit when a different unit
1906 * that we were processing specifies it in Also=. */
1907 if (i->type == UNIT_FILE_TYPE_MASKED) {
1908 unit_file_changes_add(changes, n_changes, UNIT_FILE_IS_MASKED, i->path, NULL);
1909 if (r >= 0)
1910 /* Assume that something *could* have been enabled here,
1911 * avoid "empty [Install] section" warning. */
1912 r += 1;
1913 continue;
1914 }
1915
1916 if (i->type != UNIT_FILE_TYPE_REGULAR)
1917 continue;
1918
1919 q = install_info_apply(i, paths, config_path, force, changes, n_changes);
1920 if (r >= 0) {
1921 if (q < 0)
1922 r = q;
1923 else
1924 r += q;
1925 }
1926 }
1927
1928 return r;
1929 }
1930
1931 static int install_context_mark_for_removal(
1932 UnitFileScope scope,
1933 InstallContext *c,
1934 const LookupPaths *paths,
1935 Set **remove_symlinks_to,
1936 UnitFileChange **changes,
1937 size_t *n_changes) {
1938
1939 UnitFileInstallInfo *i;
1940 int r;
1941
1942 assert(c);
1943 assert(paths);
1944
1945 /* Marks all items for removal */
1946
1947 if (ordered_hashmap_isempty(c->will_process))
1948 return 0;
1949
1950 r = ordered_hashmap_ensure_allocated(&c->have_processed, &string_hash_ops);
1951 if (r < 0)
1952 return r;
1953
1954 while ((i = ordered_hashmap_first(c->will_process))) {
1955
1956 r = ordered_hashmap_move_one(c->have_processed, c->will_process, i->name);
1957 if (r < 0)
1958 return r;
1959
1960 r = install_info_traverse(scope, c, paths, i, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, NULL);
1961 if (r == -ENOLINK) {
1962 log_debug_errno(r, "Name %s leads to a dangling symlink, removing name.", i->name);
1963 unit_file_changes_add(changes, n_changes, UNIT_FILE_IS_DANGLING, i->path ?: i->name, NULL);
1964 } else if (r == -ENOENT) {
1965
1966 if (i->auxiliary) /* some unit specified in Also= or similar is missing */
1967 log_debug_errno(r, "Auxiliary unit of %s not found, removing name.", i->name);
1968 else {
1969 log_debug_errno(r, "Unit %s not found, removing name.", i->name);
1970 unit_file_changes_add(changes, n_changes, r, i->path ?: i->name, NULL);
1971 }
1972
1973 } else if (r < 0) {
1974 log_debug_errno(r, "Failed to find unit %s, removing name: %m", i->name);
1975 unit_file_changes_add(changes, n_changes, r, i->path ?: i->name, NULL);
1976 } else if (i->type == UNIT_FILE_TYPE_MASKED) {
1977 log_debug("Unit file %s is masked, ignoring.", i->name);
1978 unit_file_changes_add(changes, n_changes, UNIT_FILE_IS_MASKED, i->path ?: i->name, NULL);
1979 continue;
1980 } else if (i->type != UNIT_FILE_TYPE_REGULAR) {
1981 log_debug("Unit %s has type %s, ignoring.", i->name, unit_file_type_to_string(i->type) ?: "invalid");
1982 continue;
1983 }
1984
1985 r = mark_symlink_for_removal(remove_symlinks_to, i->name);
1986 if (r < 0)
1987 return r;
1988 }
1989
1990 return 0;
1991 }
1992
1993 int unit_file_mask(
1994 UnitFileScope scope,
1995 UnitFileFlags flags,
1996 const char *root_dir,
1997 char **files,
1998 UnitFileChange **changes,
1999 size_t *n_changes) {
2000
2001 _cleanup_(lookup_paths_free) LookupPaths paths = {};
2002 const char *config_path;
2003 char **i;
2004 int r;
2005
2006 assert(scope >= 0);
2007 assert(scope < _UNIT_FILE_SCOPE_MAX);
2008
2009 r = lookup_paths_init(&paths, scope, 0, root_dir);
2010 if (r < 0)
2011 return r;
2012
2013 config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config;
2014 if (!config_path)
2015 return -ENXIO;
2016
2017 STRV_FOREACH(i, files) {
2018 _cleanup_free_ char *path = NULL;
2019 int q;
2020
2021 if (!unit_name_is_valid(*i, UNIT_NAME_ANY)) {
2022 if (r == 0)
2023 r = -EINVAL;
2024 continue;
2025 }
2026
2027 path = path_make_absolute(*i, config_path);
2028 if (!path)
2029 return -ENOMEM;
2030
2031 q = create_symlink(&paths, "/dev/null", path, !!(flags & UNIT_FILE_FORCE), changes, n_changes);
2032 if (q < 0 && r >= 0)
2033 r = q;
2034 }
2035
2036 return r;
2037 }
2038
2039 int unit_file_unmask(
2040 UnitFileScope scope,
2041 UnitFileFlags flags,
2042 const char *root_dir,
2043 char **files,
2044 UnitFileChange **changes,
2045 size_t *n_changes) {
2046
2047 _cleanup_(lookup_paths_free) LookupPaths paths = {};
2048 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
2049 _cleanup_strv_free_ char **todo = NULL;
2050 size_t n_todo = 0, n_allocated = 0;
2051 const char *config_path;
2052 char **i;
2053 bool dry_run = !!(flags & UNIT_FILE_DRY_RUN);
2054 int r, q;
2055
2056 assert(scope >= 0);
2057 assert(scope < _UNIT_FILE_SCOPE_MAX);
2058
2059 r = lookup_paths_init(&paths, scope, 0, root_dir);
2060 if (r < 0)
2061 return r;
2062
2063 STRV_FOREACH(i, files) {
2064 if (!unit_name_is_valid(*i, UNIT_NAME_ANY))
2065 return -EINVAL;
2066
2067 FOREACH_STRING(config_path, paths.runtime_config, paths.persistent_config) {
2068 _cleanup_free_ char *path = NULL;
2069
2070 path = path_make_absolute(*i, config_path);
2071 if (!path)
2072 return -ENOMEM;
2073
2074 r = null_or_empty_path(path);
2075 if (r == -ENOENT)
2076 continue;
2077 if (r < 0)
2078 return r;
2079 if (r == 0)
2080 continue;
2081
2082 if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2))
2083 return -ENOMEM;
2084
2085 todo[n_todo] = strdup(*i);
2086 if (!todo[n_todo])
2087 return -ENOMEM;
2088
2089 n_todo++;
2090 }
2091 }
2092
2093 strv_uniq(todo);
2094
2095 r = 0;
2096 FOREACH_STRING(config_path, paths.runtime_config, paths.persistent_config) {
2097 STRV_FOREACH(i, todo) {
2098 _cleanup_free_ char *path = NULL;
2099 const char *rp;
2100
2101 path = path_make_absolute(*i, config_path);
2102 if (!path)
2103 return -ENOMEM;
2104
2105 if (!dry_run && unlink(path) < 0) {
2106 if (errno != ENOENT) {
2107 if (r >= 0)
2108 r = -errno;
2109 unit_file_changes_add(changes, n_changes, -errno, path, NULL);
2110 }
2111
2112 continue;
2113 }
2114
2115 unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, path, NULL);
2116
2117 rp = skip_root(&paths, path);
2118 q = mark_symlink_for_removal(&remove_symlinks_to, rp ?: path);
2119 if (q < 0)
2120 return q;
2121 }
2122
2123 q = remove_marked_symlinks(remove_symlinks_to, config_path, &paths, dry_run, changes, n_changes);
2124 if (r >= 0)
2125 r = q;
2126 }
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 = prefix_root(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 = strappend(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 = strjoin(*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 bool dry_run = !!(flags & UNIT_FILE_DRY_RUN);
2511 const char *config_path;
2512 char **i;
2513 int r;
2514
2515 assert(scope >= 0);
2516 assert(scope < _UNIT_FILE_SCOPE_MAX);
2517
2518 r = lookup_paths_init(&paths, scope, 0, root_dir);
2519 if (r < 0)
2520 return r;
2521
2522 STRV_FOREACH(i, files) {
2523 if (!unit_name_is_valid(*i, UNIT_NAME_ANY))
2524 return -EINVAL;
2525
2526 r = install_info_add(&c, *i, NULL, false, NULL);
2527 if (r < 0)
2528 return r;
2529 }
2530
2531 r = install_context_mark_for_removal(scope, &c, &paths, &remove_symlinks_to, changes, n_changes);
2532 if (r < 0)
2533 return r;
2534
2535 FOREACH_STRING(config_path, paths.runtime_config, paths.persistent_config) {
2536 r = remove_marked_symlinks(remove_symlinks_to, config_path, &paths, dry_run, changes, n_changes);
2537 if (r < 0)
2538 return r;
2539 }
2540
2541 return 0;
2542 }
2543
2544 int unit_file_reenable(
2545 UnitFileScope scope,
2546 UnitFileFlags flags,
2547 const char *root_dir,
2548 char **files,
2549 UnitFileChange **changes,
2550 size_t *n_changes) {
2551
2552 char **n;
2553 int r;
2554 size_t l, i;
2555
2556 /* First, we invoke the disable command with only the basename... */
2557 l = strv_length(files);
2558 n = newa(char*, l+1);
2559 for (i = 0; i < l; i++)
2560 n[i] = basename(files[i]);
2561 n[i] = NULL;
2562
2563 r = unit_file_disable(scope, flags, root_dir, n, changes, n_changes);
2564 if (r < 0)
2565 return r;
2566
2567 /* But the enable command with the full name */
2568 return unit_file_enable(scope, flags, root_dir, files, changes, n_changes);
2569 }
2570
2571 int unit_file_set_default(
2572 UnitFileScope scope,
2573 UnitFileFlags flags,
2574 const char *root_dir,
2575 const char *name,
2576 UnitFileChange **changes,
2577 size_t *n_changes) {
2578
2579 _cleanup_(lookup_paths_free) LookupPaths paths = {};
2580 _cleanup_(install_context_done) InstallContext c = {};
2581 UnitFileInstallInfo *i;
2582 const char *new_path;
2583 int r;
2584
2585 assert(scope >= 0);
2586 assert(scope < _UNIT_FILE_SCOPE_MAX);
2587 assert(name);
2588
2589 if (unit_name_to_type(name) != UNIT_TARGET) /* this also validates the name */
2590 return -EINVAL;
2591 if (streq(name, SPECIAL_DEFAULT_TARGET))
2592 return -EINVAL;
2593
2594 r = lookup_paths_init(&paths, scope, 0, root_dir);
2595 if (r < 0)
2596 return r;
2597
2598 r = install_info_discover_and_check(scope, &c, &paths, name, 0, &i, changes, n_changes);
2599 if (r < 0)
2600 return r;
2601
2602 new_path = strjoina(paths.persistent_config, "/" SPECIAL_DEFAULT_TARGET);
2603 return create_symlink(&paths, i->path, new_path, !!(flags & UNIT_FILE_FORCE), changes, n_changes);
2604 }
2605
2606 int unit_file_get_default(
2607 UnitFileScope scope,
2608 const char *root_dir,
2609 char **name) {
2610
2611 _cleanup_(lookup_paths_free) LookupPaths paths = {};
2612 _cleanup_(install_context_done) InstallContext c = {};
2613 UnitFileInstallInfo *i;
2614 char *n;
2615 int r;
2616
2617 assert(scope >= 0);
2618 assert(scope < _UNIT_FILE_SCOPE_MAX);
2619 assert(name);
2620
2621 r = lookup_paths_init(&paths, scope, 0, root_dir);
2622 if (r < 0)
2623 return r;
2624
2625 r = install_info_discover(scope, &c, &paths, SPECIAL_DEFAULT_TARGET, SEARCH_FOLLOW_CONFIG_SYMLINKS,
2626 &i, NULL, NULL);
2627 if (r < 0)
2628 return r;
2629 r = install_info_may_process(i, &paths, NULL, 0);
2630 if (r < 0)
2631 return r;
2632
2633 n = strdup(i->name);
2634 if (!n)
2635 return -ENOMEM;
2636
2637 *name = n;
2638 return 0;
2639 }
2640
2641 int unit_file_lookup_state(
2642 UnitFileScope scope,
2643 const LookupPaths *paths,
2644 const char *name,
2645 UnitFileState *ret) {
2646
2647 _cleanup_(install_context_done) InstallContext c = {};
2648 UnitFileInstallInfo *i;
2649 UnitFileState state;
2650 int r;
2651
2652 assert(paths);
2653 assert(name);
2654
2655 if (!unit_name_is_valid(name, UNIT_NAME_ANY))
2656 return -EINVAL;
2657
2658 r = install_info_discover(scope, &c, paths, name, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS,
2659 &i, NULL, NULL);
2660 if (r < 0)
2661 return r;
2662
2663 /* Shortcut things, if the caller just wants to know if this unit exists. */
2664 if (!ret)
2665 return 0;
2666
2667 switch (i->type) {
2668
2669 case UNIT_FILE_TYPE_MASKED:
2670 r = path_is_runtime(paths, i->path, true);
2671 if (r < 0)
2672 return r;
2673
2674 state = r > 0 ? UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED;
2675 break;
2676
2677 case UNIT_FILE_TYPE_REGULAR:
2678 r = path_is_generator(paths, i->path);
2679 if (r < 0)
2680 return r;
2681 if (r > 0) {
2682 state = UNIT_FILE_GENERATED;
2683 break;
2684 }
2685
2686 r = path_is_transient(paths, i->path);
2687 if (r < 0)
2688 return r;
2689 if (r > 0) {
2690 state = UNIT_FILE_TRANSIENT;
2691 break;
2692 }
2693
2694 /* Check if any of the Alias= symlinks have been created.
2695 * We ignore other aliases, and only check those that would
2696 * be created by systemctl enable for this unit. */
2697 r = find_symlinks_in_scope(scope, paths, i, true, &state);
2698 if (r < 0)
2699 return r;
2700 if (r > 0)
2701 break;
2702
2703 /* Check if the file is known under other names. If it is,
2704 * it might be in use. Report that as UNIT_FILE_INDIRECT. */
2705 r = find_symlinks_in_scope(scope, paths, i, false, &state);
2706 if (r < 0)
2707 return r;
2708 if (r > 0)
2709 state = UNIT_FILE_INDIRECT;
2710 else {
2711 if (unit_file_install_info_has_rules(i))
2712 state = UNIT_FILE_DISABLED;
2713 else if (unit_file_install_info_has_also(i))
2714 state = UNIT_FILE_INDIRECT;
2715 else
2716 state = UNIT_FILE_STATIC;
2717 }
2718
2719 break;
2720
2721 default:
2722 assert_not_reached("Unexpect unit file type.");
2723 }
2724
2725 *ret = state;
2726 return 0;
2727 }
2728
2729 int unit_file_get_state(
2730 UnitFileScope scope,
2731 const char *root_dir,
2732 const char *name,
2733 UnitFileState *ret) {
2734
2735 _cleanup_(lookup_paths_free) LookupPaths paths = {};
2736 int r;
2737
2738 assert(scope >= 0);
2739 assert(scope < _UNIT_FILE_SCOPE_MAX);
2740 assert(name);
2741
2742 r = lookup_paths_init(&paths, scope, 0, root_dir);
2743 if (r < 0)
2744 return r;
2745
2746 return unit_file_lookup_state(scope, &paths, name, ret);
2747 }
2748
2749 int unit_file_exists(UnitFileScope scope, const LookupPaths *paths, const char *name) {
2750 _cleanup_(install_context_done) InstallContext c = {};
2751 int r;
2752
2753 assert(paths);
2754 assert(name);
2755
2756 if (!unit_name_is_valid(name, UNIT_NAME_ANY))
2757 return -EINVAL;
2758
2759 r = install_info_discover(scope, &c, paths, name, 0, NULL, NULL, NULL);
2760 if (r == -ENOENT)
2761 return 0;
2762 if (r < 0)
2763 return r;
2764
2765 return 1;
2766 }
2767
2768 static int split_pattern_into_name_and_instances(const char *pattern, char **out_unit_name, char ***out_instances) {
2769 _cleanup_strv_free_ char **instances = NULL;
2770 _cleanup_free_ char *unit_name = NULL;
2771 int r;
2772
2773 assert(pattern);
2774 assert(out_instances);
2775 assert(out_unit_name);
2776
2777 r = extract_first_word(&pattern, &unit_name, NULL, 0);
2778 if (r < 0)
2779 return r;
2780
2781 /* We handle the instances logic when unit name is extracted */
2782 if (pattern) {
2783 /* We only create instances when a rule of templated unit
2784 * is seen. A rule like enable foo@.service a b c will
2785 * result in an array of (a, b, c) as instance names */
2786 if (!unit_name_is_valid(unit_name, UNIT_NAME_TEMPLATE))
2787 return -EINVAL;
2788
2789 instances = strv_split(pattern, WHITESPACE);
2790 if (!instances)
2791 return -ENOMEM;
2792
2793 *out_instances = TAKE_PTR(instances);
2794 }
2795
2796 *out_unit_name = TAKE_PTR(unit_name);
2797
2798 return 0;
2799 }
2800
2801 static int read_presets(UnitFileScope scope, const char *root_dir, Presets *presets) {
2802 _cleanup_(presets_freep) Presets ps = {};
2803 size_t n_allocated = 0;
2804 _cleanup_strv_free_ char **files = NULL;
2805 char **p;
2806 int r;
2807
2808 assert(scope >= 0);
2809 assert(scope < _UNIT_FILE_SCOPE_MAX);
2810 assert(presets);
2811
2812 switch (scope) {
2813 case UNIT_FILE_SYSTEM:
2814 r = conf_files_list(&files, ".preset", root_dir, 0,
2815 "/etc/systemd/system-preset",
2816 "/run/systemd/system-preset",
2817 "/usr/local/lib/systemd/system-preset",
2818 "/usr/lib/systemd/system-preset",
2819 #if HAVE_SPLIT_USR
2820 "/lib/systemd/system-preset",
2821 #endif
2822 NULL);
2823 break;
2824
2825 case UNIT_FILE_GLOBAL:
2826 case UNIT_FILE_USER:
2827 r = conf_files_list(&files, ".preset", root_dir, 0,
2828 "/etc/systemd/user-preset",
2829 "/run/systemd/user-preset",
2830 "/usr/local/lib/systemd/user-preset",
2831 "/usr/lib/systemd/user-preset",
2832 NULL);
2833 break;
2834
2835 default:
2836 assert_not_reached("Invalid unit file scope");
2837 }
2838
2839 if (r < 0)
2840 return r;
2841
2842 STRV_FOREACH(p, files) {
2843 _cleanup_fclose_ FILE *f;
2844 int n = 0;
2845
2846 f = fopen(*p, "re");
2847 if (!f) {
2848 if (errno == ENOENT)
2849 continue;
2850
2851 return -errno;
2852 }
2853
2854 for (;;) {
2855 _cleanup_free_ char *line = NULL;
2856 PresetRule rule = {};
2857 const char *parameter;
2858 char *l;
2859
2860 r = read_line(f, LONG_LINE_MAX, &line);
2861 if (r < 0)
2862 return r;
2863 if (r == 0)
2864 break;
2865
2866 l = strstrip(line);
2867 n++;
2868
2869 if (isempty(l))
2870 continue;
2871 if (strchr(COMMENTS, *l))
2872 continue;
2873
2874 parameter = first_word(l, "enable");
2875 if (parameter) {
2876 char *unit_name;
2877 char **instances = NULL;
2878
2879 /* Unit_name will remain the same as parameter when no instances are specified */
2880 r = split_pattern_into_name_and_instances(parameter, &unit_name, &instances);
2881 if (r < 0) {
2882 log_syntax(NULL, LOG_WARNING, *p, n, r, "Couldn't parse line '%s'. Ignoring.", line);
2883 continue;
2884 }
2885
2886 rule = (PresetRule) {
2887 .pattern = unit_name,
2888 .action = PRESET_ENABLE,
2889 .instances = instances,
2890 };
2891 }
2892
2893 parameter = first_word(l, "disable");
2894 if (parameter) {
2895 char *pattern;
2896
2897 pattern = strdup(parameter);
2898 if (!pattern)
2899 return -ENOMEM;
2900
2901 rule = (PresetRule) {
2902 .pattern = pattern,
2903 .action = PRESET_DISABLE,
2904 };
2905 }
2906
2907 if (rule.action) {
2908 if (!GREEDY_REALLOC(ps.rules, n_allocated, ps.n_rules + 1))
2909 return -ENOMEM;
2910
2911 ps.rules[ps.n_rules++] = rule;
2912 continue;
2913 }
2914
2915 log_syntax(NULL, LOG_WARNING, *p, n, 0, "Couldn't parse line '%s'. Ignoring.", line);
2916 }
2917 }
2918
2919 *presets = ps;
2920 ps = (Presets){};
2921
2922 return 0;
2923 }
2924
2925 static int pattern_match_multiple_instances(
2926 const PresetRule rule,
2927 const char *unit_name,
2928 char ***ret) {
2929
2930 _cleanup_free_ char *templated_name = NULL;
2931 int r;
2932
2933 /* If no ret is needed or the rule itself does not have instances
2934 * initalized, we return not matching */
2935 if (!ret || !rule.instances)
2936 return 0;
2937
2938 r = unit_name_template(unit_name, &templated_name);
2939 if (r < 0)
2940 return r;
2941 if (!streq(rule.pattern, templated_name))
2942 return 0;
2943
2944 /* Compose a list of specified instances when unit name is a template */
2945 if (unit_name_is_valid(unit_name, UNIT_NAME_TEMPLATE)) {
2946 _cleanup_free_ char *prefix = NULL;
2947 _cleanup_strv_free_ char **out_strv = NULL;
2948 char **iter;
2949
2950 r = unit_name_to_prefix(unit_name, &prefix);
2951 if (r < 0)
2952 return r;
2953
2954 STRV_FOREACH(iter, rule.instances) {
2955 _cleanup_free_ char *name = NULL;
2956 r = unit_name_build(prefix, *iter, ".service", &name);
2957 if (r < 0)
2958 return r;
2959 r = strv_extend(&out_strv, name);
2960 if (r < 0)
2961 return r;
2962 }
2963
2964 *ret = TAKE_PTR(out_strv);
2965 return 1;
2966 } else {
2967 /* We now know the input unit name is an instance name */
2968 _cleanup_free_ char *instance_name = NULL;
2969
2970 r = unit_name_to_instance(unit_name, &instance_name);
2971 if (r < 0)
2972 return r;
2973
2974 if (strv_find(rule.instances, instance_name))
2975 return 1;
2976 }
2977 return 0;
2978 }
2979
2980 static int query_presets(const char *name, const Presets presets, char ***instance_name_list) {
2981 PresetAction action = PRESET_UNKNOWN;
2982 size_t i;
2983 char **s;
2984 if (!unit_name_is_valid(name, UNIT_NAME_ANY))
2985 return -EINVAL;
2986
2987 for (i = 0; i < presets.n_rules; i++)
2988 if (pattern_match_multiple_instances(presets.rules[i], name, instance_name_list) > 0 ||
2989 fnmatch(presets.rules[i].pattern, name, FNM_NOESCAPE) == 0) {
2990 action = presets.rules[i].action;
2991 break;
2992 }
2993
2994 switch (action) {
2995 case PRESET_UNKNOWN:
2996 log_debug("Preset files don't specify rule for %s. Enabling.", name);
2997 return 1;
2998 case PRESET_ENABLE:
2999 if (instance_name_list && *instance_name_list)
3000 STRV_FOREACH(s, *instance_name_list)
3001 log_debug("Preset files say enable %s.", *s);
3002 else
3003 log_debug("Preset files say enable %s.", name);
3004 return 1;
3005 case PRESET_DISABLE:
3006 log_debug("Preset files say disable %s.", name);
3007 return 0;
3008 default:
3009 assert_not_reached("invalid preset action");
3010 }
3011 }
3012
3013 int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name) {
3014 _cleanup_(presets_freep) Presets presets = {};
3015 int r;
3016
3017 r = read_presets(scope, root_dir, &presets);
3018 if (r < 0)
3019 return r;
3020
3021 return query_presets(name, presets, NULL);
3022 }
3023
3024 static int execute_preset(
3025 UnitFileScope scope,
3026 UnitFileFlags flags,
3027 InstallContext *plus,
3028 InstallContext *minus,
3029 const LookupPaths *paths,
3030 char **files,
3031 UnitFilePresetMode mode,
3032 UnitFileChange **changes,
3033 size_t *n_changes) {
3034
3035 const char *config_path;
3036 bool force = !!(flags & UNIT_FILE_FORCE);
3037 bool runtime = !!(flags & UNIT_FILE_RUNTIME);
3038 int r = 0, q;
3039
3040 assert(plus);
3041 assert(minus);
3042 assert(paths);
3043
3044 if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) {
3045 _cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
3046
3047 q = install_context_mark_for_removal(scope, minus, paths, &remove_symlinks_to, changes, n_changes);
3048 if (q < 0)
3049 return q;
3050
3051 FOREACH_STRING(config_path, paths->runtime_config, paths->persistent_config) {
3052 q = remove_marked_symlinks(remove_symlinks_to, config_path, paths, false, changes, n_changes);
3053 if (r == 0)
3054 r = q;
3055 }
3056 }
3057
3058 if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) {
3059 /* Returns number of symlinks that where supposed to be installed. */
3060 q = install_context_apply(scope, plus, paths,
3061 runtime ? paths->runtime_config : paths->persistent_config,
3062 force, SEARCH_LOAD, changes, n_changes);
3063 if (r == 0)
3064 r = q;
3065 }
3066
3067 return r;
3068 }
3069
3070 static int preset_prepare_one(
3071 UnitFileScope scope,
3072 InstallContext *plus,
3073 InstallContext *minus,
3074 LookupPaths *paths,
3075 const char *name,
3076 Presets presets,
3077 UnitFileChange **changes,
3078 size_t *n_changes) {
3079
3080 _cleanup_(install_context_done) InstallContext tmp = {};
3081 _cleanup_strv_free_ char **instance_name_list = NULL;
3082 UnitFileInstallInfo *i;
3083 int r;
3084
3085 if (install_info_find(plus, name) || install_info_find(minus, name))
3086 return 0;
3087
3088 r = install_info_discover(scope, &tmp, paths, name, SEARCH_FOLLOW_CONFIG_SYMLINKS,
3089 &i, changes, n_changes);
3090 if (r < 0)
3091 return r;
3092 if (!streq(name, i->name)) {
3093 log_debug("Skipping %s because it is an alias for %s.", name, i->name);
3094 return 0;
3095 }
3096
3097 r = query_presets(name, presets, &instance_name_list);
3098 if (r < 0)
3099 return r;
3100
3101 if (r > 0) {
3102 if (instance_name_list) {
3103 char **s;
3104 STRV_FOREACH(s, instance_name_list) {
3105 r = install_info_discover_and_check(scope, plus, paths, *s, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS,
3106 &i, changes, n_changes);
3107 if (r < 0)
3108 return r;
3109 }
3110 } else {
3111 r = install_info_discover_and_check(scope, plus, paths, name, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS,
3112 &i, changes, n_changes);
3113 if (r < 0)
3114 return r;
3115 }
3116
3117 } else
3118 r = install_info_discover(scope, minus, paths, name, SEARCH_FOLLOW_CONFIG_SYMLINKS,
3119 &i, changes, n_changes);
3120
3121 return r;
3122 }
3123
3124 int unit_file_preset(
3125 UnitFileScope scope,
3126 UnitFileFlags flags,
3127 const char *root_dir,
3128 char **files,
3129 UnitFilePresetMode mode,
3130 UnitFileChange **changes,
3131 size_t *n_changes) {
3132
3133 _cleanup_(install_context_done) InstallContext plus = {}, minus = {};
3134 _cleanup_(lookup_paths_free) LookupPaths paths = {};
3135 _cleanup_(presets_freep) Presets presets = {};
3136 char **i;
3137 int r;
3138
3139 assert(scope >= 0);
3140 assert(scope < _UNIT_FILE_SCOPE_MAX);
3141 assert(mode < _UNIT_FILE_PRESET_MAX);
3142
3143 r = lookup_paths_init(&paths, scope, 0, root_dir);
3144 if (r < 0)
3145 return r;
3146
3147 r = read_presets(scope, root_dir, &presets);
3148 if (r < 0)
3149 return r;
3150
3151 STRV_FOREACH(i, files) {
3152 r = preset_prepare_one(scope, &plus, &minus, &paths, *i, presets, changes, n_changes);
3153 if (r < 0)
3154 return r;
3155 }
3156
3157 return execute_preset(scope, flags, &plus, &minus, &paths, files, mode, changes, n_changes);
3158 }
3159
3160 int unit_file_preset_all(
3161 UnitFileScope scope,
3162 UnitFileFlags flags,
3163 const char *root_dir,
3164 UnitFilePresetMode mode,
3165 UnitFileChange **changes,
3166 size_t *n_changes) {
3167
3168 _cleanup_(install_context_done) InstallContext plus = {}, minus = {};
3169 _cleanup_(lookup_paths_free) LookupPaths paths = {};
3170 _cleanup_(presets_freep) Presets presets = {};
3171 char **i;
3172 int r;
3173
3174 assert(scope >= 0);
3175 assert(scope < _UNIT_FILE_SCOPE_MAX);
3176 assert(mode < _UNIT_FILE_PRESET_MAX);
3177
3178 r = lookup_paths_init(&paths, scope, 0, root_dir);
3179 if (r < 0)
3180 return r;
3181
3182 r = read_presets(scope, root_dir, &presets);
3183 if (r < 0)
3184 return r;
3185
3186 STRV_FOREACH(i, paths.search_path) {
3187 _cleanup_closedir_ DIR *d = NULL;
3188 struct dirent *de;
3189
3190 d = opendir(*i);
3191 if (!d) {
3192 if (errno == ENOENT)
3193 continue;
3194
3195 return -errno;
3196 }
3197
3198 FOREACH_DIRENT(de, d, return -errno) {
3199 if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
3200 continue;
3201
3202 dirent_ensure_type(d, de);
3203
3204 if (!IN_SET(de->d_type, DT_LNK, DT_REG))
3205 continue;
3206
3207 /* we don't pass changes[] in, because we want to handle errors on our own */
3208 r = preset_prepare_one(scope, &plus, &minus, &paths, de->d_name, presets, NULL, 0);
3209 if (r == -ERFKILL)
3210 r = unit_file_changes_add(changes, n_changes,
3211 UNIT_FILE_IS_MASKED, de->d_name, NULL);
3212 else if (r == -ENOLINK)
3213 r = unit_file_changes_add(changes, n_changes,
3214 UNIT_FILE_IS_DANGLING, de->d_name, NULL);
3215 else if (r == -EADDRNOTAVAIL) /* Ignore generated/transient units when applying preset */
3216 continue;
3217 if (r < 0)
3218 return r;
3219 }
3220 }
3221
3222 return execute_preset(scope, flags, &plus, &minus, &paths, NULL, mode, changes, n_changes);
3223 }
3224
3225 static void unit_file_list_free_one(UnitFileList *f) {
3226 if (!f)
3227 return;
3228
3229 free(f->path);
3230 free(f);
3231 }
3232
3233 Hashmap* unit_file_list_free(Hashmap *h) {
3234 return hashmap_free_with_destructor(h, unit_file_list_free_one);
3235 }
3236
3237 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitFileList*, unit_file_list_free_one);
3238
3239 int unit_file_get_list(
3240 UnitFileScope scope,
3241 const char *root_dir,
3242 Hashmap *h,
3243 char **states,
3244 char **patterns) {
3245
3246 _cleanup_(lookup_paths_free) LookupPaths paths = {};
3247 char **i;
3248 int r;
3249
3250 assert(scope >= 0);
3251 assert(scope < _UNIT_FILE_SCOPE_MAX);
3252 assert(h);
3253
3254 r = lookup_paths_init(&paths, scope, 0, root_dir);
3255 if (r < 0)
3256 return r;
3257
3258 STRV_FOREACH(i, paths.search_path) {
3259 _cleanup_closedir_ DIR *d = NULL;
3260 struct dirent *de;
3261
3262 d = opendir(*i);
3263 if (!d) {
3264 if (errno == ENOENT)
3265 continue;
3266 if (IN_SET(errno, ENOTDIR, EACCES)) {
3267 log_debug_errno(errno, "Failed to open \"%s\": %m", *i);
3268 continue;
3269 }
3270
3271 return -errno;
3272 }
3273
3274 FOREACH_DIRENT(de, d, return -errno) {
3275 _cleanup_(unit_file_list_free_onep) UnitFileList *f = NULL;
3276
3277 if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
3278 continue;
3279
3280 if (!strv_fnmatch_or_empty(patterns, de->d_name, FNM_NOESCAPE))
3281 continue;
3282
3283 if (hashmap_get(h, de->d_name))
3284 continue;
3285
3286 dirent_ensure_type(d, de);
3287
3288 if (!IN_SET(de->d_type, DT_LNK, DT_REG))
3289 continue;
3290
3291 f = new0(UnitFileList, 1);
3292 if (!f)
3293 return -ENOMEM;
3294
3295 f->path = path_make_absolute(de->d_name, *i);
3296 if (!f->path)
3297 return -ENOMEM;
3298
3299 r = unit_file_lookup_state(scope, &paths, de->d_name, &f->state);
3300 if (r < 0)
3301 f->state = UNIT_FILE_BAD;
3302
3303 if (!strv_isempty(states) &&
3304 !strv_contains(states, unit_file_state_to_string(f->state)))
3305 continue;
3306
3307 r = hashmap_put(h, basename(f->path), f);
3308 if (r < 0)
3309 return r;
3310
3311 f = NULL; /* prevent cleanup */
3312 }
3313 }
3314
3315 return 0;
3316 }
3317
3318 static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
3319 [UNIT_FILE_ENABLED] = "enabled",
3320 [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
3321 [UNIT_FILE_LINKED] = "linked",
3322 [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
3323 [UNIT_FILE_MASKED] = "masked",
3324 [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
3325 [UNIT_FILE_STATIC] = "static",
3326 [UNIT_FILE_DISABLED] = "disabled",
3327 [UNIT_FILE_INDIRECT] = "indirect",
3328 [UNIT_FILE_GENERATED] = "generated",
3329 [UNIT_FILE_TRANSIENT] = "transient",
3330 [UNIT_FILE_BAD] = "bad",
3331 };
3332
3333 DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
3334
3335 static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
3336 [UNIT_FILE_SYMLINK] = "symlink",
3337 [UNIT_FILE_UNLINK] = "unlink",
3338 [UNIT_FILE_IS_MASKED] = "masked",
3339 [UNIT_FILE_IS_DANGLING] = "dangling",
3340 };
3341
3342 DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);
3343
3344 static const char* const unit_file_preset_mode_table[_UNIT_FILE_PRESET_MAX] = {
3345 [UNIT_FILE_PRESET_FULL] = "full",
3346 [UNIT_FILE_PRESET_ENABLE_ONLY] = "enable-only",
3347 [UNIT_FILE_PRESET_DISABLE_ONLY] = "disable-only",
3348 };
3349
3350 DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode, UnitFilePresetMode);