2 This file is part of systemd.
4 Copyright 2010 Lennart Poettering
5 Copyright 2013 Thomas H.P. Andersen
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.
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.
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/>.
25 #include <sys/types.h>
27 #include <sys/xattr.h>
30 #include "alloc-util.h"
31 #include "conf-parser.h"
32 #include "cpu-set-util.h"
37 #include "fstab-util.h"
38 #include "glob-util.h"
41 #include "parse-util.h"
42 #include "path-util.h"
43 #include "proc-cmdline.h"
44 #include "process-util.h"
46 #include "signal-util.h"
48 #include "stat-util.h"
49 #include "string-util.h"
51 #include "user-util.h"
55 #include "xattr-util.h"
57 static void test_align_power2(void) {
60 assert_se(ALIGN_POWER2(0) == 0);
61 assert_se(ALIGN_POWER2(1) == 1);
62 assert_se(ALIGN_POWER2(2) == 2);
63 assert_se(ALIGN_POWER2(3) == 4);
64 assert_se(ALIGN_POWER2(12) == 16);
66 assert_se(ALIGN_POWER2(ULONG_MAX) == 0);
67 assert_se(ALIGN_POWER2(ULONG_MAX - 1) == 0);
68 assert_se(ALIGN_POWER2(ULONG_MAX - 1024) == 0);
69 assert_se(ALIGN_POWER2(ULONG_MAX / 2) == ULONG_MAX / 2 + 1);
70 assert_se(ALIGN_POWER2(ULONG_MAX + 1) == 0);
72 for (i = 1; i < 131071; ++i) {
73 for (p2 = 1; p2 < i; p2 <<= 1)
76 assert_se(ALIGN_POWER2(i) == p2);
79 for (i = ULONG_MAX - 1024; i < ULONG_MAX; ++i) {
80 for (p2 = 1; p2 && p2 < i; p2 <<= 1)
83 assert_se(ALIGN_POWER2(i) == p2);
87 static void test_max(void) {
90 int b[CONST_MAX(10, 100)];
92 .a = CONST_MAX(10, 100),
96 assert_cc(sizeof(val1.b) == sizeof(int) * 100);
98 /* CONST_MAX returns (void) instead of a value if the passed arguments
99 * are not of the same type or not constant expressions. */
100 assert_cc(__builtin_types_compatible_p(typeof(CONST_MAX(1, 10)), int));
101 assert_cc(__builtin_types_compatible_p(typeof(CONST_MAX(1, 1U)), void));
103 assert_se(val1.a == 100);
104 assert_se(MAX(++d, 0) == 1);
107 assert_cc(MAXSIZE(char[3], uint16_t) == 3);
108 assert_cc(MAXSIZE(char[3], uint32_t) == 4);
109 assert_cc(MAXSIZE(char, long) == sizeof(long));
111 assert_se(MAX(-5, 5) == 5);
112 assert_se(MAX(5, 5) == 5);
113 assert_se(MAX(MAX(1, MAX(2, MAX(3, 4))), 5) == 5);
114 assert_se(MAX(MAX(1, MAX(2, MAX(3, 2))), 1) == 3);
115 assert_se(MAX(MIN(1, MIN(2, MIN(3, 4))), 5) == 5);
116 assert_se(MAX(MAX(1, MIN(2, MIN(3, 2))), 1) == 2);
117 assert_se(LESS_BY(8, 4) == 4);
118 assert_se(LESS_BY(8, 8) == 0);
119 assert_se(LESS_BY(4, 8) == 0);
120 assert_se(LESS_BY(16, LESS_BY(8, 4)) == 12);
121 assert_se(LESS_BY(4, LESS_BY(8, 4)) == 0);
122 assert_se(CLAMP(-5, 0, 1) == 0);
123 assert_se(CLAMP(5, 0, 1) == 1);
124 assert_se(CLAMP(5, -10, 1) == 1);
125 assert_se(CLAMP(5, -10, 10) == 5);
126 assert_se(CLAMP(CLAMP(0, -10, 10), CLAMP(-5, 10, 20), CLAMP(100, -5, 20)) == 10);
129 static void test_container_of(void) {
135 } _packed_ myval = { };
137 assert_cc(sizeof(myval) == 17);
138 assert_se(container_of(&myval.v1, struct mytype, v1) == &myval);
139 assert_se(container_of(&myval.v2, struct mytype, v2) == &myval);
140 assert_se(container_of(&container_of(&myval.v2,
147 static void test_alloca(void) {
148 static const uint8_t zero[997] = { };
151 t = alloca_align(17, 512);
152 assert_se(!((uintptr_t)t & 0xff));
155 t = alloca0_align(997, 1024);
156 assert_se(!((uintptr_t)t & 0x1ff));
157 assert_se(!memcmp(t, zero, 997));
160 static void test_div_round_up(void) {
164 assert_se(DIV_ROUND_UP(0, 8) == 0);
165 assert_se(DIV_ROUND_UP(1, 8) == 1);
166 assert_se(DIV_ROUND_UP(8, 8) == 1);
167 assert_se(DIV_ROUND_UP(12, 8) == 2);
168 assert_se(DIV_ROUND_UP(16, 8) == 2);
170 /* test multiple evaluation */
172 assert_se(DIV_ROUND_UP(div++, 8) == 0 && div == 1);
173 assert_se(DIV_ROUND_UP(++div, 8) == 1 && div == 2);
174 assert_se(DIV_ROUND_UP(8, div++) == 4 && div == 3);
175 assert_se(DIV_ROUND_UP(8, ++div) == 2 && div == 4);
177 /* overflow test with exact division */
178 assert_se(sizeof(0U) == 4);
179 assert_se(0xfffffffaU % 10U == 0U);
180 assert_se(0xfffffffaU / 10U == 429496729U);
181 assert_se(DIV_ROUND_UP(0xfffffffaU, 10U) == 429496729U);
182 assert_se((0xfffffffaU + 10U - 1U) / 10U == 0U);
183 assert_se(0xfffffffaU / 10U + !!(0xfffffffaU % 10U) == 429496729U);
185 /* overflow test with rounded division */
186 assert_se(0xfffffffdU % 10U == 3U);
187 assert_se(0xfffffffdU / 10U == 429496729U);
188 assert_se(DIV_ROUND_UP(0xfffffffdU, 10U) == 429496730U);
189 assert_se((0xfffffffdU + 10U - 1U) / 10U == 0U);
190 assert_se(0xfffffffdU / 10U + !!(0xfffffffdU % 10U) == 429496730U);
193 static void test_close_many(void) {
195 char name0[] = "/tmp/test-close-many.XXXXXX";
196 char name1[] = "/tmp/test-close-many.XXXXXX";
197 char name2[] = "/tmp/test-close-many.XXXXXX";
199 fds[0] = mkostemp_safe(name0, O_RDWR|O_CLOEXEC);
200 fds[1] = mkostemp_safe(name1, O_RDWR|O_CLOEXEC);
201 fds[2] = mkostemp_safe(name2, O_RDWR|O_CLOEXEC);
205 assert_se(fcntl(fds[0], F_GETFD) == -1);
206 assert_se(fcntl(fds[1], F_GETFD) == -1);
207 assert_se(fcntl(fds[2], F_GETFD) >= 0);
216 static void test_parse_uid(void) {
220 r = parse_uid("100", &uid);
222 assert_se(uid == 100);
224 r = parse_uid("65535", &uid);
225 assert_se(r == -ENXIO);
227 r = parse_uid("asdsdas", &uid);
228 assert_se(r == -EINVAL);
231 static void test_memdup_multiply(void) {
232 int org[] = {1, 2, 3};
235 dup = (int*)memdup_multiply(org, sizeof(int), 3);
238 assert_se(dup[0] == 1);
239 assert_se(dup[1] == 2);
240 assert_se(dup[2] == 3);
244 static void test_u64log2(void) {
245 assert_se(u64log2(0) == 0);
246 assert_se(u64log2(8) == 3);
247 assert_se(u64log2(9) == 3);
248 assert_se(u64log2(15) == 3);
249 assert_se(u64log2(16) == 4);
250 assert_se(u64log2(1024*1024) == 20);
251 assert_se(u64log2(1024*1024+5) == 20);
254 static void test_protect_errno(void) {
260 assert_se(errno == 12);
263 static void test_parse_cpu_set(void) {
268 /* Simple range (from CPUAffinity example) */
269 ncpus = parse_cpu_set_and_warn("1 2", &c, NULL, "fake", 1, "CPUAffinity");
270 assert_se(ncpus >= 1024);
271 assert_se(CPU_ISSET_S(1, CPU_ALLOC_SIZE(ncpus), c));
272 assert_se(CPU_ISSET_S(2, CPU_ALLOC_SIZE(ncpus), c));
273 assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 2);
276 /* A more interesting range */
277 ncpus = parse_cpu_set_and_warn("0 1 2 3 8 9 10 11", &c, NULL, "fake", 1, "CPUAffinity");
278 assert_se(ncpus >= 1024);
279 assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
280 for (cpu = 0; cpu < 4; cpu++)
281 assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
282 for (cpu = 8; cpu < 12; cpu++)
283 assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
287 ncpus = parse_cpu_set_and_warn("8 '9' 10 \"11\"", &c, NULL, "fake", 1, "CPUAffinity");
288 assert_se(ncpus >= 1024);
289 assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 4);
290 for (cpu = 8; cpu < 12; cpu++)
291 assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
294 /* Use commas as separators */
295 ncpus = parse_cpu_set_and_warn("0,1,2,3 8,9,10,11", &c, NULL, "fake", 1, "CPUAffinity");
296 assert_se(ncpus >= 1024);
297 assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
298 for (cpu = 0; cpu < 4; cpu++)
299 assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
300 for (cpu = 8; cpu < 12; cpu++)
301 assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
304 /* Commas with spaces (and trailing comma, space) */
305 ncpus = parse_cpu_set_and_warn("0, 1, 2, 3, 4, 5, 6, 7, ", &c, NULL, "fake", 1, "CPUAffinity");
306 assert_se(ncpus >= 1024);
307 assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
308 for (cpu = 0; cpu < 8; cpu++)
309 assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
313 ncpus = parse_cpu_set_and_warn("0-3,8-11", &c, NULL, "fake", 1, "CPUAffinity");
314 assert_se(ncpus >= 1024);
315 assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
316 for (cpu = 0; cpu < 4; cpu++)
317 assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
318 for (cpu = 8; cpu < 12; cpu++)
319 assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
322 /* Ranges with trailing comma, space */
323 ncpus = parse_cpu_set_and_warn("0-3 8-11, ", &c, NULL, "fake", 1, "CPUAffinity");
324 assert_se(ncpus >= 1024);
325 assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
326 for (cpu = 0; cpu < 4; cpu++)
327 assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
328 for (cpu = 8; cpu < 12; cpu++)
329 assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
332 /* Negative range (returns empty cpu_set) */
333 ncpus = parse_cpu_set_and_warn("3-0", &c, NULL, "fake", 1, "CPUAffinity");
334 assert_se(ncpus >= 1024);
335 assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 0);
338 /* Overlapping ranges */
339 ncpus = parse_cpu_set_and_warn("0-7 4-11", &c, NULL, "fake", 1, "CPUAffinity");
340 assert_se(ncpus >= 1024);
341 assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 12);
342 for (cpu = 0; cpu < 12; cpu++)
343 assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
346 /* Mix ranges and individual CPUs */
347 ncpus = parse_cpu_set_and_warn("0,1 4-11", &c, NULL, "fake", 1, "CPUAffinity");
348 assert_se(ncpus >= 1024);
349 assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 10);
350 assert_se(CPU_ISSET_S(0, CPU_ALLOC_SIZE(ncpus), c));
351 assert_se(CPU_ISSET_S(1, CPU_ALLOC_SIZE(ncpus), c));
352 for (cpu = 4; cpu < 12; cpu++)
353 assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
357 ncpus = parse_cpu_set_and_warn("0 1 2 3 garbage", &c, NULL, "fake", 1, "CPUAffinity");
358 assert_se(ncpus < 0);
361 /* Range with garbage */
362 ncpus = parse_cpu_set_and_warn("0-3 8-garbage", &c, NULL, "fake", 1, "CPUAffinity");
363 assert_se(ncpus < 0);
368 ncpus = parse_cpu_set_and_warn("", &c, NULL, "fake", 1, "CPUAffinity");
369 assert_se(ncpus == 0); /* empty string returns 0 */
372 /* Runnaway quoted string */
373 ncpus = parse_cpu_set_and_warn("0 1 2 3 \"4 5 6 7 ", &c, NULL, "fake", 1, "CPUAffinity");
374 assert_se(ncpus < 0);
378 static void test_config_parse_iec_uint64(void) {
380 assert_se(config_parse_iec_uint64(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4M", &offset, NULL) == 0);
381 assert_se(offset == 4 * 1024 * 1024);
383 assert_se(config_parse_iec_uint64(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4.5M", &offset, NULL) == 0);
386 static void test_fstab_node_to_udev_node(void) {
389 n = fstab_node_to_udev_node("LABEL=applé/jack");
391 assert_se(streq(n, "/dev/disk/by-label/applé\\x2fjack"));
394 n = fstab_node_to_udev_node("PARTLABEL=pinkié pie");
396 assert_se(streq(n, "/dev/disk/by-partlabel/pinkié\\x20pie"));
399 n = fstab_node_to_udev_node("UUID=037b9d94-148e-4ee4-8d38-67bfe15bb535");
401 assert_se(streq(n, "/dev/disk/by-uuid/037b9d94-148e-4ee4-8d38-67bfe15bb535"));
404 n = fstab_node_to_udev_node("PARTUUID=037b9d94-148e-4ee4-8d38-67bfe15bb535");
406 assert_se(streq(n, "/dev/disk/by-partuuid/037b9d94-148e-4ee4-8d38-67bfe15bb535"));
409 n = fstab_node_to_udev_node("PONIES=awesome");
411 assert_se(streq(n, "PONIES=awesome"));
414 n = fstab_node_to_udev_node("/dev/xda1");
416 assert_se(streq(n, "/dev/xda1"));
420 static void test_get_files_in_directory(void) {
421 _cleanup_strv_free_ char **l = NULL, **t = NULL;
423 assert_se(get_files_in_directory("/tmp", &l) >= 0);
424 assert_se(get_files_in_directory(".", &t) >= 0);
425 assert_se(get_files_in_directory(".", NULL) >= 0);
428 static void test_in_set(void) {
429 assert_se(IN_SET(1, 1));
430 assert_se(IN_SET(1, 1, 2, 3, 4));
431 assert_se(IN_SET(2, 1, 2, 3, 4));
432 assert_se(IN_SET(3, 1, 2, 3, 4));
433 assert_se(IN_SET(4, 1, 2, 3, 4));
434 assert_se(!IN_SET(0, 1));
435 assert_se(!IN_SET(0, 1, 2, 3, 4));
438 static void test_writing_tmpfile(void) {
439 char name[] = "/tmp/test-systemd_writing_tmpfile.XXXXXX";
440 _cleanup_free_ char *contents = NULL;
445 IOVEC_SET_STRING(iov[0], "abc\n");
446 IOVEC_SET_STRING(iov[1], ALPHANUMERICAL "\n");
447 IOVEC_SET_STRING(iov[2], "");
449 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
450 printf("tmpfile: %s", name);
452 r = writev(fd, iov, 3);
455 r = read_full_file(name, &contents, &size);
457 printf("contents: %s", contents);
458 assert_se(streq(contents, "abc\n" ALPHANUMERICAL "\n"));
463 static void test_log2i(void) {
464 assert_se(log2i(1) == 0);
465 assert_se(log2i(2) == 1);
466 assert_se(log2i(3) == 1);
467 assert_se(log2i(4) == 2);
468 assert_se(log2i(32) == 5);
469 assert_se(log2i(33) == 5);
470 assert_se(log2i(63) == 5);
471 assert_se(log2i(INT_MAX) == sizeof(int)*8-2);
474 static void test_filename_is_valid(void) {
475 char foo[FILENAME_MAX+2];
478 assert_se(!filename_is_valid(""));
479 assert_se(!filename_is_valid("/bar/foo"));
480 assert_se(!filename_is_valid("/"));
481 assert_se(!filename_is_valid("."));
482 assert_se(!filename_is_valid(".."));
484 for (i=0; i<FILENAME_MAX+1; i++)
486 foo[FILENAME_MAX+1] = '\0';
488 assert_se(!filename_is_valid(foo));
490 assert_se(filename_is_valid("foo_bar-333"));
491 assert_se(filename_is_valid("o.o"));
494 static void test_files_same(void) {
495 _cleanup_close_ int fd = -1;
496 char name[] = "/tmp/test-files_same.XXXXXX";
497 char name_alias[] = "/tmp/test-files_same.alias";
499 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
501 assert_se(symlink(name, name_alias) >= 0);
503 assert_se(files_same(name, name));
504 assert_se(files_same(name, name_alias));
510 static void test_is_valid_documentation_url(void) {
511 assert_se(documentation_url_is_valid("http://www.freedesktop.org/wiki/Software/systemd"));
512 assert_se(documentation_url_is_valid("https://www.kernel.org/doc/Documentation/binfmt_misc.txt"));
513 assert_se(documentation_url_is_valid("file:/foo/foo"));
514 assert_se(documentation_url_is_valid("man:systemd.special(7)"));
515 assert_se(documentation_url_is_valid("info:bar"));
517 assert_se(!documentation_url_is_valid("foo:"));
518 assert_se(!documentation_url_is_valid("info:"));
519 assert_se(!documentation_url_is_valid(""));
522 static void test_file_in_same_dir(void) {
525 t = file_in_same_dir("/", "a");
526 assert_se(streq(t, "/a"));
529 t = file_in_same_dir("/", "/a");
530 assert_se(streq(t, "/a"));
533 t = file_in_same_dir("", "a");
534 assert_se(streq(t, "a"));
537 t = file_in_same_dir("a/", "a");
538 assert_se(streq(t, "a/a"));
541 t = file_in_same_dir("bar/foo", "bar");
542 assert_se(streq(t, "bar/bar"));
546 static void test_close_nointr(void) {
547 char name[] = "/tmp/test-test-close_nointr.XXXXXX";
550 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
552 assert_se(close_nointr(fd) >= 0);
553 assert_se(close_nointr(fd) < 0);
559 static void test_unlink_noerrno(void) {
560 char name[] = "/tmp/test-close_nointr.XXXXXX";
563 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
565 assert_se(close_nointr(fd) >= 0);
570 assert_se(unlink_noerrno(name) >= 0);
571 assert_se(errno == -42);
572 assert_se(unlink_noerrno(name) < 0);
573 assert_se(errno == -42);
577 static void test_readlink_and_make_absolute(void) {
578 char tempdir[] = "/tmp/test-readlink_and_make_absolute";
579 char name[] = "/tmp/test-readlink_and_make_absolute/original";
580 char name2[] = "test-readlink_and_make_absolute/original";
581 char name_alias[] = "/tmp/test-readlink_and_make_absolute-alias";
584 assert_se(mkdir_safe(tempdir, 0755, getuid(), getgid()) >= 0);
585 assert_se(touch(name) >= 0);
587 assert_se(symlink(name, name_alias) >= 0);
588 assert_se(readlink_and_make_absolute(name_alias, &r) >= 0);
589 assert_se(streq(r, name));
591 assert_se(unlink(name_alias) >= 0);
593 assert_se(chdir(tempdir) >= 0);
594 assert_se(symlink(name2, name_alias) >= 0);
595 assert_se(readlink_and_make_absolute(name_alias, &r) >= 0);
596 assert_se(streq(r, name));
598 assert_se(unlink(name_alias) >= 0);
600 assert_se(rm_rf(tempdir, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
603 static void test_ignore_signals(void) {
604 assert_se(ignore_signals(SIGINT, -1) >= 0);
605 assert_se(kill(getpid(), SIGINT) >= 0);
606 assert_se(ignore_signals(SIGUSR1, SIGUSR2, SIGTERM, SIGPIPE, -1) >= 0);
607 assert_se(kill(getpid(), SIGUSR1) >= 0);
608 assert_se(kill(getpid(), SIGUSR2) >= 0);
609 assert_se(kill(getpid(), SIGTERM) >= 0);
610 assert_se(kill(getpid(), SIGPIPE) >= 0);
611 assert_se(default_signals(SIGINT, SIGUSR1, SIGUSR2, SIGTERM, SIGPIPE, -1) >= 0);
614 static void test_is_symlink(void) {
615 char name[] = "/tmp/test-is_symlink.XXXXXX";
616 char name_link[] = "/tmp/test-is_symlink.link";
617 _cleanup_close_ int fd = -1;
619 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
621 assert_se(symlink(name, name_link) >= 0);
623 assert_se(is_symlink(name) == 0);
624 assert_se(is_symlink(name_link) == 1);
625 assert_se(is_symlink("/a/file/which/does/not/exist/i/guess") < 0);
632 static void test_search_and_fopen(void) {
633 const char *dirs[] = {"/tmp/foo/bar", "/tmp", NULL};
634 char name[] = "/tmp/test-search_and_fopen.XXXXXX";
639 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
643 r = search_and_fopen(basename(name), "r", NULL, dirs, &f);
647 r = search_and_fopen(name, "r", NULL, dirs, &f);
651 r = search_and_fopen(basename(name), "r", "/", dirs, &f);
655 r = search_and_fopen("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f);
657 r = search_and_fopen("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f);
663 r = search_and_fopen(basename(name), "r", NULL, dirs, &f);
668 static void test_search_and_fopen_nulstr(void) {
669 const char dirs[] = "/tmp/foo/bar\0/tmp\0";
670 char name[] = "/tmp/test-search_and_fopen.XXXXXX";
675 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
679 r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f);
683 r = search_and_fopen_nulstr(name, "r", NULL, dirs, &f);
687 r = search_and_fopen_nulstr("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f);
689 r = search_and_fopen_nulstr("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f);
695 r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f);
699 static void test_glob_exists(void) {
700 char name[] = "/tmp/test-glob_exists.XXXXXX";
704 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
708 r = glob_exists("/tmp/test-glob_exists*");
713 r = glob_exists("/tmp/test-glob_exists*");
717 static void test_execute_directory(void) {
718 char template_lo[] = "/tmp/test-readlink_and_make_absolute-lo.XXXXXXX";
719 char template_hi[] = "/tmp/test-readlink_and_make_absolute-hi.XXXXXXX";
720 const char * dirs[] = {template_hi, template_lo, NULL};
721 const char *name, *name2, *name3, *overridden, *override, *masked, *mask;
723 assert_se(mkdtemp(template_lo));
724 assert_se(mkdtemp(template_hi));
726 name = strjoina(template_lo, "/script");
727 name2 = strjoina(template_hi, "/script2");
728 name3 = strjoina(template_lo, "/useless");
729 overridden = strjoina(template_lo, "/overridden");
730 override = strjoina(template_hi, "/overridden");
731 masked = strjoina(template_lo, "/masked");
732 mask = strjoina(template_hi, "/masked");
734 assert_se(write_string_file(name, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/it_works", WRITE_STRING_FILE_CREATE) == 0);
735 assert_se(write_string_file(name2, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/it_works2", WRITE_STRING_FILE_CREATE) == 0);
736 assert_se(write_string_file(overridden, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed", WRITE_STRING_FILE_CREATE) == 0);
737 assert_se(write_string_file(override, "#!/bin/sh\necho 'Executing '$0", WRITE_STRING_FILE_CREATE) == 0);
738 assert_se(write_string_file(masked, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed", WRITE_STRING_FILE_CREATE) == 0);
739 assert_se(symlink("/dev/null", mask) == 0);
740 assert_se(chmod(name, 0755) == 0);
741 assert_se(chmod(name2, 0755) == 0);
742 assert_se(chmod(overridden, 0755) == 0);
743 assert_se(chmod(override, 0755) == 0);
744 assert_se(chmod(masked, 0755) == 0);
745 assert_se(touch(name3) >= 0);
747 execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL);
749 assert_se(chdir(template_lo) == 0);
750 assert_se(access("it_works", F_OK) >= 0);
751 assert_se(access("failed", F_OK) < 0);
753 assert_se(chdir(template_hi) == 0);
754 assert_se(access("it_works2", F_OK) >= 0);
755 assert_se(access("failed", F_OK) < 0);
757 (void) rm_rf(template_lo, REMOVE_ROOT|REMOVE_PHYSICAL);
758 (void) rm_rf(template_hi, REMOVE_ROOT|REMOVE_PHYSICAL);
761 static int parse_item(const char *key, const char *value) {
764 log_info("kernel cmdline option <%s> = <%s>", key, strna(value));
768 static void test_parse_proc_cmdline(void) {
769 assert_se(parse_proc_cmdline(parse_item) >= 0);
772 static void test_raw_clone(void) {
773 pid_t parent, pid, pid2;
776 log_info("before clone: getpid()→"PID_FMT, parent);
777 assert_se(raw_getpid() == parent);
779 pid = raw_clone(0, NULL);
783 log_info("raw_clone: "PID_FMT" getpid()→"PID_FMT" raw_getpid()→"PID_FMT,
784 pid, getpid(), pid2);
786 assert_se(pid2 != parent);
791 assert_se(pid2 == parent);
792 waitpid(pid, &status, __WCLONE);
793 assert_se(WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS);
797 static void test_same_fd(void) {
798 _cleanup_close_pair_ int p[2] = { -1, -1 };
799 _cleanup_close_ int a = -1, b = -1, c = -1;
801 assert_se(pipe2(p, O_CLOEXEC) >= 0);
802 assert_se((a = dup(p[0])) >= 0);
803 assert_se((b = open("/dev/null", O_RDONLY|O_CLOEXEC)) >= 0);
804 assert_se((c = dup(a)) >= 0);
806 assert_se(same_fd(p[0], p[0]) > 0);
807 assert_se(same_fd(p[1], p[1]) > 0);
808 assert_se(same_fd(a, a) > 0);
809 assert_se(same_fd(b, b) > 0);
811 assert_se(same_fd(a, p[0]) > 0);
812 assert_se(same_fd(p[0], a) > 0);
813 assert_se(same_fd(c, p[0]) > 0);
814 assert_se(same_fd(p[0], c) > 0);
815 assert_se(same_fd(a, c) > 0);
816 assert_se(same_fd(c, a) > 0);
818 assert_se(same_fd(p[0], p[1]) == 0);
819 assert_se(same_fd(p[1], p[0]) == 0);
820 assert_se(same_fd(p[0], b) == 0);
821 assert_se(same_fd(b, p[0]) == 0);
822 assert_se(same_fd(p[1], a) == 0);
823 assert_se(same_fd(a, p[1]) == 0);
824 assert_se(same_fd(p[1], b) == 0);
825 assert_se(same_fd(b, p[1]) == 0);
827 assert_se(same_fd(a, b) == 0);
828 assert_se(same_fd(b, a) == 0);
831 static void test_uid_ptr(void) {
833 assert_se(UID_TO_PTR(0) != NULL);
834 assert_se(UID_TO_PTR(1000) != NULL);
836 assert_se(PTR_TO_UID(UID_TO_PTR(0)) == 0);
837 assert_se(PTR_TO_UID(UID_TO_PTR(1000)) == 1000);
840 static void test_sparse_write_one(int fd, const char *buffer, size_t n) {
843 assert_se(lseek(fd, 0, SEEK_SET) == 0);
844 assert_se(ftruncate(fd, 0) >= 0);
845 assert_se(sparse_write(fd, buffer, n, 4) == (ssize_t) n);
847 assert_se(lseek(fd, 0, SEEK_CUR) == (off_t) n);
848 assert_se(ftruncate(fd, n) >= 0);
850 assert_se(lseek(fd, 0, SEEK_SET) == 0);
851 assert_se(read(fd, check, n) == (ssize_t) n);
853 assert_se(memcmp(buffer, check, n) == 0);
856 static void test_sparse_write(void) {
857 const char test_a[] = "test";
858 const char test_b[] = "\0\0\0\0test\0\0\0\0";
859 const char test_c[] = "\0\0test\0\0\0\0";
860 const char test_d[] = "\0\0test\0\0\0test\0\0\0\0test\0\0\0\0\0test\0\0\0test\0\0\0\0test\0\0\0\0\0\0\0\0";
861 const char test_e[] = "test\0\0\0\0test";
862 _cleanup_close_ int fd = -1;
863 char fn[] = "/tmp/sparseXXXXXX";
865 fd = mkostemp(fn, O_CLOEXEC);
869 test_sparse_write_one(fd, test_a, sizeof(test_a));
870 test_sparse_write_one(fd, test_b, sizeof(test_b));
871 test_sparse_write_one(fd, test_c, sizeof(test_c));
872 test_sparse_write_one(fd, test_d, sizeof(test_d));
873 test_sparse_write_one(fd, test_e, sizeof(test_e));
876 static void test_tempfn(void) {
877 char *ret = NULL, *p;
879 assert_se(tempfn_xxxxxx("/foo/bar/waldo", NULL, &ret) >= 0);
880 assert_se(streq_ptr(ret, "/foo/bar/.#waldoXXXXXX"));
883 assert_se(tempfn_xxxxxx("/foo/bar/waldo", "[miau]", &ret) >= 0);
884 assert_se(streq_ptr(ret, "/foo/bar/.#[miau]waldoXXXXXX"));
887 assert_se(tempfn_random("/foo/bar/waldo", NULL, &ret) >= 0);
888 assert_se(p = startswith(ret, "/foo/bar/.#waldo"));
889 assert_se(strlen(p) == 16);
890 assert_se(in_charset(p, "0123456789abcdef"));
893 assert_se(tempfn_random("/foo/bar/waldo", "[wuff]", &ret) >= 0);
894 assert_se(p = startswith(ret, "/foo/bar/.#[wuff]waldo"));
895 assert_se(strlen(p) == 16);
896 assert_se(in_charset(p, "0123456789abcdef"));
899 assert_se(tempfn_random_child("/foo/bar/waldo", NULL, &ret) >= 0);
900 assert_se(p = startswith(ret, "/foo/bar/waldo/.#"));
901 assert_se(strlen(p) == 16);
902 assert_se(in_charset(p, "0123456789abcdef"));
905 assert_se(tempfn_random_child("/foo/bar/waldo", "[kikiriki]", &ret) >= 0);
906 assert_se(p = startswith(ret, "/foo/bar/waldo/.#[kikiriki]"));
907 assert_se(strlen(p) == 16);
908 assert_se(in_charset(p, "0123456789abcdef"));
912 static void test_fgetxattrat_fake(void) {
913 char t[] = "/var/tmp/xattrtestXXXXXX";
914 _cleanup_close_ int fd = -1;
919 assert_se(mkdtemp(t));
920 x = strjoina(t, "/test");
921 assert_se(touch(x) >= 0);
923 r = setxattr(x, "user.foo", "bar", 3, 0);
924 if (r < 0 && errno == EOPNOTSUPP) /* no xattrs supported on /var/tmp... */
928 fd = open(t, O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY);
931 assert_se(fgetxattrat_fake(fd, "test", "user.foo", v, 3, 0) >= 0);
932 assert_se(memcmp(v, "bar", 3) == 0);
935 fd = open("/", O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY);
937 assert_se(fgetxattrat_fake(fd, "usr", "user.idontexist", v, 3, 0) == -ENODATA);
940 assert_se(unlink(x) >= 0);
941 assert_se(rmdir(t) >= 0);
944 static void test_runlevel_to_target(void) {
945 assert_se(streq_ptr(runlevel_to_target(NULL), NULL));
946 assert_se(streq_ptr(runlevel_to_target("unknown-runlevel"), NULL));
947 assert_se(streq_ptr(runlevel_to_target("3"), SPECIAL_MULTI_USER_TARGET));
950 int main(int argc, char *argv[]) {
951 log_parse_environment();
961 test_memdup_multiply();
963 test_protect_errno();
964 test_parse_cpu_set();
965 test_config_parse_iec_uint64();
966 test_fstab_node_to_udev_node();
967 test_get_files_in_directory();
969 test_writing_tmpfile();
971 test_filename_is_valid();
973 test_is_valid_documentation_url();
974 test_file_in_same_dir();
976 test_unlink_noerrno();
977 test_readlink_and_make_absolute();
978 test_ignore_signals();
980 test_search_and_fopen();
981 test_search_and_fopen_nulstr();
983 test_execute_directory();
984 test_parse_proc_cmdline();
990 test_fgetxattrat_fake();
991 test_runlevel_to_target();