]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-util.c
tree-wide: never use the off_t unless glibc makes us use it
[thirdparty/systemd.git] / src / test / test-util.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7 Copyright 2013 Thomas H.P. Andersen
8
9 systemd is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
13
14 systemd is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public License
20 along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 ***/
22
23 #include <string.h>
24 #include <unistd.h>
25 #include <fcntl.h>
26 #include <locale.h>
27 #include <errno.h>
28 #include <signal.h>
29 #include <math.h>
30 #include <sys/wait.h>
31
32 #include "util.h"
33 #include "mkdir.h"
34 #include "rm-rf.h"
35 #include "strv.h"
36 #include "def.h"
37 #include "fileio.h"
38 #include "conf-parser.h"
39 #include "virt.h"
40 #include "process-util.h"
41 #include "signal-util.h"
42
43 static void test_streq_ptr(void) {
44 assert_se(streq_ptr(NULL, NULL));
45 assert_se(!streq_ptr("abc", "cdef"));
46 }
47
48 static void test_align_power2(void) {
49 unsigned long i, p2;
50
51 assert_se(ALIGN_POWER2(0) == 0);
52 assert_se(ALIGN_POWER2(1) == 1);
53 assert_se(ALIGN_POWER2(2) == 2);
54 assert_se(ALIGN_POWER2(3) == 4);
55 assert_se(ALIGN_POWER2(12) == 16);
56
57 assert_se(ALIGN_POWER2(ULONG_MAX) == 0);
58 assert_se(ALIGN_POWER2(ULONG_MAX - 1) == 0);
59 assert_se(ALIGN_POWER2(ULONG_MAX - 1024) == 0);
60 assert_se(ALIGN_POWER2(ULONG_MAX / 2) == ULONG_MAX / 2 + 1);
61 assert_se(ALIGN_POWER2(ULONG_MAX + 1) == 0);
62
63 for (i = 1; i < 131071; ++i) {
64 for (p2 = 1; p2 < i; p2 <<= 1)
65 /* empty */ ;
66
67 assert_se(ALIGN_POWER2(i) == p2);
68 }
69
70 for (i = ULONG_MAX - 1024; i < ULONG_MAX; ++i) {
71 for (p2 = 1; p2 && p2 < i; p2 <<= 1)
72 /* empty */ ;
73
74 assert_se(ALIGN_POWER2(i) == p2);
75 }
76 }
77
78 static void test_max(void) {
79 static const struct {
80 int a;
81 int b[CONST_MAX(10, 100)];
82 } val1 = {
83 .a = CONST_MAX(10, 100),
84 };
85 int d = 0;
86
87 assert_cc(sizeof(val1.b) == sizeof(int) * 100);
88
89 /* CONST_MAX returns (void) instead of a value if the passed arguments
90 * are not of the same type or not constant expressions. */
91 assert_cc(__builtin_types_compatible_p(typeof(CONST_MAX(1, 10)), int));
92 assert_cc(__builtin_types_compatible_p(typeof(CONST_MAX(1, 1U)), void));
93
94 assert_se(val1.a == 100);
95 assert_se(MAX(++d, 0) == 1);
96 assert_se(d == 1);
97
98 assert_cc(MAXSIZE(char[3], uint16_t) == 3);
99 assert_cc(MAXSIZE(char[3], uint32_t) == 4);
100 assert_cc(MAXSIZE(char, long) == sizeof(long));
101
102 assert_se(MAX(-5, 5) == 5);
103 assert_se(MAX(5, 5) == 5);
104 assert_se(MAX(MAX(1, MAX(2, MAX(3, 4))), 5) == 5);
105 assert_se(MAX(MAX(1, MAX(2, MAX(3, 2))), 1) == 3);
106 assert_se(MAX(MIN(1, MIN(2, MIN(3, 4))), 5) == 5);
107 assert_se(MAX(MAX(1, MIN(2, MIN(3, 2))), 1) == 2);
108 assert_se(LESS_BY(8, 4) == 4);
109 assert_se(LESS_BY(8, 8) == 0);
110 assert_se(LESS_BY(4, 8) == 0);
111 assert_se(LESS_BY(16, LESS_BY(8, 4)) == 12);
112 assert_se(LESS_BY(4, LESS_BY(8, 4)) == 0);
113 assert_se(CLAMP(-5, 0, 1) == 0);
114 assert_se(CLAMP(5, 0, 1) == 1);
115 assert_se(CLAMP(5, -10, 1) == 1);
116 assert_se(CLAMP(5, -10, 10) == 5);
117 assert_se(CLAMP(CLAMP(0, -10, 10), CLAMP(-5, 10, 20), CLAMP(100, -5, 20)) == 10);
118 }
119
120 static void test_container_of(void) {
121 struct mytype {
122 uint8_t pad1[3];
123 uint64_t v1;
124 uint8_t pad2[2];
125 uint32_t v2;
126 } _packed_ myval = { };
127
128 assert_cc(sizeof(myval) == 17);
129 assert_se(container_of(&myval.v1, struct mytype, v1) == &myval);
130 assert_se(container_of(&myval.v2, struct mytype, v2) == &myval);
131 assert_se(container_of(&container_of(&myval.v2,
132 struct mytype,
133 v2)->v1,
134 struct mytype,
135 v1) == &myval);
136 }
137
138 static void test_alloca(void) {
139 static const uint8_t zero[997] = { };
140 char *t;
141
142 t = alloca_align(17, 512);
143 assert_se(!((uintptr_t)t & 0xff));
144 memzero(t, 17);
145
146 t = alloca0_align(997, 1024);
147 assert_se(!((uintptr_t)t & 0x1ff));
148 assert_se(!memcmp(t, zero, 997));
149 }
150
151 static void test_div_round_up(void) {
152 int div;
153
154 /* basic tests */
155 assert_se(DIV_ROUND_UP(0, 8) == 0);
156 assert_se(DIV_ROUND_UP(1, 8) == 1);
157 assert_se(DIV_ROUND_UP(8, 8) == 1);
158 assert_se(DIV_ROUND_UP(12, 8) == 2);
159 assert_se(DIV_ROUND_UP(16, 8) == 2);
160
161 /* test multiple evaluation */
162 div = 0;
163 assert_se(DIV_ROUND_UP(div++, 8) == 0 && div == 1);
164 assert_se(DIV_ROUND_UP(++div, 8) == 1 && div == 2);
165 assert_se(DIV_ROUND_UP(8, div++) == 4 && div == 3);
166 assert_se(DIV_ROUND_UP(8, ++div) == 2 && div == 4);
167
168 /* overflow test with exact division */
169 assert_se(sizeof(0U) == 4);
170 assert_se(0xfffffffaU % 10U == 0U);
171 assert_se(0xfffffffaU / 10U == 429496729U);
172 assert_se(DIV_ROUND_UP(0xfffffffaU, 10U) == 429496729U);
173 assert_se((0xfffffffaU + 10U - 1U) / 10U == 0U);
174 assert_se(0xfffffffaU / 10U + !!(0xfffffffaU % 10U) == 429496729U);
175
176 /* overflow test with rounded division */
177 assert_se(0xfffffffdU % 10U == 3U);
178 assert_se(0xfffffffdU / 10U == 429496729U);
179 assert_se(DIV_ROUND_UP(0xfffffffdU, 10U) == 429496730U);
180 assert_se((0xfffffffdU + 10U - 1U) / 10U == 0U);
181 assert_se(0xfffffffdU / 10U + !!(0xfffffffdU % 10U) == 429496730U);
182 }
183
184 static void test_first_word(void) {
185 assert_se(first_word("Hello", ""));
186 assert_se(first_word("Hello", "Hello"));
187 assert_se(first_word("Hello world", "Hello"));
188 assert_se(first_word("Hello\tworld", "Hello"));
189 assert_se(first_word("Hello\nworld", "Hello"));
190 assert_se(first_word("Hello\rworld", "Hello"));
191 assert_se(first_word("Hello ", "Hello"));
192
193 assert_se(!first_word("Hello", "Hellooo"));
194 assert_se(!first_word("Hello", "xxxxx"));
195 assert_se(!first_word("Hellooo", "Hello"));
196 }
197
198 static void test_close_many(void) {
199 int fds[3];
200 char name0[] = "/tmp/test-close-many.XXXXXX";
201 char name1[] = "/tmp/test-close-many.XXXXXX";
202 char name2[] = "/tmp/test-close-many.XXXXXX";
203
204 fds[0] = mkostemp_safe(name0, O_RDWR|O_CLOEXEC);
205 fds[1] = mkostemp_safe(name1, O_RDWR|O_CLOEXEC);
206 fds[2] = mkostemp_safe(name2, O_RDWR|O_CLOEXEC);
207
208 close_many(fds, 2);
209
210 assert_se(fcntl(fds[0], F_GETFD) == -1);
211 assert_se(fcntl(fds[1], F_GETFD) == -1);
212 assert_se(fcntl(fds[2], F_GETFD) >= 0);
213
214 safe_close(fds[2]);
215
216 unlink(name0);
217 unlink(name1);
218 unlink(name2);
219 }
220
221 static void test_parse_boolean(void) {
222 assert_se(parse_boolean("1") == 1);
223 assert_se(parse_boolean("y") == 1);
224 assert_se(parse_boolean("Y") == 1);
225 assert_se(parse_boolean("yes") == 1);
226 assert_se(parse_boolean("YES") == 1);
227 assert_se(parse_boolean("true") == 1);
228 assert_se(parse_boolean("TRUE") == 1);
229 assert_se(parse_boolean("on") == 1);
230 assert_se(parse_boolean("ON") == 1);
231
232 assert_se(parse_boolean("0") == 0);
233 assert_se(parse_boolean("n") == 0);
234 assert_se(parse_boolean("N") == 0);
235 assert_se(parse_boolean("no") == 0);
236 assert_se(parse_boolean("NO") == 0);
237 assert_se(parse_boolean("false") == 0);
238 assert_se(parse_boolean("FALSE") == 0);
239 assert_se(parse_boolean("off") == 0);
240 assert_se(parse_boolean("OFF") == 0);
241
242 assert_se(parse_boolean("garbage") < 0);
243 assert_se(parse_boolean("") < 0);
244 assert_se(parse_boolean("full") < 0);
245 }
246
247 static void test_parse_pid(void) {
248 int r;
249 pid_t pid;
250
251 r = parse_pid("100", &pid);
252 assert_se(r == 0);
253 assert_se(pid == 100);
254
255 r = parse_pid("0x7FFFFFFF", &pid);
256 assert_se(r == 0);
257 assert_se(pid == 2147483647);
258
259 pid = 65; /* pid is left unchanged on ERANGE. Set to known arbitrary value. */
260 r = parse_pid("0", &pid);
261 assert_se(r == -ERANGE);
262 assert_se(pid == 65);
263
264 pid = 65; /* pid is left unchanged on ERANGE. Set to known arbitrary value. */
265 r = parse_pid("-100", &pid);
266 assert_se(r == -ERANGE);
267 assert_se(pid == 65);
268
269 pid = 65; /* pid is left unchanged on ERANGE. Set to known arbitrary value. */
270 r = parse_pid("0xFFFFFFFFFFFFFFFFF", &pid);
271 assert_se(r == -ERANGE);
272 assert_se(pid == 65);
273
274 r = parse_pid("junk", &pid);
275 assert_se(r == -EINVAL);
276 }
277
278 static void test_parse_uid(void) {
279 int r;
280 uid_t uid;
281
282 r = parse_uid("100", &uid);
283 assert_se(r == 0);
284 assert_se(uid == 100);
285
286 r = parse_uid("65535", &uid);
287 assert_se(r == -ENXIO);
288
289 r = parse_uid("asdsdas", &uid);
290 assert_se(r == -EINVAL);
291 }
292
293 static void test_safe_atou16(void) {
294 int r;
295 uint16_t l;
296
297 r = safe_atou16("12345", &l);
298 assert_se(r == 0);
299 assert_se(l == 12345);
300
301 r = safe_atou16("123456", &l);
302 assert_se(r == -ERANGE);
303
304 r = safe_atou16("junk", &l);
305 assert_se(r == -EINVAL);
306 }
307
308 static void test_safe_atoi16(void) {
309 int r;
310 int16_t l;
311
312 r = safe_atoi16("-12345", &l);
313 assert_se(r == 0);
314 assert_se(l == -12345);
315
316 r = safe_atoi16("36536", &l);
317 assert_se(r == -ERANGE);
318
319 r = safe_atoi16("junk", &l);
320 assert_se(r == -EINVAL);
321 }
322
323 static void test_safe_atolli(void) {
324 int r;
325 long long l;
326
327 r = safe_atolli("12345", &l);
328 assert_se(r == 0);
329 assert_se(l == 12345);
330
331 r = safe_atolli("junk", &l);
332 assert_se(r == -EINVAL);
333 }
334
335 static void test_safe_atod(void) {
336 int r;
337 double d;
338 char *e;
339
340 r = safe_atod("junk", &d);
341 assert_se(r == -EINVAL);
342
343 r = safe_atod("0.2244", &d);
344 assert_se(r == 0);
345 assert_se(fabs(d - 0.2244) < 0.000001);
346
347 r = safe_atod("0,5", &d);
348 assert_se(r == -EINVAL);
349
350 errno = 0;
351 strtod("0,5", &e);
352 assert_se(*e == ',');
353
354 /* Check if this really is locale independent */
355 if (setlocale(LC_NUMERIC, "de_DE.utf8")) {
356
357 r = safe_atod("0.2244", &d);
358 assert_se(r == 0);
359 assert_se(fabs(d - 0.2244) < 0.000001);
360
361 r = safe_atod("0,5", &d);
362 assert_se(r == -EINVAL);
363
364 errno = 0;
365 assert_se(fabs(strtod("0,5", &e) - 0.5) < 0.00001);
366 }
367
368 /* And check again, reset */
369 assert_se(setlocale(LC_NUMERIC, "C"));
370
371 r = safe_atod("0.2244", &d);
372 assert_se(r == 0);
373 assert_se(fabs(d - 0.2244) < 0.000001);
374
375 r = safe_atod("0,5", &d);
376 assert_se(r == -EINVAL);
377
378 errno = 0;
379 strtod("0,5", &e);
380 assert_se(*e == ',');
381 }
382
383 static void test_strappend(void) {
384 _cleanup_free_ char *t1, *t2, *t3, *t4;
385
386 t1 = strappend(NULL, NULL);
387 assert_se(streq(t1, ""));
388
389 t2 = strappend(NULL, "suf");
390 assert_se(streq(t2, "suf"));
391
392 t3 = strappend("pre", NULL);
393 assert_se(streq(t3, "pre"));
394
395 t4 = strappend("pre", "suf");
396 assert_se(streq(t4, "presuf"));
397 }
398
399 static void test_strstrip(void) {
400 char *r;
401 char input[] = " hello, waldo. ";
402
403 r = strstrip(input);
404 assert_se(streq(r, "hello, waldo."));
405 }
406
407 static void test_delete_chars(void) {
408 char *r;
409 char input[] = " hello, waldo. abc";
410
411 r = delete_chars(input, WHITESPACE);
412 assert_se(streq(r, "hello,waldo.abc"));
413 }
414
415 static void test_in_charset(void) {
416 assert_se(in_charset("dddaaabbbcccc", "abcd"));
417 assert_se(!in_charset("dddaaabbbcccc", "abc f"));
418 }
419
420 static void test_hexchar(void) {
421 assert_se(hexchar(0xa) == 'a');
422 assert_se(hexchar(0x0) == '0');
423 }
424
425 static void test_unhexchar(void) {
426 assert_se(unhexchar('a') == 0xA);
427 assert_se(unhexchar('A') == 0xA);
428 assert_se(unhexchar('0') == 0x0);
429 }
430
431 static void test_base32hexchar(void) {
432 assert_se(base32hexchar(0) == '0');
433 assert_se(base32hexchar(9) == '9');
434 assert_se(base32hexchar(10) == 'A');
435 assert_se(base32hexchar(31) == 'V');
436 }
437
438 static void test_unbase32hexchar(void) {
439 assert_se(unbase32hexchar('0') == 0);
440 assert_se(unbase32hexchar('9') == 9);
441 assert_se(unbase32hexchar('A') == 10);
442 assert_se(unbase32hexchar('V') == 31);
443 assert_se(unbase32hexchar('=') == -EINVAL);
444 }
445
446 static void test_base64char(void) {
447 assert_se(base64char(0) == 'A');
448 assert_se(base64char(26) == 'a');
449 assert_se(base64char(63) == '/');
450 }
451
452 static void test_unbase64char(void) {
453 assert_se(unbase64char('A') == 0);
454 assert_se(unbase64char('Z') == 25);
455 assert_se(unbase64char('a') == 26);
456 assert_se(unbase64char('z') == 51);
457 assert_se(unbase64char('0') == 52);
458 assert_se(unbase64char('9') == 61);
459 assert_se(unbase64char('+') == 62);
460 assert_se(unbase64char('/') == 63);
461 assert_se(unbase64char('=') == -EINVAL);
462 }
463
464 static void test_octchar(void) {
465 assert_se(octchar(00) == '0');
466 assert_se(octchar(07) == '7');
467 }
468
469 static void test_unoctchar(void) {
470 assert_se(unoctchar('0') == 00);
471 assert_se(unoctchar('7') == 07);
472 }
473
474 static void test_decchar(void) {
475 assert_se(decchar(0) == '0');
476 assert_se(decchar(9) == '9');
477 }
478
479 static void test_undecchar(void) {
480 assert_se(undecchar('0') == 0);
481 assert_se(undecchar('9') == 9);
482 }
483
484 static void test_unhexmem(void) {
485 const char *hex = "efa214921";
486 const char *hex_invalid = "efa214921o";
487 _cleanup_free_ char *hex2 = NULL;
488 _cleanup_free_ void *mem = NULL;
489 size_t len;
490
491 assert_se(unhexmem(hex, strlen(hex), &mem, &len) == 0);
492 assert_se(unhexmem(hex, strlen(hex) + 1, &mem, &len) == -EINVAL);
493 assert_se(unhexmem(hex_invalid, strlen(hex_invalid), &mem, &len) == -EINVAL);
494
495 assert_se((hex2 = hexmem(mem, len)));
496
497 free(mem);
498
499 assert_se(memcmp(hex, hex2, strlen(hex)) == 0);
500
501 free(hex2);
502
503 assert_se(unhexmem(hex, strlen(hex) - 1, &mem, &len) == 0);
504 assert_se((hex2 = hexmem(mem, len)));
505 assert_se(memcmp(hex, hex2, strlen(hex) - 1) == 0);
506 }
507
508 /* https://tools.ietf.org/html/rfc4648#section-10 */
509 static void test_base32hexmem(void) {
510 char *b32;
511
512 b32 = base32hexmem("", strlen(""), true);
513 assert_se(b32);
514 assert_se(streq(b32, ""));
515 free(b32);
516
517 b32 = base32hexmem("f", strlen("f"), true);
518 assert_se(b32);
519 assert_se(streq(b32, "CO======"));
520 free(b32);
521
522 b32 = base32hexmem("fo", strlen("fo"), true);
523 assert_se(b32);
524 assert_se(streq(b32, "CPNG===="));
525 free(b32);
526
527 b32 = base32hexmem("foo", strlen("foo"), true);
528 assert_se(b32);
529 assert_se(streq(b32, "CPNMU==="));
530 free(b32);
531
532 b32 = base32hexmem("foob", strlen("foob"), true);
533 assert_se(b32);
534 assert_se(streq(b32, "CPNMUOG="));
535 free(b32);
536
537 b32 = base32hexmem("fooba", strlen("fooba"), true);
538 assert_se(b32);
539 assert_se(streq(b32, "CPNMUOJ1"));
540 free(b32);
541
542 b32 = base32hexmem("foobar", strlen("foobar"), true);
543 assert_se(b32);
544 assert_se(streq(b32, "CPNMUOJ1E8======"));
545 free(b32);
546
547 b32 = base32hexmem("", strlen(""), false);
548 assert_se(b32);
549 assert_se(streq(b32, ""));
550 free(b32);
551
552 b32 = base32hexmem("f", strlen("f"), false);
553 assert_se(b32);
554 assert_se(streq(b32, "CO"));
555 free(b32);
556
557 b32 = base32hexmem("fo", strlen("fo"), false);
558 assert_se(b32);
559 assert_se(streq(b32, "CPNG"));
560 free(b32);
561
562 b32 = base32hexmem("foo", strlen("foo"), false);
563 assert_se(b32);
564 assert_se(streq(b32, "CPNMU"));
565 free(b32);
566
567 b32 = base32hexmem("foob", strlen("foob"), false);
568 assert_se(b32);
569 assert_se(streq(b32, "CPNMUOG"));
570 free(b32);
571
572 b32 = base32hexmem("fooba", strlen("fooba"), false);
573 assert_se(b32);
574 assert_se(streq(b32, "CPNMUOJ1"));
575 free(b32);
576
577 b32 = base32hexmem("foobar", strlen("foobar"), false);
578 assert_se(b32);
579 assert_se(streq(b32, "CPNMUOJ1E8"));
580 free(b32);
581 }
582
583 static void test_unbase32hexmem(void) {
584 void *mem;
585 size_t len;
586
587 assert_se(unbase32hexmem("", strlen(""), true, &mem, &len) == 0);
588 assert_se(streq(strndupa(mem, len), ""));
589 free(mem);
590
591 assert_se(unbase32hexmem("CO======", strlen("CO======"), true, &mem, &len) == 0);
592 assert_se(streq(strndupa(mem, len), "f"));
593 free(mem);
594
595 assert_se(unbase32hexmem("CPNG====", strlen("CPNG===="), true, &mem, &len) == 0);
596 assert_se(streq(strndupa(mem, len), "fo"));
597 free(mem);
598
599 assert_se(unbase32hexmem("CPNMU===", strlen("CPNMU==="), true, &mem, &len) == 0);
600 assert_se(streq(strndupa(mem, len), "foo"));
601 free(mem);
602
603 assert_se(unbase32hexmem("CPNMUOG=", strlen("CPNMUOG="), true, &mem, &len) == 0);
604 assert_se(streq(strndupa(mem, len), "foob"));
605 free(mem);
606
607 assert_se(unbase32hexmem("CPNMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == 0);
608 assert_se(streq(strndupa(mem, len), "fooba"));
609 free(mem);
610
611 assert_se(unbase32hexmem("CPNMUOJ1E8======", strlen("CPNMUOJ1E8======"), true, &mem, &len) == 0);
612 assert_se(streq(strndupa(mem, len), "foobar"));
613 free(mem);
614
615 assert_se(unbase32hexmem("A", strlen("A"), true, &mem, &len) == -EINVAL);
616 assert_se(unbase32hexmem("A=======", strlen("A======="), true, &mem, &len) == -EINVAL);
617 assert_se(unbase32hexmem("AAA=====", strlen("AAA====="), true, &mem, &len) == -EINVAL);
618 assert_se(unbase32hexmem("AAAAAA==", strlen("AAAAAA=="), true, &mem, &len) == -EINVAL);
619 assert_se(unbase32hexmem("AB======", strlen("AB======"), true, &mem, &len) == -EINVAL);
620 assert_se(unbase32hexmem("AAAB====", strlen("AAAB===="), true, &mem, &len) == -EINVAL);
621 assert_se(unbase32hexmem("AAAAB===", strlen("AAAAB==="), true, &mem, &len) == -EINVAL);
622 assert_se(unbase32hexmem("AAAAAAB=", strlen("AAAAAAB="), true, &mem, &len) == -EINVAL);
623
624 assert_se(unbase32hexmem("XPNMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
625 assert_se(unbase32hexmem("CXNMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
626 assert_se(unbase32hexmem("CPXMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
627 assert_se(unbase32hexmem("CPNXUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
628 assert_se(unbase32hexmem("CPNMXOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
629 assert_se(unbase32hexmem("CPNMUXJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
630 assert_se(unbase32hexmem("CPNMUOX1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
631 assert_se(unbase32hexmem("CPNMUOJX", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
632
633 assert_se(unbase32hexmem("", strlen(""), false, &mem, &len) == 0);
634 assert_se(streq(strndupa(mem, len), ""));
635 free(mem);
636
637 assert_se(unbase32hexmem("CO", strlen("CO"), false, &mem, &len) == 0);
638 assert_se(streq(strndupa(mem, len), "f"));
639 free(mem);
640
641 assert_se(unbase32hexmem("CPNG", strlen("CPNG"), false, &mem, &len) == 0);
642 assert_se(streq(strndupa(mem, len), "fo"));
643 free(mem);
644
645 assert_se(unbase32hexmem("CPNMU", strlen("CPNMU"), false, &mem, &len) == 0);
646 assert_se(streq(strndupa(mem, len), "foo"));
647 free(mem);
648
649 assert_se(unbase32hexmem("CPNMUOG", strlen("CPNMUOG"), false, &mem, &len) == 0);
650 assert_se(streq(strndupa(mem, len), "foob"));
651 free(mem);
652
653 assert_se(unbase32hexmem("CPNMUOJ1", strlen("CPNMUOJ1"), false, &mem, &len) == 0);
654 assert_se(streq(strndupa(mem, len), "fooba"));
655 free(mem);
656
657 assert_se(unbase32hexmem("CPNMUOJ1E8", strlen("CPNMUOJ1E8"), false, &mem, &len) == 0);
658 assert_se(streq(strndupa(mem, len), "foobar"));
659 free(mem);
660
661 assert_se(unbase32hexmem("CPNMUOG=", strlen("CPNMUOG="), false, &mem, &len) == -EINVAL);
662 assert_se(unbase32hexmem("CPNMUOJ1E8======", strlen("CPNMUOJ1E8======"), false, &mem, &len) == -EINVAL);
663 assert_se(unbase32hexmem("A", strlen("A"), false, &mem, &len) == -EINVAL);
664 assert_se(unbase32hexmem("A", strlen("A"), false, &mem, &len) == -EINVAL);
665 assert_se(unbase32hexmem("AAA", strlen("AAA"), false, &mem, &len) == -EINVAL);
666 assert_se(unbase32hexmem("AAAAAA", strlen("AAAAAA"), false, &mem, &len) == -EINVAL);
667 assert_se(unbase32hexmem("AB", strlen("AB"), false, &mem, &len) == -EINVAL);
668 assert_se(unbase32hexmem("AAAB", strlen("AAAB"), false, &mem, &len) == -EINVAL);
669 assert_se(unbase32hexmem("AAAAB", strlen("AAAAB"), false, &mem, &len) == -EINVAL);
670 assert_se(unbase32hexmem("AAAAAAB", strlen("AAAAAAB"), false, &mem, &len) == -EINVAL);
671 }
672
673 /* https://tools.ietf.org/html/rfc4648#section-10 */
674 static void test_base64mem(void) {
675 char *b64;
676
677 b64 = base64mem("", strlen(""));
678 assert_se(b64);
679 assert_se(streq(b64, ""));
680 free(b64);
681
682 b64 = base64mem("f", strlen("f"));
683 assert_se(b64);
684 assert_se(streq(b64, "Zg=="));
685 free(b64);
686
687 b64 = base64mem("fo", strlen("fo"));
688 assert_se(b64);
689 assert_se(streq(b64, "Zm8="));
690 free(b64);
691
692 b64 = base64mem("foo", strlen("foo"));
693 assert_se(b64);
694 assert_se(streq(b64, "Zm9v"));
695 free(b64);
696
697 b64 = base64mem("foob", strlen("foob"));
698 assert_se(b64);
699 assert_se(streq(b64, "Zm9vYg=="));
700 free(b64);
701
702 b64 = base64mem("fooba", strlen("fooba"));
703 assert_se(b64);
704 assert_se(streq(b64, "Zm9vYmE="));
705 free(b64);
706
707 b64 = base64mem("foobar", strlen("foobar"));
708 assert_se(b64);
709 assert_se(streq(b64, "Zm9vYmFy"));
710 free(b64);
711 }
712
713 static void test_unbase64mem(void) {
714 void *mem;
715 size_t len;
716
717 assert_se(unbase64mem("", strlen(""), &mem, &len) == 0);
718 assert_se(streq(strndupa(mem, len), ""));
719 free(mem);
720
721 assert_se(unbase64mem("Zg==", strlen("Zg=="), &mem, &len) == 0);
722 assert_se(streq(strndupa(mem, len), "f"));
723 free(mem);
724
725 assert_se(unbase64mem("Zm8=", strlen("Zm8="), &mem, &len) == 0);
726 assert_se(streq(strndupa(mem, len), "fo"));
727 free(mem);
728
729 assert_se(unbase64mem("Zm9v", strlen("Zm9v"), &mem, &len) == 0);
730 assert_se(streq(strndupa(mem, len), "foo"));
731 free(mem);
732
733 assert_se(unbase64mem("Zm9vYg==", strlen("Zm9vYg=="), &mem, &len) == 0);
734 assert_se(streq(strndupa(mem, len), "foob"));
735 free(mem);
736
737 assert_se(unbase64mem("Zm9vYmE=", strlen("Zm9vYmE="), &mem, &len) == 0);
738 assert_se(streq(strndupa(mem, len), "fooba"));
739 free(mem);
740
741 assert_se(unbase64mem("Zm9vYmFy", strlen("Zm9vYmFy"), &mem, &len) == 0);
742 assert_se(streq(strndupa(mem, len), "foobar"));
743 free(mem);
744
745 assert_se(unbase64mem("A", strlen("A"), &mem, &len) == -EINVAL);
746 assert_se(unbase64mem("A====", strlen("A===="), &mem, &len) == -EINVAL);
747 assert_se(unbase64mem("AAB==", strlen("AAB=="), &mem, &len) == -EINVAL);
748 assert_se(unbase64mem("AAAB=", strlen("AAAB="), &mem, &len) == -EINVAL);
749 }
750
751 static void test_cescape(void) {
752 _cleanup_free_ char *escaped;
753
754 assert_se(escaped = cescape("abc\\\"\b\f\n\r\t\v\a\003\177\234\313"));
755 assert_se(streq(escaped, "abc\\\\\\\"\\b\\f\\n\\r\\t\\v\\a\\003\\177\\234\\313"));
756 }
757
758 static void test_cunescape(void) {
759 _cleanup_free_ char *unescaped;
760
761 assert_se(cunescape("abc\\\\\\\"\\b\\f\\a\\n\\r\\t\\v\\003\\177\\234\\313\\000\\x00", 0, &unescaped) < 0);
762 assert_se(cunescape("abc\\\\\\\"\\b\\f\\a\\n\\r\\t\\v\\003\\177\\234\\313\\000\\x00", UNESCAPE_RELAX, &unescaped) >= 0);
763 assert_se(streq_ptr(unescaped, "abc\\\"\b\f\a\n\r\t\v\003\177\234\313\\000\\x00"));
764 unescaped = mfree(unescaped);
765
766 /* incomplete sequences */
767 assert_se(cunescape("\\x0", 0, &unescaped) < 0);
768 assert_se(cunescape("\\x0", UNESCAPE_RELAX, &unescaped) >= 0);
769 assert_se(streq_ptr(unescaped, "\\x0"));
770 unescaped = mfree(unescaped);
771
772 assert_se(cunescape("\\x", 0, &unescaped) < 0);
773 assert_se(cunescape("\\x", UNESCAPE_RELAX, &unescaped) >= 0);
774 assert_se(streq_ptr(unescaped, "\\x"));
775 unescaped = mfree(unescaped);
776
777 assert_se(cunescape("\\", 0, &unescaped) < 0);
778 assert_se(cunescape("\\", UNESCAPE_RELAX, &unescaped) >= 0);
779 assert_se(streq_ptr(unescaped, "\\"));
780 unescaped = mfree(unescaped);
781
782 assert_se(cunescape("\\11", 0, &unescaped) < 0);
783 assert_se(cunescape("\\11", UNESCAPE_RELAX, &unescaped) >= 0);
784 assert_se(streq_ptr(unescaped, "\\11"));
785 unescaped = mfree(unescaped);
786
787 assert_se(cunescape("\\1", 0, &unescaped) < 0);
788 assert_se(cunescape("\\1", UNESCAPE_RELAX, &unescaped) >= 0);
789 assert_se(streq_ptr(unescaped, "\\1"));
790 unescaped = mfree(unescaped);
791
792 assert_se(cunescape("\\u0000", 0, &unescaped) < 0);
793 assert_se(cunescape("\\u00DF\\U000000df\\u03a0\\U00000041", UNESCAPE_RELAX, &unescaped) >= 0);
794 assert_se(streq_ptr(unescaped, "ßßΠA"));
795 unescaped = mfree(unescaped);
796
797 assert_se(cunescape("\\073", 0, &unescaped) >= 0);
798 assert_se(streq_ptr(unescaped, ";"));
799 }
800
801 static void test_foreach_word(void) {
802 const char *word, *state;
803 size_t l;
804 int i = 0;
805 const char test[] = "test abc d\te f ";
806 const char * const expected[] = {
807 "test",
808 "abc",
809 "d",
810 "e",
811 "f",
812 "",
813 NULL
814 };
815
816 FOREACH_WORD(word, l, test, state)
817 assert_se(strneq(expected[i++], word, l));
818 }
819
820 static void check(const char *test, char** expected, bool trailing) {
821 const char *word, *state;
822 size_t l;
823 int i = 0;
824
825 printf("<<<%s>>>\n", test);
826 FOREACH_WORD_QUOTED(word, l, test, state) {
827 _cleanup_free_ char *t = NULL;
828
829 assert_se(t = strndup(word, l));
830 assert_se(strneq(expected[i++], word, l));
831 printf("<%s>\n", t);
832 }
833 printf("<<<%s>>>\n", state);
834 assert_se(expected[i] == NULL);
835 assert_se(isempty(state) == !trailing);
836 }
837
838 static void test_foreach_word_quoted(void) {
839 check("test a b c 'd' e '' '' hhh '' '' \"a b c\"",
840 STRV_MAKE("test",
841 "a",
842 "b",
843 "c",
844 "d",
845 "e",
846 "",
847 "",
848 "hhh",
849 "",
850 "",
851 "a b c"),
852 false);
853
854 check("test \"xxx",
855 STRV_MAKE("test"),
856 true);
857
858 check("test\\",
859 STRV_MAKE_EMPTY,
860 true);
861 }
862
863 static void test_memdup_multiply(void) {
864 int org[] = {1, 2, 3};
865 int *dup;
866
867 dup = (int*)memdup_multiply(org, sizeof(int), 3);
868
869 assert_se(dup);
870 assert_se(dup[0] == 1);
871 assert_se(dup[1] == 2);
872 assert_se(dup[2] == 3);
873 free(dup);
874 }
875
876 static void test_u64log2(void) {
877 assert_se(u64log2(0) == 0);
878 assert_se(u64log2(8) == 3);
879 assert_se(u64log2(9) == 3);
880 assert_se(u64log2(15) == 3);
881 assert_se(u64log2(16) == 4);
882 assert_se(u64log2(1024*1024) == 20);
883 assert_se(u64log2(1024*1024+5) == 20);
884 }
885
886 static void test_protect_errno(void) {
887 errno = 12;
888 {
889 PROTECT_ERRNO;
890 errno = 11;
891 }
892 assert_se(errno == 12);
893 }
894
895 static void test_parse_size(void) {
896 uint64_t bytes;
897
898 assert_se(parse_size("111", 1024, &bytes) == 0);
899 assert_se(bytes == 111);
900
901 assert_se(parse_size("111.4", 1024, &bytes) == 0);
902 assert_se(bytes == 111);
903
904 assert_se(parse_size(" 112 B", 1024, &bytes) == 0);
905 assert_se(bytes == 112);
906
907 assert_se(parse_size(" 112.6 B", 1024, &bytes) == 0);
908 assert_se(bytes == 112);
909
910 assert_se(parse_size("3.5 K", 1024, &bytes) == 0);
911 assert_se(bytes == 3*1024 + 512);
912
913 assert_se(parse_size("3. K", 1024, &bytes) == 0);
914 assert_se(bytes == 3*1024);
915
916 assert_se(parse_size("3.0 K", 1024, &bytes) == 0);
917 assert_se(bytes == 3*1024);
918
919 assert_se(parse_size("3. 0 K", 1024, &bytes) == -EINVAL);
920
921 assert_se(parse_size(" 4 M 11.5K", 1024, &bytes) == 0);
922 assert_se(bytes == 4*1024*1024 + 11 * 1024 + 512);
923
924 assert_se(parse_size("3B3.5G", 1024, &bytes) == -EINVAL);
925
926 assert_se(parse_size("3.5G3B", 1024, &bytes) == 0);
927 assert_se(bytes == 3ULL*1024*1024*1024 + 512*1024*1024 + 3);
928
929 assert_se(parse_size("3.5G 4B", 1024, &bytes) == 0);
930 assert_se(bytes == 3ULL*1024*1024*1024 + 512*1024*1024 + 4);
931
932 assert_se(parse_size("3B3G4T", 1024, &bytes) == -EINVAL);
933
934 assert_se(parse_size("4T3G3B", 1024, &bytes) == 0);
935 assert_se(bytes == (4ULL*1024 + 3)*1024*1024*1024 + 3);
936
937 assert_se(parse_size(" 4 T 3 G 3 B", 1024, &bytes) == 0);
938 assert_se(bytes == (4ULL*1024 + 3)*1024*1024*1024 + 3);
939
940 assert_se(parse_size("12P", 1024, &bytes) == 0);
941 assert_se(bytes == 12ULL * 1024*1024*1024*1024*1024);
942
943 assert_se(parse_size("12P12P", 1024, &bytes) == -EINVAL);
944
945 assert_se(parse_size("3E 2P", 1024, &bytes) == 0);
946 assert_se(bytes == (3 * 1024 + 2ULL) * 1024*1024*1024*1024*1024);
947
948 assert_se(parse_size("12X", 1024, &bytes) == -EINVAL);
949
950 assert_se(parse_size("12.5X", 1024, &bytes) == -EINVAL);
951
952 assert_se(parse_size("12.5e3", 1024, &bytes) == -EINVAL);
953
954 assert_se(parse_size("1024E", 1024, &bytes) == -ERANGE);
955 assert_se(parse_size("-1", 1024, &bytes) == -ERANGE);
956 assert_se(parse_size("-1024E", 1024, &bytes) == -ERANGE);
957
958 assert_se(parse_size("-1024P", 1024, &bytes) == -ERANGE);
959
960 assert_se(parse_size("-10B 20K", 1024, &bytes) == -ERANGE);
961 }
962
963 static void test_config_parse_iec_uint64(void) {
964 uint64_t offset = 0;
965 assert_se(config_parse_iec_uint64(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4M", &offset, NULL) == 0);
966 assert_se(offset == 4 * 1024 * 1024);
967
968 assert_se(config_parse_iec_uint64(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4.5M", &offset, NULL) == 0);
969 }
970
971 static void test_strextend(void) {
972 _cleanup_free_ char *str = strdup("0123");
973 strextend(&str, "456", "78", "9", NULL);
974 assert_se(streq(str, "0123456789"));
975 }
976
977 static void test_strrep(void) {
978 _cleanup_free_ char *one, *three, *zero;
979 one = strrep("waldo", 1);
980 three = strrep("waldo", 3);
981 zero = strrep("waldo", 0);
982
983 assert_se(streq(one, "waldo"));
984 assert_se(streq(three, "waldowaldowaldo"));
985 assert_se(streq(zero, ""));
986 }
987
988 static void test_split_pair(void) {
989 _cleanup_free_ char *a = NULL, *b = NULL;
990
991 assert_se(split_pair("", "", &a, &b) == -EINVAL);
992 assert_se(split_pair("foo=bar", "", &a, &b) == -EINVAL);
993 assert_se(split_pair("", "=", &a, &b) == -EINVAL);
994 assert_se(split_pair("foo=bar", "=", &a, &b) >= 0);
995 assert_se(streq(a, "foo"));
996 assert_se(streq(b, "bar"));
997 free(a);
998 free(b);
999 assert_se(split_pair("==", "==", &a, &b) >= 0);
1000 assert_se(streq(a, ""));
1001 assert_se(streq(b, ""));
1002 free(a);
1003 free(b);
1004
1005 assert_se(split_pair("===", "==", &a, &b) >= 0);
1006 assert_se(streq(a, ""));
1007 assert_se(streq(b, "="));
1008 }
1009
1010 static void test_fstab_node_to_udev_node(void) {
1011 char *n;
1012
1013 n = fstab_node_to_udev_node("LABEL=applé/jack");
1014 puts(n);
1015 assert_se(streq(n, "/dev/disk/by-label/applé\\x2fjack"));
1016 free(n);
1017
1018 n = fstab_node_to_udev_node("PARTLABEL=pinkié pie");
1019 puts(n);
1020 assert_se(streq(n, "/dev/disk/by-partlabel/pinkié\\x20pie"));
1021 free(n);
1022
1023 n = fstab_node_to_udev_node("UUID=037b9d94-148e-4ee4-8d38-67bfe15bb535");
1024 puts(n);
1025 assert_se(streq(n, "/dev/disk/by-uuid/037b9d94-148e-4ee4-8d38-67bfe15bb535"));
1026 free(n);
1027
1028 n = fstab_node_to_udev_node("PARTUUID=037b9d94-148e-4ee4-8d38-67bfe15bb535");
1029 puts(n);
1030 assert_se(streq(n, "/dev/disk/by-partuuid/037b9d94-148e-4ee4-8d38-67bfe15bb535"));
1031 free(n);
1032
1033 n = fstab_node_to_udev_node("PONIES=awesome");
1034 puts(n);
1035 assert_se(streq(n, "PONIES=awesome"));
1036 free(n);
1037
1038 n = fstab_node_to_udev_node("/dev/xda1");
1039 puts(n);
1040 assert_se(streq(n, "/dev/xda1"));
1041 free(n);
1042 }
1043
1044 static void test_get_files_in_directory(void) {
1045 _cleanup_strv_free_ char **l = NULL, **t = NULL;
1046
1047 assert_se(get_files_in_directory("/tmp", &l) >= 0);
1048 assert_se(get_files_in_directory(".", &t) >= 0);
1049 assert_se(get_files_in_directory(".", NULL) >= 0);
1050 }
1051
1052 static void test_in_set(void) {
1053 assert_se(IN_SET(1, 1));
1054 assert_se(IN_SET(1, 1, 2, 3, 4));
1055 assert_se(IN_SET(2, 1, 2, 3, 4));
1056 assert_se(IN_SET(3, 1, 2, 3, 4));
1057 assert_se(IN_SET(4, 1, 2, 3, 4));
1058 assert_se(!IN_SET(0, 1));
1059 assert_se(!IN_SET(0, 1, 2, 3, 4));
1060 }
1061
1062 static void test_writing_tmpfile(void) {
1063 char name[] = "/tmp/test-systemd_writing_tmpfile.XXXXXX";
1064 _cleanup_free_ char *contents = NULL;
1065 size_t size;
1066 int fd, r;
1067 struct iovec iov[3];
1068
1069 IOVEC_SET_STRING(iov[0], "abc\n");
1070 IOVEC_SET_STRING(iov[1], ALPHANUMERICAL "\n");
1071 IOVEC_SET_STRING(iov[2], "");
1072
1073 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
1074 printf("tmpfile: %s", name);
1075
1076 r = writev(fd, iov, 3);
1077 assert_se(r >= 0);
1078
1079 r = read_full_file(name, &contents, &size);
1080 assert_se(r == 0);
1081 printf("contents: %s", contents);
1082 assert_se(streq(contents, "abc\n" ALPHANUMERICAL "\n"));
1083
1084 unlink(name);
1085 }
1086
1087 static void test_hexdump(void) {
1088 uint8_t data[146];
1089 unsigned i;
1090
1091 hexdump(stdout, NULL, 0);
1092 hexdump(stdout, "", 0);
1093 hexdump(stdout, "", 1);
1094 hexdump(stdout, "x", 1);
1095 hexdump(stdout, "x", 2);
1096 hexdump(stdout, "foobar", 7);
1097 hexdump(stdout, "f\nobar", 7);
1098 hexdump(stdout, "xxxxxxxxxxxxxxxxxxxxyz", 23);
1099
1100 for (i = 0; i < ELEMENTSOF(data); i++)
1101 data[i] = i*2;
1102
1103 hexdump(stdout, data, sizeof(data));
1104 }
1105
1106 static void test_log2i(void) {
1107 assert_se(log2i(1) == 0);
1108 assert_se(log2i(2) == 1);
1109 assert_se(log2i(3) == 1);
1110 assert_se(log2i(4) == 2);
1111 assert_se(log2i(32) == 5);
1112 assert_se(log2i(33) == 5);
1113 assert_se(log2i(63) == 5);
1114 assert_se(log2i(INT_MAX) == sizeof(int)*8-2);
1115 }
1116
1117 static void test_foreach_string(void) {
1118 const char * const t[] = {
1119 "foo",
1120 "bar",
1121 "waldo",
1122 NULL
1123 };
1124 const char *x;
1125 unsigned i = 0;
1126
1127 FOREACH_STRING(x, "foo", "bar", "waldo")
1128 assert_se(streq_ptr(t[i++], x));
1129
1130 assert_se(i == 3);
1131
1132 FOREACH_STRING(x, "zzz")
1133 assert_se(streq(x, "zzz"));
1134 }
1135
1136 static void test_filename_is_valid(void) {
1137 char foo[FILENAME_MAX+2];
1138 int i;
1139
1140 assert_se(!filename_is_valid(""));
1141 assert_se(!filename_is_valid("/bar/foo"));
1142 assert_se(!filename_is_valid("/"));
1143 assert_se(!filename_is_valid("."));
1144 assert_se(!filename_is_valid(".."));
1145
1146 for (i=0; i<FILENAME_MAX+1; i++)
1147 foo[i] = 'a';
1148 foo[FILENAME_MAX+1] = '\0';
1149
1150 assert_se(!filename_is_valid(foo));
1151
1152 assert_se(filename_is_valid("foo_bar-333"));
1153 assert_se(filename_is_valid("o.o"));
1154 }
1155
1156 static void test_string_has_cc(void) {
1157 assert_se(string_has_cc("abc\1", NULL));
1158 assert_se(string_has_cc("abc\x7f", NULL));
1159 assert_se(string_has_cc("abc\x7f", NULL));
1160 assert_se(string_has_cc("abc\t\x7f", "\t"));
1161 assert_se(string_has_cc("abc\t\x7f", "\t"));
1162 assert_se(string_has_cc("\x7f", "\t"));
1163 assert_se(string_has_cc("\x7f", "\t\a"));
1164
1165 assert_se(!string_has_cc("abc\t\t", "\t"));
1166 assert_se(!string_has_cc("abc\t\t\a", "\t\a"));
1167 assert_se(!string_has_cc("a\ab\tc", "\t\a"));
1168 }
1169
1170 static void test_ascii_strlower(void) {
1171 char a[] = "AabBcC Jk Ii Od LKJJJ kkd LK";
1172 assert_se(streq(ascii_strlower(a), "aabbcc jk ii od lkjjj kkd lk"));
1173 }
1174
1175 static void test_files_same(void) {
1176 _cleanup_close_ int fd = -1;
1177 char name[] = "/tmp/test-files_same.XXXXXX";
1178 char name_alias[] = "/tmp/test-files_same.alias";
1179
1180 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
1181 assert_se(fd >= 0);
1182 assert_se(symlink(name, name_alias) >= 0);
1183
1184 assert_se(files_same(name, name));
1185 assert_se(files_same(name, name_alias));
1186
1187 unlink(name);
1188 unlink(name_alias);
1189 }
1190
1191 static void test_is_valid_documentation_url(void) {
1192 assert_se(documentation_url_is_valid("http://www.freedesktop.org/wiki/Software/systemd"));
1193 assert_se(documentation_url_is_valid("https://www.kernel.org/doc/Documentation/binfmt_misc.txt"));
1194 assert_se(documentation_url_is_valid("file:/foo/foo"));
1195 assert_se(documentation_url_is_valid("man:systemd.special(7)"));
1196 assert_se(documentation_url_is_valid("info:bar"));
1197
1198 assert_se(!documentation_url_is_valid("foo:"));
1199 assert_se(!documentation_url_is_valid("info:"));
1200 assert_se(!documentation_url_is_valid(""));
1201 }
1202
1203 static void test_file_in_same_dir(void) {
1204 char *t;
1205
1206 t = file_in_same_dir("/", "a");
1207 assert_se(streq(t, "/a"));
1208 free(t);
1209
1210 t = file_in_same_dir("/", "/a");
1211 assert_se(streq(t, "/a"));
1212 free(t);
1213
1214 t = file_in_same_dir("", "a");
1215 assert_se(streq(t, "a"));
1216 free(t);
1217
1218 t = file_in_same_dir("a/", "a");
1219 assert_se(streq(t, "a/a"));
1220 free(t);
1221
1222 t = file_in_same_dir("bar/foo", "bar");
1223 assert_se(streq(t, "bar/bar"));
1224 free(t);
1225 }
1226
1227 static void test_endswith(void) {
1228 assert_se(endswith("foobar", "bar"));
1229 assert_se(endswith("foobar", ""));
1230 assert_se(endswith("foobar", "foobar"));
1231 assert_se(endswith("", ""));
1232
1233 assert_se(!endswith("foobar", "foo"));
1234 assert_se(!endswith("foobar", "foobarfoofoo"));
1235 }
1236
1237 static void test_endswith_no_case(void) {
1238 assert_se(endswith_no_case("fooBAR", "bar"));
1239 assert_se(endswith_no_case("foobar", ""));
1240 assert_se(endswith_no_case("foobar", "FOOBAR"));
1241 assert_se(endswith_no_case("", ""));
1242
1243 assert_se(!endswith_no_case("foobar", "FOO"));
1244 assert_se(!endswith_no_case("foobar", "FOOBARFOOFOO"));
1245 }
1246
1247 static void test_close_nointr(void) {
1248 char name[] = "/tmp/test-test-close_nointr.XXXXXX";
1249 int fd;
1250
1251 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
1252 assert_se(fd >= 0);
1253 assert_se(close_nointr(fd) >= 0);
1254 assert_se(close_nointr(fd) < 0);
1255
1256 unlink(name);
1257 }
1258
1259
1260 static void test_unlink_noerrno(void) {
1261 char name[] = "/tmp/test-close_nointr.XXXXXX";
1262 int fd;
1263
1264 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
1265 assert_se(fd >= 0);
1266 assert_se(close_nointr(fd) >= 0);
1267
1268 {
1269 PROTECT_ERRNO;
1270 errno = -42;
1271 assert_se(unlink_noerrno(name) >= 0);
1272 assert_se(errno == -42);
1273 assert_se(unlink_noerrno(name) < 0);
1274 assert_se(errno == -42);
1275 }
1276 }
1277
1278 static void test_readlink_and_make_absolute(void) {
1279 char tempdir[] = "/tmp/test-readlink_and_make_absolute";
1280 char name[] = "/tmp/test-readlink_and_make_absolute/original";
1281 char name2[] = "test-readlink_and_make_absolute/original";
1282 char name_alias[] = "/tmp/test-readlink_and_make_absolute-alias";
1283 char *r = NULL;
1284
1285 assert_se(mkdir_safe(tempdir, 0755, getuid(), getgid()) >= 0);
1286 assert_se(touch(name) >= 0);
1287
1288 assert_se(symlink(name, name_alias) >= 0);
1289 assert_se(readlink_and_make_absolute(name_alias, &r) >= 0);
1290 assert_se(streq(r, name));
1291 free(r);
1292 assert_se(unlink(name_alias) >= 0);
1293
1294 assert_se(chdir(tempdir) >= 0);
1295 assert_se(symlink(name2, name_alias) >= 0);
1296 assert_se(readlink_and_make_absolute(name_alias, &r) >= 0);
1297 assert_se(streq(r, name));
1298 free(r);
1299 assert_se(unlink(name_alias) >= 0);
1300
1301 assert_se(rm_rf(tempdir, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
1302 }
1303
1304 static void test_ignore_signals(void) {
1305 assert_se(ignore_signals(SIGINT, -1) >= 0);
1306 assert_se(kill(getpid(), SIGINT) >= 0);
1307 assert_se(ignore_signals(SIGUSR1, SIGUSR2, SIGTERM, SIGPIPE, -1) >= 0);
1308 assert_se(kill(getpid(), SIGUSR1) >= 0);
1309 assert_se(kill(getpid(), SIGUSR2) >= 0);
1310 assert_se(kill(getpid(), SIGTERM) >= 0);
1311 assert_se(kill(getpid(), SIGPIPE) >= 0);
1312 assert_se(default_signals(SIGINT, SIGUSR1, SIGUSR2, SIGTERM, SIGPIPE, -1) >= 0);
1313 }
1314
1315 static void test_strshorten(void) {
1316 char s[] = "foobar";
1317
1318 assert_se(strlen(strshorten(s, 6)) == 6);
1319 assert_se(strlen(strshorten(s, 12)) == 6);
1320 assert_se(strlen(strshorten(s, 2)) == 2);
1321 assert_se(strlen(strshorten(s, 0)) == 0);
1322 }
1323
1324 static void test_strjoina(void) {
1325 char *actual;
1326
1327 actual = strjoina("", "foo", "bar");
1328 assert_se(streq(actual, "foobar"));
1329
1330 actual = strjoina("foo", "bar", "baz");
1331 assert_se(streq(actual, "foobarbaz"));
1332
1333 actual = strjoina("foo", "", "bar", "baz");
1334 assert_se(streq(actual, "foobarbaz"));
1335
1336 actual = strjoina("foo");
1337 assert_se(streq(actual, "foo"));
1338
1339 actual = strjoina(NULL);
1340 assert_se(streq(actual, ""));
1341
1342 actual = strjoina(NULL, "foo");
1343 assert_se(streq(actual, ""));
1344
1345 actual = strjoina("foo", NULL, "bar");
1346 assert_se(streq(actual, "foo"));
1347 }
1348
1349 static void test_is_symlink(void) {
1350 char name[] = "/tmp/test-is_symlink.XXXXXX";
1351 char name_link[] = "/tmp/test-is_symlink.link";
1352 _cleanup_close_ int fd = -1;
1353
1354 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
1355 assert_se(fd >= 0);
1356 assert_se(symlink(name, name_link) >= 0);
1357
1358 assert_se(is_symlink(name) == 0);
1359 assert_se(is_symlink(name_link) == 1);
1360 assert_se(is_symlink("/a/file/which/does/not/exist/i/guess") < 0);
1361
1362
1363 unlink(name);
1364 unlink(name_link);
1365 }
1366
1367 static void test_search_and_fopen(void) {
1368 const char *dirs[] = {"/tmp/foo/bar", "/tmp", NULL};
1369 char name[] = "/tmp/test-search_and_fopen.XXXXXX";
1370 int fd = -1;
1371 int r;
1372 FILE *f;
1373
1374 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
1375 assert_se(fd >= 0);
1376 close(fd);
1377
1378 r = search_and_fopen(basename(name), "r", NULL, dirs, &f);
1379 assert_se(r >= 0);
1380 fclose(f);
1381
1382 r = search_and_fopen(name, "r", NULL, dirs, &f);
1383 assert_se(r >= 0);
1384 fclose(f);
1385
1386 r = search_and_fopen(basename(name), "r", "/", dirs, &f);
1387 assert_se(r >= 0);
1388 fclose(f);
1389
1390 r = search_and_fopen("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f);
1391 assert_se(r < 0);
1392 r = search_and_fopen("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f);
1393 assert_se(r < 0);
1394
1395 r = unlink(name);
1396 assert_se(r == 0);
1397
1398 r = search_and_fopen(basename(name), "r", NULL, dirs, &f);
1399 assert_se(r < 0);
1400 }
1401
1402
1403 static void test_search_and_fopen_nulstr(void) {
1404 const char dirs[] = "/tmp/foo/bar\0/tmp\0";
1405 char name[] = "/tmp/test-search_and_fopen.XXXXXX";
1406 int fd = -1;
1407 int r;
1408 FILE *f;
1409
1410 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
1411 assert_se(fd >= 0);
1412 close(fd);
1413
1414 r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f);
1415 assert_se(r >= 0);
1416 fclose(f);
1417
1418 r = search_and_fopen_nulstr(name, "r", NULL, dirs, &f);
1419 assert_se(r >= 0);
1420 fclose(f);
1421
1422 r = search_and_fopen_nulstr("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f);
1423 assert_se(r < 0);
1424 r = search_and_fopen_nulstr("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f);
1425 assert_se(r < 0);
1426
1427 r = unlink(name);
1428 assert_se(r == 0);
1429
1430 r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f);
1431 assert_se(r < 0);
1432 }
1433
1434 static void test_glob_exists(void) {
1435 char name[] = "/tmp/test-glob_exists.XXXXXX";
1436 int fd = -1;
1437 int r;
1438
1439 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
1440 assert_se(fd >= 0);
1441 close(fd);
1442
1443 r = glob_exists("/tmp/test-glob_exists*");
1444 assert_se(r == 1);
1445
1446 r = unlink(name);
1447 assert_se(r == 0);
1448 r = glob_exists("/tmp/test-glob_exists*");
1449 assert_se(r == 0);
1450 }
1451
1452 static void test_execute_directory(void) {
1453 char template_lo[] = "/tmp/test-readlink_and_make_absolute-lo.XXXXXXX";
1454 char template_hi[] = "/tmp/test-readlink_and_make_absolute-hi.XXXXXXX";
1455 const char * dirs[] = {template_hi, template_lo, NULL};
1456 const char *name, *name2, *name3, *overridden, *override, *masked, *mask;
1457
1458 assert_se(mkdtemp(template_lo));
1459 assert_se(mkdtemp(template_hi));
1460
1461 name = strjoina(template_lo, "/script");
1462 name2 = strjoina(template_hi, "/script2");
1463 name3 = strjoina(template_lo, "/useless");
1464 overridden = strjoina(template_lo, "/overridden");
1465 override = strjoina(template_hi, "/overridden");
1466 masked = strjoina(template_lo, "/masked");
1467 mask = strjoina(template_hi, "/masked");
1468
1469 assert_se(write_string_file(name, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/it_works", WRITE_STRING_FILE_CREATE) == 0);
1470 assert_se(write_string_file(name2, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/it_works2", WRITE_STRING_FILE_CREATE) == 0);
1471 assert_se(write_string_file(overridden, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed", WRITE_STRING_FILE_CREATE) == 0);
1472 assert_se(write_string_file(override, "#!/bin/sh\necho 'Executing '$0", WRITE_STRING_FILE_CREATE) == 0);
1473 assert_se(write_string_file(masked, "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed", WRITE_STRING_FILE_CREATE) == 0);
1474 assert_se(symlink("/dev/null", mask) == 0);
1475 assert_se(chmod(name, 0755) == 0);
1476 assert_se(chmod(name2, 0755) == 0);
1477 assert_se(chmod(overridden, 0755) == 0);
1478 assert_se(chmod(override, 0755) == 0);
1479 assert_se(chmod(masked, 0755) == 0);
1480 assert_se(touch(name3) >= 0);
1481
1482 execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL);
1483
1484 assert_se(chdir(template_lo) == 0);
1485 assert_se(access("it_works", F_OK) >= 0);
1486 assert_se(access("failed", F_OK) < 0);
1487
1488 assert_se(chdir(template_hi) == 0);
1489 assert_se(access("it_works2", F_OK) >= 0);
1490 assert_se(access("failed", F_OK) < 0);
1491
1492 (void) rm_rf(template_lo, REMOVE_ROOT|REMOVE_PHYSICAL);
1493 (void) rm_rf(template_hi, REMOVE_ROOT|REMOVE_PHYSICAL);
1494 }
1495
1496 static void test_extract_first_word(void) {
1497 const char *p, *original;
1498 char *t;
1499
1500 p = original = "foobar waldo";
1501 assert_se(extract_first_word(&p, &t, NULL, 0) > 0);
1502 assert_se(streq(t, "foobar"));
1503 free(t);
1504 assert_se(p == original + 7);
1505
1506 assert_se(extract_first_word(&p, &t, NULL, 0) > 0);
1507 assert_se(streq(t, "waldo"));
1508 free(t);
1509 assert_se(isempty(p));
1510
1511 assert_se(extract_first_word(&p, &t, NULL, 0) == 0);
1512 assert_se(!t);
1513 assert_se(isempty(p));
1514
1515 p = original = "\"foobar\" \'waldo\'";
1516 assert_se(extract_first_word(&p, &t, NULL, 0) > 0);
1517 assert_se(streq(t, "\"foobar\""));
1518 free(t);
1519 assert_se(p == original + 9);
1520
1521 assert_se(extract_first_word(&p, &t, NULL, 0) > 0);
1522 assert_se(streq(t, "\'waldo\'"));
1523 free(t);
1524 assert_se(isempty(p));
1525
1526 assert_se(extract_first_word(&p, &t, NULL, 0) == 0);
1527 assert_se(!t);
1528 assert_se(isempty(p));
1529
1530 p = original = "\"foobar\" \'waldo\'";
1531 assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0);
1532 assert_se(streq(t, "foobar"));
1533 free(t);
1534 assert_se(p == original + 9);
1535
1536 assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0);
1537 assert_se(streq(t, "waldo"));
1538 free(t);
1539 assert_se(isempty(p));
1540
1541 assert_se(extract_first_word(&p, &t, NULL, 0) == 0);
1542 assert_se(!t);
1543 assert_se(isempty(p));
1544
1545 p = original = "\"";
1546 assert_se(extract_first_word(&p, &t, NULL, 0) == 1);
1547 assert_se(streq(t, "\""));
1548 free(t);
1549 assert_se(isempty(p));
1550
1551 p = original = "\"";
1552 assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) == -EINVAL);
1553 assert_se(p == original + 1);
1554
1555 p = original = "\'";
1556 assert_se(extract_first_word(&p, &t, NULL, 0) == 1);
1557 assert_se(streq(t, "\'"));
1558 free(t);
1559 assert_se(isempty(p));
1560
1561 p = original = "\'";
1562 assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) == -EINVAL);
1563 assert_se(p == original + 1);
1564
1565 p = original = "\'fooo";
1566 assert_se(extract_first_word(&p, &t, NULL, 0) == 1);
1567 assert_se(streq(t, "\'fooo"));
1568 free(t);
1569 assert_se(isempty(p));
1570
1571 p = original = "\'fooo";
1572 assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) == -EINVAL);
1573 assert_se(p == original + 5);
1574
1575 p = original = "\'fooo";
1576 assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX) > 0);
1577 assert_se(streq(t, "fooo"));
1578 free(t);
1579 assert_se(isempty(p));
1580
1581 p = original = "yay\'foo\'bar";
1582 assert_se(extract_first_word(&p, &t, NULL, 0) > 0);
1583 assert_se(streq(t, "yay\'foo\'bar"));
1584 free(t);
1585 assert_se(isempty(p));
1586
1587 p = original = "yay\'foo\'bar";
1588 assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0);
1589 assert_se(streq(t, "yayfoobar"));
1590 free(t);
1591 assert_se(isempty(p));
1592
1593 p = original = " foobar ";
1594 assert_se(extract_first_word(&p, &t, NULL, 0) > 0);
1595 assert_se(streq(t, "foobar"));
1596 free(t);
1597 assert_se(isempty(p));
1598
1599 p = original = " foo\\ba\\x6ar ";
1600 assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE) > 0);
1601 assert_se(streq(t, "foo\ba\x6ar"));
1602 free(t);
1603 assert_se(isempty(p));
1604
1605 p = original = " foo\\ba\\x6ar ";
1606 assert_se(extract_first_word(&p, &t, NULL, 0) > 0);
1607 assert_se(streq(t, "foobax6ar"));
1608 free(t);
1609 assert_se(isempty(p));
1610
1611 p = original = " f\\u00f6o \"pi\\U0001F4A9le\" ";
1612 assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE) > 0);
1613 assert_se(streq(t, "föo"));
1614 free(t);
1615 assert_se(p == original + 13);
1616
1617 assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE) > 0);
1618 assert_se(streq(t, "pi\360\237\222\251le"));
1619 free(t);
1620 assert_se(isempty(p));
1621
1622 p = original = "fooo\\";
1623 assert_se(extract_first_word(&p, &t, NULL, EXTRACT_RELAX) > 0);
1624 assert_se(streq(t, "fooo"));
1625 free(t);
1626 assert_se(isempty(p));
1627
1628 p = original = "fooo\\";
1629 assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE_RELAX) > 0);
1630 assert_se(streq(t, "fooo\\"));
1631 free(t);
1632 assert_se(isempty(p));
1633
1634 p = original = "fooo\\";
1635 assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0);
1636 assert_se(streq(t, "fooo\\"));
1637 free(t);
1638 assert_se(isempty(p));
1639
1640 p = original = "fooo\\";
1641 assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX) > 0);
1642 assert_se(streq(t, "fooo\\"));
1643 free(t);
1644 assert_se(isempty(p));
1645
1646 p = original = "\"foo\\";
1647 assert_se(extract_first_word(&p, &t, NULL, 0) == -EINVAL);
1648 assert_se(p == original + 5);
1649
1650 p = original = "\"foo\\";
1651 assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX) > 0);
1652 assert_se(streq(t, "foo"));
1653 free(t);
1654 assert_se(isempty(p));
1655
1656 p = original = "foo::bar";
1657 assert_se(extract_first_word(&p, &t, ":", 0) == 1);
1658 assert_se(streq(t, "foo"));
1659 free(t);
1660 assert_se(p == original + 5);
1661
1662 assert_se(extract_first_word(&p, &t, ":", 0) == 1);
1663 assert_se(streq(t, "bar"));
1664 free(t);
1665 assert_se(isempty(p));
1666
1667 assert_se(extract_first_word(&p, &t, ":", 0) == 0);
1668 assert_se(!t);
1669 assert_se(isempty(p));
1670
1671 p = original = "foo\\:bar::waldo";
1672 assert_se(extract_first_word(&p, &t, ":", 0) == 1);
1673 assert_se(streq(t, "foo:bar"));
1674 free(t);
1675 assert_se(p == original + 10);
1676
1677 assert_se(extract_first_word(&p, &t, ":", 0) == 1);
1678 assert_se(streq(t, "waldo"));
1679 free(t);
1680 assert_se(isempty(p));
1681
1682 assert_se(extract_first_word(&p, &t, ":", 0) == 0);
1683 assert_se(!t);
1684 assert_se(isempty(p));
1685
1686 p = original = "\"foo\\";
1687 assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE_RELAX) == -EINVAL);
1688 assert_se(p == original + 5);
1689
1690 p = original = "\"foo\\";
1691 assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0);
1692 assert_se(streq(t, "foo\\"));
1693 free(t);
1694 assert_se(isempty(p));
1695
1696 p = original = "\"foo\\";
1697 assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0);
1698 assert_se(streq(t, "foo\\"));
1699 free(t);
1700 assert_se(isempty(p));
1701
1702 p = original = "fooo\\ bar quux";
1703 assert_se(extract_first_word(&p, &t, NULL, EXTRACT_RELAX) > 0);
1704 assert_se(streq(t, "fooo bar"));
1705 free(t);
1706 assert_se(p == original + 10);
1707
1708 p = original = "fooo\\ bar quux";
1709 assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE_RELAX) > 0);
1710 assert_se(streq(t, "fooo bar"));
1711 free(t);
1712 assert_se(p == original + 10);
1713
1714 p = original = "fooo\\ bar quux";
1715 assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0);
1716 assert_se(streq(t, "fooo bar"));
1717 free(t);
1718 assert_se(p == original + 10);
1719
1720 p = original = "fooo\\ bar quux";
1721 assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE) == -EINVAL);
1722 assert_se(p == original + 5);
1723
1724 p = original = "fooo\\ bar quux";
1725 assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX) > 0);
1726 assert_se(streq(t, "fooo\\ bar"));
1727 free(t);
1728 assert_se(p == original + 10);
1729
1730 p = original = "\\w+@\\K[\\d.]+";
1731 assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE) == -EINVAL);
1732 assert_se(p == original + 1);
1733
1734 p = original = "\\w+@\\K[\\d.]+";
1735 assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX) > 0);
1736 assert_se(streq(t, "\\w+@\\K[\\d.]+"));
1737 free(t);
1738 assert_se(isempty(p));
1739
1740 p = original = "\\w+\\b";
1741 assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX) > 0);
1742 assert_se(streq(t, "\\w+\b"));
1743 free(t);
1744 assert_se(isempty(p));
1745
1746 p = original = "-N ''";
1747 assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0);
1748 assert_se(streq(t, "-N"));
1749 free(t);
1750 assert_se(p == original + 3);
1751
1752 assert_se(extract_first_word(&p, &t, NULL, EXTRACT_QUOTES) > 0);
1753 assert_se(streq(t, ""));
1754 free(t);
1755 assert_se(isempty(p));
1756
1757 p = original = ":foo\\:bar::waldo:";
1758 assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1);
1759 assert_se(t);
1760 assert_se(streq(t, ""));
1761 free(t);
1762 assert_se(p == original + 1);
1763
1764 assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1);
1765 assert_se(streq(t, "foo:bar"));
1766 free(t);
1767 assert_se(p == original + 10);
1768
1769 assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1);
1770 assert_se(t);
1771 assert_se(streq(t, ""));
1772 free(t);
1773 assert_se(p == original + 11);
1774
1775 assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1);
1776 assert_se(streq(t, "waldo"));
1777 free(t);
1778 assert_se(p == original + 17);
1779
1780 assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1);
1781 assert_se(streq(t, ""));
1782 free(t);
1783 assert_se(p == NULL);
1784
1785 assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 0);
1786 assert_se(!t);
1787 assert_se(!p);
1788 }
1789
1790 static void test_extract_first_word_and_warn(void) {
1791 const char *p, *original;
1792 char *t;
1793
1794 p = original = "foobar waldo";
1795 assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0);
1796 assert_se(streq(t, "foobar"));
1797 free(t);
1798 assert_se(p == original + 7);
1799
1800 assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0);
1801 assert_se(streq(t, "waldo"));
1802 free(t);
1803 assert_se(isempty(p));
1804
1805 assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) == 0);
1806 assert_se(!t);
1807 assert_se(isempty(p));
1808
1809 p = original = "\"foobar\" \'waldo\'";
1810 assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) > 0);
1811 assert_se(streq(t, "foobar"));
1812 free(t);
1813 assert_se(p == original + 9);
1814
1815 assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) > 0);
1816 assert_se(streq(t, "waldo"));
1817 free(t);
1818 assert_se(isempty(p));
1819
1820 assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) == 0);
1821 assert_se(!t);
1822 assert_se(isempty(p));
1823
1824 p = original = "\"";
1825 assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) == -EINVAL);
1826 assert_se(p == original + 1);
1827
1828 p = original = "\'";
1829 assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) == -EINVAL);
1830 assert_se(p == original + 1);
1831
1832 p = original = "\'fooo";
1833 assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) == -EINVAL);
1834 assert_se(p == original + 5);
1835
1836 p = original = "\'fooo";
1837 assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX, NULL, "fake", 1, original) > 0);
1838 assert_se(streq(t, "fooo"));
1839 free(t);
1840 assert_se(isempty(p));
1841
1842 p = original = " foo\\ba\\x6ar ";
1843 assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0);
1844 assert_se(streq(t, "foo\ba\x6ar"));
1845 free(t);
1846 assert_se(isempty(p));
1847
1848 p = original = " foo\\ba\\x6ar ";
1849 assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0);
1850 assert_se(streq(t, "foobax6ar"));
1851 free(t);
1852 assert_se(isempty(p));
1853
1854 p = original = " f\\u00f6o \"pi\\U0001F4A9le\" ";
1855 assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0);
1856 assert_se(streq(t, "föo"));
1857 free(t);
1858 assert_se(p == original + 13);
1859
1860 assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0);
1861 assert_se(streq(t, "pi\360\237\222\251le"));
1862 free(t);
1863 assert_se(isempty(p));
1864
1865 p = original = "fooo\\";
1866 assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_RELAX, NULL, "fake", 1, original) > 0);
1867 assert_se(streq(t, "fooo"));
1868 free(t);
1869 assert_se(isempty(p));
1870
1871 p = original = "fooo\\";
1872 assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0);
1873 assert_se(streq(t, "fooo\\"));
1874 free(t);
1875 assert_se(isempty(p));
1876
1877 p = original = "fooo\\";
1878 assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0);
1879 assert_se(streq(t, "fooo\\"));
1880 free(t);
1881 assert_se(isempty(p));
1882
1883 p = original = "\"foo\\";
1884 assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES, NULL, "fake", 1, original) == -EINVAL);
1885 assert_se(p == original + 5);
1886
1887 p = original = "\"foo\\";
1888 assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_RELAX, NULL, "fake", 1, original) > 0);
1889 assert_se(streq(t, "foo"));
1890 free(t);
1891 assert_se(isempty(p));
1892
1893 p = original = "\"foo\\";
1894 assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE, NULL, "fake", 1, original) == -EINVAL);
1895 assert_se(p == original + 5);
1896
1897 p = original = "\"foo\\";
1898 assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE|EXTRACT_RELAX, NULL, "fake", 1, original) > 0);
1899 assert_se(streq(t, "foo"));
1900 free(t);
1901 assert_se(isempty(p));
1902
1903 p = original = "fooo\\ bar quux";
1904 assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_RELAX, NULL, "fake", 1, original) > 0);
1905 assert_se(streq(t, "fooo bar"));
1906 free(t);
1907 assert_se(p == original + 10);
1908
1909 p = original = "fooo\\ bar quux";
1910 assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0);
1911 assert_se(streq(t, "fooo bar"));
1912 free(t);
1913 assert_se(p == original + 10);
1914
1915 p = original = "fooo\\ bar quux";
1916 assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0);
1917 assert_se(streq(t, "fooo\\ bar"));
1918 free(t);
1919 assert_se(p == original + 10);
1920
1921 p = original = "\\w+@\\K[\\d.]+";
1922 assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0);
1923 assert_se(streq(t, "\\w+@\\K[\\d.]+"));
1924 free(t);
1925 assert_se(isempty(p));
1926
1927 p = original = "\\w+\\b";
1928 assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0);
1929 assert_se(streq(t, "\\w+\b"));
1930 free(t);
1931 assert_se(isempty(p));
1932 }
1933
1934 static void test_extract_many_words(void) {
1935 const char *p, *original;
1936 char *a, *b, *c;
1937
1938 p = original = "foobar waldi piep";
1939 assert_se(extract_many_words(&p, NULL, 0, &a, &b, &c, NULL) == 3);
1940 assert_se(isempty(p));
1941 assert_se(streq_ptr(a, "foobar"));
1942 assert_se(streq_ptr(b, "waldi"));
1943 assert_se(streq_ptr(c, "piep"));
1944 free(a);
1945 free(b);
1946 free(c);
1947
1948 p = original = "'foobar' wa\"ld\"i ";
1949 assert_se(extract_many_words(&p, NULL, 0, &a, &b, &c, NULL) == 2);
1950 assert_se(isempty(p));
1951 assert_se(streq_ptr(a, "'foobar'"));
1952 assert_se(streq_ptr(b, "wa\"ld\"i"));
1953 assert_se(streq_ptr(c, NULL));
1954 free(a);
1955 free(b);
1956
1957 p = original = "'foobar' wa\"ld\"i ";
1958 assert_se(extract_many_words(&p, NULL, EXTRACT_QUOTES, &a, &b, &c, NULL) == 2);
1959 assert_se(isempty(p));
1960 assert_se(streq_ptr(a, "foobar"));
1961 assert_se(streq_ptr(b, "waldi"));
1962 assert_se(streq_ptr(c, NULL));
1963 free(a);
1964 free(b);
1965
1966 p = original = "";
1967 assert_se(extract_many_words(&p, NULL, 0, &a, &b, &c, NULL) == 0);
1968 assert_se(isempty(p));
1969 assert_se(streq_ptr(a, NULL));
1970 assert_se(streq_ptr(b, NULL));
1971 assert_se(streq_ptr(c, NULL));
1972
1973 p = original = " ";
1974 assert_se(extract_many_words(&p, NULL, 0, &a, &b, &c, NULL) == 0);
1975 assert_se(isempty(p));
1976 assert_se(streq_ptr(a, NULL));
1977 assert_se(streq_ptr(b, NULL));
1978 assert_se(streq_ptr(c, NULL));
1979
1980 p = original = "foobar";
1981 assert_se(extract_many_words(&p, NULL, 0, NULL) == 0);
1982 assert_se(p == original);
1983
1984 p = original = "foobar waldi";
1985 assert_se(extract_many_words(&p, NULL, 0, &a, NULL) == 1);
1986 assert_se(p == original+7);
1987 assert_se(streq_ptr(a, "foobar"));
1988 free(a);
1989
1990 p = original = " foobar ";
1991 assert_se(extract_many_words(&p, NULL, 0, &a, NULL) == 1);
1992 assert_se(isempty(p));
1993 assert_se(streq_ptr(a, "foobar"));
1994 free(a);
1995 }
1996
1997 static int parse_item(const char *key, const char *value) {
1998 assert_se(key);
1999
2000 log_info("kernel cmdline option <%s> = <%s>", key, strna(value));
2001 return 0;
2002 }
2003
2004 static void test_parse_proc_cmdline(void) {
2005 assert_se(parse_proc_cmdline(parse_item) >= 0);
2006 }
2007
2008 static void test_raw_clone(void) {
2009 pid_t parent, pid, pid2;
2010
2011 parent = getpid();
2012 log_info("before clone: getpid()→"PID_FMT, parent);
2013 assert_se(raw_getpid() == parent);
2014
2015 pid = raw_clone(0, NULL);
2016 assert_se(pid >= 0);
2017
2018 pid2 = raw_getpid();
2019 log_info("raw_clone: "PID_FMT" getpid()→"PID_FMT" raw_getpid()→"PID_FMT,
2020 pid, getpid(), pid2);
2021 if (pid == 0) {
2022 assert_se(pid2 != parent);
2023 _exit(EXIT_SUCCESS);
2024 } else {
2025 int status;
2026
2027 assert_se(pid2 == parent);
2028 waitpid(pid, &status, __WCLONE);
2029 assert_se(WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS);
2030 }
2031 }
2032
2033 static void test_same_fd(void) {
2034 _cleanup_close_pair_ int p[2] = { -1, -1 };
2035 _cleanup_close_ int a = -1, b = -1, c = -1;
2036
2037 assert_se(pipe2(p, O_CLOEXEC) >= 0);
2038 assert_se((a = dup(p[0])) >= 0);
2039 assert_se((b = open("/dev/null", O_RDONLY|O_CLOEXEC)) >= 0);
2040 assert_se((c = dup(a)) >= 0);
2041
2042 assert_se(same_fd(p[0], p[0]) > 0);
2043 assert_se(same_fd(p[1], p[1]) > 0);
2044 assert_se(same_fd(a, a) > 0);
2045 assert_se(same_fd(b, b) > 0);
2046
2047 assert_se(same_fd(a, p[0]) > 0);
2048 assert_se(same_fd(p[0], a) > 0);
2049 assert_se(same_fd(c, p[0]) > 0);
2050 assert_se(same_fd(p[0], c) > 0);
2051 assert_se(same_fd(a, c) > 0);
2052 assert_se(same_fd(c, a) > 0);
2053
2054 assert_se(same_fd(p[0], p[1]) == 0);
2055 assert_se(same_fd(p[1], p[0]) == 0);
2056 assert_se(same_fd(p[0], b) == 0);
2057 assert_se(same_fd(b, p[0]) == 0);
2058 assert_se(same_fd(p[1], a) == 0);
2059 assert_se(same_fd(a, p[1]) == 0);
2060 assert_se(same_fd(p[1], b) == 0);
2061 assert_se(same_fd(b, p[1]) == 0);
2062
2063 assert_se(same_fd(a, b) == 0);
2064 assert_se(same_fd(b, a) == 0);
2065 }
2066
2067 static void test_uid_ptr(void) {
2068
2069 assert_se(UID_TO_PTR(0) != NULL);
2070 assert_se(UID_TO_PTR(1000) != NULL);
2071
2072 assert_se(PTR_TO_UID(UID_TO_PTR(0)) == 0);
2073 assert_se(PTR_TO_UID(UID_TO_PTR(1000)) == 1000);
2074 }
2075
2076 static void test_sparse_write_one(int fd, const char *buffer, size_t n) {
2077 char check[n];
2078
2079 assert_se(lseek(fd, 0, SEEK_SET) == 0);
2080 assert_se(ftruncate(fd, 0) >= 0);
2081 assert_se(sparse_write(fd, buffer, n, 4) == (ssize_t) n);
2082
2083 assert_se(lseek(fd, 0, SEEK_CUR) == (off_t) n);
2084 assert_se(ftruncate(fd, n) >= 0);
2085
2086 assert_se(lseek(fd, 0, SEEK_SET) == 0);
2087 assert_se(read(fd, check, n) == (ssize_t) n);
2088
2089 assert_se(memcmp(buffer, check, n) == 0);
2090 }
2091
2092 static void test_sparse_write(void) {
2093 const char test_a[] = "test";
2094 const char test_b[] = "\0\0\0\0test\0\0\0\0";
2095 const char test_c[] = "\0\0test\0\0\0\0";
2096 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";
2097 const char test_e[] = "test\0\0\0\0test";
2098 _cleanup_close_ int fd = -1;
2099 char fn[] = "/tmp/sparseXXXXXX";
2100
2101 fd = mkostemp(fn, O_CLOEXEC);
2102 assert_se(fd >= 0);
2103 unlink(fn);
2104
2105 test_sparse_write_one(fd, test_a, sizeof(test_a));
2106 test_sparse_write_one(fd, test_b, sizeof(test_b));
2107 test_sparse_write_one(fd, test_c, sizeof(test_c));
2108 test_sparse_write_one(fd, test_d, sizeof(test_d));
2109 test_sparse_write_one(fd, test_e, sizeof(test_e));
2110 }
2111
2112 static void test_shell_escape_one(const char *s, const char *bad, const char *expected) {
2113 _cleanup_free_ char *r;
2114
2115 assert_se(r = shell_escape(s, bad));
2116 assert_se(streq_ptr(r, expected));
2117 }
2118
2119 static void test_shell_escape(void) {
2120 test_shell_escape_one("", "", "");
2121 test_shell_escape_one("\\", "", "\\\\");
2122 test_shell_escape_one("foobar", "", "foobar");
2123 test_shell_escape_one("foobar", "o", "f\\o\\obar");
2124 test_shell_escape_one("foo:bar,baz", ",:", "foo\\:bar\\,baz");
2125 }
2126
2127 static void test_shell_maybe_quote_one(const char *s, const char *expected) {
2128 _cleanup_free_ char *r;
2129
2130 assert_se(r = shell_maybe_quote(s));
2131 assert_se(streq(r, expected));
2132 }
2133
2134 static void test_shell_maybe_quote(void) {
2135
2136 test_shell_maybe_quote_one("", "");
2137 test_shell_maybe_quote_one("\\", "\"\\\\\"");
2138 test_shell_maybe_quote_one("\"", "\"\\\"\"");
2139 test_shell_maybe_quote_one("foobar", "foobar");
2140 test_shell_maybe_quote_one("foo bar", "\"foo bar\"");
2141 test_shell_maybe_quote_one("foo \"bar\" waldo", "\"foo \\\"bar\\\" waldo\"");
2142 test_shell_maybe_quote_one("foo$bar", "\"foo\\$bar\"");
2143 }
2144
2145 static void test_parse_mode(void) {
2146 mode_t m;
2147
2148 assert_se(parse_mode("-1", &m) < 0);
2149 assert_se(parse_mode("", &m) < 0);
2150 assert_se(parse_mode("888", &m) < 0);
2151 assert_se(parse_mode("77777", &m) < 0);
2152
2153 assert_se(parse_mode("544", &m) >= 0 && m == 0544);
2154 assert_se(parse_mode("777", &m) >= 0 && m == 0777);
2155 assert_se(parse_mode("7777", &m) >= 0 && m == 07777);
2156 assert_se(parse_mode("0", &m) >= 0 && m == 0);
2157 }
2158
2159 static void test_tempfn(void) {
2160 char *ret = NULL, *p;
2161
2162 assert_se(tempfn_xxxxxx("/foo/bar/waldo", NULL, &ret) >= 0);
2163 assert_se(streq_ptr(ret, "/foo/bar/.#waldoXXXXXX"));
2164 free(ret);
2165
2166 assert_se(tempfn_xxxxxx("/foo/bar/waldo", "[miau]", &ret) >= 0);
2167 assert_se(streq_ptr(ret, "/foo/bar/.#[miau]waldoXXXXXX"));
2168 free(ret);
2169
2170 assert_se(tempfn_random("/foo/bar/waldo", NULL, &ret) >= 0);
2171 assert_se(p = startswith(ret, "/foo/bar/.#waldo"));
2172 assert_se(strlen(p) == 16);
2173 assert_se(in_charset(p, "0123456789abcdef"));
2174 free(ret);
2175
2176 assert_se(tempfn_random("/foo/bar/waldo", "[wuff]", &ret) >= 0);
2177 assert_se(p = startswith(ret, "/foo/bar/.#[wuff]waldo"));
2178 assert_se(strlen(p) == 16);
2179 assert_se(in_charset(p, "0123456789abcdef"));
2180 free(ret);
2181
2182 assert_se(tempfn_random_child("/foo/bar/waldo", NULL, &ret) >= 0);
2183 assert_se(p = startswith(ret, "/foo/bar/waldo/.#"));
2184 assert_se(strlen(p) == 16);
2185 assert_se(in_charset(p, "0123456789abcdef"));
2186 free(ret);
2187
2188 assert_se(tempfn_random_child("/foo/bar/waldo", "[kikiriki]", &ret) >= 0);
2189 assert_se(p = startswith(ret, "/foo/bar/waldo/.#[kikiriki]"));
2190 assert_se(strlen(p) == 16);
2191 assert_se(in_charset(p, "0123456789abcdef"));
2192 free(ret);
2193 }
2194
2195 static void test_strcmp_ptr(void) {
2196 assert_se(strcmp_ptr(NULL, NULL) == 0);
2197 assert_se(strcmp_ptr("", NULL) > 0);
2198 assert_se(strcmp_ptr("foo", NULL) > 0);
2199 assert_se(strcmp_ptr(NULL, "") < 0);
2200 assert_se(strcmp_ptr(NULL, "bar") < 0);
2201 assert_se(strcmp_ptr("foo", "bar") > 0);
2202 assert_se(strcmp_ptr("bar", "baz") < 0);
2203 assert_se(strcmp_ptr("foo", "foo") == 0);
2204 assert_se(strcmp_ptr("", "") == 0);
2205 }
2206
2207 int main(int argc, char *argv[]) {
2208 log_parse_environment();
2209 log_open();
2210
2211 test_streq_ptr();
2212 test_align_power2();
2213 test_max();
2214 test_container_of();
2215 test_alloca();
2216 test_div_round_up();
2217 test_first_word();
2218 test_close_many();
2219 test_parse_boolean();
2220 test_parse_pid();
2221 test_parse_uid();
2222 test_safe_atou16();
2223 test_safe_atoi16();
2224 test_safe_atolli();
2225 test_safe_atod();
2226 test_strappend();
2227 test_strstrip();
2228 test_delete_chars();
2229 test_in_charset();
2230 test_hexchar();
2231 test_unhexchar();
2232 test_base32hexchar();
2233 test_unbase32hexchar();
2234 test_base64char();
2235 test_unbase64char();
2236 test_octchar();
2237 test_unoctchar();
2238 test_decchar();
2239 test_undecchar();
2240 test_unhexmem();
2241 test_base32hexmem();
2242 test_unbase32hexmem();
2243 test_base64mem();
2244 test_unbase64mem();
2245 test_cescape();
2246 test_cunescape();
2247 test_foreach_word();
2248 test_foreach_word_quoted();
2249 test_memdup_multiply();
2250 test_u64log2();
2251 test_protect_errno();
2252 test_parse_size();
2253 test_config_parse_iec_uint64();
2254 test_strextend();
2255 test_strrep();
2256 test_split_pair();
2257 test_fstab_node_to_udev_node();
2258 test_get_files_in_directory();
2259 test_in_set();
2260 test_writing_tmpfile();
2261 test_hexdump();
2262 test_log2i();
2263 test_foreach_string();
2264 test_filename_is_valid();
2265 test_string_has_cc();
2266 test_ascii_strlower();
2267 test_files_same();
2268 test_is_valid_documentation_url();
2269 test_file_in_same_dir();
2270 test_endswith();
2271 test_endswith_no_case();
2272 test_close_nointr();
2273 test_unlink_noerrno();
2274 test_readlink_and_make_absolute();
2275 test_ignore_signals();
2276 test_strshorten();
2277 test_strjoina();
2278 test_is_symlink();
2279 test_search_and_fopen();
2280 test_search_and_fopen_nulstr();
2281 test_glob_exists();
2282 test_execute_directory();
2283 test_extract_first_word();
2284 test_extract_first_word_and_warn();
2285 test_extract_many_words();
2286 test_parse_proc_cmdline();
2287 test_raw_clone();
2288 test_same_fd();
2289 test_uid_ptr();
2290 test_sparse_write();
2291 test_shell_escape();
2292 test_shell_maybe_quote();
2293 test_parse_mode();
2294 test_tempfn();
2295 test_strcmp_ptr();
2296
2297 return 0;
2298 }