]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/dropin.c
util-lib: split our string related calls from util.[ch] into its own file string...
[thirdparty/systemd.git] / src / shared / dropin.c
CommitLineData
29686440
ZJS
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2014 Zbigniew Jędrzejewski-Szmek
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
1a7f1b38 22#include "conf-files.h"
4f5dd394
LP
23#include "escape.h"
24#include "fileio-label.h"
25#include "mkdir.h"
07630cea 26#include "string-util.h"
4f5dd394
LP
27#include "strv.h"
28#include "util.h"
29#include "dropin.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
34 _cleanup_free_ char *b = NULL;
35 char *p, *q;
36
8eea8687
ZJS
37 char prefix[DECIMAL_STR_MAX(unsigned)];
38
29686440
ZJS
39 assert(unit);
40 assert(name);
41 assert(_p);
42 assert(_q);
43
8eea8687
ZJS
44 sprintf(prefix, "%u", level);
45
29686440
ZJS
46 b = xescape(name, "/.");
47 if (!b)
48 return -ENOMEM;
49
ae6c3cc0 50 if (!filename_is_valid(b))
29686440
ZJS
51 return -EINVAL;
52
53 p = strjoin(dir, "/", unit, ".d", NULL);
54 if (!p)
55 return -ENOMEM;
56
8eea8687 57 q = strjoin(p, "/", prefix, "-", b, ".conf", NULL);
29686440
ZJS
58 if (!q) {
59 free(p);
60 return -ENOMEM;
61 }
62
63 *_p = p;
64 *_q = q;
65 return 0;
66}
67
8eea8687 68int write_drop_in(const char *dir, const char *unit, unsigned level,
29686440
ZJS
69 const char *name, const char *data) {
70
71 _cleanup_free_ char *p = NULL, *q = NULL;
72 int r;
73
74 assert(dir);
75 assert(unit);
76 assert(name);
77 assert(data);
78
8eea8687 79 r = drop_in_file(dir, unit, level, name, &p, &q);
29686440
ZJS
80 if (r < 0)
81 return r;
82
45519fd6 83 (void) mkdir_p(p, 0755);
29686440
ZJS
84 return write_string_file_atomic_label(q, data);
85}
86
8eea8687 87int write_drop_in_format(const char *dir, const char *unit, unsigned level,
29686440
ZJS
88 const char *name, const char *format, ...) {
89 _cleanup_free_ char *p = NULL;
90 va_list ap;
91 int r;
92
93 assert(dir);
94 assert(unit);
95 assert(name);
96 assert(format);
97
98 va_start(ap, format);
99 r = vasprintf(&p, format, ap);
100 va_end(ap);
101
102 if (r < 0)
103 return -ENOMEM;
104
8eea8687 105 return write_drop_in(dir, unit, level, name, p);
29686440 106}
1a7f1b38
ZJS
107
108static int iterate_dir(
109 const char *path,
110 UnitDependency dependency,
111 dependency_consumer_t consumer,
112 void *arg,
113 char ***strv) {
114
115 _cleanup_closedir_ DIR *d = NULL;
116 int r;
117
118 assert(path);
119
120 /* The config directories are special, since the order of the
121 * drop-ins matters */
122 if (dependency < 0) {
123 r = strv_extend(strv, path);
124 if (r < 0)
125 return log_oom();
126
127 return 0;
128 }
129
130 assert(consumer);
131
132 d = opendir(path);
133 if (!d) {
134 if (errno == ENOENT)
135 return 0;
136
45519fd6 137 return log_error_errno(errno, "Failed to open directory %s: %m", path);
1a7f1b38
ZJS
138 }
139
140 for (;;) {
141 struct dirent *de;
142 _cleanup_free_ char *f = NULL;
143
144 errno = 0;
145 de = readdir(d);
146 if (!de && errno != 0)
147 return log_error_errno(errno, "Failed to read directory %s: %m", path);
148
149 if (!de)
150 break;
151
a34bf9db 152 if (hidden_file(de->d_name))
1a7f1b38
ZJS
153 continue;
154
155 f = strjoin(path, "/", de->d_name, NULL);
156 if (!f)
157 return log_oom();
158
159 r = consumer(dependency, de->d_name, f, arg);
160 if (r < 0)
161 return r;
162 }
163
164 return 0;
165}
166
167int unit_file_process_dir(
7410616c 168 Set *unit_path_cache,
1a7f1b38
ZJS
169 const char *unit_path,
170 const char *name,
171 const char *suffix,
172 UnitDependency dependency,
173 dependency_consumer_t consumer,
174 void *arg,
175 char ***strv) {
176
177 _cleanup_free_ char *path = NULL;
7410616c 178 int r;
1a7f1b38
ZJS
179
180 assert(unit_path);
181 assert(name);
182 assert(suffix);
183
184 path = strjoin(unit_path, "/", name, suffix, NULL);
185 if (!path)
186 return log_oom();
187
188 if (!unit_path_cache || set_get(unit_path_cache, path))
7410616c 189 (void) iterate_dir(path, dependency, consumer, arg, strv);
1a7f1b38 190
7410616c 191 if (unit_name_is_valid(name, UNIT_NAME_INSTANCE)) {
1a7f1b38
ZJS
192 _cleanup_free_ char *template = NULL, *p = NULL;
193 /* Also try the template dir */
194
7410616c
LP
195 r = unit_name_template(name, &template);
196 if (r < 0)
197 return log_error_errno(r, "Failed to generate template from unit name: %m");
1a7f1b38
ZJS
198
199 p = strjoin(unit_path, "/", template, suffix, NULL);
200 if (!p)
201 return log_oom();
202
203 if (!unit_path_cache || set_get(unit_path_cache, p))
7410616c 204 (void) iterate_dir(p, dependency, consumer, arg, strv);
1a7f1b38
ZJS
205 }
206
207 return 0;
208}
209
210int unit_file_find_dropin_paths(
211 char **lookup_path,
212 Set *unit_path_cache,
213 Set *names,
214 char ***paths) {
215
216 _cleanup_strv_free_ char **strv = NULL, **ans = NULL;
217 Iterator i;
218 char *t;
219 int r;
220
221 assert(paths);
222
223 SET_FOREACH(t, names, i) {
224 char **p;
225
226 STRV_FOREACH(p, lookup_path)
227 unit_file_process_dir(unit_path_cache, *p, t, ".d", _UNIT_DEPENDENCY_INVALID, NULL, NULL, &strv);
228 }
229
230 if (strv_isempty(strv))
231 return 0;
232
233 r = conf_files_list_strv(&ans, ".conf", NULL, (const char**) strv);
234 if (r < 0)
235 return log_warning_errno(r, "Failed to get list of configuration files: %m");
236
237 *paths = ans;
238 ans = NULL;
239 return 1;
240}