]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/test/test-install-root.c
tree-wide: be more careful with the type of array sizes
[thirdparty/systemd.git] / src / test / test-install-root.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
0ec0deaa
LP
2/***
3 This file is part of systemd.
4
5 Copyright 2011 Lennart Poettering
0ec0deaa
LP
6***/
7
8#include "alloc-util.h"
9#include "fileio.h"
10#include "install.h"
11#include "mkdir.h"
12#include "rm-rf.h"
075dafd2 13#include "special.h"
0ec0deaa
LP
14#include "string-util.h"
15
16static void test_basic_mask_and_enable(const char *root) {
17 const char *p;
18 UnitFileState state;
19 UnitFileChange *changes = NULL;
da6053d0 20 size_t n_changes = 0;
0ec0deaa 21
198402d3
LP
22 log_set_max_level(LOG_DEBUG);
23
0ec0deaa
LP
24 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", NULL) == -ENOENT);
25 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", NULL) == -ENOENT);
26 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", NULL) == -ENOENT);
27 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", NULL) == -ENOENT);
28
29 p = strjoina(root, "/usr/lib/systemd/system/a.service");
30 assert_se(write_string_file(p,
31 "[Install]\n"
32 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
33
34 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", NULL) >= 0);
35 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
36
37 p = strjoina(root, "/usr/lib/systemd/system/b.service");
38 assert_se(symlink("a.service", p) >= 0);
39
40 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", NULL) >= 0);
41 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
42
43 p = strjoina(root, "/usr/lib/systemd/system/c.service");
44 assert_se(symlink("/usr/lib/systemd/system/a.service", p) >= 0);
45
46 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", NULL) >= 0);
47 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
48
49 p = strjoina(root, "/usr/lib/systemd/system/d.service");
50 assert_se(symlink("c.service", p) >= 0);
51
52 /* This one is interesting, as d follows a relative, then an absolute symlink */
53 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", NULL) >= 0);
54 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
55
b3796dd8 56 assert_se(unit_file_mask(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
57 assert_se(n_changes == 1);
58 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
59 assert_se(streq(changes[0].source, "/dev/null"));
60 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/a.service");
61 assert_se(streq(changes[0].path, p));
62
63 unit_file_changes_free(changes, n_changes);
64 changes = NULL; n_changes = 0;
65
66 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_MASKED);
67 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_MASKED);
68 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_MASKED);
69 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_MASKED);
70
71 /* Enabling a masked unit should fail! */
b3796dd8 72 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("a.service"), &changes, &n_changes) == -ERFKILL);
0ec0deaa
LP
73 unit_file_changes_free(changes, n_changes);
74 changes = NULL; n_changes = 0;
75
b3796dd8 76 assert_se(unit_file_unmask(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
77 assert_se(n_changes == 1);
78 assert_se(changes[0].type == UNIT_FILE_UNLINK);
79 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/a.service");
80 assert_se(streq(changes[0].path, p));
81 unit_file_changes_free(changes, n_changes);
82 changes = NULL; n_changes = 0;
83
b3796dd8 84 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("a.service"), &changes, &n_changes) == 1);
0ec0deaa
LP
85 assert_se(n_changes == 1);
86 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
87 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/a.service"));
88 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service");
89 assert_se(streq(changes[0].path, p));
90 unit_file_changes_free(changes, n_changes);
91 changes = NULL; n_changes = 0;
92
93 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
94 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
95 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
96 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
97
98 /* Enabling it again should succeed but be a NOP */
b3796dd8 99 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
100 assert_se(n_changes == 0);
101 unit_file_changes_free(changes, n_changes);
102 changes = NULL; n_changes = 0;
103
b3796dd8 104 assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
105 assert_se(n_changes == 1);
106 assert_se(changes[0].type == UNIT_FILE_UNLINK);
107 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service");
108 assert_se(streq(changes[0].path, p));
109 unit_file_changes_free(changes, n_changes);
110 changes = NULL; n_changes = 0;
111
112 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
113 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
114 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
115 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
116
117 /* Disabling a disabled unit must suceed but be a NOP */
b3796dd8 118 assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
119 assert_se(n_changes == 0);
120 unit_file_changes_free(changes, n_changes);
121 changes = NULL; n_changes = 0;
122
123 /* Let's enable this indirectly via a symlink */
b3796dd8 124 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("d.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
125 assert_se(n_changes == 1);
126 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
127 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/a.service"));
128 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service");
129 assert_se(streq(changes[0].path, p));
130 unit_file_changes_free(changes, n_changes);
131 changes = NULL; n_changes = 0;
132
133 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
134 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
135 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
136 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
137
138 /* Let's try to reenable */
139
b3796dd8 140 assert_se(unit_file_reenable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("b.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
141 assert_se(n_changes == 2);
142 assert_se(changes[0].type == UNIT_FILE_UNLINK);
143 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service");
144 assert_se(streq(changes[0].path, p));
145 assert_se(changes[1].type == UNIT_FILE_SYMLINK);
146 assert_se(streq(changes[1].source, "/usr/lib/systemd/system/a.service"));
147 assert_se(streq(changes[1].path, p));
148 unit_file_changes_free(changes, n_changes);
149 changes = NULL; n_changes = 0;
150
151 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
152 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
153 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
154 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
155}
156
157static void test_linked_units(const char *root) {
158 const char *p, *q;
159 UnitFileState state;
160 UnitFileChange *changes = NULL;
da6053d0 161 size_t n_changes = 0, i;
0ec0deaa
LP
162
163 /*
164 * We'll test three cases here:
165 *
166 * a) a unit file in /opt, that we use "systemctl link" and
167 * "systemctl enable" on to make it available to the system
168 *
169 * b) a unit file in /opt, that is statically linked into
170 * /usr/lib/systemd/system, that "enable" should work on
171 * correctly.
172 *
173 * c) a unit file in /opt, that is linked into
174 * /etc/systemd/system, and where "enable" should result in
175 * -ELOOP, since using information from /etc to generate
176 * information in /etc should not be allowed.
177 */
178
179 p = strjoina(root, "/opt/linked.service");
180 assert_se(write_string_file(p,
181 "[Install]\n"
182 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
183
184 p = strjoina(root, "/opt/linked2.service");
185 assert_se(write_string_file(p,
186 "[Install]\n"
187 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
188
189 p = strjoina(root, "/opt/linked3.service");
190 assert_se(write_string_file(p,
191 "[Install]\n"
192 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
193
194 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", NULL) == -ENOENT);
195 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked2.service", NULL) == -ENOENT);
196 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked3.service", NULL) == -ENOENT);
197
198 p = strjoina(root, "/usr/lib/systemd/system/linked2.service");
199 assert_se(symlink("/opt/linked2.service", p) >= 0);
200
201 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked3.service");
202 assert_se(symlink("/opt/linked3.service", p) >= 0);
203
204 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", &state) == -ENOENT);
205 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked2.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
206 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked3.service", &state) >= 0 && state == UNIT_FILE_LINKED);
207
208 /* First, let's link the unit into the search path */
b3796dd8 209 assert_se(unit_file_link(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("/opt/linked.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
210 assert_se(n_changes == 1);
211 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
212 assert_se(streq(changes[0].source, "/opt/linked.service"));
213 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service");
214 assert_se(streq(changes[0].path, p));
215 unit_file_changes_free(changes, n_changes);
216 changes = NULL; n_changes = 0;
217
218 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", &state) >= 0 && state == UNIT_FILE_LINKED);
219
220 /* Let's unlink it from the search path again */
b3796dd8 221 assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("linked.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
222 assert_se(n_changes == 1);
223 assert_se(changes[0].type == UNIT_FILE_UNLINK);
224 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service");
225 assert_se(streq(changes[0].path, p));
226 unit_file_changes_free(changes, n_changes);
227 changes = NULL; n_changes = 0;
228
229 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", NULL) == -ENOENT);
230
231 /* Now, let's not just link it, but also enable it */
b3796dd8 232 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("/opt/linked.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
233 assert_se(n_changes == 2);
234 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/linked.service");
235 q = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service");
236 for (i = 0 ; i < n_changes; i++) {
237 assert_se(changes[i].type == UNIT_FILE_SYMLINK);
238 assert_se(streq(changes[i].source, "/opt/linked.service"));
239
240 if (p && streq(changes[i].path, p))
241 p = NULL;
242 else if (q && streq(changes[i].path, q))
243 q = NULL;
244 else
245 assert_not_reached("wut?");
246 }
247 assert(!p && !q);
248 unit_file_changes_free(changes, n_changes);
249 changes = NULL; n_changes = 0;
250
251 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
252
253 /* And let's unlink it again */
b3796dd8 254 assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("linked.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
255 assert_se(n_changes == 2);
256 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/linked.service");
257 q = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service");
258 for (i = 0; i < n_changes; i++) {
259 assert_se(changes[i].type == UNIT_FILE_UNLINK);
260
261 if (p && streq(changes[i].path, p))
262 p = NULL;
263 else if (q && streq(changes[i].path, q))
264 q = NULL;
265 else
266 assert_not_reached("wut?");
267 }
268 assert(!p && !q);
269 unit_file_changes_free(changes, n_changes);
270 changes = NULL; n_changes = 0;
271
272 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", NULL) == -ENOENT);
273
b3796dd8 274 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("linked2.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
275 assert_se(n_changes == 2);
276 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/linked2.service");
277 q = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked2.service");
278 for (i = 0 ; i < n_changes; i++) {
279 assert_se(changes[i].type == UNIT_FILE_SYMLINK);
280 assert_se(streq(changes[i].source, "/opt/linked2.service"));
281
282 if (p && streq(changes[i].path, p))
283 p = NULL;
284 else if (q && streq(changes[i].path, q))
285 q = NULL;
286 else
287 assert_not_reached("wut?");
288 }
289 assert(!p && !q);
290 unit_file_changes_free(changes, n_changes);
291 changes = NULL; n_changes = 0;
292
b3796dd8 293 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("linked3.service"), &changes, &n_changes) >= 0);
f777b434
ZJS
294 assert_se(n_changes == 1);
295 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
296 assert_se(startswith(changes[0].path, root));
297 assert_se(endswith(changes[0].path, "linked3.service"));
298 assert_se(streq(changes[0].source, "/opt/linked3.service"));
0ec0deaa
LP
299 unit_file_changes_free(changes, n_changes);
300 changes = NULL; n_changes = 0;
301}
302
303static void test_default(const char *root) {
304 _cleanup_free_ char *def = NULL;
305 UnitFileChange *changes = NULL;
da6053d0 306 size_t n_changes = 0;
0ec0deaa
LP
307 const char *p;
308
309 p = strjoina(root, "/usr/lib/systemd/system/test-default-real.target");
310 assert_se(write_string_file(p, "# pretty much empty", WRITE_STRING_FILE_CREATE) >= 0);
311
312 p = strjoina(root, "/usr/lib/systemd/system/test-default.target");
313 assert_se(symlink("test-default-real.target", p) >= 0);
314
315 assert_se(unit_file_get_default(UNIT_FILE_SYSTEM, root, &def) == -ENOENT);
316
b3796dd8 317 assert_se(unit_file_set_default(UNIT_FILE_SYSTEM, 0, root, "idontexist.target", &changes, &n_changes) == -ENOENT);
59108fbe
ZJS
318 assert_se(n_changes == 1);
319 assert_se(changes[0].type == -ENOENT);
320 assert_se(streq_ptr(changes[0].path, "idontexist.target"));
0ec0deaa
LP
321 unit_file_changes_free(changes, n_changes);
322 changes = NULL; n_changes = 0;
323
324 assert_se(unit_file_get_default(UNIT_FILE_SYSTEM, root, &def) == -ENOENT);
325
b3796dd8 326 assert_se(unit_file_set_default(UNIT_FILE_SYSTEM, 0, root, "test-default.target", &changes, &n_changes) >= 0);
0ec0deaa
LP
327 assert_se(n_changes == 1);
328 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
329 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/test-default-real.target"));
075dafd2 330 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH "/" SPECIAL_DEFAULT_TARGET);
0ec0deaa
LP
331 assert_se(streq(changes[0].path, p));
332 unit_file_changes_free(changes, n_changes);
333 changes = NULL; n_changes = 0;
334
335 assert_se(unit_file_get_default(UNIT_FILE_SYSTEM, root, &def) >= 0);
336 assert_se(streq_ptr(def, "test-default-real.target"));
337}
338
339static void test_add_dependency(const char *root) {
340 UnitFileChange *changes = NULL;
da6053d0 341 size_t n_changes = 0;
0ec0deaa
LP
342 const char *p;
343
344 p = strjoina(root, "/usr/lib/systemd/system/real-add-dependency-test-target.target");
345 assert_se(write_string_file(p, "# pretty much empty", WRITE_STRING_FILE_CREATE) >= 0);
346
347 p = strjoina(root, "/usr/lib/systemd/system/add-dependency-test-target.target");
348 assert_se(symlink("real-add-dependency-test-target.target", p) >= 0);
349
350 p = strjoina(root, "/usr/lib/systemd/system/real-add-dependency-test-service.service");
351 assert_se(write_string_file(p, "# pretty much empty", WRITE_STRING_FILE_CREATE) >= 0);
352
353 p = strjoina(root, "/usr/lib/systemd/system/add-dependency-test-service.service");
354 assert_se(symlink("real-add-dependency-test-service.service", p) >= 0);
355
b3796dd8 356 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);
0ec0deaa
LP
357 assert_se(n_changes == 1);
358 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
359 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/real-add-dependency-test-service.service"));
360 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/real-add-dependency-test-target.target.wants/real-add-dependency-test-service.service");
361 assert_se(streq(changes[0].path, p));
362 unit_file_changes_free(changes, n_changes);
363 changes = NULL; n_changes = 0;
364}
365
366static void test_template_enable(const char *root) {
367 UnitFileChange *changes = NULL;
da6053d0 368 size_t n_changes = 0;
0ec0deaa
LP
369 UnitFileState state;
370 const char *p;
371
5cd8ae31
ZJS
372 log_info("== %s ==", __func__);
373
0ec0deaa
LP
374 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) == -ENOENT);
375 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) == -ENOENT);
376 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) == -ENOENT);
377 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) == -ENOENT);
378
379 p = strjoina(root, "/usr/lib/systemd/system/template@.service");
380 assert_se(write_string_file(p,
381 "[Install]\n"
382 "DefaultInstance=def\n"
383 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
384
385 p = strjoina(root, "/usr/lib/systemd/system/template-symlink@.service");
386 assert_se(symlink("template@.service", p) >= 0);
387
388 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
389 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
390 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
391 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
392 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
393 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
394
5cd8ae31
ZJS
395 log_info("== %s with template@.service enabled ==", __func__);
396
b3796dd8 397 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("template@.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
398 assert_se(n_changes == 1);
399 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
400 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/template@.service"));
401 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/template@def.service");
402 assert_se(streq(changes[0].path, p));
403 unit_file_changes_free(changes, n_changes);
404 changes = NULL; n_changes = 0;
405
406 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
407 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
408 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
409 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
410 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
411 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
412
b3796dd8 413 assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("template@.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
414 assert_se(n_changes == 1);
415 assert_se(changes[0].type == UNIT_FILE_UNLINK);
416 assert_se(streq(changes[0].path, p));
417 unit_file_changes_free(changes, n_changes);
418 changes = NULL; n_changes = 0;
419
420 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
421 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
422 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
423 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
424 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
425 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
426
5cd8ae31
ZJS
427 log_info("== %s with template@foo.service enabled ==", __func__);
428
b3796dd8 429 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("template@foo.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
430 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
431 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/template@.service"));
432 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/template@foo.service");
433 assert_se(streq(changes[0].path, p));
434 unit_file_changes_free(changes, n_changes);
435 changes = NULL; n_changes = 0;
436
d9b4b48f 437 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
0ec0deaa
LP
438 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
439 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
440 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
441 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
442 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
443
b3796dd8 444 assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("template@foo.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
445 assert_se(n_changes == 1);
446 assert_se(changes[0].type == UNIT_FILE_UNLINK);
447 assert_se(streq(changes[0].path, p));
448 unit_file_changes_free(changes, n_changes);
449 changes = NULL; n_changes = 0;
450
451 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
452 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
453 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
454 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@quux.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
455 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
456 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
457 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
458 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@quux.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
459
5cd8ae31
ZJS
460 log_info("== %s with template-symlink@quux.service enabled ==", __func__);
461
b3796dd8 462 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("template-symlink@quux.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
463 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
464 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/template@.service"));
465 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/template@quux.service");
466 assert_se(streq(changes[0].path, p));
467 unit_file_changes_free(changes, n_changes);
468 changes = NULL; n_changes = 0;
469
d9b4b48f 470 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
0ec0deaa
LP
471 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
472 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
473 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@quux.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
d9b4b48f 474 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
0ec0deaa
LP
475 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
476 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
477 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@quux.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
478}
479
480static void test_indirect(const char *root) {
481 UnitFileChange *changes = NULL;
da6053d0 482 size_t n_changes = 0;
0ec0deaa
LP
483 UnitFileState state;
484 const char *p;
485
486 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirecta.service", &state) == -ENOENT);
487 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectb.service", &state) == -ENOENT);
488 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectc.service", &state) == -ENOENT);
489
490 p = strjoina(root, "/usr/lib/systemd/system/indirecta.service");
491 assert_se(write_string_file(p,
492 "[Install]\n"
493 "Also=indirectb.service\n", WRITE_STRING_FILE_CREATE) >= 0);
494
495 p = strjoina(root, "/usr/lib/systemd/system/indirectb.service");
496 assert_se(write_string_file(p,
497 "[Install]\n"
498 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
499
500 p = strjoina(root, "/usr/lib/systemd/system/indirectc.service");
501 assert_se(symlink("indirecta.service", p) >= 0);
502
503 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirecta.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
504 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectb.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
505 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectc.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
506
b3796dd8 507 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("indirectc.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
508 assert_se(n_changes == 1);
509 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
510 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/indirectb.service"));
511 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/indirectb.service");
512 assert_se(streq(changes[0].path, p));
513 unit_file_changes_free(changes, n_changes);
514 changes = NULL; n_changes = 0;
515
516 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirecta.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
517 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectb.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
518 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectc.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
519
b3796dd8 520 assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("indirectc.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
521 assert_se(n_changes == 1);
522 assert_se(changes[0].type == UNIT_FILE_UNLINK);
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;
527}
528
529static void test_preset_and_list(const char *root) {
530 UnitFileChange *changes = NULL;
da6053d0 531 size_t n_changes = 0, i;
0ec0deaa
LP
532 const char *p, *q;
533 UnitFileState state;
534 bool got_yes = false, got_no = false;
535 Iterator j;
536 UnitFileList *fl;
537 Hashmap *h;
538
539 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) == -ENOENT);
540 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) == -ENOENT);
541
542 p = strjoina(root, "/usr/lib/systemd/system/preset-yes.service");
543 assert_se(write_string_file(p,
544 "[Install]\n"
545 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
546
547 p = strjoina(root, "/usr/lib/systemd/system/preset-no.service");
548 assert_se(write_string_file(p,
549 "[Install]\n"
550 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
551
552 p = strjoina(root, "/usr/lib/systemd/system-preset/test.preset");
553 assert_se(write_string_file(p,
554 "enable *-yes.*\n"
555 "disable *\n", WRITE_STRING_FILE_CREATE) >= 0);
556
557 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
558 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
559
b3796dd8 560 assert_se(unit_file_preset(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("preset-yes.service"), UNIT_FILE_PRESET_FULL, &changes, &n_changes) >= 0);
0ec0deaa
LP
561 assert_se(n_changes == 1);
562 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
563 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/preset-yes.service"));
564 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/preset-yes.service");
565 assert_se(streq(changes[0].path, p));
566 unit_file_changes_free(changes, n_changes);
567 changes = NULL; n_changes = 0;
568
569 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
570 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
571
b3796dd8 572 assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("preset-yes.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
573 assert_se(n_changes == 1);
574 assert_se(changes[0].type == UNIT_FILE_UNLINK);
575 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/preset-yes.service");
576 assert_se(streq(changes[0].path, p));
577 unit_file_changes_free(changes, n_changes);
578 changes = NULL; n_changes = 0;
579
580 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
581 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
582
b3796dd8 583 assert_se(unit_file_preset(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("preset-no.service"), UNIT_FILE_PRESET_FULL, &changes, &n_changes) >= 0);
0ec0deaa
LP
584 assert_se(n_changes == 0);
585 unit_file_changes_free(changes, n_changes);
586 changes = NULL; n_changes = 0;
587
588 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
589 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
590
b3796dd8 591 assert_se(unit_file_preset_all(UNIT_FILE_SYSTEM, 0, root, UNIT_FILE_PRESET_FULL, &changes, &n_changes) >= 0);
0ec0deaa
LP
592
593 assert_se(n_changes > 0);
594
595 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/preset-yes.service");
596
597 for (i = 0; i < n_changes; i++) {
598
599 if (changes[i].type == UNIT_FILE_SYMLINK) {
600 assert_se(streq(changes[i].source, "/usr/lib/systemd/system/preset-yes.service"));
601 assert_se(streq(changes[i].path, p));
602 } else
603 assert_se(changes[i].type == UNIT_FILE_UNLINK);
604 }
605
606 unit_file_changes_free(changes, n_changes);
607 changes = NULL; n_changes = 0;
608
609 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
610 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
611
612 assert_se(h = hashmap_new(&string_hash_ops));
313fe66f 613 assert_se(unit_file_get_list(UNIT_FILE_SYSTEM, root, h, NULL, NULL) >= 0);
0ec0deaa
LP
614
615 p = strjoina(root, "/usr/lib/systemd/system/preset-yes.service");
616 q = strjoina(root, "/usr/lib/systemd/system/preset-no.service");
617
618 HASHMAP_FOREACH(fl, h, j) {
619 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, basename(fl->path), &state) >= 0);
620 assert_se(fl->state == state);
621
622 if (streq(fl->path, p)) {
623 got_yes = true;
624 assert_se(fl->state == UNIT_FILE_ENABLED);
625 } else if (streq(fl->path, q)) {
626 got_no = true;
627 assert_se(fl->state == UNIT_FILE_DISABLED);
628 } else
629 assert_se(IN_SET(fl->state, UNIT_FILE_DISABLED, UNIT_FILE_STATIC, UNIT_FILE_INDIRECT));
630 }
631
632 unit_file_list_free(h);
633
634 assert_se(got_yes && got_no);
635}
636
344ca755
LP
637static void test_revert(const char *root) {
638 const char *p;
639 UnitFileState state;
640 UnitFileChange *changes = NULL;
da6053d0 641 size_t n_changes = 0;
344ca755
LP
642
643 assert(root);
644
645 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "xx.service", NULL) == -ENOENT);
646 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "yy.service", NULL) == -ENOENT);
647
648 p = strjoina(root, "/usr/lib/systemd/system/xx.service");
649 assert_se(write_string_file(p, "# Empty\n", WRITE_STRING_FILE_CREATE) >= 0);
650
651 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "xx.service", NULL) >= 0);
652 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "xx.service", &state) >= 0 && state == UNIT_FILE_STATIC);
653
654 /* Initially there's nothing to revert */
655 assert_se(unit_file_revert(UNIT_FILE_SYSTEM, root, STRV_MAKE("xx.service"), &changes, &n_changes) >= 0);
656 assert_se(n_changes == 0);
657 unit_file_changes_free(changes, n_changes);
658 changes = NULL; n_changes = 0;
659
660 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/xx.service");
661 assert_se(write_string_file(p, "# Empty override\n", WRITE_STRING_FILE_CREATE) >= 0);
662
663 /* Revert the override file */
664 assert_se(unit_file_revert(UNIT_FILE_SYSTEM, root, STRV_MAKE("xx.service"), &changes, &n_changes) >= 0);
665 assert_se(n_changes == 1);
666 assert_se(changes[0].type == UNIT_FILE_UNLINK);
667 assert_se(streq(changes[0].path, p));
668 unit_file_changes_free(changes, n_changes);
669 changes = NULL; n_changes = 0;
670
671 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/xx.service.d/dropin.conf");
672 assert_se(mkdir_parents(p, 0755) >= 0);
673 assert_se(write_string_file(p, "# Empty dropin\n", WRITE_STRING_FILE_CREATE) >= 0);
674
675 /* Revert the dropin file */
676 assert_se(unit_file_revert(UNIT_FILE_SYSTEM, root, STRV_MAKE("xx.service"), &changes, &n_changes) >= 0);
677 assert_se(n_changes == 2);
678 assert_se(changes[0].type == UNIT_FILE_UNLINK);
679 assert_se(streq(changes[0].path, p));
680
681 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/xx.service.d");
682 assert_se(changes[1].type == UNIT_FILE_UNLINK);
683 assert_se(streq(changes[1].path, p));
684 unit_file_changes_free(changes, n_changes);
685 changes = NULL; n_changes = 0;
686}
687
622d3705
AC
688static void test_preset_order(const char *root) {
689 UnitFileChange *changes = NULL;
da6053d0 690 size_t n_changes = 0;
622d3705
AC
691 const char *p;
692 UnitFileState state;
693
694 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-1.service", &state) == -ENOENT);
695 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-2.service", &state) == -ENOENT);
696
697 p = strjoina(root, "/usr/lib/systemd/system/prefix-1.service");
698 assert_se(write_string_file(p,
699 "[Install]\n"
700 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
701
702 p = strjoina(root, "/usr/lib/systemd/system/prefix-2.service");
703 assert_se(write_string_file(p,
704 "[Install]\n"
705 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
706
707 p = strjoina(root, "/usr/lib/systemd/system-preset/test.preset");
708 assert_se(write_string_file(p,
709 "enable prefix-1.service\n"
710 "disable prefix-*.service\n"
711 "enable prefix-2.service\n", WRITE_STRING_FILE_CREATE) >= 0);
712
713 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-1.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
714 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-2.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
715
b3796dd8 716 assert_se(unit_file_preset(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("prefix-1.service"), UNIT_FILE_PRESET_FULL, &changes, &n_changes) >= 0);
622d3705
AC
717 assert_se(n_changes == 1);
718 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
719 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/prefix-1.service"));
720 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/prefix-1.service");
721 assert_se(streq(changes[0].path, p));
722 unit_file_changes_free(changes, n_changes);
723 changes = NULL; n_changes = 0;
724
725 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-1.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
726 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-2.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
727
b3796dd8 728 assert_se(unit_file_preset(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("prefix-2.service"), UNIT_FILE_PRESET_FULL, &changes, &n_changes) >= 0);
622d3705
AC
729 assert_se(n_changes == 0);
730
731 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-1.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
732 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-2.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
733}
734
dfead90d
LP
735static void test_static_instance(const char *root) {
736 UnitFileState state;
737 const char *p;
738
739 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "static-instance@.service", &state) == -ENOENT);
740 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "static-instance@foo.service", &state) == -ENOENT);
741
742 p = strjoina(root, "/usr/lib/systemd/system/static-instance@.service");
743 assert_se(write_string_file(p,
744 "[Install]\n"
745 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
746
747 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "static-instance@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
748 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "static-instance@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
749
750 p = strjoina(root, "/usr/lib/systemd/system/static-instance@foo.service");
751 assert_se(symlink("static-instance@.service", p) >= 0);
752
753 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "static-instance@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
754 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "static-instance@foo.service", &state) >= 0 && state == UNIT_FILE_STATIC);
755}
756
142468d8
JL
757static void test_with_dropin(const char *root) {
758 const char *p;
759 UnitFileState state;
760 UnitFileChange *changes = NULL;
da6053d0 761 size_t n_changes = 0;
142468d8
JL
762
763 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-1.service", &state) == -ENOENT);
764 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-2.service", &state) == -ENOENT);
765 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3.service", &state) == -ENOENT);
766 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-4a.service", &state) == -ENOENT);
767 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-4b.service", &state) == -ENOENT);
768
769 p = strjoina(root, "/usr/lib/systemd/system/with-dropin-1.service");
770 assert_se(write_string_file(p,
771 "[Install]\n"
772 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
773
774 p = strjoina(root, "/usr/lib/systemd/system/with-dropin-1.service.d/dropin.conf");
775 assert_se(mkdir_parents(p, 0755) >= 0);
776 assert_se(write_string_file(p,
777 "[Install]\n"
778 "WantedBy=graphical.target\n", WRITE_STRING_FILE_CREATE) >= 0);
779
780 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-1.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
781
782 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/with-dropin-2.service");
783 assert_se(write_string_file(p,
784 "[Install]\n"
785 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
786
787 p = strjoina(root, "/usr/lib/systemd/system/with-dropin-2.service.d/dropin.conf");
788 assert_se(mkdir_parents(p, 0755) >= 0);
789 assert_se(write_string_file(p,
790 "[Install]\n"
791 "WantedBy=graphical.target\n", WRITE_STRING_FILE_CREATE) >= 0);
792
793 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-2.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
794
795 p = strjoina(root, "/usr/lib/systemd/system/with-dropin-3.service");
796 assert_se(write_string_file(p,
797 "[Install]\n"
798 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
799
800 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/with-dropin-3.service.d/dropin.conf");
801 assert_se(mkdir_parents(p, 0755) >= 0);
802 assert_se(write_string_file(p,
803 "[Install]\n"
804 "WantedBy=graphical.target\n", WRITE_STRING_FILE_CREATE) >= 0);
805
806 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
807
808 p = strjoina(root, "/usr/lib/systemd/system/with-dropin-4a.service");
809 assert_se(write_string_file(p,
810 "[Install]\n"
811 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
812
813 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/with-dropin-4a.service.d/dropin.conf");
814 assert_se(mkdir_parents(p, 0755) >= 0);
815 assert_se(write_string_file(p,
816 "[Install]\n"
817 "Also=with-dropin-4b.service\n", WRITE_STRING_FILE_CREATE) >= 0);
818
819 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-4a.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
820
821 p = strjoina(root, "/usr/lib/systemd/system/with-dropin-4b.service");
822 assert_se(write_string_file(p,
823 "[Install]\n"
824 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
825
826 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-4b.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
827
828 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("with-dropin-1.service"), &changes, &n_changes) == 1);
829 assert_se(n_changes == 2);
830 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
831 assert_se(changes[1].type == UNIT_FILE_SYMLINK);
832 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/with-dropin-1.service"));
833 assert_se(streq(changes[1].source, "/usr/lib/systemd/system/with-dropin-1.service"));
834 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/with-dropin-1.service");
835 assert_se(streq(changes[0].path, p));
836 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/graphical.target.wants/with-dropin-1.service");
837 assert_se(streq(changes[1].path, p));
838 unit_file_changes_free(changes, n_changes);
839 changes = NULL; n_changes = 0;
840
841 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("with-dropin-2.service"), &changes, &n_changes) == 1);
842 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-2.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
843 assert_se(n_changes == 2);
844 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
845 assert_se(changes[1].type == UNIT_FILE_SYMLINK);
846 assert_se(streq(changes[0].source, SYSTEM_CONFIG_UNIT_PATH"/with-dropin-2.service"));
847 assert_se(streq(changes[1].source, SYSTEM_CONFIG_UNIT_PATH"/with-dropin-2.service"));
848 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/with-dropin-2.service");
849 assert_se(streq(changes[0].path, p));
850 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/graphical.target.wants/with-dropin-2.service");
851 assert_se(streq(changes[1].path, p));
852 unit_file_changes_free(changes, n_changes);
853 changes = NULL; n_changes = 0;
854
855 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("with-dropin-3.service"), &changes, &n_changes) == 1);
856 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
857 assert_se(n_changes == 2);
858 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
859 assert_se(changes[1].type == UNIT_FILE_SYMLINK);
860 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/with-dropin-3.service"));
861 assert_se(streq(changes[1].source, "/usr/lib/systemd/system/with-dropin-3.service"));
862 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/with-dropin-3.service");
863 assert_se(streq(changes[0].path, p));
864 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/graphical.target.wants/with-dropin-3.service");
865 assert_se(streq(changes[1].path, p));
866 unit_file_changes_free(changes, n_changes);
867 changes = NULL; n_changes = 0;
868
869 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("with-dropin-4a.service"), &changes, &n_changes) == 1);
870 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
871 assert_se(n_changes == 2);
872 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
873 assert_se(changes[1].type == UNIT_FILE_SYMLINK);
874 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/with-dropin-4a.service"));
875 assert_se(streq(changes[1].source, "/usr/lib/systemd/system/with-dropin-4b.service"));
876 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/with-dropin-4a.service");
877 assert_se(streq(changes[0].path, p));
878 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/with-dropin-4b.service");
879 assert_se(streq(changes[1].path, p));
880 unit_file_changes_free(changes, n_changes);
881 changes = NULL; n_changes = 0;
882
883 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-1.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
884 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-2.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
885 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
886 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-4a.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
887 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-4b.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
888}
889
890static void test_with_dropin_template(const char *root) {
891 const char *p;
892 UnitFileState state;
893 UnitFileChange *changes = NULL;
da6053d0 894 size_t n_changes = 0;
142468d8
JL
895
896 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-1@.service", &state) == -ENOENT);
897 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-2@.service", &state) == -ENOENT);
898 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3@.service", &state) == -ENOENT);
899
900 p = strjoina(root, "/usr/lib/systemd/system/with-dropin-1@.service");
901 assert_se(write_string_file(p,
902 "[Install]\n"
903 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
904
905 p = strjoina(root, "/usr/lib/systemd/system/with-dropin-1@.service.d/dropin.conf");
906 assert_se(mkdir_parents(p, 0755) >= 0);
907 assert_se(write_string_file(p,
908 "[Install]\n"
909 "WantedBy=graphical.target\n", WRITE_STRING_FILE_CREATE) >= 0);
910
911 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-1@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
912
913 p = strjoina(root, "/usr/lib/systemd/system/with-dropin-2@.service");
914 assert_se(write_string_file(p,
915 "[Install]\n"
916 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
917
918 p = strjoina(root, "/usr/lib/systemd/system/with-dropin-2@instance-1.service.d/dropin.conf");
919 assert_se(mkdir_parents(p, 0755) >= 0);
920 assert_se(write_string_file(p,
921 "[Install]\n"
922 "WantedBy=graphical.target\n", WRITE_STRING_FILE_CREATE) >= 0);
923
924 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-2@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
925
926 p = strjoina(root, "/usr/lib/systemd/system/with-dropin-3@.service");
927 assert_se(write_string_file(p,
928 "[Install]\n"
929 "DefaultInstance=instance-1\n"
930 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
931
932 p = strjoina(root, "/usr/lib/systemd/system/with-dropin-3@.service.d/dropin.conf");
933 assert_se(mkdir_parents(p, 0755) >= 0);
934 assert_se(write_string_file(p,
935 "[Install]\n"
936 "DefaultInstance=instance-2\n", WRITE_STRING_FILE_CREATE) >= 0);
937
938 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
939
940 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("with-dropin-1@instance-1.service"), &changes, &n_changes) == 1);
941 assert_se(n_changes == 2);
942 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
943 assert_se(changes[1].type == UNIT_FILE_SYMLINK);
944 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/with-dropin-1@.service"));
945 assert_se(streq(changes[1].source, "/usr/lib/systemd/system/with-dropin-1@.service"));
946 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/with-dropin-1@instance-1.service");
947 assert_se(streq(changes[0].path, p));
948 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/graphical.target.wants/with-dropin-1@instance-1.service");
949 assert_se(streq(changes[1].path, p));
950 unit_file_changes_free(changes, n_changes);
951 changes = NULL; n_changes = 0;
952
953 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("with-dropin-2@instance-1.service"), &changes, &n_changes) == 1);
954 assert_se(n_changes == 2);
955 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
956 assert_se(changes[1].type == UNIT_FILE_SYMLINK);
957 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/with-dropin-2@.service"));
958 assert_se(streq(changes[1].source, "/usr/lib/systemd/system/with-dropin-2@.service"));
959 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/with-dropin-2@instance-1.service");
960 assert_se(streq(changes[0].path, p));
961 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/graphical.target.wants/with-dropin-2@instance-1.service");
962 assert_se(streq(changes[1].path, p));
963 unit_file_changes_free(changes, n_changes);
964 changes = NULL; n_changes = 0;
965
966 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("with-dropin-2@instance-2.service"), &changes, &n_changes) == 1);
967 assert_se(n_changes == 1);
968 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
969 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/with-dropin-2@.service"));
970 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/with-dropin-2@instance-2.service");
971 assert_se(streq(changes[0].path, p));
972 unit_file_changes_free(changes, n_changes);
973 changes = NULL; n_changes = 0;
974
975 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("with-dropin-3@.service"), &changes, &n_changes) == 1);
976 assert_se(n_changes == 1);
977 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
978 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/with-dropin-3@.service"));
979 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/with-dropin-3@instance-2.service");
980 assert_se(streq(changes[0].path, p));
981 unit_file_changes_free(changes, n_changes);
982 changes = NULL; n_changes = 0;
983
984 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-1@instance-1.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
985 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-2@instance-1.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
986 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-2@instance-2.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
987 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3@instance-1.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
988 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3@instance-2.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
989}
990
0ec0deaa
LP
991int main(int argc, char *argv[]) {
992 char root[] = "/tmp/rootXXXXXX";
993 const char *p;
994
995 assert_se(mkdtemp(root));
996
997 p = strjoina(root, "/usr/lib/systemd/system/");
998 assert_se(mkdir_p(p, 0755) >= 0);
999
1000 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/");
1001 assert_se(mkdir_p(p, 0755) >= 0);
1002
1003 p = strjoina(root, "/run/systemd/system/");
1004 assert_se(mkdir_p(p, 0755) >= 0);
1005
1006 p = strjoina(root, "/opt/");
1007 assert_se(mkdir_p(p, 0755) >= 0);
1008
1009 p = strjoina(root, "/usr/lib/systemd/system-preset/");
1010 assert_se(mkdir_p(p, 0755) >= 0);
1011
1012 test_basic_mask_and_enable(root);
1013 test_linked_units(root);
1014 test_default(root);
1015 test_add_dependency(root);
1016 test_template_enable(root);
1017 test_indirect(root);
1018 test_preset_and_list(root);
622d3705 1019 test_preset_order(root);
344ca755 1020 test_revert(root);
dfead90d 1021 test_static_instance(root);
142468d8
JL
1022 test_with_dropin(root);
1023 test_with_dropin_template(root);
0ec0deaa
LP
1024
1025 assert_se(rm_rf(root, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
1026
1027 return 0;
1028}