]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-install-root.c
2 This file is part of systemd.
4 Copyright 2011 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 #include "alloc-util.h"
26 #include "string-util.h"
28 static void test_basic_mask_and_enable(const char *root
) {
31 UnitFileChange
*changes
= NULL
;
32 unsigned n_changes
= 0;
34 log_set_max_level(LOG_DEBUG
);
36 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "a.service", NULL
) == -ENOENT
);
37 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "b.service", NULL
) == -ENOENT
);
38 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "c.service", NULL
) == -ENOENT
);
39 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "d.service", NULL
) == -ENOENT
);
41 p
= strjoina(root
, "/usr/lib/systemd/system/a.service");
42 assert_se(write_string_file(p
,
44 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
46 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "a.service", NULL
) >= 0);
47 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "a.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
49 p
= strjoina(root
, "/usr/lib/systemd/system/b.service");
50 assert_se(symlink("a.service", p
) >= 0);
52 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "b.service", NULL
) >= 0);
53 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "b.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
55 p
= strjoina(root
, "/usr/lib/systemd/system/c.service");
56 assert_se(symlink("/usr/lib/systemd/system/a.service", p
) >= 0);
58 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "c.service", NULL
) >= 0);
59 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "c.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
61 p
= strjoina(root
, "/usr/lib/systemd/system/d.service");
62 assert_se(symlink("c.service", p
) >= 0);
64 /* This one is interesting, as d follows a relative, then an absolute symlink */
65 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "d.service", NULL
) >= 0);
66 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "d.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
68 assert_se(unit_file_mask(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("a.service"), &changes
, &n_changes
) >= 0);
69 assert_se(n_changes
== 1);
70 assert_se(changes
[0].type
== UNIT_FILE_SYMLINK
);
71 assert_se(streq(changes
[0].source
, "/dev/null"));
72 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/a.service");
73 assert_se(streq(changes
[0].path
, p
));
75 unit_file_changes_free(changes
, n_changes
);
76 changes
= NULL
; n_changes
= 0;
78 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "a.service", &state
) >= 0 && state
== UNIT_FILE_MASKED
);
79 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "b.service", &state
) >= 0 && state
== UNIT_FILE_MASKED
);
80 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "c.service", &state
) >= 0 && state
== UNIT_FILE_MASKED
);
81 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "d.service", &state
) >= 0 && state
== UNIT_FILE_MASKED
);
83 /* Enabling a masked unit should fail! */
84 assert_se(unit_file_enable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("a.service"), &changes
, &n_changes
) == -ERFKILL
);
85 unit_file_changes_free(changes
, n_changes
);
86 changes
= NULL
; n_changes
= 0;
88 assert_se(unit_file_unmask(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("a.service"), &changes
, &n_changes
) >= 0);
89 assert_se(n_changes
== 1);
90 assert_se(changes
[0].type
== UNIT_FILE_UNLINK
);
91 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/a.service");
92 assert_se(streq(changes
[0].path
, p
));
93 unit_file_changes_free(changes
, n_changes
);
94 changes
= NULL
; n_changes
= 0;
96 assert_se(unit_file_enable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("a.service"), &changes
, &n_changes
) == 1);
97 assert_se(n_changes
== 1);
98 assert_se(changes
[0].type
== UNIT_FILE_SYMLINK
);
99 assert_se(streq(changes
[0].source
, "/usr/lib/systemd/system/a.service"));
100 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/multi-user.target.wants/a.service");
101 assert_se(streq(changes
[0].path
, p
));
102 unit_file_changes_free(changes
, n_changes
);
103 changes
= NULL
; n_changes
= 0;
105 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "a.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
106 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "b.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
107 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "c.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
108 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "d.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
110 /* Enabling it again should succeed but be a NOP */
111 assert_se(unit_file_enable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("a.service"), &changes
, &n_changes
) >= 0);
112 assert_se(n_changes
== 0);
113 unit_file_changes_free(changes
, n_changes
);
114 changes
= NULL
; n_changes
= 0;
116 assert_se(unit_file_disable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("a.service"), &changes
, &n_changes
) >= 0);
117 assert_se(n_changes
== 1);
118 assert_se(changes
[0].type
== UNIT_FILE_UNLINK
);
119 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/multi-user.target.wants/a.service");
120 assert_se(streq(changes
[0].path
, p
));
121 unit_file_changes_free(changes
, n_changes
);
122 changes
= NULL
; n_changes
= 0;
124 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "a.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
125 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "b.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
126 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "c.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
127 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "d.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
129 /* Disabling a disabled unit must suceed but be a NOP */
130 assert_se(unit_file_disable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("a.service"), &changes
, &n_changes
) >= 0);
131 assert_se(n_changes
== 0);
132 unit_file_changes_free(changes
, n_changes
);
133 changes
= NULL
; n_changes
= 0;
135 /* Let's enable this indirectly via a symlink */
136 assert_se(unit_file_enable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("d.service"), &changes
, &n_changes
) >= 0);
137 assert_se(n_changes
== 1);
138 assert_se(changes
[0].type
== UNIT_FILE_SYMLINK
);
139 assert_se(streq(changes
[0].source
, "/usr/lib/systemd/system/a.service"));
140 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/multi-user.target.wants/a.service");
141 assert_se(streq(changes
[0].path
, p
));
142 unit_file_changes_free(changes
, n_changes
);
143 changes
= NULL
; n_changes
= 0;
145 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "a.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
146 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "b.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
147 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "c.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
148 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "d.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
150 /* Let's try to reenable */
152 assert_se(unit_file_reenable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("b.service"), &changes
, &n_changes
) >= 0);
153 assert_se(n_changes
== 2);
154 assert_se(changes
[0].type
== UNIT_FILE_UNLINK
);
155 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/multi-user.target.wants/a.service");
156 assert_se(streq(changes
[0].path
, p
));
157 assert_se(changes
[1].type
== UNIT_FILE_SYMLINK
);
158 assert_se(streq(changes
[1].source
, "/usr/lib/systemd/system/a.service"));
159 assert_se(streq(changes
[1].path
, p
));
160 unit_file_changes_free(changes
, n_changes
);
161 changes
= NULL
; n_changes
= 0;
163 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "a.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
164 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "b.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
165 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "c.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
166 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "d.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
169 static void test_linked_units(const char *root
) {
172 UnitFileChange
*changes
= NULL
;
173 unsigned n_changes
= 0, i
;
176 * We'll test three cases here:
178 * a) a unit file in /opt, that we use "systemctl link" and
179 * "systemctl enable" on to make it available to the system
181 * b) a unit file in /opt, that is statically linked into
182 * /usr/lib/systemd/system, that "enable" should work on
185 * c) a unit file in /opt, that is linked into
186 * /etc/systemd/system, and where "enable" should result in
187 * -ELOOP, since using information from /etc to generate
188 * information in /etc should not be allowed.
191 p
= strjoina(root
, "/opt/linked.service");
192 assert_se(write_string_file(p
,
194 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
196 p
= strjoina(root
, "/opt/linked2.service");
197 assert_se(write_string_file(p
,
199 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
201 p
= strjoina(root
, "/opt/linked3.service");
202 assert_se(write_string_file(p
,
204 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
206 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "linked.service", NULL
) == -ENOENT
);
207 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "linked2.service", NULL
) == -ENOENT
);
208 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "linked3.service", NULL
) == -ENOENT
);
210 p
= strjoina(root
, "/usr/lib/systemd/system/linked2.service");
211 assert_se(symlink("/opt/linked2.service", p
) >= 0);
213 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/linked3.service");
214 assert_se(symlink("/opt/linked3.service", p
) >= 0);
216 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "linked.service", &state
) == -ENOENT
);
217 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "linked2.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
218 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "linked3.service", &state
) >= 0 && state
== UNIT_FILE_LINKED
);
220 /* First, let's link the unit into the search path */
221 assert_se(unit_file_link(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("/opt/linked.service"), &changes
, &n_changes
) >= 0);
222 assert_se(n_changes
== 1);
223 assert_se(changes
[0].type
== UNIT_FILE_SYMLINK
);
224 assert_se(streq(changes
[0].source
, "/opt/linked.service"));
225 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/linked.service");
226 assert_se(streq(changes
[0].path
, p
));
227 unit_file_changes_free(changes
, n_changes
);
228 changes
= NULL
; n_changes
= 0;
230 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "linked.service", &state
) >= 0 && state
== UNIT_FILE_LINKED
);
232 /* Let's unlink it from the search path again */
233 assert_se(unit_file_disable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("linked.service"), &changes
, &n_changes
) >= 0);
234 assert_se(n_changes
== 1);
235 assert_se(changes
[0].type
== UNIT_FILE_UNLINK
);
236 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/linked.service");
237 assert_se(streq(changes
[0].path
, p
));
238 unit_file_changes_free(changes
, n_changes
);
239 changes
= NULL
; n_changes
= 0;
241 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "linked.service", NULL
) == -ENOENT
);
243 /* Now, let's not just link it, but also enable it */
244 assert_se(unit_file_enable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("/opt/linked.service"), &changes
, &n_changes
) >= 0);
245 assert_se(n_changes
== 2);
246 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/multi-user.target.wants/linked.service");
247 q
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/linked.service");
248 for (i
= 0 ; i
< n_changes
; i
++) {
249 assert_se(changes
[i
].type
== UNIT_FILE_SYMLINK
);
250 assert_se(streq(changes
[i
].source
, "/opt/linked.service"));
252 if (p
&& streq(changes
[i
].path
, p
))
254 else if (q
&& streq(changes
[i
].path
, q
))
257 assert_not_reached("wut?");
260 unit_file_changes_free(changes
, n_changes
);
261 changes
= NULL
; n_changes
= 0;
263 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "linked.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
265 /* And let's unlink it again */
266 assert_se(unit_file_disable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("linked.service"), &changes
, &n_changes
) >= 0);
267 assert_se(n_changes
== 2);
268 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/multi-user.target.wants/linked.service");
269 q
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/linked.service");
270 for (i
= 0; i
< n_changes
; i
++) {
271 assert_se(changes
[i
].type
== UNIT_FILE_UNLINK
);
273 if (p
&& streq(changes
[i
].path
, p
))
275 else if (q
&& streq(changes
[i
].path
, q
))
278 assert_not_reached("wut?");
281 unit_file_changes_free(changes
, n_changes
);
282 changes
= NULL
; n_changes
= 0;
284 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "linked.service", NULL
) == -ENOENT
);
286 assert_se(unit_file_enable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("linked2.service"), &changes
, &n_changes
) >= 0);
287 assert_se(n_changes
== 2);
288 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/multi-user.target.wants/linked2.service");
289 q
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/linked2.service");
290 for (i
= 0 ; i
< n_changes
; i
++) {
291 assert_se(changes
[i
].type
== UNIT_FILE_SYMLINK
);
292 assert_se(streq(changes
[i
].source
, "/opt/linked2.service"));
294 if (p
&& streq(changes
[i
].path
, p
))
296 else if (q
&& streq(changes
[i
].path
, q
))
299 assert_not_reached("wut?");
302 unit_file_changes_free(changes
, n_changes
);
303 changes
= NULL
; n_changes
= 0;
305 assert_se(unit_file_enable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("linked3.service"), &changes
, &n_changes
) >= 0);
306 assert_se(n_changes
== 1);
307 assert_se(changes
[0].type
== UNIT_FILE_SYMLINK
);
308 assert_se(startswith(changes
[0].path
, root
));
309 assert_se(endswith(changes
[0].path
, "linked3.service"));
310 assert_se(streq(changes
[0].source
, "/opt/linked3.service"));
311 unit_file_changes_free(changes
, n_changes
);
312 changes
= NULL
; n_changes
= 0;
315 static void test_default(const char *root
) {
316 _cleanup_free_
char *def
= NULL
;
317 UnitFileChange
*changes
= NULL
;
318 unsigned n_changes
= 0;
321 p
= strjoina(root
, "/usr/lib/systemd/system/test-default-real.target");
322 assert_se(write_string_file(p
, "# pretty much empty", WRITE_STRING_FILE_CREATE
) >= 0);
324 p
= strjoina(root
, "/usr/lib/systemd/system/test-default.target");
325 assert_se(symlink("test-default-real.target", p
) >= 0);
327 assert_se(unit_file_get_default(UNIT_FILE_SYSTEM
, root
, &def
) == -ENOENT
);
329 assert_se(unit_file_set_default(UNIT_FILE_SYSTEM
, 0, root
, "idontexist.target", &changes
, &n_changes
) == -ENOENT
);
330 assert_se(n_changes
== 1);
331 assert_se(changes
[0].type
== -ENOENT
);
332 assert_se(streq_ptr(changes
[0].path
, "idontexist.target"));
333 unit_file_changes_free(changes
, n_changes
);
334 changes
= NULL
; n_changes
= 0;
336 assert_se(unit_file_get_default(UNIT_FILE_SYSTEM
, root
, &def
) == -ENOENT
);
338 assert_se(unit_file_set_default(UNIT_FILE_SYSTEM
, 0, root
, "test-default.target", &changes
, &n_changes
) >= 0);
339 assert_se(n_changes
== 1);
340 assert_se(changes
[0].type
== UNIT_FILE_SYMLINK
);
341 assert_se(streq(changes
[0].source
, "/usr/lib/systemd/system/test-default-real.target"));
342 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/" SPECIAL_DEFAULT_TARGET
);
343 assert_se(streq(changes
[0].path
, p
));
344 unit_file_changes_free(changes
, n_changes
);
345 changes
= NULL
; n_changes
= 0;
347 assert_se(unit_file_get_default(UNIT_FILE_SYSTEM
, root
, &def
) >= 0);
348 assert_se(streq_ptr(def
, "test-default-real.target"));
351 static void test_add_dependency(const char *root
) {
352 UnitFileChange
*changes
= NULL
;
353 unsigned n_changes
= 0;
356 p
= strjoina(root
, "/usr/lib/systemd/system/real-add-dependency-test-target.target");
357 assert_se(write_string_file(p
, "# pretty much empty", WRITE_STRING_FILE_CREATE
) >= 0);
359 p
= strjoina(root
, "/usr/lib/systemd/system/add-dependency-test-target.target");
360 assert_se(symlink("real-add-dependency-test-target.target", p
) >= 0);
362 p
= strjoina(root
, "/usr/lib/systemd/system/real-add-dependency-test-service.service");
363 assert_se(write_string_file(p
, "# pretty much empty", WRITE_STRING_FILE_CREATE
) >= 0);
365 p
= strjoina(root
, "/usr/lib/systemd/system/add-dependency-test-service.service");
366 assert_se(symlink("real-add-dependency-test-service.service", p
) >= 0);
368 assert_se(unit_file_add_dependency(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("add-dependency-test-service.service"), "add-dependency-test-target.target", UNIT_WANTS
, &changes
, &n_changes
) >= 0);
369 assert_se(n_changes
== 1);
370 assert_se(changes
[0].type
== UNIT_FILE_SYMLINK
);
371 assert_se(streq(changes
[0].source
, "/usr/lib/systemd/system/real-add-dependency-test-service.service"));
372 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/real-add-dependency-test-target.target.wants/real-add-dependency-test-service.service");
373 assert_se(streq(changes
[0].path
, p
));
374 unit_file_changes_free(changes
, n_changes
);
375 changes
= NULL
; n_changes
= 0;
378 static void test_template_enable(const char *root
) {
379 UnitFileChange
*changes
= NULL
;
380 unsigned n_changes
= 0;
384 log_info("== %s ==", __func__
);
386 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template@.service", &state
) == -ENOENT
);
387 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template@def.service", &state
) == -ENOENT
);
388 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template@foo.service", &state
) == -ENOENT
);
389 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template-symlink@foo.service", &state
) == -ENOENT
);
391 p
= strjoina(root
, "/usr/lib/systemd/system/template@.service");
392 assert_se(write_string_file(p
,
394 "DefaultInstance=def\n"
395 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
397 p
= strjoina(root
, "/usr/lib/systemd/system/template-symlink@.service");
398 assert_se(symlink("template@.service", p
) >= 0);
400 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template@.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
401 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template@def.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
402 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template@foo.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
403 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template-symlink@.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
404 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template-symlink@def.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
405 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template-symlink@foo.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
407 log_info("== %s with template@.service enabled ==", __func__
);
409 assert_se(unit_file_enable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("template@.service"), &changes
, &n_changes
) >= 0);
410 assert_se(n_changes
== 1);
411 assert_se(changes
[0].type
== UNIT_FILE_SYMLINK
);
412 assert_se(streq(changes
[0].source
, "/usr/lib/systemd/system/template@.service"));
413 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/multi-user.target.wants/template@def.service");
414 assert_se(streq(changes
[0].path
, p
));
415 unit_file_changes_free(changes
, n_changes
);
416 changes
= NULL
; n_changes
= 0;
418 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template@.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
419 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template@def.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
420 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template@foo.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
421 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template-symlink@.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
422 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template-symlink@def.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
423 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template-symlink@foo.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
425 assert_se(unit_file_disable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("template@.service"), &changes
, &n_changes
) >= 0);
426 assert_se(n_changes
== 1);
427 assert_se(changes
[0].type
== UNIT_FILE_UNLINK
);
428 assert_se(streq(changes
[0].path
, p
));
429 unit_file_changes_free(changes
, n_changes
);
430 changes
= NULL
; n_changes
= 0;
432 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template@.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
433 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template@def.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
434 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template@foo.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
435 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template-symlink@.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
436 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template-symlink@def.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
437 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template-symlink@foo.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
439 log_info("== %s with template@foo.service enabled ==", __func__
);
441 assert_se(unit_file_enable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("template@foo.service"), &changes
, &n_changes
) >= 0);
442 assert_se(changes
[0].type
== UNIT_FILE_SYMLINK
);
443 assert_se(streq(changes
[0].source
, "/usr/lib/systemd/system/template@.service"));
444 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/multi-user.target.wants/template@foo.service");
445 assert_se(streq(changes
[0].path
, p
));
446 unit_file_changes_free(changes
, n_changes
);
447 changes
= NULL
; n_changes
= 0;
449 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template@.service", &state
) >= 0 && state
== UNIT_FILE_INDIRECT
);
450 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template@def.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
451 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template@foo.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
452 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template-symlink@foo.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
453 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template-symlink@def.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
454 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template-symlink@foo.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
456 assert_se(unit_file_disable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("template@foo.service"), &changes
, &n_changes
) >= 0);
457 assert_se(n_changes
== 1);
458 assert_se(changes
[0].type
== UNIT_FILE_UNLINK
);
459 assert_se(streq(changes
[0].path
, p
));
460 unit_file_changes_free(changes
, n_changes
);
461 changes
= NULL
; n_changes
= 0;
463 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template@.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
464 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template@def.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
465 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template@foo.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
466 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template@quux.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
467 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template-symlink@.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
468 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template-symlink@def.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
469 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template-symlink@foo.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
470 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template-symlink@quux.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
472 log_info("== %s with template-symlink@quux.service enabled ==", __func__
);
474 assert_se(unit_file_enable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("template-symlink@quux.service"), &changes
, &n_changes
) >= 0);
475 assert_se(changes
[0].type
== UNIT_FILE_SYMLINK
);
476 assert_se(streq(changes
[0].source
, "/usr/lib/systemd/system/template@.service"));
477 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/multi-user.target.wants/template@quux.service");
478 assert_se(streq(changes
[0].path
, p
));
479 unit_file_changes_free(changes
, n_changes
);
480 changes
= NULL
; n_changes
= 0;
482 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template@.service", &state
) >= 0 && state
== UNIT_FILE_INDIRECT
);
483 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template@def.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
484 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template@foo.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
485 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template@quux.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
486 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template-symlink@.service", &state
) >= 0 && state
== UNIT_FILE_INDIRECT
);
487 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template-symlink@def.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
488 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template-symlink@foo.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
489 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template-symlink@quux.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
492 static void test_indirect(const char *root
) {
493 UnitFileChange
*changes
= NULL
;
494 unsigned n_changes
= 0;
498 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "indirecta.service", &state
) == -ENOENT
);
499 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "indirectb.service", &state
) == -ENOENT
);
500 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "indirectc.service", &state
) == -ENOENT
);
502 p
= strjoina(root
, "/usr/lib/systemd/system/indirecta.service");
503 assert_se(write_string_file(p
,
505 "Also=indirectb.service\n", WRITE_STRING_FILE_CREATE
) >= 0);
507 p
= strjoina(root
, "/usr/lib/systemd/system/indirectb.service");
508 assert_se(write_string_file(p
,
510 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
512 p
= strjoina(root
, "/usr/lib/systemd/system/indirectc.service");
513 assert_se(symlink("indirecta.service", p
) >= 0);
515 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "indirecta.service", &state
) >= 0 && state
== UNIT_FILE_INDIRECT
);
516 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "indirectb.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
517 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "indirectc.service", &state
) >= 0 && state
== UNIT_FILE_INDIRECT
);
519 assert_se(unit_file_enable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("indirectc.service"), &changes
, &n_changes
) >= 0);
520 assert_se(n_changes
== 1);
521 assert_se(changes
[0].type
== UNIT_FILE_SYMLINK
);
522 assert_se(streq(changes
[0].source
, "/usr/lib/systemd/system/indirectb.service"));
523 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/multi-user.target.wants/indirectb.service");
524 assert_se(streq(changes
[0].path
, p
));
525 unit_file_changes_free(changes
, n_changes
);
526 changes
= NULL
; n_changes
= 0;
528 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "indirecta.service", &state
) >= 0 && state
== UNIT_FILE_INDIRECT
);
529 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "indirectb.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
530 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "indirectc.service", &state
) >= 0 && state
== UNIT_FILE_INDIRECT
);
532 assert_se(unit_file_disable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("indirectc.service"), &changes
, &n_changes
) >= 0);
533 assert_se(n_changes
== 1);
534 assert_se(changes
[0].type
== UNIT_FILE_UNLINK
);
535 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/multi-user.target.wants/indirectb.service");
536 assert_se(streq(changes
[0].path
, p
));
537 unit_file_changes_free(changes
, n_changes
);
538 changes
= NULL
; n_changes
= 0;
541 static void test_preset_and_list(const char *root
) {
542 UnitFileChange
*changes
= NULL
;
543 unsigned n_changes
= 0, i
;
546 bool got_yes
= false, got_no
= false;
551 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "preset-yes.service", &state
) == -ENOENT
);
552 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "preset-no.service", &state
) == -ENOENT
);
554 p
= strjoina(root
, "/usr/lib/systemd/system/preset-yes.service");
555 assert_se(write_string_file(p
,
557 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
559 p
= strjoina(root
, "/usr/lib/systemd/system/preset-no.service");
560 assert_se(write_string_file(p
,
562 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
564 p
= strjoina(root
, "/usr/lib/systemd/system-preset/test.preset");
565 assert_se(write_string_file(p
,
567 "disable *\n", WRITE_STRING_FILE_CREATE
) >= 0);
569 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "preset-yes.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
570 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "preset-no.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
572 assert_se(unit_file_preset(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("preset-yes.service"), UNIT_FILE_PRESET_FULL
, &changes
, &n_changes
) >= 0);
573 assert_se(n_changes
== 1);
574 assert_se(changes
[0].type
== UNIT_FILE_SYMLINK
);
575 assert_se(streq(changes
[0].source
, "/usr/lib/systemd/system/preset-yes.service"));
576 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/multi-user.target.wants/preset-yes.service");
577 assert_se(streq(changes
[0].path
, p
));
578 unit_file_changes_free(changes
, n_changes
);
579 changes
= NULL
; n_changes
= 0;
581 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "preset-yes.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
582 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "preset-no.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
584 assert_se(unit_file_disable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("preset-yes.service"), &changes
, &n_changes
) >= 0);
585 assert_se(n_changes
== 1);
586 assert_se(changes
[0].type
== UNIT_FILE_UNLINK
);
587 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/multi-user.target.wants/preset-yes.service");
588 assert_se(streq(changes
[0].path
, p
));
589 unit_file_changes_free(changes
, n_changes
);
590 changes
= NULL
; n_changes
= 0;
592 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "preset-yes.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
593 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "preset-no.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
595 assert_se(unit_file_preset(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("preset-no.service"), UNIT_FILE_PRESET_FULL
, &changes
, &n_changes
) >= 0);
596 assert_se(n_changes
== 0);
597 unit_file_changes_free(changes
, n_changes
);
598 changes
= NULL
; n_changes
= 0;
600 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "preset-yes.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
601 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "preset-no.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
603 assert_se(unit_file_preset_all(UNIT_FILE_SYSTEM
, 0, root
, UNIT_FILE_PRESET_FULL
, &changes
, &n_changes
) >= 0);
605 assert_se(n_changes
> 0);
607 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/multi-user.target.wants/preset-yes.service");
609 for (i
= 0; i
< n_changes
; i
++) {
611 if (changes
[i
].type
== UNIT_FILE_SYMLINK
) {
612 assert_se(streq(changes
[i
].source
, "/usr/lib/systemd/system/preset-yes.service"));
613 assert_se(streq(changes
[i
].path
, p
));
615 assert_se(changes
[i
].type
== UNIT_FILE_UNLINK
);
618 unit_file_changes_free(changes
, n_changes
);
619 changes
= NULL
; n_changes
= 0;
621 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "preset-yes.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
622 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "preset-no.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
624 assert_se(h
= hashmap_new(&string_hash_ops
));
625 assert_se(unit_file_get_list(UNIT_FILE_SYSTEM
, root
, h
, NULL
, NULL
) >= 0);
627 p
= strjoina(root
, "/usr/lib/systemd/system/preset-yes.service");
628 q
= strjoina(root
, "/usr/lib/systemd/system/preset-no.service");
630 HASHMAP_FOREACH(fl
, h
, j
) {
631 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, basename(fl
->path
), &state
) >= 0);
632 assert_se(fl
->state
== state
);
634 if (streq(fl
->path
, p
)) {
636 assert_se(fl
->state
== UNIT_FILE_ENABLED
);
637 } else if (streq(fl
->path
, q
)) {
639 assert_se(fl
->state
== UNIT_FILE_DISABLED
);
641 assert_se(IN_SET(fl
->state
, UNIT_FILE_DISABLED
, UNIT_FILE_STATIC
, UNIT_FILE_INDIRECT
));
644 unit_file_list_free(h
);
646 assert_se(got_yes
&& got_no
);
649 static void test_revert(const char *root
) {
652 UnitFileChange
*changes
= NULL
;
653 unsigned n_changes
= 0;
657 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "xx.service", NULL
) == -ENOENT
);
658 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "yy.service", NULL
) == -ENOENT
);
660 p
= strjoina(root
, "/usr/lib/systemd/system/xx.service");
661 assert_se(write_string_file(p
, "# Empty\n", WRITE_STRING_FILE_CREATE
) >= 0);
663 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "xx.service", NULL
) >= 0);
664 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "xx.service", &state
) >= 0 && state
== UNIT_FILE_STATIC
);
666 /* Initially there's nothing to revert */
667 assert_se(unit_file_revert(UNIT_FILE_SYSTEM
, root
, STRV_MAKE("xx.service"), &changes
, &n_changes
) >= 0);
668 assert_se(n_changes
== 0);
669 unit_file_changes_free(changes
, n_changes
);
670 changes
= NULL
; n_changes
= 0;
672 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/xx.service");
673 assert_se(write_string_file(p
, "# Empty override\n", WRITE_STRING_FILE_CREATE
) >= 0);
675 /* Revert the override file */
676 assert_se(unit_file_revert(UNIT_FILE_SYSTEM
, root
, STRV_MAKE("xx.service"), &changes
, &n_changes
) >= 0);
677 assert_se(n_changes
== 1);
678 assert_se(changes
[0].type
== UNIT_FILE_UNLINK
);
679 assert_se(streq(changes
[0].path
, p
));
680 unit_file_changes_free(changes
, n_changes
);
681 changes
= NULL
; n_changes
= 0;
683 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/xx.service.d/dropin.conf");
684 assert_se(mkdir_parents(p
, 0755) >= 0);
685 assert_se(write_string_file(p
, "# Empty dropin\n", WRITE_STRING_FILE_CREATE
) >= 0);
687 /* Revert the dropin file */
688 assert_se(unit_file_revert(UNIT_FILE_SYSTEM
, root
, STRV_MAKE("xx.service"), &changes
, &n_changes
) >= 0);
689 assert_se(n_changes
== 2);
690 assert_se(changes
[0].type
== UNIT_FILE_UNLINK
);
691 assert_se(streq(changes
[0].path
, p
));
693 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/xx.service.d");
694 assert_se(changes
[1].type
== UNIT_FILE_UNLINK
);
695 assert_se(streq(changes
[1].path
, p
));
696 unit_file_changes_free(changes
, n_changes
);
697 changes
= NULL
; n_changes
= 0;
700 static void test_preset_order(const char *root
) {
701 UnitFileChange
*changes
= NULL
;
702 unsigned n_changes
= 0;
706 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "prefix-1.service", &state
) == -ENOENT
);
707 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "prefix-2.service", &state
) == -ENOENT
);
709 p
= strjoina(root
, "/usr/lib/systemd/system/prefix-1.service");
710 assert_se(write_string_file(p
,
712 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
714 p
= strjoina(root
, "/usr/lib/systemd/system/prefix-2.service");
715 assert_se(write_string_file(p
,
717 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
719 p
= strjoina(root
, "/usr/lib/systemd/system-preset/test.preset");
720 assert_se(write_string_file(p
,
721 "enable prefix-1.service\n"
722 "disable prefix-*.service\n"
723 "enable prefix-2.service\n", WRITE_STRING_FILE_CREATE
) >= 0);
725 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "prefix-1.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
726 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "prefix-2.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
728 assert_se(unit_file_preset(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("prefix-1.service"), UNIT_FILE_PRESET_FULL
, &changes
, &n_changes
) >= 0);
729 assert_se(n_changes
== 1);
730 assert_se(changes
[0].type
== UNIT_FILE_SYMLINK
);
731 assert_se(streq(changes
[0].source
, "/usr/lib/systemd/system/prefix-1.service"));
732 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/multi-user.target.wants/prefix-1.service");
733 assert_se(streq(changes
[0].path
, p
));
734 unit_file_changes_free(changes
, n_changes
);
735 changes
= NULL
; n_changes
= 0;
737 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "prefix-1.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
738 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "prefix-2.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
740 assert_se(unit_file_preset(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("prefix-2.service"), UNIT_FILE_PRESET_FULL
, &changes
, &n_changes
) >= 0);
741 assert_se(n_changes
== 0);
743 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "prefix-1.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
744 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "prefix-2.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
747 static void test_static_instance(const char *root
) {
751 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "static-instance@.service", &state
) == -ENOENT
);
752 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "static-instance@foo.service", &state
) == -ENOENT
);
754 p
= strjoina(root
, "/usr/lib/systemd/system/static-instance@.service");
755 assert_se(write_string_file(p
,
757 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
759 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "static-instance@.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
760 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "static-instance@foo.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
762 p
= strjoina(root
, "/usr/lib/systemd/system/static-instance@foo.service");
763 assert_se(symlink("static-instance@.service", p
) >= 0);
765 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "static-instance@.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
766 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "static-instance@foo.service", &state
) >= 0 && state
== UNIT_FILE_STATIC
);
769 static void test_with_dropin(const char *root
) {
772 UnitFileChange
*changes
= NULL
;
773 unsigned n_changes
= 0;
775 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "with-dropin-1.service", &state
) == -ENOENT
);
776 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "with-dropin-2.service", &state
) == -ENOENT
);
777 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "with-dropin-3.service", &state
) == -ENOENT
);
778 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "with-dropin-4a.service", &state
) == -ENOENT
);
779 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "with-dropin-4b.service", &state
) == -ENOENT
);
781 p
= strjoina(root
, "/usr/lib/systemd/system/with-dropin-1.service");
782 assert_se(write_string_file(p
,
784 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
786 p
= strjoina(root
, "/usr/lib/systemd/system/with-dropin-1.service.d/dropin.conf");
787 assert_se(mkdir_parents(p
, 0755) >= 0);
788 assert_se(write_string_file(p
,
790 "WantedBy=graphical.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
792 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "with-dropin-1.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
794 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/with-dropin-2.service");
795 assert_se(write_string_file(p
,
797 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
799 p
= strjoina(root
, "/usr/lib/systemd/system/with-dropin-2.service.d/dropin.conf");
800 assert_se(mkdir_parents(p
, 0755) >= 0);
801 assert_se(write_string_file(p
,
803 "WantedBy=graphical.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
805 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "with-dropin-2.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
807 p
= strjoina(root
, "/usr/lib/systemd/system/with-dropin-3.service");
808 assert_se(write_string_file(p
,
810 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
812 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/with-dropin-3.service.d/dropin.conf");
813 assert_se(mkdir_parents(p
, 0755) >= 0);
814 assert_se(write_string_file(p
,
816 "WantedBy=graphical.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
818 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "with-dropin-3.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
820 p
= strjoina(root
, "/usr/lib/systemd/system/with-dropin-4a.service");
821 assert_se(write_string_file(p
,
823 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
825 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/with-dropin-4a.service.d/dropin.conf");
826 assert_se(mkdir_parents(p
, 0755) >= 0);
827 assert_se(write_string_file(p
,
829 "Also=with-dropin-4b.service\n", WRITE_STRING_FILE_CREATE
) >= 0);
831 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "with-dropin-4a.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
833 p
= strjoina(root
, "/usr/lib/systemd/system/with-dropin-4b.service");
834 assert_se(write_string_file(p
,
836 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
838 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "with-dropin-4b.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
840 assert_se(unit_file_enable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("with-dropin-1.service"), &changes
, &n_changes
) == 1);
841 assert_se(n_changes
== 2);
842 assert_se(changes
[0].type
== UNIT_FILE_SYMLINK
);
843 assert_se(changes
[1].type
== UNIT_FILE_SYMLINK
);
844 assert_se(streq(changes
[0].source
, "/usr/lib/systemd/system/with-dropin-1.service"));
845 assert_se(streq(changes
[1].source
, "/usr/lib/systemd/system/with-dropin-1.service"));
846 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/multi-user.target.wants/with-dropin-1.service");
847 assert_se(streq(changes
[0].path
, p
));
848 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/graphical.target.wants/with-dropin-1.service");
849 assert_se(streq(changes
[1].path
, p
));
850 unit_file_changes_free(changes
, n_changes
);
851 changes
= NULL
; n_changes
= 0;
853 assert_se(unit_file_enable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("with-dropin-2.service"), &changes
, &n_changes
) == 1);
854 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "with-dropin-2.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
855 assert_se(n_changes
== 2);
856 assert_se(changes
[0].type
== UNIT_FILE_SYMLINK
);
857 assert_se(changes
[1].type
== UNIT_FILE_SYMLINK
);
858 assert_se(streq(changes
[0].source
, SYSTEM_CONFIG_UNIT_PATH
"/with-dropin-2.service"));
859 assert_se(streq(changes
[1].source
, SYSTEM_CONFIG_UNIT_PATH
"/with-dropin-2.service"));
860 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/multi-user.target.wants/with-dropin-2.service");
861 assert_se(streq(changes
[0].path
, p
));
862 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/graphical.target.wants/with-dropin-2.service");
863 assert_se(streq(changes
[1].path
, p
));
864 unit_file_changes_free(changes
, n_changes
);
865 changes
= NULL
; n_changes
= 0;
867 assert_se(unit_file_enable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("with-dropin-3.service"), &changes
, &n_changes
) == 1);
868 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "with-dropin-3.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
869 assert_se(n_changes
== 2);
870 assert_se(changes
[0].type
== UNIT_FILE_SYMLINK
);
871 assert_se(changes
[1].type
== UNIT_FILE_SYMLINK
);
872 assert_se(streq(changes
[0].source
, "/usr/lib/systemd/system/with-dropin-3.service"));
873 assert_se(streq(changes
[1].source
, "/usr/lib/systemd/system/with-dropin-3.service"));
874 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/multi-user.target.wants/with-dropin-3.service");
875 assert_se(streq(changes
[0].path
, p
));
876 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/graphical.target.wants/with-dropin-3.service");
877 assert_se(streq(changes
[1].path
, p
));
878 unit_file_changes_free(changes
, n_changes
);
879 changes
= NULL
; n_changes
= 0;
881 assert_se(unit_file_enable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("with-dropin-4a.service"), &changes
, &n_changes
) == 1);
882 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "with-dropin-3.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
883 assert_se(n_changes
== 2);
884 assert_se(changes
[0].type
== UNIT_FILE_SYMLINK
);
885 assert_se(changes
[1].type
== UNIT_FILE_SYMLINK
);
886 assert_se(streq(changes
[0].source
, "/usr/lib/systemd/system/with-dropin-4a.service"));
887 assert_se(streq(changes
[1].source
, "/usr/lib/systemd/system/with-dropin-4b.service"));
888 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/multi-user.target.wants/with-dropin-4a.service");
889 assert_se(streq(changes
[0].path
, p
));
890 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/multi-user.target.wants/with-dropin-4b.service");
891 assert_se(streq(changes
[1].path
, p
));
892 unit_file_changes_free(changes
, n_changes
);
893 changes
= NULL
; n_changes
= 0;
895 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "with-dropin-1.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
896 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "with-dropin-2.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
897 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "with-dropin-3.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
898 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "with-dropin-4a.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
899 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "with-dropin-4b.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
902 static void test_with_dropin_template(const char *root
) {
905 UnitFileChange
*changes
= NULL
;
906 unsigned n_changes
= 0;
908 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "with-dropin-1@.service", &state
) == -ENOENT
);
909 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "with-dropin-2@.service", &state
) == -ENOENT
);
910 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "with-dropin-3@.service", &state
) == -ENOENT
);
912 p
= strjoina(root
, "/usr/lib/systemd/system/with-dropin-1@.service");
913 assert_se(write_string_file(p
,
915 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
917 p
= strjoina(root
, "/usr/lib/systemd/system/with-dropin-1@.service.d/dropin.conf");
918 assert_se(mkdir_parents(p
, 0755) >= 0);
919 assert_se(write_string_file(p
,
921 "WantedBy=graphical.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
923 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "with-dropin-1@.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
925 p
= strjoina(root
, "/usr/lib/systemd/system/with-dropin-2@.service");
926 assert_se(write_string_file(p
,
928 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
930 p
= strjoina(root
, "/usr/lib/systemd/system/with-dropin-2@instance-1.service.d/dropin.conf");
931 assert_se(mkdir_parents(p
, 0755) >= 0);
932 assert_se(write_string_file(p
,
934 "WantedBy=graphical.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
936 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "with-dropin-2@.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
938 p
= strjoina(root
, "/usr/lib/systemd/system/with-dropin-3@.service");
939 assert_se(write_string_file(p
,
941 "DefaultInstance=instance-1\n"
942 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
944 p
= strjoina(root
, "/usr/lib/systemd/system/with-dropin-3@.service.d/dropin.conf");
945 assert_se(mkdir_parents(p
, 0755) >= 0);
946 assert_se(write_string_file(p
,
948 "DefaultInstance=instance-2\n", WRITE_STRING_FILE_CREATE
) >= 0);
950 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "with-dropin-3@.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
952 assert_se(unit_file_enable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("with-dropin-1@instance-1.service"), &changes
, &n_changes
) == 1);
953 assert_se(n_changes
== 2);
954 assert_se(changes
[0].type
== UNIT_FILE_SYMLINK
);
955 assert_se(changes
[1].type
== UNIT_FILE_SYMLINK
);
956 assert_se(streq(changes
[0].source
, "/usr/lib/systemd/system/with-dropin-1@.service"));
957 assert_se(streq(changes
[1].source
, "/usr/lib/systemd/system/with-dropin-1@.service"));
958 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/multi-user.target.wants/with-dropin-1@instance-1.service");
959 assert_se(streq(changes
[0].path
, p
));
960 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/graphical.target.wants/with-dropin-1@instance-1.service");
961 assert_se(streq(changes
[1].path
, p
));
962 unit_file_changes_free(changes
, n_changes
);
963 changes
= NULL
; n_changes
= 0;
965 assert_se(unit_file_enable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("with-dropin-2@instance-1.service"), &changes
, &n_changes
) == 1);
966 assert_se(n_changes
== 2);
967 assert_se(changes
[0].type
== UNIT_FILE_SYMLINK
);
968 assert_se(changes
[1].type
== UNIT_FILE_SYMLINK
);
969 assert_se(streq(changes
[0].source
, "/usr/lib/systemd/system/with-dropin-2@.service"));
970 assert_se(streq(changes
[1].source
, "/usr/lib/systemd/system/with-dropin-2@.service"));
971 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/multi-user.target.wants/with-dropin-2@instance-1.service");
972 assert_se(streq(changes
[0].path
, p
));
973 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/graphical.target.wants/with-dropin-2@instance-1.service");
974 assert_se(streq(changes
[1].path
, p
));
975 unit_file_changes_free(changes
, n_changes
);
976 changes
= NULL
; n_changes
= 0;
978 assert_se(unit_file_enable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("with-dropin-2@instance-2.service"), &changes
, &n_changes
) == 1);
979 assert_se(n_changes
== 1);
980 assert_se(changes
[0].type
== UNIT_FILE_SYMLINK
);
981 assert_se(streq(changes
[0].source
, "/usr/lib/systemd/system/with-dropin-2@.service"));
982 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/multi-user.target.wants/with-dropin-2@instance-2.service");
983 assert_se(streq(changes
[0].path
, p
));
984 unit_file_changes_free(changes
, n_changes
);
985 changes
= NULL
; n_changes
= 0;
987 assert_se(unit_file_enable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("with-dropin-3@.service"), &changes
, &n_changes
) == 1);
988 assert_se(n_changes
== 1);
989 assert_se(changes
[0].type
== UNIT_FILE_SYMLINK
);
990 assert_se(streq(changes
[0].source
, "/usr/lib/systemd/system/with-dropin-3@.service"));
991 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/multi-user.target.wants/with-dropin-3@instance-2.service");
992 assert_se(streq(changes
[0].path
, p
));
993 unit_file_changes_free(changes
, n_changes
);
994 changes
= NULL
; n_changes
= 0;
996 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "with-dropin-1@instance-1.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
997 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "with-dropin-2@instance-1.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
998 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "with-dropin-2@instance-2.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
999 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "with-dropin-3@instance-1.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
1000 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "with-dropin-3@instance-2.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
1003 int main(int argc
, char *argv
[]) {
1004 char root
[] = "/tmp/rootXXXXXX";
1007 assert_se(mkdtemp(root
));
1009 p
= strjoina(root
, "/usr/lib/systemd/system/");
1010 assert_se(mkdir_p(p
, 0755) >= 0);
1012 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/");
1013 assert_se(mkdir_p(p
, 0755) >= 0);
1015 p
= strjoina(root
, "/run/systemd/system/");
1016 assert_se(mkdir_p(p
, 0755) >= 0);
1018 p
= strjoina(root
, "/opt/");
1019 assert_se(mkdir_p(p
, 0755) >= 0);
1021 p
= strjoina(root
, "/usr/lib/systemd/system-preset/");
1022 assert_se(mkdir_p(p
, 0755) >= 0);
1024 test_basic_mask_and_enable(root
);
1025 test_linked_units(root
);
1027 test_add_dependency(root
);
1028 test_template_enable(root
);
1029 test_indirect(root
);
1030 test_preset_and_list(root
);
1031 test_preset_order(root
);
1033 test_static_instance(root
);
1034 test_with_dropin(root
);
1035 test_with_dropin_template(root
);
1037 assert_se(rm_rf(root
, REMOVE_ROOT
|REMOVE_PHYSICAL
) >= 0);