]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-install-root.c
Merge pull request #4417 from keszybz/man-and-rlimit
[thirdparty/systemd.git] / src / test / test-install-root.c
1 /***
2 This file is part of systemd.
3
4 Copyright 2011 Lennart Poettering
5
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.
10
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.
15
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/>.
18 ***/
19
20 #include "alloc-util.h"
21 #include "fileio.h"
22 #include "install.h"
23 #include "mkdir.h"
24 #include "rm-rf.h"
25 #include "string-util.h"
26
27 static void test_basic_mask_and_enable(const char *root) {
28 const char *p;
29 UnitFileState state;
30 UnitFileChange *changes = NULL;
31 unsigned n_changes = 0;
32
33 log_set_max_level(LOG_DEBUG);
34
35 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", NULL) == -ENOENT);
36 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", NULL) == -ENOENT);
37 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", NULL) == -ENOENT);
38 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", NULL) == -ENOENT);
39
40 p = strjoina(root, "/usr/lib/systemd/system/a.service");
41 assert_se(write_string_file(p,
42 "[Install]\n"
43 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
44
45 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", NULL) >= 0);
46 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
47
48 p = strjoina(root, "/usr/lib/systemd/system/b.service");
49 assert_se(symlink("a.service", p) >= 0);
50
51 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", NULL) >= 0);
52 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
53
54 p = strjoina(root, "/usr/lib/systemd/system/c.service");
55 assert_se(symlink("/usr/lib/systemd/system/a.service", p) >= 0);
56
57 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", NULL) >= 0);
58 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
59
60 p = strjoina(root, "/usr/lib/systemd/system/d.service");
61 assert_se(symlink("c.service", p) >= 0);
62
63 /* This one is interesting, as d follows a relative, then an absolute symlink */
64 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", NULL) >= 0);
65 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
66
67 assert_se(unit_file_mask(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), false, &changes, &n_changes) >= 0);
68 assert_se(n_changes == 1);
69 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
70 assert_se(streq(changes[0].source, "/dev/null"));
71 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/a.service");
72 assert_se(streq(changes[0].path, p));
73
74 unit_file_changes_free(changes, n_changes);
75 changes = NULL; n_changes = 0;
76
77 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_MASKED);
78 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_MASKED);
79 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_MASKED);
80 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_MASKED);
81
82 /* Enabling a masked unit should fail! */
83 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), false, &changes, &n_changes) == -ERFKILL);
84 unit_file_changes_free(changes, n_changes);
85 changes = NULL; n_changes = 0;
86
87 assert_se(unit_file_unmask(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0);
88 assert_se(n_changes == 1);
89 assert_se(changes[0].type == UNIT_FILE_UNLINK);
90 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/a.service");
91 assert_se(streq(changes[0].path, p));
92 unit_file_changes_free(changes, n_changes);
93 changes = NULL; n_changes = 0;
94
95 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), false, &changes, &n_changes) == 1);
96 assert_se(n_changes == 1);
97 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
98 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/a.service"));
99 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service");
100 assert_se(streq(changes[0].path, p));
101 unit_file_changes_free(changes, n_changes);
102 changes = NULL; n_changes = 0;
103
104 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
105 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
106 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
107 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
108
109 /* Enabling it again should succeed but be a NOP */
110 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), false, &changes, &n_changes) >= 0);
111 assert_se(n_changes == 0);
112 unit_file_changes_free(changes, n_changes);
113 changes = NULL; n_changes = 0;
114
115 assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0);
116 assert_se(n_changes == 1);
117 assert_se(changes[0].type == UNIT_FILE_UNLINK);
118 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service");
119 assert_se(streq(changes[0].path, p));
120 unit_file_changes_free(changes, n_changes);
121 changes = NULL; n_changes = 0;
122
123 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
124 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
125 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
126 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
127
128 /* Disabling a disabled unit must suceed but be a NOP */
129 assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0);
130 assert_se(n_changes == 0);
131 unit_file_changes_free(changes, n_changes);
132 changes = NULL; n_changes = 0;
133
134 /* Let's enable this indirectly via a symlink */
135 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("d.service"), false, &changes, &n_changes) >= 0);
136 assert_se(n_changes == 1);
137 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
138 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/a.service"));
139 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service");
140 assert_se(streq(changes[0].path, p));
141 unit_file_changes_free(changes, n_changes);
142 changes = NULL; n_changes = 0;
143
144 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
145 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
146 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
147 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
148
149 /* Let's try to reenable */
150
151 assert_se(unit_file_reenable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("b.service"), false, &changes, &n_changes) >= 0);
152 assert_se(n_changes == 2);
153 assert_se(changes[0].type == UNIT_FILE_UNLINK);
154 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service");
155 assert_se(streq(changes[0].path, p));
156 assert_se(changes[1].type == UNIT_FILE_SYMLINK);
157 assert_se(streq(changes[1].source, "/usr/lib/systemd/system/a.service"));
158 assert_se(streq(changes[1].path, p));
159 unit_file_changes_free(changes, n_changes);
160 changes = NULL; n_changes = 0;
161
162 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
163 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
164 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
165 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
166 }
167
168 static void test_linked_units(const char *root) {
169 const char *p, *q;
170 UnitFileState state;
171 UnitFileChange *changes = NULL;
172 unsigned n_changes = 0, i;
173
174 /*
175 * We'll test three cases here:
176 *
177 * a) a unit file in /opt, that we use "systemctl link" and
178 * "systemctl enable" on to make it available to the system
179 *
180 * b) a unit file in /opt, that is statically linked into
181 * /usr/lib/systemd/system, that "enable" should work on
182 * correctly.
183 *
184 * c) a unit file in /opt, that is linked into
185 * /etc/systemd/system, and where "enable" should result in
186 * -ELOOP, since using information from /etc to generate
187 * information in /etc should not be allowed.
188 */
189
190 p = strjoina(root, "/opt/linked.service");
191 assert_se(write_string_file(p,
192 "[Install]\n"
193 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
194
195 p = strjoina(root, "/opt/linked2.service");
196 assert_se(write_string_file(p,
197 "[Install]\n"
198 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
199
200 p = strjoina(root, "/opt/linked3.service");
201 assert_se(write_string_file(p,
202 "[Install]\n"
203 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
204
205 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", NULL) == -ENOENT);
206 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked2.service", NULL) == -ENOENT);
207 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked3.service", NULL) == -ENOENT);
208
209 p = strjoina(root, "/usr/lib/systemd/system/linked2.service");
210 assert_se(symlink("/opt/linked2.service", p) >= 0);
211
212 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked3.service");
213 assert_se(symlink("/opt/linked3.service", p) >= 0);
214
215 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", &state) == -ENOENT);
216 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked2.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
217 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked3.service", &state) >= 0 && state == UNIT_FILE_LINKED);
218
219 /* First, let's link the unit into the search path */
220 assert_se(unit_file_link(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("/opt/linked.service"), false, &changes, &n_changes) >= 0);
221 assert_se(n_changes == 1);
222 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
223 assert_se(streq(changes[0].source, "/opt/linked.service"));
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", &state) >= 0 && state == UNIT_FILE_LINKED);
230
231 /* Let's unlink it from the search path again */
232 assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("linked.service"), &changes, &n_changes) >= 0);
233 assert_se(n_changes == 1);
234 assert_se(changes[0].type == UNIT_FILE_UNLINK);
235 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service");
236 assert_se(streq(changes[0].path, p));
237 unit_file_changes_free(changes, n_changes);
238 changes = NULL; n_changes = 0;
239
240 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", NULL) == -ENOENT);
241
242 /* Now, let's not just link it, but also enable it */
243 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("/opt/linked.service"), false, &changes, &n_changes) >= 0);
244 assert_se(n_changes == 2);
245 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/linked.service");
246 q = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service");
247 for (i = 0 ; i < n_changes; i++) {
248 assert_se(changes[i].type == UNIT_FILE_SYMLINK);
249 assert_se(streq(changes[i].source, "/opt/linked.service"));
250
251 if (p && streq(changes[i].path, p))
252 p = NULL;
253 else if (q && streq(changes[i].path, q))
254 q = NULL;
255 else
256 assert_not_reached("wut?");
257 }
258 assert(!p && !q);
259 unit_file_changes_free(changes, n_changes);
260 changes = NULL; n_changes = 0;
261
262 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
263
264 /* And let's unlink it again */
265 assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("linked.service"), &changes, &n_changes) >= 0);
266 assert_se(n_changes == 2);
267 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/linked.service");
268 q = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service");
269 for (i = 0; i < n_changes; i++) {
270 assert_se(changes[i].type == UNIT_FILE_UNLINK);
271
272 if (p && streq(changes[i].path, p))
273 p = NULL;
274 else if (q && streq(changes[i].path, q))
275 q = NULL;
276 else
277 assert_not_reached("wut?");
278 }
279 assert(!p && !q);
280 unit_file_changes_free(changes, n_changes);
281 changes = NULL; n_changes = 0;
282
283 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", NULL) == -ENOENT);
284
285 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("linked2.service"), false, &changes, &n_changes) >= 0);
286 assert_se(n_changes == 2);
287 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/linked2.service");
288 q = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked2.service");
289 for (i = 0 ; i < n_changes; i++) {
290 assert_se(changes[i].type == UNIT_FILE_SYMLINK);
291 assert_se(streq(changes[i].source, "/opt/linked2.service"));
292
293 if (p && streq(changes[i].path, p))
294 p = NULL;
295 else if (q && streq(changes[i].path, q))
296 q = NULL;
297 else
298 assert_not_reached("wut?");
299 }
300 assert(!p && !q);
301 unit_file_changes_free(changes, n_changes);
302 changes = NULL; n_changes = 0;
303
304 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("linked3.service"), false, &changes, &n_changes) >= 0);
305 assert_se(n_changes == 1);
306 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
307 assert_se(startswith(changes[0].path, root));
308 assert_se(endswith(changes[0].path, "linked3.service"));
309 assert_se(streq(changes[0].source, "/opt/linked3.service"));
310 unit_file_changes_free(changes, n_changes);
311 changes = NULL; n_changes = 0;
312 }
313
314 static void test_default(const char *root) {
315 _cleanup_free_ char *def = NULL;
316 UnitFileChange *changes = NULL;
317 unsigned n_changes = 0;
318 const char *p;
319
320 p = strjoina(root, "/usr/lib/systemd/system/test-default-real.target");
321 assert_se(write_string_file(p, "# pretty much empty", WRITE_STRING_FILE_CREATE) >= 0);
322
323 p = strjoina(root, "/usr/lib/systemd/system/test-default.target");
324 assert_se(symlink("test-default-real.target", p) >= 0);
325
326 assert_se(unit_file_get_default(UNIT_FILE_SYSTEM, root, &def) == -ENOENT);
327
328 assert_se(unit_file_set_default(UNIT_FILE_SYSTEM, root, "idontexist.target", false, &changes, &n_changes) == -ENOENT);
329 assert_se(n_changes == 1);
330 assert_se(changes[0].type == -ENOENT);
331 assert_se(streq_ptr(changes[0].path, "idontexist.target"));
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) == -ENOENT);
336
337 assert_se(unit_file_set_default(UNIT_FILE_SYSTEM, root, "test-default.target", false, &changes, &n_changes) >= 0);
338 assert_se(n_changes == 1);
339 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
340 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/test-default-real.target"));
341 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/default.target");
342 assert_se(streq(changes[0].path, p));
343 unit_file_changes_free(changes, n_changes);
344 changes = NULL; n_changes = 0;
345
346 assert_se(unit_file_get_default(UNIT_FILE_SYSTEM, root, &def) >= 0);
347 assert_se(streq_ptr(def, "test-default-real.target"));
348 }
349
350 static void test_add_dependency(const char *root) {
351 UnitFileChange *changes = NULL;
352 unsigned n_changes = 0;
353 const char *p;
354
355 p = strjoina(root, "/usr/lib/systemd/system/real-add-dependency-test-target.target");
356 assert_se(write_string_file(p, "# pretty much empty", WRITE_STRING_FILE_CREATE) >= 0);
357
358 p = strjoina(root, "/usr/lib/systemd/system/add-dependency-test-target.target");
359 assert_se(symlink("real-add-dependency-test-target.target", p) >= 0);
360
361 p = strjoina(root, "/usr/lib/systemd/system/real-add-dependency-test-service.service");
362 assert_se(write_string_file(p, "# pretty much empty", WRITE_STRING_FILE_CREATE) >= 0);
363
364 p = strjoina(root, "/usr/lib/systemd/system/add-dependency-test-service.service");
365 assert_se(symlink("real-add-dependency-test-service.service", p) >= 0);
366
367 assert_se(unit_file_add_dependency(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("add-dependency-test-service.service"), "add-dependency-test-target.target", UNIT_WANTS, false, &changes, &n_changes) >= 0);
368 assert_se(n_changes == 1);
369 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
370 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/real-add-dependency-test-service.service"));
371 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/real-add-dependency-test-target.target.wants/real-add-dependency-test-service.service");
372 assert_se(streq(changes[0].path, p));
373 unit_file_changes_free(changes, n_changes);
374 changes = NULL; n_changes = 0;
375 }
376
377 static void test_template_enable(const char *root) {
378 UnitFileChange *changes = NULL;
379 unsigned n_changes = 0;
380 UnitFileState state;
381 const char *p;
382
383 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) == -ENOENT);
384 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) == -ENOENT);
385 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) == -ENOENT);
386 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) == -ENOENT);
387
388 p = strjoina(root, "/usr/lib/systemd/system/template@.service");
389 assert_se(write_string_file(p,
390 "[Install]\n"
391 "DefaultInstance=def\n"
392 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
393
394 p = strjoina(root, "/usr/lib/systemd/system/template-symlink@.service");
395 assert_se(symlink("template@.service", p) >= 0);
396
397 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
398 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
399 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
400 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
401 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
402 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
403
404 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("template@.service"), false, &changes, &n_changes) >= 0);
405 assert_se(n_changes == 1);
406 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
407 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/template@.service"));
408 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/template@def.service");
409 assert_se(streq(changes[0].path, p));
410 unit_file_changes_free(changes, n_changes);
411 changes = NULL; n_changes = 0;
412
413 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
414 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
415 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
416 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
417 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
418 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
419
420 assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("template@.service"), &changes, &n_changes) >= 0);
421 assert_se(n_changes == 1);
422 assert_se(changes[0].type == UNIT_FILE_UNLINK);
423 assert_se(streq(changes[0].path, p));
424 unit_file_changes_free(changes, n_changes);
425 changes = NULL; n_changes = 0;
426
427 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
428 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
429 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
430 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
431 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
432 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
433
434 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("template@foo.service"), false, &changes, &n_changes) >= 0);
435 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
436 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/template@.service"));
437 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/template@foo.service");
438 assert_se(streq(changes[0].path, p));
439 unit_file_changes_free(changes, n_changes);
440 changes = NULL; n_changes = 0;
441
442 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
443 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
444 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
445 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
446 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
447 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
448
449 assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("template@foo.service"), &changes, &n_changes) >= 0);
450 assert_se(n_changes == 1);
451 assert_se(changes[0].type == UNIT_FILE_UNLINK);
452 assert_se(streq(changes[0].path, p));
453 unit_file_changes_free(changes, n_changes);
454 changes = NULL; n_changes = 0;
455
456 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
457 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
458 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
459 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@quux.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
460 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
461 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
462 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
463 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@quux.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
464
465 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("template-symlink@quux.service"), false, &changes, &n_changes) >= 0);
466 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
467 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/template@.service"));
468 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/template@quux.service");
469 assert_se(streq(changes[0].path, p));
470 unit_file_changes_free(changes, n_changes);
471 changes = NULL; n_changes = 0;
472
473 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
474 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
475 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
476 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@quux.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
477 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
478 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
479 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
480 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@quux.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
481 }
482
483 static void test_indirect(const char *root) {
484 UnitFileChange *changes = NULL;
485 unsigned n_changes = 0;
486 UnitFileState state;
487 const char *p;
488
489 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirecta.service", &state) == -ENOENT);
490 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectb.service", &state) == -ENOENT);
491 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectc.service", &state) == -ENOENT);
492
493 p = strjoina(root, "/usr/lib/systemd/system/indirecta.service");
494 assert_se(write_string_file(p,
495 "[Install]\n"
496 "Also=indirectb.service\n", WRITE_STRING_FILE_CREATE) >= 0);
497
498 p = strjoina(root, "/usr/lib/systemd/system/indirectb.service");
499 assert_se(write_string_file(p,
500 "[Install]\n"
501 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
502
503 p = strjoina(root, "/usr/lib/systemd/system/indirectc.service");
504 assert_se(symlink("indirecta.service", p) >= 0);
505
506 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirecta.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
507 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectb.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
508 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectc.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
509
510 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("indirectc.service"), false, &changes, &n_changes) >= 0);
511 assert_se(n_changes == 1);
512 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
513 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/indirectb.service"));
514 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/indirectb.service");
515 assert_se(streq(changes[0].path, p));
516 unit_file_changes_free(changes, n_changes);
517 changes = NULL; n_changes = 0;
518
519 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirecta.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
520 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectb.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
521 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectc.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
522
523 assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("indirectc.service"), &changes, &n_changes) >= 0);
524 assert_se(n_changes == 1);
525 assert_se(changes[0].type == UNIT_FILE_UNLINK);
526 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/indirectb.service");
527 assert_se(streq(changes[0].path, p));
528 unit_file_changes_free(changes, n_changes);
529 changes = NULL; n_changes = 0;
530 }
531
532 static void test_preset_and_list(const char *root) {
533 UnitFileChange *changes = NULL;
534 unsigned n_changes = 0, i;
535 const char *p, *q;
536 UnitFileState state;
537 bool got_yes = false, got_no = false;
538 Iterator j;
539 UnitFileList *fl;
540 Hashmap *h;
541
542 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) == -ENOENT);
543 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) == -ENOENT);
544
545 p = strjoina(root, "/usr/lib/systemd/system/preset-yes.service");
546 assert_se(write_string_file(p,
547 "[Install]\n"
548 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
549
550 p = strjoina(root, "/usr/lib/systemd/system/preset-no.service");
551 assert_se(write_string_file(p,
552 "[Install]\n"
553 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
554
555 p = strjoina(root, "/usr/lib/systemd/system-preset/test.preset");
556 assert_se(write_string_file(p,
557 "enable *-yes.*\n"
558 "disable *\n", WRITE_STRING_FILE_CREATE) >= 0);
559
560 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
561 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
562
563 assert_se(unit_file_preset(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("preset-yes.service"), UNIT_FILE_PRESET_FULL, false, &changes, &n_changes) >= 0);
564 assert_se(n_changes == 1);
565 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
566 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/preset-yes.service"));
567 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/preset-yes.service");
568 assert_se(streq(changes[0].path, p));
569 unit_file_changes_free(changes, n_changes);
570 changes = NULL; n_changes = 0;
571
572 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
573 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
574
575 assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("preset-yes.service"), &changes, &n_changes) >= 0);
576 assert_se(n_changes == 1);
577 assert_se(changes[0].type == UNIT_FILE_UNLINK);
578 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/preset-yes.service");
579 assert_se(streq(changes[0].path, p));
580 unit_file_changes_free(changes, n_changes);
581 changes = NULL; n_changes = 0;
582
583 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
584 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
585
586 assert_se(unit_file_preset(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("preset-no.service"), UNIT_FILE_PRESET_FULL, false, &changes, &n_changes) >= 0);
587 assert_se(n_changes == 0);
588 unit_file_changes_free(changes, n_changes);
589 changes = NULL; n_changes = 0;
590
591 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
592 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
593
594 assert_se(unit_file_preset_all(UNIT_FILE_SYSTEM, false, root, UNIT_FILE_PRESET_FULL, false, &changes, &n_changes) >= 0);
595
596 assert_se(n_changes > 0);
597
598 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/preset-yes.service");
599
600 for (i = 0; i < n_changes; i++) {
601
602 if (changes[i].type == UNIT_FILE_SYMLINK) {
603 assert_se(streq(changes[i].source, "/usr/lib/systemd/system/preset-yes.service"));
604 assert_se(streq(changes[i].path, p));
605 } else
606 assert_se(changes[i].type == UNIT_FILE_UNLINK);
607 }
608
609 unit_file_changes_free(changes, n_changes);
610 changes = NULL; n_changes = 0;
611
612 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
613 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
614
615 assert_se(h = hashmap_new(&string_hash_ops));
616 assert_se(unit_file_get_list(UNIT_FILE_SYSTEM, root, h, NULL, NULL) >= 0);
617
618 p = strjoina(root, "/usr/lib/systemd/system/preset-yes.service");
619 q = strjoina(root, "/usr/lib/systemd/system/preset-no.service");
620
621 HASHMAP_FOREACH(fl, h, j) {
622 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, basename(fl->path), &state) >= 0);
623 assert_se(fl->state == state);
624
625 if (streq(fl->path, p)) {
626 got_yes = true;
627 assert_se(fl->state == UNIT_FILE_ENABLED);
628 } else if (streq(fl->path, q)) {
629 got_no = true;
630 assert_se(fl->state == UNIT_FILE_DISABLED);
631 } else
632 assert_se(IN_SET(fl->state, UNIT_FILE_DISABLED, UNIT_FILE_STATIC, UNIT_FILE_INDIRECT));
633 }
634
635 unit_file_list_free(h);
636
637 assert_se(got_yes && got_no);
638 }
639
640 static void test_revert(const char *root) {
641 const char *p;
642 UnitFileState state;
643 UnitFileChange *changes = NULL;
644 unsigned n_changes = 0;
645
646 assert(root);
647
648 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "xx.service", NULL) == -ENOENT);
649 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "yy.service", NULL) == -ENOENT);
650
651 p = strjoina(root, "/usr/lib/systemd/system/xx.service");
652 assert_se(write_string_file(p, "# Empty\n", WRITE_STRING_FILE_CREATE) >= 0);
653
654 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "xx.service", NULL) >= 0);
655 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "xx.service", &state) >= 0 && state == UNIT_FILE_STATIC);
656
657 /* Initially there's nothing to revert */
658 assert_se(unit_file_revert(UNIT_FILE_SYSTEM, root, STRV_MAKE("xx.service"), &changes, &n_changes) >= 0);
659 assert_se(n_changes == 0);
660 unit_file_changes_free(changes, n_changes);
661 changes = NULL; n_changes = 0;
662
663 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/xx.service");
664 assert_se(write_string_file(p, "# Empty override\n", WRITE_STRING_FILE_CREATE) >= 0);
665
666 /* Revert the override file */
667 assert_se(unit_file_revert(UNIT_FILE_SYSTEM, root, STRV_MAKE("xx.service"), &changes, &n_changes) >= 0);
668 assert_se(n_changes == 1);
669 assert_se(changes[0].type == UNIT_FILE_UNLINK);
670 assert_se(streq(changes[0].path, p));
671 unit_file_changes_free(changes, n_changes);
672 changes = NULL; n_changes = 0;
673
674 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/xx.service.d/dropin.conf");
675 assert_se(mkdir_parents(p, 0755) >= 0);
676 assert_se(write_string_file(p, "# Empty dropin\n", WRITE_STRING_FILE_CREATE) >= 0);
677
678 /* Revert the dropin file */
679 assert_se(unit_file_revert(UNIT_FILE_SYSTEM, root, STRV_MAKE("xx.service"), &changes, &n_changes) >= 0);
680 assert_se(n_changes == 2);
681 assert_se(changes[0].type == UNIT_FILE_UNLINK);
682 assert_se(streq(changes[0].path, p));
683
684 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/xx.service.d");
685 assert_se(changes[1].type == UNIT_FILE_UNLINK);
686 assert_se(streq(changes[1].path, p));
687 unit_file_changes_free(changes, n_changes);
688 changes = NULL; n_changes = 0;
689 }
690
691 static void test_preset_order(const char *root) {
692 UnitFileChange *changes = NULL;
693 unsigned n_changes = 0;
694 const char *p;
695 UnitFileState state;
696
697 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-1.service", &state) == -ENOENT);
698 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-2.service", &state) == -ENOENT);
699
700 p = strjoina(root, "/usr/lib/systemd/system/prefix-1.service");
701 assert_se(write_string_file(p,
702 "[Install]\n"
703 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
704
705 p = strjoina(root, "/usr/lib/systemd/system/prefix-2.service");
706 assert_se(write_string_file(p,
707 "[Install]\n"
708 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
709
710 p = strjoina(root, "/usr/lib/systemd/system-preset/test.preset");
711 assert_se(write_string_file(p,
712 "enable prefix-1.service\n"
713 "disable prefix-*.service\n"
714 "enable prefix-2.service\n", WRITE_STRING_FILE_CREATE) >= 0);
715
716 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-1.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
717 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-2.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
718
719 assert_se(unit_file_preset(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("prefix-1.service"), UNIT_FILE_PRESET_FULL, false, &changes, &n_changes) >= 0);
720 assert_se(n_changes == 1);
721 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
722 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/prefix-1.service"));
723 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/prefix-1.service");
724 assert_se(streq(changes[0].path, p));
725 unit_file_changes_free(changes, n_changes);
726 changes = NULL; n_changes = 0;
727
728 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-1.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
729 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-2.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
730
731 assert_se(unit_file_preset(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("prefix-2.service"), UNIT_FILE_PRESET_FULL, false, &changes, &n_changes) >= 0);
732 assert_se(n_changes == 0);
733
734 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-1.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
735 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-2.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
736 }
737
738 int main(int argc, char *argv[]) {
739 char root[] = "/tmp/rootXXXXXX";
740 const char *p;
741
742 assert_se(mkdtemp(root));
743
744 p = strjoina(root, "/usr/lib/systemd/system/");
745 assert_se(mkdir_p(p, 0755) >= 0);
746
747 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/");
748 assert_se(mkdir_p(p, 0755) >= 0);
749
750 p = strjoina(root, "/run/systemd/system/");
751 assert_se(mkdir_p(p, 0755) >= 0);
752
753 p = strjoina(root, "/opt/");
754 assert_se(mkdir_p(p, 0755) >= 0);
755
756 p = strjoina(root, "/usr/lib/systemd/system-preset/");
757 assert_se(mkdir_p(p, 0755) >= 0);
758
759 test_basic_mask_and_enable(root);
760 test_linked_units(root);
761 test_default(root);
762 test_add_dependency(root);
763 test_template_enable(root);
764 test_indirect(root);
765 test_preset_and_list(root);
766 test_preset_order(root);
767 test_revert(root);
768
769 assert_se(rm_rf(root, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
770
771 return 0;
772 }