Line data Source code
1 : /* SPDX-License-Identifier: LGPL-2.1+ */
2 :
3 : #include "conf-parser.h"
4 : #include "fs-util.h"
5 : #include "load-dropin.h"
6 : #include "load-fragment.h"
7 : #include "log.h"
8 : #include "stat-util.h"
9 : #include "string-util.h"
10 : #include "strv.h"
11 : #include "unit-name.h"
12 : #include "unit.h"
13 :
14 0 : static int unit_name_compatible(const char *a, const char *b) {
15 0 : _cleanup_free_ char *template = NULL;
16 : int r;
17 :
18 : /* The straightforward case: the symlink name matches the target */
19 0 : if (streq(a, b))
20 0 : return 1;
21 :
22 0 : r = unit_name_template(a, &template);
23 0 : if (r == -EINVAL)
24 0 : return 0; /* Not a template */
25 0 : if (r < 0)
26 0 : return r; /* OOM, or some other failure. Just skip the warning. */
27 :
28 : /* An instance name points to a target that is just the template name */
29 0 : return streq(template, b);
30 : }
31 :
32 3586 : static int process_deps(Unit *u, UnitDependency dependency, const char *dir_suffix) {
33 3586 : _cleanup_strv_free_ char **paths = NULL;
34 : char **p;
35 : int r;
36 :
37 7172 : r = unit_file_find_dropin_paths(NULL,
38 3586 : u->manager->lookup_paths.search_path,
39 3586 : u->manager->unit_path_cache,
40 : dir_suffix,
41 : NULL,
42 3586 : u->names,
43 : &paths);
44 3586 : if (r < 0)
45 0 : return r;
46 :
47 3586 : STRV_FOREACH(p, paths) {
48 0 : _cleanup_free_ char *target = NULL;
49 : const char *entry;
50 :
51 0 : entry = basename(*p);
52 :
53 0 : if (null_or_empty_path(*p) > 0) {
54 : /* an error usually means an invalid symlink, which is not a mask */
55 0 : log_unit_debug(u, "%s dependency on %s is masked by %s, ignoring.",
56 : unit_dependency_to_string(dependency), entry, *p);
57 0 : continue;
58 : }
59 :
60 0 : r = is_symlink(*p);
61 0 : if (r < 0) {
62 0 : log_unit_warning_errno(u, r, "%s dropin %s unreadable, ignoring: %m",
63 : unit_dependency_to_string(dependency), *p);
64 0 : continue;
65 : }
66 0 : if (r == 0) {
67 0 : log_unit_warning(u, "%s dependency dropin %s is not a symlink, ignoring.",
68 : unit_dependency_to_string(dependency), *p);
69 0 : continue;
70 : }
71 :
72 0 : if (!unit_name_is_valid(entry, UNIT_NAME_ANY)) {
73 0 : log_unit_warning(u, "%s dependency dropin %s is not a valid unit name, ignoring.",
74 : unit_dependency_to_string(dependency), *p);
75 0 : continue;
76 : }
77 :
78 0 : r = readlink_malloc(*p, &target);
79 0 : if (r < 0) {
80 0 : log_unit_warning_errno(u, r, "readlink(\"%s\") failed, ignoring: %m", *p);
81 0 : continue;
82 : }
83 :
84 : /* We don't treat this as an error, especially because we didn't check this for a
85 : * long time. Nevertheless, we warn, because such mismatch can be mighty confusing. */
86 0 : r = unit_name_compatible(entry, basename(target));
87 0 : if (r < 0) {
88 0 : log_unit_warning_errno(u, r, "Can't check if names %s and %s are compatible, ignoring: %m", entry, basename(target));
89 0 : continue;
90 : }
91 0 : if (r == 0)
92 0 : log_unit_warning(u, "%s dependency dropin %s target %s has different name",
93 : unit_dependency_to_string(dependency), *p, target);
94 :
95 0 : r = unit_add_dependency_by_name(u, dependency, entry, true, UNIT_DEPENDENCY_FILE);
96 0 : if (r < 0)
97 0 : log_unit_warning_errno(u, r, "Cannot add %s dependency on %s, ignoring: %m",
98 : unit_dependency_to_string(dependency), entry);
99 : }
100 :
101 3586 : return 0;
102 : }
103 :
104 1793 : int unit_load_dropin(Unit *u) {
105 1793 : _cleanup_strv_free_ char **l = NULL;
106 : char **f;
107 : int r;
108 :
109 1793 : assert(u);
110 :
111 : /* Load dependencies from .wants and .requires directories */
112 1793 : r = process_deps(u, UNIT_WANTS, ".wants");
113 1793 : if (r < 0)
114 0 : return r;
115 :
116 1793 : r = process_deps(u, UNIT_REQUIRES, ".requires");
117 1793 : if (r < 0)
118 0 : return r;
119 :
120 : /* Load .conf dropins */
121 1793 : r = unit_find_dropin_paths(u, &l);
122 1793 : if (r <= 0)
123 1792 : return 0;
124 :
125 1 : if (!u->dropin_paths)
126 1 : u->dropin_paths = TAKE_PTR(l);
127 : else {
128 0 : r = strv_extend_strv(&u->dropin_paths, l, true);
129 0 : if (r < 0)
130 0 : return log_oom();
131 : }
132 :
133 4 : STRV_FOREACH(f, u->dropin_paths)
134 3 : (void) config_parse(u->id, *f, NULL,
135 3 : UNIT_VTABLE(u)->sections,
136 : config_item_perf_lookup, load_fragment_gperf_lookup,
137 : 0, u);
138 :
139 1 : u->dropin_mtime = now(CLOCK_REALTIME);
140 :
141 1 : return 0;
142 : }
|