]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/load-dropin.c
man: also mention /run/log/journal in systemd-jouranld.service(8)
[thirdparty/systemd.git] / src / core / load-dropin.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
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
22 #include <dirent.h>
23 #include <errno.h>
24
25 #include "unit.h"
26 #include "load-dropin.h"
27 #include "log.h"
28 #include "strv.h"
29 #include "unit-name.h"
30 #include "conf-parser.h"
31 #include "load-fragment.h"
32 #include "conf-files.h"
33
34 static int iterate_dir(
35 Unit *u,
36 const char *path,
37 UnitDependency dependency,
38 char ***strv) {
39
40 _cleanup_closedir_ DIR *d = NULL;
41 int r;
42
43 assert(u);
44 assert(path);
45
46 /* The config directories are special, since the order of the
47 * drop-ins matters */
48 if (dependency < 0) {
49 r = strv_extend(strv, path);
50 if (r < 0)
51 return log_oom();
52
53 return 0;
54 }
55
56 d = opendir(path);
57 if (!d) {
58 if (errno == ENOENT)
59 return 0;
60
61 return -errno;
62 }
63
64 for (;;) {
65 struct dirent *de;
66 union dirent_storage buf;
67 _cleanup_free_ char *f = NULL;
68 int k;
69
70 k = readdir_r(d, &buf.de, &de);
71 if (k != 0) {
72 log_error("Failed to read directory %s: %s", path, strerror(k));
73 return -k;
74 }
75
76 if (!de)
77 break;
78
79 if (ignore_file(de->d_name))
80 continue;
81
82 f = strjoin(path, "/", de->d_name, NULL);
83 if (!f)
84 return log_oom();
85
86 r = unit_add_dependency_by_name(u, dependency, de->d_name, f, true);
87 if (r < 0)
88 log_error("Cannot add dependency %s to %s, ignoring: %s", de->d_name, u->id, strerror(-r));
89 }
90
91 return 0;
92 }
93
94 static int process_dir(
95 Unit *u,
96 const char *unit_path,
97 const char *name,
98 const char *suffix,
99 UnitDependency dependency,
100 char ***strv) {
101
102 int r;
103 char *path;
104
105 assert(u);
106 assert(unit_path);
107 assert(name);
108 assert(suffix);
109
110 path = strjoin(unit_path, "/", name, suffix, NULL);
111 if (!path)
112 return log_oom();
113
114 if (u->manager->unit_path_cache &&
115 !set_get(u->manager->unit_path_cache, path))
116 r = 0;
117 else
118 r = iterate_dir(u, path, dependency, strv);
119 free(path);
120
121 if (r < 0)
122 return r;
123
124 if (u->instance) {
125 char *template;
126 /* Also try the template dir */
127
128 template = unit_name_template(name);
129 if (!template)
130 return log_oom();
131
132 path = strjoin(unit_path, "/", template, suffix, NULL);
133 free(template);
134
135 if (!path)
136 return log_oom();
137
138 if (u->manager->unit_path_cache &&
139 !set_get(u->manager->unit_path_cache, path))
140 r = 0;
141 else
142 r = iterate_dir(u, path, dependency, strv);
143 free(path);
144
145 if (r < 0)
146 return r;
147 }
148
149 return 0;
150 }
151
152 char **unit_find_dropin_paths(Unit *u) {
153 _cleanup_strv_free_ char **strv = NULL;
154 char **configs = NULL;
155 Iterator i;
156 char *t;
157 int r;
158
159 assert(u);
160
161 SET_FOREACH(t, u->names, i) {
162 char **p;
163
164 STRV_FOREACH(p, u->manager->lookup_paths.unit_path) {
165 /* This loads the drop-in config snippets */
166 r = process_dir(u, *p, t, ".d", _UNIT_DEPENDENCY_INVALID, &strv);
167 if (r < 0)
168 return NULL;
169 }
170 }
171
172 if (strv_isempty(strv))
173 return NULL;
174
175 r = conf_files_list_strv(&configs, ".conf", NULL, (const char**) strv);
176 if (r < 0) {
177 log_error("Failed to get list of configuration files: %s", strerror(-r));
178 strv_free(configs);
179 return NULL;
180 }
181
182 return configs;
183 }
184
185 int unit_load_dropin(Unit *u) {
186 Iterator i;
187 char *t, **f;
188 int r;
189
190 assert(u);
191
192 /* Load dependencies from supplementary drop-in directories */
193
194 SET_FOREACH(t, u->names, i) {
195 char **p;
196
197 STRV_FOREACH(p, u->manager->lookup_paths.unit_path) {
198 r = process_dir(u, *p, t, ".wants", UNIT_WANTS, NULL);
199 if (r < 0)
200 return r;
201
202 r = process_dir(u, *p, t, ".requires", UNIT_REQUIRES, NULL);
203 if (r < 0)
204 return r;
205 }
206 }
207
208 u->dropin_paths = unit_find_dropin_paths(u);
209 if (! u->dropin_paths)
210 return 0;
211
212 STRV_FOREACH(f, u->dropin_paths) {
213 r = config_parse(u->id, *f, NULL,
214 UNIT_VTABLE(u)->sections, config_item_perf_lookup,
215 (void*) load_fragment_gperf_lookup, false, false, u);
216 if (r < 0)
217 return r;
218 }
219
220 u->dropin_mtime = now(CLOCK_REALTIME);
221
222 return 0;
223 }