]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/dropin.c
load-dropin: rename variable
[thirdparty/systemd.git] / src / shared / dropin.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
29686440
ZJS
2/***
3 This file is part of systemd.
4
5 Copyright 2014 Zbigniew Jędrzejewski-Szmek
29686440
ZJS
6***/
7
a8fbdf54
TA
8#include <errno.h>
9#include <stdarg.h>
10#include <stdio.h>
11#include <stdlib.h>
12
b5efdb8a 13#include "alloc-util.h"
1a7f1b38 14#include "conf-files.h"
8fb3f009 15#include "dirent-util.h"
3ffd4af2 16#include "dropin.h"
4f5dd394 17#include "escape.h"
3ffd4af2 18#include "fd-util.h"
4f5dd394 19#include "fileio-label.h"
17e78d18 20#include "fs-util.h"
a8fbdf54
TA
21#include "hashmap.h"
22#include "log.h"
23#include "macro.h"
4f5dd394 24#include "mkdir.h"
bb15fafe 25#include "path-util.h"
a8fbdf54 26#include "set.h"
07630cea 27#include "string-util.h"
4f5dd394 28#include "strv.h"
a8fbdf54 29#include "unit-name.h"
29686440 30
8eea8687 31int drop_in_file(const char *dir, const char *unit, unsigned level,
29686440
ZJS
32 const char *name, char **_p, char **_q) {
33
09c62487 34 char prefix[DECIMAL_STR_MAX(unsigned)];
29686440
ZJS
35 _cleanup_free_ char *b = NULL;
36 char *p, *q;
37
38 assert(unit);
39 assert(name);
40 assert(_p);
41 assert(_q);
42
8eea8687
ZJS
43 sprintf(prefix, "%u", level);
44
29686440
ZJS
45 b = xescape(name, "/.");
46 if (!b)
47 return -ENOMEM;
48
ae6c3cc0 49 if (!filename_is_valid(b))
29686440
ZJS
50 return -EINVAL;
51
605405c6 52 p = strjoin(dir, "/", unit, ".d");
29686440
ZJS
53 if (!p)
54 return -ENOMEM;
55
605405c6 56 q = strjoin(p, "/", prefix, "-", b, ".conf");
29686440
ZJS
57 if (!q) {
58 free(p);
59 return -ENOMEM;
60 }
61
62 *_p = p;
63 *_q = q;
64 return 0;
65}
66
8eea8687 67int write_drop_in(const char *dir, const char *unit, unsigned level,
29686440
ZJS
68 const char *name, const char *data) {
69
70 _cleanup_free_ char *p = NULL, *q = NULL;
71 int r;
72
73 assert(dir);
74 assert(unit);
75 assert(name);
76 assert(data);
77
8eea8687 78 r = drop_in_file(dir, unit, level, name, &p, &q);
29686440
ZJS
79 if (r < 0)
80 return r;
81
45519fd6 82 (void) mkdir_p(p, 0755);
29686440
ZJS
83 return write_string_file_atomic_label(q, data);
84}
85
8eea8687 86int write_drop_in_format(const char *dir, const char *unit, unsigned level,
29686440
ZJS
87 const char *name, const char *format, ...) {
88 _cleanup_free_ char *p = NULL;
89 va_list ap;
90 int r;
91
92 assert(dir);
93 assert(unit);
94 assert(name);
95 assert(format);
96
97 va_start(ap, format);
98 r = vasprintf(&p, format, ap);
99 va_end(ap);
100
101 if (r < 0)
102 return -ENOMEM;
103
8eea8687 104 return write_drop_in(dir, unit, level, name, p);
29686440 105}
1a7f1b38 106
dcc4f30e 107static int unit_file_find_dir(
17e78d18 108 const char *original_root,
dcc4f30e
ZJS
109 const char *path,
110 char ***dirs) {
1a7f1b38 111
17e78d18 112 _cleanup_free_ char *chased = NULL;
1a7f1b38
ZJS
113 int r;
114
115 assert(path);
116
17e78d18 117 r = chase_symlinks(path, original_root, 0, &chased);
dfeec916
LN
118 /* Ignore -ENOENT, after all most units won't have a drop-in dir.
119 * Also ignore -ENAMETOOLONG, users are not even able to create
120 * the drop-in dir in such case. This mostly happens for device units with long /sys path.
121 * */
122 if (IN_SET(r, -ENOENT, -ENAMETOOLONG))
09c62487 123 return 0;
17e78d18 124 if (r < 0)
09c62487 125 return log_full_errno(LOG_WARNING, r, "Failed to canonicalize path %s: %m", path);
17e78d18 126
dcc4f30e
ZJS
127 r = strv_push(dirs, chased);
128 if (r < 0)
129 return log_oom();
1a7f1b38 130
dcc4f30e 131 chased = NULL;
1a7f1b38
ZJS
132 return 0;
133}
134
dcc4f30e 135static int unit_file_find_dirs(
17e78d18 136 const char *original_root,
7410616c 137 Set *unit_path_cache,
1a7f1b38
ZJS
138 const char *unit_path,
139 const char *name,
140 const char *suffix,
dcc4f30e 141 char ***dirs) {
1a7f1b38 142
96bb2fd8 143 char *path;
7410616c 144 int r;
1a7f1b38
ZJS
145
146 assert(unit_path);
147 assert(name);
148 assert(suffix);
149
96bb2fd8 150 path = strjoina(unit_path, "/", name, suffix);
1a7f1b38 151
dcc4f30e
ZJS
152 if (!unit_path_cache || set_get(unit_path_cache, path)) {
153 r = unit_file_find_dir(original_root, path, dirs);
154 if (r < 0)
155 return r;
156 }
1a7f1b38 157
7410616c 158 if (unit_name_is_valid(name, UNIT_NAME_INSTANCE)) {
1a7f1b38
ZJS
159 /* Also try the template dir */
160
a09d3eaf
LP
161 _cleanup_free_ char *template = NULL;
162
7410616c
LP
163 r = unit_name_template(name, &template);
164 if (r < 0)
165 return log_error_errno(r, "Failed to generate template from unit name: %m");
1a7f1b38 166
a09d3eaf 167 return unit_file_find_dirs(original_root, unit_path_cache, unit_path, template, suffix, dirs);
1a7f1b38
ZJS
168 }
169
170 return 0;
171}
172
173int unit_file_find_dropin_paths(
17e78d18 174 const char *original_root,
1a7f1b38
ZJS
175 char **lookup_path,
176 Set *unit_path_cache,
95778782
ZJS
177 const char *dir_suffix,
178 const char *file_suffix,
1a7f1b38 179 Set *names,
058db925 180 char ***ret) {
1a7f1b38 181
3f6de63b 182 _cleanup_strv_free_ char **dirs = NULL;
1a7f1b38 183 Iterator i;
dcc4f30e 184 char *t, **p;
1a7f1b38
ZJS
185 int r;
186
058db925 187 assert(ret);
1a7f1b38 188
dcc4f30e 189 SET_FOREACH(t, names, i)
1a7f1b38 190 STRV_FOREACH(p, lookup_path)
dcc4f30e 191 unit_file_find_dirs(original_root, unit_path_cache, *p, t, dir_suffix, &dirs);
1a7f1b38 192
058db925
LP
193 if (strv_isempty(dirs)) {
194 *ret = NULL;
1a7f1b38 195 return 0;
058db925 196 }
1a7f1b38 197
b5084605 198 r = conf_files_list_strv(ret, file_suffix, NULL, 0, (const char**) dirs);
1a7f1b38 199 if (r < 0)
3f6de63b 200 return log_warning_errno(r, "Failed to create the list of configuration files: %m");
058db925 201
1a7f1b38
ZJS
202 return 1;
203}