]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/load-dropin.c
Merge pull request #7379 from yuwata/follow-up-7309
[thirdparty/systemd.git] / src / core / load-dropin.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright 2010 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21
22 #include "conf-parser.h"
23 #include "fs-util.h"
24 #include "load-dropin.h"
25 #include "load-fragment.h"
26 #include "log.h"
27 #include "stat-util.h"
28 #include "string-util.h"
29 #include "strv.h"
30 #include "unit-name.h"
31 #include "unit.h"
32
33 static int unit_name_compatible(const char *a, const char *b) {
34 _cleanup_free_ char *prefix = NULL;
35 int r;
36
37 /* the straightforward case: the symlink name matches the target */
38 if (streq(a, b))
39 return 1;
40
41 r = unit_name_template(a, &prefix);
42 if (r == -EINVAL)
43 /* not a template */
44 return 0;
45 if (r < 0)
46 /* oom, or some other failure. Just skip the warning. */
47 return r;
48
49 /* an instance name points to a target that is just the template name */
50 if (streq(prefix, b))
51 return 1;
52
53 return 0;
54 }
55
56 static int process_deps(Unit *u, UnitDependency dependency, const char *dir_suffix) {
57 _cleanup_strv_free_ char **paths = NULL;
58 char **p;
59 int r;
60
61 r = unit_file_find_dropin_paths(NULL,
62 u->manager->lookup_paths.search_path,
63 u->manager->unit_path_cache,
64 dir_suffix,
65 NULL,
66 u->names,
67 &paths);
68 if (r < 0)
69 return r;
70
71 STRV_FOREACH(p, paths) {
72 const char *entry;
73 _cleanup_free_ char *target = NULL;
74
75 entry = basename(*p);
76
77 if (null_or_empty_path(*p) > 0) {
78 /* an error usually means an invalid symlink, which is not a mask */
79 log_unit_debug(u, "%s dependency on %s is masked by %s, ignoring.",
80 unit_dependency_to_string(dependency), entry, *p);
81 continue;
82 }
83
84 r = is_symlink(*p);
85 if (r < 0) {
86 log_unit_warning_errno(u, r, "%s dropin %s unreadable, ignoring: %m",
87 unit_dependency_to_string(dependency), *p);
88 continue;
89 }
90 if (r == 0) {
91 log_unit_warning(u, "%s dependency dropin %s is not a symlink, ignoring.",
92 unit_dependency_to_string(dependency), *p);
93 continue;
94 }
95
96 if (!unit_name_is_valid(entry, UNIT_NAME_ANY)) {
97 log_unit_warning(u, "%s dependency dropin %s is not a valid unit name, ignoring.",
98 unit_dependency_to_string(dependency), *p);
99 continue;
100 }
101
102 r = readlink_malloc(*p, &target);
103 if (r < 0) {
104 log_unit_warning_errno(u, r, "readlink(\"%s\") failed, ignoring: %m", *p);
105 continue;
106 }
107
108 /* We don't treat this as an error, especially because we didn't check this for a
109 * long time. Nevertheless, we warn, because such mismatch can be mighty confusing. */
110 r = unit_name_compatible(entry, basename(target));
111 if (r < 0) {
112 log_unit_warning_errno(u, r, "Can't check if names %s and %s are compatible, ignoring: %m", entry, basename(target));
113 continue;
114 }
115 if (r == 0)
116 log_unit_warning(u, "%s dependency dropin %s target %s has different name",
117 unit_dependency_to_string(dependency), *p, target);
118
119 r = unit_add_dependency_by_name(u, dependency, entry, *p, true, UNIT_DEPENDENCY_FILE);
120 if (r < 0)
121 log_unit_warning_errno(u, r, "Cannot add %s dependency on %s, ignoring: %m",
122 unit_dependency_to_string(dependency), entry);
123 }
124
125 return 0;
126 }
127
128 int unit_load_dropin(Unit *u) {
129 _cleanup_strv_free_ char **l = NULL;
130 char **f;
131 int r;
132
133 assert(u);
134
135 /* Load dependencies from .wants and .requires directories */
136 r = process_deps(u, UNIT_WANTS, ".wants");
137 if (r < 0)
138 return r;
139
140 r = process_deps(u, UNIT_REQUIRES, ".requires");
141 if (r < 0)
142 return r;
143
144 /* Load .conf dropins */
145 r = unit_find_dropin_paths(u, &l);
146 if (r <= 0)
147 return 0;
148
149 if (!u->dropin_paths) {
150 u->dropin_paths = l;
151 l = NULL;
152 } else {
153 r = strv_extend_strv(&u->dropin_paths, l, true);
154 if (r < 0)
155 return log_oom();
156 }
157
158 STRV_FOREACH(f, u->dropin_paths)
159 (void) config_parse(u->id, *f, NULL,
160 UNIT_VTABLE(u)->sections,
161 config_item_perf_lookup, load_fragment_gperf_lookup,
162 0, u);
163
164 u->dropin_mtime = now(CLOCK_REALTIME);
165
166 return 0;
167 }