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