]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/load-dropin.c
treewide: use log_*_errno whenever %m is in the format string
[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
aa96c6cb
LP
34static int iterate_dir(
35 Unit *u,
36 const char *path,
37 UnitDependency dependency,
38 char ***strv) {
39
8afbb8e1 40 _cleanup_closedir_ DIR *d = NULL;
9e2f7c11
LP
41 int r;
42
99f08d14
LP
43 assert(u);
44 assert(path);
45
5926ccca
LP
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
f917c3e5
LP
56 d = opendir(path);
57 if (!d) {
9e2f7c11
LP
58 if (errno == ENOENT)
59 return 0;
60
56f64d95 61 log_error_errno(errno, "Failed to open directory %s: %m", path);
9e2f7c11
LP
62 return -errno;
63 }
64
8afbb8e1
LP
65 for (;;) {
66 struct dirent *de;
8afbb8e1 67 _cleanup_free_ char *f = NULL;
8afbb8e1 68
9fa30063
FW
69 errno = 0;
70 de = readdir(d);
23bbb0de
MS
71 if (!de && errno != 0)
72 return log_error_errno(errno, "Failed to read directory %s: %m", path);
8afbb8e1
LP
73
74 if (!de)
75 break;
9e2f7c11
LP
76
77 if (ignore_file(de->d_name))
78 continue;
79
b7def684 80 f = strjoin(path, "/", de->d_name, NULL);
8afbb8e1
LP
81 if (!f)
82 return log_oom();
9e2f7c11 83
5926ccca
LP
84 r = unit_add_dependency_by_name(u, dependency, de->d_name, f, true);
85 if (r < 0)
da927ba9 86 log_error_errno(r, "Cannot add dependency %s to %s, ignoring: %m", de->d_name, u->id);
9e2f7c11
LP
87 }
88
8afbb8e1 89 return 0;
9e2f7c11 90}
5cb5a6ff 91
aa96c6cb
LP
92static int process_dir(
93 Unit *u,
94 const char *unit_path,
95 const char *name,
96 const char *suffix,
97 UnitDependency dependency,
98 char ***strv) {
99
fdb9161c 100 _cleanup_free_ char *path = NULL;
0301abf4 101
87f0e418 102 assert(u);
99f08d14
LP
103 assert(unit_path);
104 assert(name);
105 assert(suffix);
5cb5a6ff 106
b7def684 107 path = strjoin(unit_path, "/", name, suffix, NULL);
911a4828 108 if (!path)
aa96c6cb 109 return log_oom();
5cb5a6ff 110
bcd816bd
LP
111 if (!u->manager->unit_path_cache || set_get(u->manager->unit_path_cache, path))
112 iterate_dir(u, path, dependency, strv);
0301abf4 113
ac155bb8 114 if (u->instance) {
fdb9161c 115 _cleanup_free_ char *template = NULL, *p = NULL;
99f08d14 116 /* Also try the template dir */
0301abf4 117
f917c3e5
LP
118 template = unit_name_template(name);
119 if (!template)
aa96c6cb 120 return log_oom();
0301abf4 121
fdb9161c
LP
122 p = strjoin(unit_path, "/", template, suffix, NULL);
123 if (!p)
aa96c6cb 124 return log_oom();
0301abf4 125
bcd816bd
LP
126 if (!u->manager->unit_path_cache || set_get(u->manager->unit_path_cache, p))
127 iterate_dir(u, p, dependency, strv);
99f08d14 128 }
0301abf4 129
99f08d14
LP
130 return 0;
131}
0301abf4 132
ae7a7182 133char **unit_find_dropin_paths(Unit *u) {
5926ccca 134 _cleanup_strv_free_ char **strv = NULL;
ae7a7182 135 char **configs = NULL;
aa96c6cb
LP
136 Iterator i;
137 char *t;
5926ccca
LP
138 int r;
139
ae7a7182
OS
140 assert(u);
141
142 SET_FOREACH(t, u->names, i) {
143 char **p;
144
bcd816bd
LP
145 STRV_FOREACH(p, u->manager->lookup_paths.unit_path)
146 process_dir(u, *p, t, ".d", _UNIT_DEPENDENCY_INVALID, &strv);
ae7a7182
OS
147 }
148
aa96c6cb
LP
149 if (strv_isempty(strv))
150 return NULL;
ae7a7182 151
aa96c6cb
LP
152 r = conf_files_list_strv(&configs, ".conf", NULL, (const char**) strv);
153 if (r < 0) {
da927ba9 154 log_error_errno(r, "Failed to get list of configuration files: %m");
aa96c6cb
LP
155 strv_free(configs);
156 return NULL;
ae7a7182
OS
157 }
158
159 return configs;
160}
161
162int unit_load_dropin(Unit *u) {
163 Iterator i;
164 char *t, **f;
99f08d14
LP
165
166 assert(u);
167
168 /* Load dependencies from supplementary drop-in directories */
036643a2 169
ac155bb8 170 SET_FOREACH(t, u->names, i) {
99f08d14
LP
171 char **p;
172
ac155bb8 173 STRV_FOREACH(p, u->manager->lookup_paths.unit_path) {
bcd816bd
LP
174 process_dir(u, *p, t, ".wants", UNIT_WANTS, NULL);
175 process_dir(u, *p, t, ".requires", UNIT_REQUIRES, NULL);
036643a2 176 }
0301abf4
LP
177 }
178
ae7a7182 179 u->dropin_paths = unit_find_dropin_paths(u);
e66047ff 180 if (!u->dropin_paths)
ae7a7182 181 return 0;
5926ccca 182
ae7a7182 183 STRV_FOREACH(f, u->dropin_paths) {
bcd816bd 184 config_parse(u->id, *f, NULL,
36f822c4
ZJS
185 UNIT_VTABLE(u)->sections,
186 config_item_perf_lookup, load_fragment_gperf_lookup,
187 false, false, false, u);
5926ccca
LP
188 }
189
ae7a7182
OS
190 u->dropin_mtime = now(CLOCK_REALTIME);
191
5cb5a6ff
LP
192 return 0;
193}