]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/load-dropin.c
treewide: no need to negate errno for log_*_errno()
[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 log_error("Failed to open directory %s: %m", path);
62 return -errno;
63 }
64
65 for (;;) {
66 struct dirent *de;
67 _cleanup_free_ char *f = NULL;
68 int k;
69
70 errno = 0;
71 de = readdir(d);
72 if (!de && errno != 0) {
73 k = errno;
74 log_error("Failed to read directory %s: %s", path, strerror(k));
75 return -k;
76 }
77
78 if (!de)
79 break;
80
81 if (ignore_file(de->d_name))
82 continue;
83
84 f = strjoin(path, "/", de->d_name, NULL);
85 if (!f)
86 return log_oom();
87
88 r = unit_add_dependency_by_name(u, dependency, de->d_name, f, true);
89 if (r < 0)
90 log_error_errno(r, "Cannot add dependency %s to %s, ignoring: %m", de->d_name, u->id);
91 }
92
93 return 0;
94 }
95
96 static int process_dir(
97 Unit *u,
98 const char *unit_path,
99 const char *name,
100 const char *suffix,
101 UnitDependency dependency,
102 char ***strv) {
103
104 _cleanup_free_ char *path = NULL;
105
106 assert(u);
107 assert(unit_path);
108 assert(name);
109 assert(suffix);
110
111 path = strjoin(unit_path, "/", name, suffix, NULL);
112 if (!path)
113 return log_oom();
114
115 if (!u->manager->unit_path_cache || set_get(u->manager->unit_path_cache, path))
116 iterate_dir(u, path, dependency, strv);
117
118 if (u->instance) {
119 _cleanup_free_ char *template = NULL, *p = NULL;
120 /* Also try the template dir */
121
122 template = unit_name_template(name);
123 if (!template)
124 return log_oom();
125
126 p = strjoin(unit_path, "/", template, suffix, NULL);
127 if (!p)
128 return log_oom();
129
130 if (!u->manager->unit_path_cache || set_get(u->manager->unit_path_cache, p))
131 iterate_dir(u, p, dependency, strv);
132 }
133
134 return 0;
135 }
136
137 char **unit_find_dropin_paths(Unit *u) {
138 _cleanup_strv_free_ char **strv = NULL;
139 char **configs = NULL;
140 Iterator i;
141 char *t;
142 int r;
143
144 assert(u);
145
146 SET_FOREACH(t, u->names, i) {
147 char **p;
148
149 STRV_FOREACH(p, u->manager->lookup_paths.unit_path)
150 process_dir(u, *p, t, ".d", _UNIT_DEPENDENCY_INVALID, &strv);
151 }
152
153 if (strv_isempty(strv))
154 return NULL;
155
156 r = conf_files_list_strv(&configs, ".conf", NULL, (const char**) strv);
157 if (r < 0) {
158 log_error_errno(r, "Failed to get list of configuration files: %m");
159 strv_free(configs);
160 return NULL;
161 }
162
163 return configs;
164 }
165
166 int unit_load_dropin(Unit *u) {
167 Iterator i;
168 char *t, **f;
169
170 assert(u);
171
172 /* Load dependencies from supplementary drop-in directories */
173
174 SET_FOREACH(t, u->names, i) {
175 char **p;
176
177 STRV_FOREACH(p, u->manager->lookup_paths.unit_path) {
178 process_dir(u, *p, t, ".wants", UNIT_WANTS, NULL);
179 process_dir(u, *p, t, ".requires", UNIT_REQUIRES, NULL);
180 }
181 }
182
183 u->dropin_paths = unit_find_dropin_paths(u);
184 if (!u->dropin_paths)
185 return 0;
186
187 STRV_FOREACH(f, u->dropin_paths) {
188 config_parse(u->id, *f, NULL,
189 UNIT_VTABLE(u)->sections,
190 config_item_perf_lookup, load_fragment_gperf_lookup,
191 false, false, false, u);
192 }
193
194 u->dropin_mtime = now(CLOCK_REALTIME);
195
196 return 0;
197 }