]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-unit-file.c
Merge pull request #7198 from poettering/stdin-stdout
[thirdparty/systemd.git] / src / test / test-unit-file.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright 2012 Lennart Poettering
6 Copyright 2013 Zbigniew Jędrzejewski-Szmek
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <fcntl.h>
23 #include <stddef.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <sys/capability.h>
27 #include <unistd.h>
28
29 #include "alloc-util.h"
30 #include "capability-util.h"
31 #include "fd-util.h"
32 #include "fileio.h"
33 #include "hashmap.h"
34 #include "hostname-util.h"
35 #include "install-printf.h"
36 #include "install.h"
37 #include "load-fragment.h"
38 #include "macro.h"
39 #include "rm-rf.h"
40 #include "specifier.h"
41 #include "string-util.h"
42 #include "strv.h"
43 #include "test-helper.h"
44 #include "tests.h"
45 #include "user-util.h"
46 #include "util.h"
47
48 static int test_unit_file_get_set(void) {
49 int r;
50 Hashmap *h;
51 Iterator i;
52 UnitFileList *p;
53
54 h = hashmap_new(&string_hash_ops);
55 assert_se(h);
56
57 r = unit_file_get_list(UNIT_FILE_SYSTEM, NULL, h, NULL, NULL);
58
59 if (IN_SET(r, -EPERM, -EACCES)) {
60 log_notice_errno(r, "Skipping test: unit_file_get_list: %m");
61 return EXIT_TEST_SKIP;
62 }
63
64 log_full_errno(r == 0 ? LOG_INFO : LOG_ERR, r,
65 "unit_file_get_list: %m");
66 if (r < 0)
67 return EXIT_FAILURE;
68
69 HASHMAP_FOREACH(p, h, i)
70 printf("%s = %s\n", p->path, unit_file_state_to_string(p->state));
71
72 unit_file_list_free(h);
73
74 return 0;
75 }
76
77 static void check_execcommand(ExecCommand *c,
78 const char* path,
79 const char* argv0,
80 const char* argv1,
81 const char* argv2,
82 bool ignore) {
83 size_t n;
84
85 assert_se(c);
86 log_info("expect: \"%s\" [\"%s\" \"%s\" \"%s\"]",
87 path, argv0 ?: path, argv1, argv2);
88 n = strv_length(c->argv);
89 log_info("actual: \"%s\" [\"%s\" \"%s\" \"%s\"]",
90 c->path, c->argv[0], n > 0 ? c->argv[1] : NULL, n > 1 ? c->argv[2] : NULL);
91 assert_se(streq(c->path, path));
92 assert_se(streq(c->argv[0], argv0 ?: path));
93 if (n > 0)
94 assert_se(streq_ptr(c->argv[1], argv1));
95 if (n > 1)
96 assert_se(streq_ptr(c->argv[2], argv2));
97 assert_se(!!(c->flags & EXEC_COMMAND_IGNORE_FAILURE) == ignore);
98 }
99
100 static void test_config_parse_exec(void) {
101 /* int config_parse_exec(
102 const char *unit,
103 const char *filename,
104 unsigned line,
105 const char *section,
106 unsigned section_line,
107 const char *lvalue,
108 int ltype,
109 const char *rvalue,
110 void *data,
111 void *userdata) */
112 int r;
113
114 ExecCommand *c = NULL, *c1;
115 const char *ccc;
116 Manager *m = NULL;
117 Unit *u = NULL;
118
119 r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_MINIMAL, &m);
120 if (MANAGER_SKIP_TEST(r)) {
121 log_notice_errno(r, "Skipping test: manager_new: %m");
122 return;
123 }
124
125 assert_se(r >= 0);
126 assert_se(manager_startup(m, NULL, NULL) >= 0);
127
128 assert_se(u = unit_new(m, sizeof(Service)));
129
130 log_info("/* basic test */");
131 r = config_parse_exec(NULL, "fake", 1, "section", 1,
132 "LValue", 0, "/RValue r1",
133 &c, u);
134 assert_se(r >= 0);
135 check_execcommand(c, "/RValue", "/RValue", "r1", NULL, false);
136
137 r = config_parse_exec(NULL, "fake", 2, "section", 1,
138 "LValue", 0, "/RValue///slashes r1///",
139 &c, u);
140
141 log_info("/* test slashes */");
142 assert_se(r >= 0);
143 c1 = c->command_next;
144 check_execcommand(c1, "/RValue/slashes", "/RValue///slashes", "r1///", NULL, false);
145
146 log_info("/* trailing slash */");
147 r = config_parse_exec(NULL, "fake", 4, "section", 1,
148 "LValue", 0, "/RValue/ argv0 r1",
149 &c, u);
150 assert_se(r == -ENOEXEC);
151 assert_se(c1->command_next == NULL);
152
153 log_info("/* honour_argv0 */");
154 r = config_parse_exec(NULL, "fake", 3, "section", 1,
155 "LValue", 0, "@/RValue///slashes2 ///argv0 r1",
156 &c, u);
157 assert_se(r >= 0);
158 c1 = c1->command_next;
159 check_execcommand(c1, "/RValue/slashes2", "///argv0", "r1", NULL, false);
160
161 log_info("/* honour_argv0, no args */");
162 r = config_parse_exec(NULL, "fake", 3, "section", 1,
163 "LValue", 0, "@/RValue",
164 &c, u);
165 assert_se(r == -ENOEXEC);
166 assert_se(c1->command_next == NULL);
167
168 log_info("/* no command, whitespace only, reset */");
169 r = config_parse_exec(NULL, "fake", 3, "section", 1,
170 "LValue", 0, " ",
171 &c, u);
172 assert_se(r == 0);
173 assert_se(c == NULL);
174
175 log_info("/* ignore && honour_argv0 */");
176 r = config_parse_exec(NULL, "fake", 4, "section", 1,
177 "LValue", 0, "-@/RValue///slashes3 argv0a r1",
178 &c, u);
179 assert_se(r >= 0);
180 c1 = c;
181 check_execcommand(c1, "/RValue/slashes3", "argv0a", "r1", NULL, true);
182
183 log_info("/* ignore && honour_argv0 */");
184 r = config_parse_exec(NULL, "fake", 4, "section", 1,
185 "LValue", 0, "@-/RValue///slashes4 argv0b r1",
186 &c, u);
187 assert_se(r >= 0);
188 c1 = c1->command_next;
189 check_execcommand(c1, "/RValue/slashes4", "argv0b", "r1", NULL, true);
190
191 log_info("/* ignore && ignore */");
192 r = config_parse_exec(NULL, "fake", 4, "section", 1,
193 "LValue", 0, "--/RValue argv0 r1",
194 &c, u);
195 assert_se(r == 0);
196 assert_se(c1->command_next == NULL);
197
198 log_info("/* ignore && ignore (2) */");
199 r = config_parse_exec(NULL, "fake", 4, "section", 1,
200 "LValue", 0, "-@-/RValue argv0 r1",
201 &c, u);
202 assert_se(r == 0);
203 assert_se(c1->command_next == NULL);
204
205 log_info("/* semicolon */");
206 r = config_parse_exec(NULL, "fake", 5, "section", 1,
207 "LValue", 0,
208 "-@/RValue argv0 r1 ; "
209 "/goo/goo boo",
210 &c, u);
211 assert_se(r >= 0);
212 c1 = c1->command_next;
213 check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
214
215 c1 = c1->command_next;
216 check_execcommand(c1, "/goo/goo", NULL, "boo", NULL, false);
217
218 log_info("/* two semicolons in a row */");
219 r = config_parse_exec(NULL, "fake", 5, "section", 1,
220 "LValue", 0,
221 "-@/RValue argv0 r1 ; ; "
222 "/goo/goo boo",
223 &c, u);
224 assert_se(r == -ENOEXEC);
225 c1 = c1->command_next;
226 check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
227
228 /* second command fails because the executable name is ";" */
229 assert_se(c1->command_next == NULL);
230
231 log_info("/* trailing semicolon */");
232 r = config_parse_exec(NULL, "fake", 5, "section", 1,
233 "LValue", 0,
234 "-@/RValue argv0 r1 ; ",
235 &c, u);
236 assert_se(r >= 0);
237 c1 = c1->command_next;
238 check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
239
240 assert_se(c1->command_next == NULL);
241
242 log_info("/* trailing semicolon, no whitespace */");
243 r = config_parse_exec(NULL, "fake", 5, "section", 1,
244 "LValue", 0,
245 "-@/RValue argv0 r1 ;",
246 &c, u);
247 assert_se(r >= 0);
248 c1 = c1->command_next;
249 check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
250
251 assert_se(c1->command_next == NULL);
252
253 log_info("/* trailing semicolon in single quotes */");
254 r = config_parse_exec(NULL, "fake", 5, "section", 1,
255 "LValue", 0,
256 "-@/RValue argv0 r1 ';'",
257 &c, u);
258 assert_se(r >= 0);
259 c1 = c1->command_next;
260 check_execcommand(c1, "/RValue", "argv0", "r1", ";", true);
261
262 log_info("/* escaped semicolon */");
263 r = config_parse_exec(NULL, "fake", 5, "section", 1,
264 "LValue", 0,
265 "/bin/find \\;",
266 &c, u);
267 assert_se(r >= 0);
268 c1 = c1->command_next;
269 check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
270
271 log_info("/* escaped semicolon with following arg */");
272 r = config_parse_exec(NULL, "fake", 5, "section", 1,
273 "LValue", 0,
274 "/sbin/find \\; /x",
275 &c, u);
276 assert_se(r >= 0);
277 c1 = c1->command_next;
278 check_execcommand(c1,
279 "/sbin/find", NULL, ";", "/x", false);
280
281 log_info("/* escaped semicolon as part of an expression */");
282 r = config_parse_exec(NULL, "fake", 5, "section", 1,
283 "LValue", 0,
284 "/sbin/find \\;x",
285 &c, u);
286 assert_se(r >= 0);
287 c1 = c1->command_next;
288 check_execcommand(c1,
289 "/sbin/find", NULL, "\\;x", NULL, false);
290
291 log_info("/* encoded semicolon */");
292 r = config_parse_exec(NULL, "fake", 5, "section", 1,
293 "LValue", 0,
294 "/bin/find \\073",
295 &c, u);
296 assert_se(r >= 0);
297 c1 = c1->command_next;
298 check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
299
300 log_info("/* quoted semicolon */");
301 r = config_parse_exec(NULL, "fake", 5, "section", 1,
302 "LValue", 0,
303 "/bin/find \";\"",
304 &c, u);
305 assert_se(r >= 0);
306 c1 = c1->command_next;
307 check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
308
309 log_info("/* quoted semicolon with following arg */");
310 r = config_parse_exec(NULL, "fake", 5, "section", 1,
311 "LValue", 0,
312 "/sbin/find \";\" /x",
313 &c, u);
314 assert_se(r >= 0);
315 c1 = c1->command_next;
316 check_execcommand(c1,
317 "/sbin/find", NULL, ";", "/x", false);
318
319 log_info("/* spaces in the filename */");
320 r = config_parse_exec(NULL, "fake", 5, "section", 1,
321 "LValue", 0,
322 "\"/PATH WITH SPACES/daemon\" -1 -2",
323 &c, u);
324 assert_se(r >= 0);
325 c1 = c1->command_next;
326 check_execcommand(c1,
327 "/PATH WITH SPACES/daemon", NULL, "-1", "-2", false);
328
329 log_info("/* spaces in the filename, no args */");
330 r = config_parse_exec(NULL, "fake", 5, "section", 1,
331 "LValue", 0,
332 "\"/PATH WITH SPACES/daemon -1 -2\"",
333 &c, u);
334 assert_se(r >= 0);
335 c1 = c1->command_next;
336 check_execcommand(c1,
337 "/PATH WITH SPACES/daemon -1 -2", NULL, NULL, NULL, false);
338
339 log_info("/* spaces in the filename, everything quoted */");
340 r = config_parse_exec(NULL, "fake", 5, "section", 1,
341 "LValue", 0,
342 "\"/PATH WITH SPACES/daemon\" \"-1\" '-2'",
343 &c, u);
344 assert_se(r >= 0);
345 c1 = c1->command_next;
346 check_execcommand(c1,
347 "/PATH WITH SPACES/daemon", NULL, "-1", "-2", false);
348
349 log_info("/* escaped spaces in the filename */");
350 r = config_parse_exec(NULL, "fake", 5, "section", 1,
351 "LValue", 0,
352 "\"/PATH\\sWITH\\sSPACES/daemon\" '-1 -2'",
353 &c, u);
354 assert_se(r >= 0);
355 c1 = c1->command_next;
356 check_execcommand(c1,
357 "/PATH WITH SPACES/daemon", NULL, "-1 -2", NULL, false);
358
359 log_info("/* escaped spaces in the filename (2) */");
360 r = config_parse_exec(NULL, "fake", 5, "section", 1,
361 "LValue", 0,
362 "\"/PATH\\x20WITH\\x20SPACES/daemon\" \"-1 -2\"",
363 &c, u);
364 assert_se(r >= 0);
365 c1 = c1->command_next;
366 check_execcommand(c1,
367 "/PATH WITH SPACES/daemon", NULL, "-1 -2", NULL, false);
368
369 for (ccc = "abfnrtv\\\'\"x"; *ccc; ccc++) {
370 /* \\x is an incomplete hexadecimal sequence, invalid because of the slash */
371 char path[] = "/path\\X";
372 path[sizeof(path) - 2] = *ccc;
373
374 log_info("/* invalid character: \\%c */", *ccc);
375 r = config_parse_exec(NULL, "fake", 4, "section", 1,
376 "LValue", 0, path,
377 &c, u);
378 assert_se(r == -ENOEXEC);
379 assert_se(c1->command_next == NULL);
380 }
381
382 log_info("/* valid character: \\s */");
383 r = config_parse_exec(NULL, "fake", 4, "section", 1,
384 "LValue", 0, "/path\\s",
385 &c, u);
386 assert_se(r >= 0);
387 c1 = c1->command_next;
388 check_execcommand(c1, "/path ", NULL, NULL, NULL, false);
389
390 log_info("/* quoted backslashes */");
391 r = config_parse_exec(NULL, "fake", 5, "section", 1,
392 "LValue", 0,
393 "/bin/grep '\\w+\\K'",
394 &c, u);
395 assert_se(r >= 0);
396 c1 = c1->command_next;
397 check_execcommand(c1, "/bin/grep", NULL, "\\w+\\K", NULL, false);
398
399
400 log_info("/* trailing backslash: \\ */");
401 /* backslash is invalid */
402 r = config_parse_exec(NULL, "fake", 4, "section", 1,
403 "LValue", 0, "/path\\",
404 &c, u);
405 assert_se(r == -ENOEXEC);
406 assert_se(c1->command_next == NULL);
407
408 log_info("/* missing ending ' */");
409 r = config_parse_exec(NULL, "fake", 4, "section", 1,
410 "LValue", 0, "/path 'foo",
411 &c, u);
412 assert_se(r == -ENOEXEC);
413 assert_se(c1->command_next == NULL);
414
415 log_info("/* missing ending ' with trailing backslash */");
416 r = config_parse_exec(NULL, "fake", 4, "section", 1,
417 "LValue", 0, "/path 'foo\\",
418 &c, u);
419 assert_se(r == -ENOEXEC);
420 assert_se(c1->command_next == NULL);
421
422 log_info("/* invalid space between modifiers */");
423 r = config_parse_exec(NULL, "fake", 4, "section", 1,
424 "LValue", 0, "- /path",
425 &c, u);
426 assert_se(r == 0);
427 assert_se(c1->command_next == NULL);
428
429 log_info("/* only modifiers, no path */");
430 r = config_parse_exec(NULL, "fake", 4, "section", 1,
431 "LValue", 0, "-",
432 &c, u);
433 assert_se(r == 0);
434 assert_se(c1->command_next == NULL);
435
436 log_info("/* empty argument, reset */");
437 r = config_parse_exec(NULL, "fake", 4, "section", 1,
438 "LValue", 0, "",
439 &c, u);
440 assert_se(r == 0);
441 assert_se(c == NULL);
442
443 exec_command_free_list(c);
444
445 unit_free(u);
446 manager_free(m);
447 }
448
449 static void test_config_parse_log_extra_fields(void) {
450 /* int config_parse_log_extra_fields(
451 const char *unit,
452 const char *filename,
453 unsigned line,
454 const char *section,
455 unsigned section_line,
456 const char *lvalue,
457 int ltype,
458 const char *rvalue,
459 void *data,
460 void *userdata) */
461
462 int r;
463
464 Manager *m = NULL;
465 Unit *u = NULL;
466 ExecContext c = {};
467
468 r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_MINIMAL, &m);
469 if (MANAGER_SKIP_TEST(r)) {
470 log_notice_errno(r, "Skipping test: manager_new: %m");
471 return;
472 }
473
474 assert_se(r >= 0);
475 assert_se(manager_startup(m, NULL, NULL) >= 0);
476
477 assert_se(u = unit_new(m, sizeof(Service)));
478
479 log_info("/* %s – basic test */", __func__);
480 r = config_parse_log_extra_fields(NULL, "fake", 1, "section", 1,
481 "LValue", 0, "FOO=BAR \"QOOF=quux ' ' \"",
482 &c, u);
483 assert_se(r >= 0);
484 assert_se(c.n_log_extra_fields == 2);
485 assert_se(strneq(c.log_extra_fields[0].iov_base, "FOO=BAR", c.log_extra_fields[0].iov_len));
486 assert_se(strneq(c.log_extra_fields[1].iov_base, "QOOF=quux ' ' ", c.log_extra_fields[1].iov_len));
487
488 log_info("/* %s – add some */", __func__);
489 r = config_parse_log_extra_fields(NULL, "fake", 1, "section", 1,
490 "LValue", 0, "FOO2=BAR2 QOOF2=quux ' '",
491 &c, u);
492 assert_se(r >= 0);
493 assert_se(c.n_log_extra_fields == 4);
494 assert_se(strneq(c.log_extra_fields[0].iov_base, "FOO=BAR", c.log_extra_fields[0].iov_len));
495 assert_se(strneq(c.log_extra_fields[1].iov_base, "QOOF=quux ' ' ", c.log_extra_fields[1].iov_len));
496 assert_se(strneq(c.log_extra_fields[2].iov_base, "FOO2=BAR2", c.log_extra_fields[2].iov_len));
497 assert_se(strneq(c.log_extra_fields[3].iov_base, "QOOF2=quux", c.log_extra_fields[3].iov_len));
498
499 exec_context_dump(&c, stdout, " --> ");
500
501 log_info("/* %s – reset */", __func__);
502 r = config_parse_log_extra_fields(NULL, "fake", 1, "section", 1,
503 "LValue", 0, "",
504 &c, u);
505 assert_se(r >= 0);
506 assert_se(c.n_log_extra_fields == 0);
507
508 exec_context_free_log_extra_fields(&c);
509
510 unit_free(u);
511 manager_free(m);
512
513 log_info("/* %s – bye */", __func__);
514 }
515
516 #define env_file_1 \
517 "a=a\n" \
518 "b=b\\\n" \
519 "c\n" \
520 "d=d\\\n" \
521 "e\\\n" \
522 "f\n" \
523 "g=g\\ \n" \
524 "h=h\n" \
525 "i=i\\"
526
527 #define env_file_2 \
528 "a=a\\\n"
529
530 #define env_file_3 \
531 "#SPAMD_ARGS=\"-d --socketpath=/var/lib/bulwark/spamd \\\n" \
532 "#--nouser-config \\\n" \
533 "normal=line"
534
535 #define env_file_4 \
536 "# Generated\n" \
537 "\n" \
538 "HWMON_MODULES=\"coretemp f71882fg\"\n" \
539 "\n" \
540 "# For compatibility reasons\n" \
541 "\n" \
542 "MODULE_0=coretemp\n" \
543 "MODULE_1=f71882fg"
544
545 #define env_file_5 \
546 "a=\n" \
547 "b="
548
549 static void test_load_env_file_1(void) {
550 _cleanup_strv_free_ char **data = NULL;
551 int r;
552
553 char name[] = "/tmp/test-load-env-file.XXXXXX";
554 _cleanup_close_ int fd;
555
556 fd = mkostemp_safe(name);
557 assert_se(fd >= 0);
558 assert_se(write(fd, env_file_1, sizeof(env_file_1)) == sizeof(env_file_1));
559
560 r = load_env_file(NULL, name, NULL, &data);
561 assert_se(r == 0);
562 assert_se(streq(data[0], "a=a"));
563 assert_se(streq(data[1], "b=bc"));
564 assert_se(streq(data[2], "d=def"));
565 assert_se(streq(data[3], "g=g "));
566 assert_se(streq(data[4], "h=h"));
567 assert_se(streq(data[5], "i=i"));
568 assert_se(data[6] == NULL);
569 unlink(name);
570 }
571
572 static void test_load_env_file_2(void) {
573 _cleanup_strv_free_ char **data = NULL;
574 int r;
575
576 char name[] = "/tmp/test-load-env-file.XXXXXX";
577 _cleanup_close_ int fd;
578
579 fd = mkostemp_safe(name);
580 assert_se(fd >= 0);
581 assert_se(write(fd, env_file_2, sizeof(env_file_2)) == sizeof(env_file_2));
582
583 r = load_env_file(NULL, name, NULL, &data);
584 assert_se(r == 0);
585 assert_se(streq(data[0], "a=a"));
586 assert_se(data[1] == NULL);
587 unlink(name);
588 }
589
590 static void test_load_env_file_3(void) {
591 _cleanup_strv_free_ char **data = NULL;
592 int r;
593
594 char name[] = "/tmp/test-load-env-file.XXXXXX";
595 _cleanup_close_ int fd;
596
597 fd = mkostemp_safe(name);
598 assert_se(fd >= 0);
599 assert_se(write(fd, env_file_3, sizeof(env_file_3)) == sizeof(env_file_3));
600
601 r = load_env_file(NULL, name, NULL, &data);
602 assert_se(r == 0);
603 assert_se(data == NULL);
604 unlink(name);
605 }
606
607 static void test_load_env_file_4(void) {
608 _cleanup_strv_free_ char **data = NULL;
609 char name[] = "/tmp/test-load-env-file.XXXXXX";
610 _cleanup_close_ int fd;
611 int r;
612
613 fd = mkostemp_safe(name);
614 assert_se(fd >= 0);
615 assert_se(write(fd, env_file_4, sizeof(env_file_4)) == sizeof(env_file_4));
616
617 r = load_env_file(NULL, name, NULL, &data);
618 assert_se(r == 0);
619 assert_se(streq(data[0], "HWMON_MODULES=coretemp f71882fg"));
620 assert_se(streq(data[1], "MODULE_0=coretemp"));
621 assert_se(streq(data[2], "MODULE_1=f71882fg"));
622 assert_se(data[3] == NULL);
623 unlink(name);
624 }
625
626 static void test_load_env_file_5(void) {
627 _cleanup_strv_free_ char **data = NULL;
628 int r;
629
630 char name[] = "/tmp/test-load-env-file.XXXXXX";
631 _cleanup_close_ int fd;
632
633 fd = mkostemp_safe(name);
634 assert_se(fd >= 0);
635 assert_se(write(fd, env_file_5, sizeof(env_file_5)) == sizeof(env_file_5));
636
637 r = load_env_file(NULL, name, NULL, &data);
638 assert_se(r == 0);
639 assert_se(streq(data[0], "a="));
640 assert_se(streq(data[1], "b="));
641 assert_se(data[2] == NULL);
642 unlink(name);
643 }
644
645 static void test_install_printf(void) {
646 char name[] = "name.service",
647 path[] = "/run/systemd/system/name.service";
648 UnitFileInstallInfo i = { .name = name, .path = path, };
649 UnitFileInstallInfo i2 = { .name= name, .path = path, };
650 char name3[] = "name@inst.service",
651 path3[] = "/run/systemd/system/name.service";
652 UnitFileInstallInfo i3 = { .name = name3, .path = path3, };
653 UnitFileInstallInfo i4 = { .name = name3, .path = path3, };
654
655 _cleanup_free_ char *mid = NULL, *bid = NULL, *host = NULL, *uid = NULL, *user = NULL;
656
657 assert_se(specifier_machine_id('m', NULL, NULL, &mid) >= 0 && mid);
658 assert_se(specifier_boot_id('b', NULL, NULL, &bid) >= 0 && bid);
659 assert_se((host = gethostname_malloc()));
660 assert_se((user = uid_to_name(getuid())));
661 assert_se(asprintf(&uid, UID_FMT, getuid()) >= 0);
662
663 #define expect(src, pattern, result) \
664 do { \
665 _cleanup_free_ char *t = NULL; \
666 _cleanup_free_ char \
667 *d1 = strdup(i.name), \
668 *d2 = strdup(i.path); \
669 assert_se(install_full_printf(&src, pattern, &t) >= 0 || !result); \
670 memzero(i.name, strlen(i.name)); \
671 memzero(i.path, strlen(i.path)); \
672 assert_se(d1 && d2); \
673 if (result) { \
674 printf("%s\n", t); \
675 assert_se(streq(t, result)); \
676 } else assert_se(t == NULL); \
677 strcpy(i.name, d1); \
678 strcpy(i.path, d2); \
679 } while (false)
680
681 expect(i, "%n", "name.service");
682 expect(i, "%N", "name");
683 expect(i, "%p", "name");
684 expect(i, "%i", "");
685 expect(i, "%u", user);
686 expect(i, "%U", uid);
687
688 expect(i, "%m", mid);
689 expect(i, "%b", bid);
690 expect(i, "%H", host);
691
692 expect(i2, "%u", user);
693 expect(i2, "%U", uid);
694
695 expect(i3, "%n", "name@inst.service");
696 expect(i3, "%N", "name@inst");
697 expect(i3, "%p", "name");
698 expect(i3, "%u", user);
699 expect(i3, "%U", uid);
700
701 expect(i3, "%m", mid);
702 expect(i3, "%b", bid);
703 expect(i3, "%H", host);
704
705 expect(i4, "%u", user);
706 expect(i4, "%U", uid);
707 }
708
709 static uint64_t make_cap(int cap) {
710 return ((uint64_t) 1ULL << (uint64_t) cap);
711 }
712
713 static void test_config_parse_capability_set(void) {
714 /* int config_parse_capability_set(
715 const char *unit,
716 const char *filename,
717 unsigned line,
718 const char *section,
719 unsigned section_line,
720 const char *lvalue,
721 int ltype,
722 const char *rvalue,
723 void *data,
724 void *userdata) */
725 int r;
726 uint64_t capability_bounding_set = 0;
727
728 r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
729 "CapabilityBoundingSet", 0, "CAP_NET_RAW",
730 &capability_bounding_set, NULL);
731 assert_se(r >= 0);
732 assert_se(capability_bounding_set == make_cap(CAP_NET_RAW));
733
734 r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
735 "CapabilityBoundingSet", 0, "CAP_NET_ADMIN",
736 &capability_bounding_set, NULL);
737 assert_se(r >= 0);
738 assert_se(capability_bounding_set == (make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN)));
739
740 r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
741 "CapabilityBoundingSet", 0, "~CAP_NET_ADMIN",
742 &capability_bounding_set, NULL);
743 assert_se(r >= 0);
744 assert_se(capability_bounding_set == make_cap(CAP_NET_RAW));
745
746 r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
747 "CapabilityBoundingSet", 0, "",
748 &capability_bounding_set, NULL);
749 assert_se(r >= 0);
750 assert_se(capability_bounding_set == UINT64_C(0));
751
752 r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
753 "CapabilityBoundingSet", 0, "~",
754 &capability_bounding_set, NULL);
755 assert_se(r >= 0);
756 assert_se(cap_test_all(capability_bounding_set));
757
758 capability_bounding_set = 0;
759 r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
760 "CapabilityBoundingSet", 0, " 'CAP_NET_RAW' WAT_CAP??? CAP_NET_ADMIN CAP'_trailing_garbage",
761 &capability_bounding_set, NULL);
762 assert_se(r >= 0);
763 assert_se(capability_bounding_set == (make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN)));
764 }
765
766 static void test_config_parse_rlimit(void) {
767 struct rlimit * rl[_RLIMIT_MAX] = {};
768
769 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55", rl, NULL) >= 0);
770 assert_se(rl[RLIMIT_NOFILE]);
771 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 55);
772 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
773
774 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55:66", rl, NULL) >= 0);
775 assert_se(rl[RLIMIT_NOFILE]);
776 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 55);
777 assert_se(rl[RLIMIT_NOFILE]->rlim_max == 66);
778
779 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "infinity", rl, NULL) >= 0);
780 assert_se(rl[RLIMIT_NOFILE]);
781 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == RLIM_INFINITY);
782 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
783
784 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "infinity:infinity", rl, NULL) >= 0);
785 assert_se(rl[RLIMIT_NOFILE]);
786 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == RLIM_INFINITY);
787 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
788
789 rl[RLIMIT_NOFILE]->rlim_cur = 10;
790 rl[RLIMIT_NOFILE]->rlim_max = 20;
791
792 /* Invalid values don't change rl */
793 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "10:20:30", rl, NULL) >= 0);
794 assert_se(rl[RLIMIT_NOFILE]);
795 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
796 assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
797
798 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "wat:wat", rl, NULL) >= 0);
799 assert_se(rl[RLIMIT_NOFILE]);
800 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
801 assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
802
803 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "66:wat", rl, NULL) >= 0);
804 assert_se(rl[RLIMIT_NOFILE]);
805 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
806 assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
807
808 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "200:100", rl, NULL) >= 0);
809 assert_se(rl[RLIMIT_NOFILE]);
810 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
811 assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
812
813 rl[RLIMIT_NOFILE] = mfree(rl[RLIMIT_NOFILE]);
814
815 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "56", rl, NULL) >= 0);
816 assert_se(rl[RLIMIT_CPU]);
817 assert_se(rl[RLIMIT_CPU]->rlim_cur == 56);
818 assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
819
820 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "57s", rl, NULL) >= 0);
821 assert_se(rl[RLIMIT_CPU]);
822 assert_se(rl[RLIMIT_CPU]->rlim_cur == 57);
823 assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
824
825 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "40s:1m", rl, NULL) >= 0);
826 assert_se(rl[RLIMIT_CPU]);
827 assert_se(rl[RLIMIT_CPU]->rlim_cur == 40);
828 assert_se(rl[RLIMIT_CPU]->rlim_max == 60);
829
830 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "infinity", rl, NULL) >= 0);
831 assert_se(rl[RLIMIT_CPU]);
832 assert_se(rl[RLIMIT_CPU]->rlim_cur == RLIM_INFINITY);
833 assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
834
835 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "1234ms", rl, NULL) >= 0);
836 assert_se(rl[RLIMIT_CPU]);
837 assert_se(rl[RLIMIT_CPU]->rlim_cur == 2);
838 assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
839
840 rl[RLIMIT_CPU] = mfree(rl[RLIMIT_CPU]);
841
842 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58", rl, NULL) >= 0);
843 assert_se(rl[RLIMIT_RTTIME]);
844 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 58);
845 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
846
847 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58:60", rl, NULL) >= 0);
848 assert_se(rl[RLIMIT_RTTIME]);
849 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 58);
850 assert_se(rl[RLIMIT_RTTIME]->rlim_max == 60);
851
852 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s", rl, NULL) >= 0);
853 assert_se(rl[RLIMIT_RTTIME]);
854 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 59 * USEC_PER_SEC);
855 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
856
857 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s:123s", rl, NULL) >= 0);
858 assert_se(rl[RLIMIT_RTTIME]);
859 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 59 * USEC_PER_SEC);
860 assert_se(rl[RLIMIT_RTTIME]->rlim_max == 123 * USEC_PER_SEC);
861
862 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity", rl, NULL) >= 0);
863 assert_se(rl[RLIMIT_RTTIME]);
864 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == RLIM_INFINITY);
865 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
866
867 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity:infinity", rl, NULL) >= 0);
868 assert_se(rl[RLIMIT_RTTIME]);
869 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == RLIM_INFINITY);
870 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
871
872 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "2345ms", rl, NULL) >= 0);
873 assert_se(rl[RLIMIT_RTTIME]);
874 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 2345 * USEC_PER_MSEC);
875 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
876
877 rl[RLIMIT_RTTIME] = mfree(rl[RLIMIT_RTTIME]);
878 }
879
880 static void test_config_parse_pass_environ(void) {
881 /* int config_parse_pass_environ(
882 const char *unit,
883 const char *filename,
884 unsigned line,
885 const char *section,
886 unsigned section_line,
887 const char *lvalue,
888 int ltype,
889 const char *rvalue,
890 void *data,
891 void *userdata) */
892 int r;
893 _cleanup_strv_free_ char **passenv = NULL;
894
895 r = config_parse_pass_environ(NULL, "fake", 1, "section", 1,
896 "PassEnvironment", 0, "A B",
897 &passenv, NULL);
898 assert_se(r >= 0);
899 assert_se(strv_length(passenv) == 2);
900 assert_se(streq(passenv[0], "A"));
901 assert_se(streq(passenv[1], "B"));
902
903 r = config_parse_pass_environ(NULL, "fake", 1, "section", 1,
904 "PassEnvironment", 0, "",
905 &passenv, NULL);
906 assert_se(r >= 0);
907 assert_se(strv_isempty(passenv));
908
909 r = config_parse_pass_environ(NULL, "fake", 1, "section", 1,
910 "PassEnvironment", 0, "'invalid name' 'normal_name' A=1 \\",
911 &passenv, NULL);
912 assert_se(r >= 0);
913 assert_se(strv_length(passenv) == 1);
914 assert_se(streq(passenv[0], "normal_name"));
915
916 }
917
918 static void test_unit_dump_config_items(void) {
919 unit_dump_config_items(stdout);
920 }
921
922 int main(int argc, char *argv[]) {
923 _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
924 int r;
925
926 log_parse_environment();
927 log_open();
928
929 r = enter_cgroup_subroot();
930 if (r == -ENOMEDIUM) {
931 log_notice_errno(r, "Skipping test: cgroupfs not available");
932 return EXIT_TEST_SKIP;
933 }
934
935 assert_se(runtime_dir = setup_fake_runtime_dir());
936
937 r = test_unit_file_get_set();
938 test_config_parse_exec();
939 test_config_parse_log_extra_fields();
940 test_config_parse_capability_set();
941 test_config_parse_rlimit();
942 test_config_parse_pass_environ();
943 test_load_env_file_1();
944 test_load_env_file_2();
945 test_load_env_file_3();
946 test_load_env_file_4();
947 test_load_env_file_5();
948 TEST_REQ_RUNNING_SYSTEMD(test_install_printf());
949 test_unit_dump_config_items();
950
951 return r;
952 }