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