]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/dropin.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 Copyright 2014 Zbigniew Jędrzejewski-Szmek
11 #include "alloc-util.h"
12 #include "conf-files.h"
13 #include "dirent-util.h"
17 #include "fileio-label.h"
23 #include "path-util.h"
25 #include "string-util.h"
27 #include "unit-name.h"
29 int drop_in_file(const char *dir
, const char *unit
, unsigned level
,
30 const char *name
, char **_p
, char **_q
) {
32 char prefix
[DECIMAL_STR_MAX(unsigned)];
33 _cleanup_free_
char *b
= NULL
;
41 sprintf(prefix
, "%u", level
);
43 b
= xescape(name
, "/.");
47 if (!filename_is_valid(b
))
50 p
= strjoin(dir
, "/", unit
, ".d");
54 q
= strjoin(p
, "/", prefix
, "-", b
, ".conf");
65 int write_drop_in(const char *dir
, const char *unit
, unsigned level
,
66 const char *name
, const char *data
) {
68 _cleanup_free_
char *p
= NULL
, *q
= NULL
;
76 r
= drop_in_file(dir
, unit
, level
, name
, &p
, &q
);
80 (void) mkdir_p(p
, 0755);
81 return write_string_file_atomic_label(q
, data
);
84 int write_drop_in_format(const char *dir
, const char *unit
, unsigned level
,
85 const char *name
, const char *format
, ...) {
86 _cleanup_free_
char *p
= NULL
;
96 r
= vasprintf(&p
, format
, ap
);
102 return write_drop_in(dir
, unit
, level
, name
, p
);
105 static int unit_file_find_dir(
106 const char *original_root
,
110 _cleanup_free_
char *chased
= NULL
;
115 r
= chase_symlinks(path
, original_root
, 0, &chased
);
116 if (r
== -ENOENT
) /* Ignore -ENOENT, after all most units won't have a drop-in dir. */
118 if (r
== -ENAMETOOLONG
) {
119 /* Also, ignore -ENAMETOOLONG but log about it. After all, users are not even able to create the
120 * drop-in dir in such case. This mostly happens for device units with an overly long /sys path. */
121 log_debug_errno(r
, "Path '%s' too long, couldn't canonicalize, ignoring.", path
);
125 return log_warning_errno(r
, "Failed to canonicalize path '%s': %m", path
);
127 r
= strv_push(dirs
, chased
);
135 static int unit_file_find_dirs(
136 const char *original_root
,
137 Set
*unit_path_cache
,
138 const char *unit_path
,
143 _cleanup_free_
char *prefix
= NULL
, *instance
= NULL
, *built
= NULL
;
144 bool is_instance
, chopped
;
155 path
= strjoina(unit_path
, "/", name
, suffix
);
156 if (!unit_path_cache
|| set_get(unit_path_cache
, path
)) {
157 r
= unit_file_find_dir(original_root
, path
, dirs
);
162 is_instance
= unit_name_is_valid(name
, UNIT_NAME_INSTANCE
);
163 if (is_instance
) { /* Also try the template dir */
164 _cleanup_free_
char *template = NULL
;
166 r
= unit_name_template(name
, &template);
168 return log_error_errno(r
, "Failed to generate template from unit name: %m");
170 r
= unit_file_find_dirs(original_root
, unit_path_cache
, unit_path
, template, suffix
, dirs
);
175 /* Let's see if there's a "-" prefix for this unit name. If so, let's invoke ourselves for it. This will then
176 * recursively do the same for all our prefixes. i.e. this means given "foo-bar-waldo.service" we'll also
177 * search "foo-bar-.service" and "foo-.service".
179 * Note the order in which we do it: we traverse up adding drop-ins on each step. This means the more specific
180 * drop-ins may override the more generic drop-ins, which is the intended behaviour. */
182 r
= unit_name_to_prefix(name
, &prefix
);
184 return log_error_errno(r
, "Failed to derive unit name prefix from unit name: %m");
188 dash
= strrchr(prefix
, '-');
189 if (!dash
) /* No dash? if so we are done */
192 n
= (size_t) (dash
- prefix
);
193 if (n
== 0) /* Leading dash? If so, we are done */
196 if (prefix
[n
+1] != 0 || chopped
) {
201 /* Trailing dash? If so, chop it off and try again, but not more than once. */
206 if (!unit_prefix_is_valid(prefix
))
209 type
= unit_name_to_type(name
);
211 log_error("Failed to to derive unit type from unit name: %s", name
);
216 r
= unit_name_to_instance(name
, &instance
);
218 return log_error_errno(r
, "Failed to derive unit name instance from unit name: %m");
221 r
= unit_name_build_from_type(prefix
, instance
, type
, &built
);
223 return log_error_errno(r
, "Failed to build prefix unit name: %m");
225 return unit_file_find_dirs(original_root
, unit_path_cache
, unit_path
, built
, suffix
, dirs
);
228 int unit_file_find_dropin_paths(
229 const char *original_root
,
231 Set
*unit_path_cache
,
232 const char *dir_suffix
,
233 const char *file_suffix
,
237 _cleanup_strv_free_
char **dirs
= NULL
;
244 SET_FOREACH(t
, names
, i
)
245 STRV_FOREACH(p
, lookup_path
)
246 (void) unit_file_find_dirs(original_root
, unit_path_cache
, *p
, t
, dir_suffix
, &dirs
);
248 if (strv_isempty(dirs
)) {
253 r
= conf_files_list_strv(ret
, file_suffix
, NULL
, 0, (const char**) dirs
);
255 return log_warning_errno(r
, "Failed to create the list of configuration files: %m");