]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/load-dropin.c
kdbus: update kdbus.h from upstream
[thirdparty/systemd.git] / src / core / load-dropin.c
CommitLineData
d6c9574f 1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
5cb5a6ff 2
a7334b09
LP
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
5430f7f2
LP
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
a7334b09
LP
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
5430f7f2 16 Lesser General Public License for more details.
a7334b09 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
a7334b09
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
0301abf4
LP
22#include <dirent.h>
23#include <errno.h>
24
25#include "unit.h"
5cb5a6ff 26#include "load-dropin.h"
b952f2e1 27#include "log.h"
036643a2 28#include "strv.h"
9e2f7c11 29#include "unit-name.h"
8afbb8e1
LP
30#include "conf-parser.h"
31#include "load-fragment.h"
5926ccca 32#include "conf-files.h"
8afbb8e1 33
5926ccca 34static int iterate_dir(Unit *u, const char *path, UnitDependency dependency, char ***strv) {
8afbb8e1 35 _cleanup_closedir_ DIR *d = NULL;
9e2f7c11
LP
36 int r;
37
99f08d14
LP
38 assert(u);
39 assert(path);
40
5926ccca
LP
41 /* The config directories are special, since the order of the
42 * drop-ins matters */
43 if (dependency < 0) {
44 r = strv_extend(strv, path);
45 if (r < 0)
46 return log_oom();
47
48 return 0;
49 }
50
f917c3e5
LP
51 d = opendir(path);
52 if (!d) {
9e2f7c11
LP
53 if (errno == ENOENT)
54 return 0;
55
56 return -errno;
57 }
58
8afbb8e1
LP
59 for (;;) {
60 struct dirent *de;
61 union dirent_storage buf;
62 _cleanup_free_ char *f = NULL;
63 int k;
64
65 k = readdir_r(d, &buf.de, &de);
66 if (k != 0) {
67 log_error("Failed to read directory %s: %s", path, strerror(k));
68 return -k;
69 }
70
71 if (!de)
72 break;
9e2f7c11
LP
73
74 if (ignore_file(de->d_name))
75 continue;
76
b7def684 77 f = strjoin(path, "/", de->d_name, NULL);
8afbb8e1
LP
78 if (!f)
79 return log_oom();
9e2f7c11 80
5926ccca
LP
81 r = unit_add_dependency_by_name(u, dependency, de->d_name, f, true);
82 if (r < 0)
83 log_error("Cannot add dependency %s to %s, ignoring: %s", de->d_name, u->id, strerror(-r));
9e2f7c11
LP
84 }
85
8afbb8e1 86 return 0;
9e2f7c11 87}
5cb5a6ff 88
5926ccca 89static int process_dir(Unit *u, const char *unit_path, const char *name, const char *suffix, UnitDependency dependency, char ***strv) {
0301abf4 90 int r;
99f08d14 91 char *path;
0301abf4 92
87f0e418 93 assert(u);
99f08d14
LP
94 assert(unit_path);
95 assert(name);
96 assert(suffix);
5cb5a6ff 97
b7def684 98 path = strjoin(unit_path, "/", name, suffix, NULL);
911a4828 99 if (!path)
99f08d14 100 return -ENOMEM;
5cb5a6ff 101
ac155bb8
MS
102 if (u->manager->unit_path_cache &&
103 !set_get(u->manager->unit_path_cache, path))
99f08d14
LP
104 r = 0;
105 else
5926ccca 106 r = iterate_dir(u, path, dependency, strv);
99f08d14 107 free(path);
0301abf4 108
99f08d14
LP
109 if (r < 0)
110 return r;
0301abf4 111
ac155bb8 112 if (u->instance) {
99f08d14
LP
113 char *template;
114 /* Also try the template dir */
0301abf4 115
f917c3e5
LP
116 template = unit_name_template(name);
117 if (!template)
99f08d14 118 return -ENOMEM;
0301abf4 119
b7def684 120 path = strjoin(unit_path, "/", template, suffix, NULL);
99f08d14 121 free(template);
0301abf4 122
cd0ed1db 123 if (!path)
99f08d14 124 return -ENOMEM;
0301abf4 125
ac155bb8
MS
126 if (u->manager->unit_path_cache &&
127 !set_get(u->manager->unit_path_cache, path))
99f08d14
LP
128 r = 0;
129 else
5926ccca 130 r = iterate_dir(u, path, dependency, strv);
99f08d14 131 free(path);
0301abf4 132
99f08d14
LP
133 if (r < 0)
134 return r;
135 }
0301abf4 136
99f08d14
LP
137 return 0;
138}
0301abf4 139
ae7a7182 140char **unit_find_dropin_paths(Unit *u) {
99f08d14
LP
141 Iterator i;
142 char *t;
5926ccca 143 _cleanup_strv_free_ char **strv = NULL;
ae7a7182 144 char **configs = NULL;
5926ccca
LP
145 int r;
146
ae7a7182
OS
147 assert(u);
148
149 SET_FOREACH(t, u->names, i) {
150 char **p;
151
152 STRV_FOREACH(p, u->manager->lookup_paths.unit_path) {
153 /* This loads the drop-in config snippets */
154 r = process_dir(u, *p, t, ".d", _UNIT_DEPENDENCY_INVALID, &strv);
155 if (r < 0)
156 return NULL;
157 }
158 }
159
160 if (!strv_isempty(strv)) {
161 r = conf_files_list_strv(&configs, ".conf", NULL, (const char**) strv);
162 if (r < 0) {
163 log_error("Failed to get list of configuration files: %s", strerror(-r));
164 strv_free(configs);
165 return NULL;
166 }
167
168 }
169
170 return configs;
171}
172
173int unit_load_dropin(Unit *u) {
174 Iterator i;
175 char *t, **f;
ae7a7182 176 int r;
99f08d14
LP
177
178 assert(u);
179
180 /* Load dependencies from supplementary drop-in directories */
036643a2 181
ac155bb8 182 SET_FOREACH(t, u->names, i) {
99f08d14
LP
183 char **p;
184
ac155bb8 185 STRV_FOREACH(p, u->manager->lookup_paths.unit_path) {
5926ccca 186 r = process_dir(u, *p, t, ".wants", UNIT_WANTS, NULL);
f917c3e5 187 if (r < 0)
99f08d14
LP
188 return r;
189
5926ccca 190 r = process_dir(u, *p, t, ".requires", UNIT_REQUIRES, NULL);
f917c3e5 191 if (r < 0)
99f08d14 192 return r;
036643a2 193 }
0301abf4
LP
194 }
195
ae7a7182
OS
196 u->dropin_paths = unit_find_dropin_paths(u);
197 if (! u->dropin_paths)
198 return 0;
5926ccca 199
ae7a7182 200 STRV_FOREACH(f, u->dropin_paths) {
e8e581bf
ZJS
201 r = config_parse(u->id, *f, NULL,
202 UNIT_VTABLE(u)->sections, config_item_perf_lookup,
203 (void*) load_fragment_gperf_lookup, false, u);
ae7a7182 204 if (r < 0)
5926ccca 205 return r;
5926ccca
LP
206 }
207
ae7a7182
OS
208 u->dropin_mtime = now(CLOCK_REALTIME);
209
5cb5a6ff
LP
210 return 0;
211}