]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/dropin.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
8 #include "alloc-util.h"
9 #include "conf-files.h"
10 #include "dirent-util.h"
14 #include "fileio-label.h"
20 #include "path-util.h"
22 #include "string-util.h"
24 #include "unit-name.h"
26 int drop_in_file(const char *dir
, const char *unit
, unsigned level
,
27 const char *name
, char **_p
, char **_q
) {
29 char prefix
[DECIMAL_STR_MAX(unsigned)];
30 _cleanup_free_
char *b
= NULL
;
38 sprintf(prefix
, "%u", level
);
40 b
= xescape(name
, "/.");
44 if (!filename_is_valid(b
))
47 p
= strjoin(dir
, "/", unit
, ".d");
51 q
= strjoin(p
, "/", prefix
, "-", b
, ".conf");
62 int write_drop_in(const char *dir
, const char *unit
, unsigned level
,
63 const char *name
, const char *data
) {
65 _cleanup_free_
char *p
= NULL
, *q
= NULL
;
73 r
= drop_in_file(dir
, unit
, level
, name
, &p
, &q
);
77 (void) mkdir_p(p
, 0755);
78 return write_string_file_atomic_label(q
, data
);
81 int write_drop_in_format(const char *dir
, const char *unit
, unsigned level
,
82 const char *name
, const char *format
, ...) {
83 _cleanup_free_
char *p
= NULL
;
93 r
= vasprintf(&p
, format
, ap
);
99 return write_drop_in(dir
, unit
, level
, name
, p
);
102 static int unit_file_find_dir(
103 const char *original_root
,
107 _cleanup_free_
char *chased
= NULL
;
112 r
= chase_symlinks(path
, original_root
, 0, &chased
);
113 if (r
== -ENOENT
) /* Ignore -ENOENT, after all most units won't have a drop-in dir. */
115 if (r
== -ENAMETOOLONG
) {
116 /* Also, ignore -ENAMETOOLONG but log about it. After all, users are not even able to create the
117 * drop-in dir in such case. This mostly happens for device units with an overly long /sys path. */
118 log_debug_errno(r
, "Path '%s' too long, couldn't canonicalize, ignoring.", path
);
122 return log_warning_errno(r
, "Failed to canonicalize path '%s': %m", path
);
124 r
= strv_push(dirs
, chased
);
132 static int unit_file_find_dirs(
133 const char *original_root
,
134 Set
*unit_path_cache
,
135 const char *unit_path
,
140 _cleanup_free_
char *prefix
= NULL
, *instance
= NULL
, *built
= NULL
;
141 bool is_instance
, chopped
;
152 path
= strjoina(unit_path
, "/", name
, suffix
);
153 if (!unit_path_cache
|| set_get(unit_path_cache
, path
)) {
154 r
= unit_file_find_dir(original_root
, path
, dirs
);
159 is_instance
= unit_name_is_valid(name
, UNIT_NAME_INSTANCE
);
160 if (is_instance
) { /* Also try the template dir */
161 _cleanup_free_
char *template = NULL
;
163 r
= unit_name_template(name
, &template);
165 return log_error_errno(r
, "Failed to generate template from unit name: %m");
167 r
= unit_file_find_dirs(original_root
, unit_path_cache
, unit_path
, template, suffix
, dirs
);
172 /* Let's see if there's a "-" prefix for this unit name. If so, let's invoke ourselves for it. This will then
173 * recursively do the same for all our prefixes. i.e. this means given "foo-bar-waldo.service" we'll also
174 * search "foo-bar-.service" and "foo-.service".
176 * Note the order in which we do it: we traverse up adding drop-ins on each step. This means the more specific
177 * drop-ins may override the more generic drop-ins, which is the intended behaviour. */
179 r
= unit_name_to_prefix(name
, &prefix
);
181 return log_error_errno(r
, "Failed to derive unit name prefix from unit name: %m");
185 dash
= strrchr(prefix
, '-');
186 if (!dash
) /* No dash? if so we are done */
189 n
= (size_t) (dash
- prefix
);
190 if (n
== 0) /* Leading dash? If so, we are done */
193 if (prefix
[n
+1] != 0 || chopped
) {
198 /* Trailing dash? If so, chop it off and try again, but not more than once. */
203 if (!unit_prefix_is_valid(prefix
))
206 type
= unit_name_to_type(name
);
208 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
209 "Failed to to derive unit type from unit name: %s",
213 r
= unit_name_to_instance(name
, &instance
);
215 return log_error_errno(r
, "Failed to derive unit name instance from unit name: %m");
218 r
= unit_name_build_from_type(prefix
, instance
, type
, &built
);
220 return log_error_errno(r
, "Failed to build prefix unit name: %m");
222 return unit_file_find_dirs(original_root
, unit_path_cache
, unit_path
, built
, suffix
, dirs
);
225 int unit_file_find_dropin_paths(
226 const char *original_root
,
228 Set
*unit_path_cache
,
229 const char *dir_suffix
,
230 const char *file_suffix
,
234 _cleanup_strv_free_
char **dirs
= NULL
;
241 SET_FOREACH(t
, names
, i
)
242 STRV_FOREACH(p
, lookup_path
)
243 (void) unit_file_find_dirs(original_root
, unit_path_cache
, *p
, t
, dir_suffix
, &dirs
);
245 if (strv_isempty(dirs
)) {
250 r
= conf_files_list_strv(ret
, file_suffix
, NULL
, 0, (const char**) dirs
);
252 return log_warning_errno(r
, "Failed to create the list of configuration files: %m");