]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/test/test-fileio.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / test / test-fileio.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
f73141d7
LP
2/***
3 This file is part of systemd.
4
5 Copyright 2013 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19***/
20
f73141d7 21#include <fcntl.h>
cf0fbc49 22#include <stdio.h>
f73141d7
LP
23#include <unistd.h>
24
b5efdb8a 25#include "alloc-util.h"
1e5413f7 26#include "ctype.h"
3ffd4af2
LP
27#include "def.h"
28#include "env-util.h"
29#include "fd-util.h"
30#include "fileio.h"
897891f0 31#include "io-util.h"
6bedfcbb 32#include "parse-util.h"
3ffd4af2 33#include "process-util.h"
07630cea 34#include "string-util.h"
3ffd4af2
LP
35#include "strv.h"
36#include "util.h"
f73141d7
LP
37
38static void test_parse_env_file(void) {
095b30cb
ZJS
39 char t[] = "/tmp/test-fileio-in-XXXXXX",
40 p[] = "/tmp/test-fileio-out-XXXXXX";
f73141d7
LP
41 int fd, r;
42 FILE *f;
ebc05a09
HH
43 _cleanup_free_ char *one = NULL, *two = NULL, *three = NULL, *four = NULL, *five = NULL,
44 *six = NULL, *seven = NULL, *eight = NULL, *nine = NULL, *ten = NULL;
768100ef 45 _cleanup_strv_free_ char **a = NULL, **b = NULL;
f73141d7 46 char **i;
768100ef 47 unsigned k;
f73141d7 48
646853bd 49 fd = mkostemp_safe(p);
d514feaa
TA
50 assert_se(fd >= 0);
51 close(fd);
095b30cb 52
646853bd 53 fd = mkostemp_safe(t);
f73141d7
LP
54 assert_se(fd >= 0);
55
56 f = fdopen(fd, "w");
57 assert_se(f);
58
59 fputs("one=BAR \n"
60 "# comment\n"
61 " # comment \n"
98f59e59 62 " ; comment \n"
f73141d7
LP
63 " two = bar \n"
64 "invalid line\n"
98f59e59 65 "invalid line #comment\n"
f73141d7
LP
66 "three = \"333\n"
67 "xxxx\"\n"
68 "four = \'44\\\"44\'\n"
69 "five = \'55\\\'55\' \"FIVE\" cinco \n"
70 "six = seis sechs\\\n"
71 " sis\n"
98f59e59
HH
72 "seven=\"sevenval\" #nocomment\n"
73 "eight=eightval #nocomment\n"
ebc05a09 74 "export nine=nineval\n"
99003e01
ZJS
75 "ten=ignored\n"
76 "ten=ignored\n"
ebc05a09 77 "ten=", f);
f73141d7
LP
78
79 fflush(f);
80 fclose(f);
81
717603e3 82 r = load_env_file(NULL, t, NULL, &a);
ebc05a09
HH
83 assert_se(r >= 0);
84
85 STRV_FOREACH(i, a)
86 log_info("Got: <%s>", *i);
87
5fba7bbf
TA
88 assert_se(streq_ptr(a[0], "one=BAR"));
89 assert_se(streq_ptr(a[1], "two=bar"));
90 assert_se(streq_ptr(a[2], "three=333\nxxxx"));
91 assert_se(streq_ptr(a[3], "four=44\"44"));
92 assert_se(streq_ptr(a[4], "five=55\'55FIVEcinco"));
93 assert_se(streq_ptr(a[5], "six=seis sechs sis"));
94 assert_se(streq_ptr(a[6], "seven=sevenval#nocomment"));
95 assert_se(streq_ptr(a[7], "eight=eightval #nocomment"));
96 assert_se(streq_ptr(a[8], "export nine=nineval"));
97 assert_se(streq_ptr(a[9], "ten="));
ebc05a09
HH
98 assert_se(a[10] == NULL);
99
039f0e70 100 strv_env_clean(a);
ebc05a09 101
ebc05a09
HH
102 k = 0;
103 STRV_FOREACH(i, b) {
104 log_info("Got2: <%s>", *i);
105 assert_se(streq(*i, a[k++]));
106 }
107
f73141d7
LP
108 r = parse_env_file(
109 t, NULL,
110 "one", &one,
111 "two", &two,
112 "three", &three,
113 "four", &four,
114 "five", &five,
115 "six", &six,
116 "seven", &seven,
db537209 117 "eight", &eight,
ebc05a09
HH
118 "export nine", &nine,
119 "ten", &ten,
f73141d7
LP
120 NULL);
121
122 assert_se(r >= 0);
123
124 log_info("one=[%s]", strna(one));
125 log_info("two=[%s]", strna(two));
126 log_info("three=[%s]", strna(three));
127 log_info("four=[%s]", strna(four));
128 log_info("five=[%s]", strna(five));
129 log_info("six=[%s]", strna(six));
130 log_info("seven=[%s]", strna(seven));
db537209 131 log_info("eight=[%s]", strna(eight));
ebc05a09
HH
132 log_info("export nine=[%s]", strna(nine));
133 log_info("ten=[%s]", strna(nine));
f73141d7
LP
134
135 assert_se(streq(one, "BAR"));
136 assert_se(streq(two, "bar"));
137 assert_se(streq(three, "333\nxxxx"));
138 assert_se(streq(four, "44\"44"));
139 assert_se(streq(five, "55\'55FIVEcinco"));
140 assert_se(streq(six, "seis sechs sis"));
98f59e59
HH
141 assert_se(streq(seven, "sevenval#nocomment"));
142 assert_se(streq(eight, "eightval #nocomment"));
ebc05a09
HH
143 assert_se(streq(nine, "nineval"));
144 assert_se(ten == NULL);
f73141d7 145
095b30cb 146 r = write_env_file(p, a);
98f59e59
HH
147 assert_se(r >= 0);
148
717603e3 149 r = load_env_file(NULL, p, NULL, &b);
98f59e59
HH
150 assert_se(r >= 0);
151
f73141d7 152 unlink(t);
095b30cb 153 unlink(p);
f73141d7
LP
154}
155
ac4c8d6d
ZJS
156static void test_parse_multiline_env_file(void) {
157 char t[] = "/tmp/test-fileio-in-XXXXXX",
158 p[] = "/tmp/test-fileio-out-XXXXXX";
159 int fd, r;
160 FILE *f;
161 _cleanup_strv_free_ char **a = NULL, **b = NULL;
162 char **i;
163
646853bd 164 fd = mkostemp_safe(p);
d514feaa
TA
165 assert_se(fd >= 0);
166 close(fd);
ac4c8d6d 167
646853bd 168 fd = mkostemp_safe(t);
ac4c8d6d
ZJS
169 assert_se(fd >= 0);
170
171 f = fdopen(fd, "w");
172 assert_se(f);
173
174 fputs("one=BAR\\\n"
175 " VAR\\\n"
176 "\tGAR\n"
177 "#comment\n"
178 "two=\"bar\\\n"
179 " var\\\n"
180 "\tgar\"\n"
181 "#comment\n"
182 "tri=\"bar \\\n"
183 " var \\\n"
184 "\tgar \"\n", f);
185
186 fflush(f);
187 fclose(f);
188
717603e3 189 r = load_env_file(NULL, t, NULL, &a);
ac4c8d6d
ZJS
190 assert_se(r >= 0);
191
192 STRV_FOREACH(i, a)
193 log_info("Got: <%s>", *i);
194
5fba7bbf
TA
195 assert_se(streq_ptr(a[0], "one=BAR VAR\tGAR"));
196 assert_se(streq_ptr(a[1], "two=bar var\tgar"));
197 assert_se(streq_ptr(a[2], "tri=bar var \tgar "));
ac4c8d6d
ZJS
198 assert_se(a[3] == NULL);
199
200 r = write_env_file(p, a);
201 assert_se(r >= 0);
202
717603e3 203 r = load_env_file(NULL, p, NULL, &b);
ac4c8d6d
ZJS
204 assert_se(r >= 0);
205
206 unlink(t);
207 unlink(p);
208}
209
37f3ffca
RS
210static void test_merge_env_file(void) {
211 char t[] = "/tmp/test-fileio-XXXXXX";
212 int fd, r;
9707d552 213 _cleanup_fclose_ FILE *f = NULL;
37f3ffca
RS
214 _cleanup_strv_free_ char **a = NULL;
215 char **i;
216
217 fd = mkostemp_safe(t);
218 assert_se(fd >= 0);
219
220 log_info("/* %s (%s) */", __func__, t);
221
222 f = fdopen(fd, "w");
223 assert_se(f);
224
225 r = write_string_stream(f,
226 "one=1 \n"
227 "twelve=${one}2\n"
228 "twentyone=2${one}\n"
229 "one=2\n"
ccad1fd0
ZJS
230 "twentytwo=2${one}\n"
231 "xxx_minus_three=$xxx - 3\n"
232 "xxx=0x$one$one$one\n"
b82f58bf
RS
233 "yyy=${one:-fallback}\n"
234 "zzz=${one:+replacement}\n"
235 "zzzz=${foobar:-${nothing}}\n"
236 "zzzzz=${nothing:+${nothing}}\n"
b1837133 237 , WRITE_STRING_FILE_AVOID_NEWLINE);
37f3ffca
RS
238 assert(r >= 0);
239
240 r = merge_env_file(&a, NULL, t);
241 assert_se(r >= 0);
242 strv_sort(a);
243
244 STRV_FOREACH(i, a)
245 log_info("Got: <%s>", *i);
246
247 assert_se(streq(a[0], "one=2"));
248 assert_se(streq(a[1], "twelve=12"));
249 assert_se(streq(a[2], "twentyone=21"));
250 assert_se(streq(a[3], "twentytwo=22"));
ccad1fd0
ZJS
251 assert_se(streq(a[4], "xxx=0x222"));
252 assert_se(streq(a[5], "xxx_minus_three= - 3"));
b82f58bf
RS
253 assert_se(streq(a[6], "yyy=2"));
254 assert_se(streq(a[7], "zzz=replacement"));
255 assert_se(streq(a[8], "zzzz="));
256 assert_se(streq(a[9], "zzzzz="));
257 assert_se(a[10] == NULL);
37f3ffca
RS
258
259 r = merge_env_file(&a, NULL, t);
260 assert_se(r >= 0);
261 strv_sort(a);
262
263 STRV_FOREACH(i, a)
264 log_info("Got2: <%s>", *i);
265
266 assert_se(streq(a[0], "one=2"));
267 assert_se(streq(a[1], "twelve=12"));
268 assert_se(streq(a[2], "twentyone=21"));
269 assert_se(streq(a[3], "twentytwo=22"));
ccad1fd0
ZJS
270 assert_se(streq(a[4], "xxx=0x222"));
271 assert_se(streq(a[5], "xxx_minus_three=0x222 - 3"));
b82f58bf
RS
272 assert_se(streq(a[6], "yyy=2"));
273 assert_se(streq(a[7], "zzz=replacement"));
274 assert_se(streq(a[8], "zzzz="));
275 assert_se(streq(a[9], "zzzzz="));
276 assert_se(a[10] == NULL);
37f3ffca 277}
ac4c8d6d 278
184d1904
ZJS
279static void test_merge_env_file_invalid(void) {
280 char t[] = "/tmp/test-fileio-XXXXXX";
281 int fd, r;
9707d552 282 _cleanup_fclose_ FILE *f = NULL;
184d1904
ZJS
283 _cleanup_strv_free_ char **a = NULL;
284 char **i;
285
286 fd = mkostemp_safe(t);
287 assert_se(fd >= 0);
288
289 log_info("/* %s (%s) */", __func__, t);
290
291 f = fdopen(fd, "w");
292 assert_se(f);
293
294 r = write_string_stream(f,
295 "unset one \n"
296 "unset one= \n"
297 "unset one=1 \n"
298 "one \n"
299 "one = \n"
300 "one two =\n"
301 "\x20two=\n"
302 "#comment=comment\n"
303 ";comment2=comment2\n"
304 "#\n"
305 "\n\n" /* empty line */
b1837133 306 , WRITE_STRING_FILE_AVOID_NEWLINE);
184d1904
ZJS
307 assert(r >= 0);
308
309 r = merge_env_file(&a, NULL, t);
310 assert_se(r >= 0);
311
312 STRV_FOREACH(i, a)
313 log_info("Got: <%s>", *i);
314
315 assert_se(strv_isempty(a));
316}
317
68fee104
ZJS
318static void test_executable_is_script(void) {
319 char t[] = "/tmp/test-executable-XXXXXX";
320 int fd, r;
321 FILE *f;
322 char *command;
323
646853bd 324 fd = mkostemp_safe(t);
68fee104
ZJS
325 assert_se(fd >= 0);
326
327 f = fdopen(fd, "w");
328 assert_se(f);
329
330 fputs("#! /bin/script -a -b \ngoo goo", f);
331 fflush(f);
332
333 r = executable_is_script(t, &command);
334 assert_se(r > 0);
335 assert_se(streq(command, "/bin/script"));
336 free(command);
337
338 r = executable_is_script("/bin/sh", &command);
339 assert_se(r == 0);
340
341 r = executable_is_script("/usr/bin/yum", &command);
342 assert_se(r > 0 || r == -ENOENT);
343 if (r > 0) {
344 assert_se(startswith(command, "/"));
345 free(command);
346 }
347
348 fclose(f);
349 unlink(t);
350}
351
69ab8088 352static void test_status_field(void) {
1e5413f7
ZJS
353 _cleanup_free_ char *t = NULL, *p = NULL, *s = NULL, *z = NULL;
354 unsigned long long total = 0, buffers = 0;
442e0083 355 int r;
69ab8088 356
c4cd1d4d 357 assert_se(get_proc_field("/proc/self/status", "Threads", WHITESPACE, &t) == 0);
69ab8088
ZJS
358 puts(t);
359 assert_se(streq(t, "1"));
360
c4cd1d4d 361 r = get_proc_field("/proc/meminfo", "MemTotal", WHITESPACE, &p);
1e5413f7 362 if (r != -ENOENT) {
bdf7026e 363 assert_se(r == 0);
1e5413f7
ZJS
364 puts(p);
365 assert_se(safe_atollu(p, &total) == 0);
366 }
69ab8088 367
c4cd1d4d 368 r = get_proc_field("/proc/meminfo", "Buffers", WHITESPACE, &s);
1e5413f7 369 if (r != -ENOENT) {
bdf7026e 370 assert_se(r == 0);
1e5413f7
ZJS
371 puts(s);
372 assert_se(safe_atollu(s, &buffers) == 0);
373 }
69ab8088 374
2b01a801 375 if (p)
bdf7026e 376 assert_se(buffers < total);
1e5413f7
ZJS
377
378 /* Seccomp should be a good test for field full of zeros. */
c4cd1d4d 379 r = get_proc_field("/proc/meminfo", "Seccomp", WHITESPACE, &z);
1e5413f7 380 if (r != -ENOENT) {
bdf7026e 381 assert_se(r == 0);
1e5413f7
ZJS
382 puts(z);
383 assert_se(safe_atollu(z, &buffers) == 0);
384 }
385}
386
387static void test_capeff(void) {
388 int pid, p;
389
390 for (pid = 0; pid < 2; pid++) {
391 _cleanup_free_ char *capeff = NULL;
392 int r;
393
394 r = get_process_capeff(0, &capeff);
395 log_info("capeff: '%s' (r=%d)", capeff, r);
396
4c701096 397 if (IN_SET(r, -ENOENT, -EPERM))
1e5413f7
ZJS
398 return;
399
bdf7026e
TA
400 assert_se(r == 0);
401 assert_se(*capeff);
1a7906ae 402 p = capeff[strspn(capeff, HEXDIGITS)];
bdf7026e 403 assert_se(!p || isspace(p));
1e5413f7 404 }
69ab8088
ZJS
405}
406
0709b743
RC
407static void test_write_string_stream(void) {
408 char fn[] = "/tmp/test-write_string_stream-XXXXXX";
409 _cleanup_fclose_ FILE *f = NULL;
410 int fd;
411 char buf[64];
412
646853bd 413 fd = mkostemp_safe(fn);
0709b743
RC
414 assert_se(fd >= 0);
415
416 f = fdopen(fd, "r");
417 assert_se(f);
b1837133 418 assert_se(write_string_stream(f, "boohoo", 0) < 0);
0709b743 419
76082570 420 f = freopen(fn, "r+", f);
0709b743
RC
421 assert_se(f);
422
b1837133 423 assert_se(write_string_stream(f, "boohoo", 0) == 0);
0709b743
RC
424 rewind(f);
425
426 assert_se(fgets(buf, sizeof(buf), f));
427 assert_se(streq(buf, "boohoo\n"));
428
40beecdb
DM
429 f = freopen(fn, "w+", f);
430 assert_se(f);
431
b1837133 432 assert_se(write_string_stream(f, "boohoo", WRITE_STRING_FILE_AVOID_NEWLINE) == 0);
40beecdb
DM
433 rewind(f);
434
435 assert_se(fgets(buf, sizeof(buf), f));
436 printf(">%s<", buf);
437 assert_se(streq(buf, "boohoo"));
438
0709b743
RC
439 unlink(fn);
440}
441
442static void test_write_string_file(void) {
443 char fn[] = "/tmp/test-write_string_file-XXXXXX";
76082570
RC
444 char buf[64] = {};
445 _cleanup_close_ int fd;
0709b743 446
646853bd 447 fd = mkostemp_safe(fn);
0709b743
RC
448 assert_se(fd >= 0);
449
4c1fc3e4 450 assert_se(write_string_file(fn, "boohoo", WRITE_STRING_FILE_CREATE) == 0);
0709b743 451
cca0efb0 452 assert_se(read(fd, buf, sizeof(buf)) == 7);
0709b743
RC
453 assert_se(streq(buf, "boohoo\n"));
454
455 unlink(fn);
456}
457
e07995a3
RC
458static void test_write_string_file_no_create(void) {
459 char fn[] = "/tmp/test-write_string_file_no_create-XXXXXX";
460 _cleanup_close_ int fd;
461 char buf[64] = {0};
462
646853bd 463 fd = mkostemp_safe(fn);
e07995a3
RC
464 assert_se(fd >= 0);
465
4c1fc3e4
DM
466 assert_se(write_string_file("/a/file/which/does/not/exists/i/guess", "boohoo", 0) < 0);
467 assert_se(write_string_file(fn, "boohoo", 0) == 0);
e07995a3 468
696c24fc 469 assert_se(read(fd, buf, sizeof(buf)) == strlen("boohoo\n"));
e07995a3
RC
470 assert_se(streq(buf, "boohoo\n"));
471
472 unlink(fn);
473}
474
eb3da901
LP
475static void test_write_string_file_verify(void) {
476 _cleanup_free_ char *buf = NULL, *buf2 = NULL;
477 int r;
478
479 assert_se(read_one_line_file("/proc/cmdline", &buf) >= 0);
605405c6 480 assert_se((buf2 = strjoin(buf, "\n")));
eb3da901
LP
481
482 r = write_string_file("/proc/cmdline", buf, 0);
4c701096 483 assert_se(IN_SET(r, -EACCES, -EIO));
eb3da901 484 r = write_string_file("/proc/cmdline", buf2, 0);
4c701096 485 assert_se(IN_SET(r, -EACCES, -EIO));
eb3da901
LP
486
487 assert_se(write_string_file("/proc/cmdline", buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE) == 0);
488 assert_se(write_string_file("/proc/cmdline", buf2, WRITE_STRING_FILE_VERIFY_ON_FAILURE) == 0);
489
490 r = write_string_file("/proc/cmdline", buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE|WRITE_STRING_FILE_AVOID_NEWLINE);
4c701096 491 assert_se(IN_SET(r, -EACCES, -EIO));
eb3da901
LP
492 assert_se(write_string_file("/proc/cmdline", buf2, WRITE_STRING_FILE_VERIFY_ON_FAILURE|WRITE_STRING_FILE_AVOID_NEWLINE) == 0);
493}
494
e07995a3
RC
495static void test_load_env_file_pairs(void) {
496 char fn[] = "/tmp/test-load_env_file_pairs-XXXXXX";
497 int fd;
498 int r;
499 _cleanup_fclose_ FILE *f = NULL;
500 _cleanup_strv_free_ char **l = NULL;
501 char **k, **v;
502
646853bd 503 fd = mkostemp_safe(fn);
e07995a3
RC
504 assert_se(fd >= 0);
505
506 r = write_string_file(fn,
507 "NAME=\"Arch Linux\"\n"
508 "ID=arch\n"
509 "PRETTY_NAME=\"Arch Linux\"\n"
510 "ANSI_COLOR=\"0;36\"\n"
511 "HOME_URL=\"https://www.archlinux.org/\"\n"
512 "SUPPORT_URL=\"https://bbs.archlinux.org/\"\n"
4c1fc3e4
DM
513 "BUG_REPORT_URL=\"https://bugs.archlinux.org/\"\n",
514 WRITE_STRING_FILE_CREATE);
e07995a3
RC
515 assert_se(r == 0);
516
517 f = fdopen(fd, "r");
518 assert_se(f);
519
520 r = load_env_file_pairs(f, fn, NULL, &l);
521 assert_se(r >= 0);
522
523 assert_se(strv_length(l) == 14);
524 STRV_FOREACH_PAIR(k, v, l) {
525 assert_se(STR_IN_SET(*k, "NAME", "ID", "PRETTY_NAME", "ANSI_COLOR", "HOME_URL", "SUPPORT_URL", "BUG_REPORT_URL"));
526 printf("%s=%s\n", *k, *v);
527 if (streq(*k, "NAME")) assert_se(streq(*v, "Arch Linux"));
528 if (streq(*k, "ID")) assert_se(streq(*v, "arch"));
529 if (streq(*k, "PRETTY_NAME")) assert_se(streq(*v, "Arch Linux"));
530 if (streq(*k, "ANSI_COLOR")) assert_se(streq(*v, "0;36"));
531 if (streq(*k, "HOME_URL")) assert_se(streq(*v, "https://www.archlinux.org/"));
532 if (streq(*k, "SUPPORT_URL")) assert_se(streq(*v, "https://bbs.archlinux.org/"));
533 if (streq(*k, "BUG_REPORT_URL")) assert_se(streq(*v, "https://bugs.archlinux.org/"));
534 }
535
536 unlink(fn);
537}
538
897891f0
RC
539static void test_search_and_fopen(void) {
540 const char *dirs[] = {"/tmp/foo/bar", "/tmp", NULL};
541 char name[] = "/tmp/test-search_and_fopen.XXXXXX";
542 int fd = -1;
543 int r;
544 FILE *f;
545
646853bd 546 fd = mkostemp_safe(name);
897891f0
RC
547 assert_se(fd >= 0);
548 close(fd);
549
550 r = search_and_fopen(basename(name), "r", NULL, dirs, &f);
551 assert_se(r >= 0);
552 fclose(f);
553
554 r = search_and_fopen(name, "r", NULL, dirs, &f);
555 assert_se(r >= 0);
556 fclose(f);
557
558 r = search_and_fopen(basename(name), "r", "/", dirs, &f);
559 assert_se(r >= 0);
560 fclose(f);
561
562 r = search_and_fopen("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f);
563 assert_se(r < 0);
564 r = search_and_fopen("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f);
565 assert_se(r < 0);
566
567 r = unlink(name);
568 assert_se(r == 0);
569
570 r = search_and_fopen(basename(name), "r", NULL, dirs, &f);
571 assert_se(r < 0);
572}
573
574
575static void test_search_and_fopen_nulstr(void) {
576 const char dirs[] = "/tmp/foo/bar\0/tmp\0";
577 char name[] = "/tmp/test-search_and_fopen.XXXXXX";
578 int fd = -1;
579 int r;
580 FILE *f;
581
646853bd 582 fd = mkostemp_safe(name);
897891f0
RC
583 assert_se(fd >= 0);
584 close(fd);
585
586 r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f);
587 assert_se(r >= 0);
588 fclose(f);
589
590 r = search_and_fopen_nulstr(name, "r", NULL, dirs, &f);
591 assert_se(r >= 0);
592 fclose(f);
593
594 r = search_and_fopen_nulstr("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f);
595 assert_se(r < 0);
596 r = search_and_fopen_nulstr("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f);
597 assert_se(r < 0);
598
599 r = unlink(name);
600 assert_se(r == 0);
601
602 r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f);
603 assert_se(r < 0);
604}
605
606static void test_writing_tmpfile(void) {
607 char name[] = "/tmp/test-systemd_writing_tmpfile.XXXXXX";
608 _cleanup_free_ char *contents = NULL;
609 size_t size;
610 int fd, r;
611 struct iovec iov[3];
612
e6a7ec4b
LP
613 iov[0] = IOVEC_MAKE_STRING("abc\n");
614 iov[1] = IOVEC_MAKE_STRING(ALPHANUMERICAL "\n");
615 iov[2] = IOVEC_MAKE_STRING("");
897891f0 616
646853bd 617 fd = mkostemp_safe(name);
897891f0
RC
618 printf("tmpfile: %s", name);
619
620 r = writev(fd, iov, 3);
621 assert_se(r >= 0);
622
623 r = read_full_file(name, &contents, &size);
624 assert_se(r == 0);
625 printf("contents: %s", contents);
626 assert_se(streq(contents, "abc\n" ALPHANUMERICAL "\n"));
627
628 unlink(name);
629}
630
631static void test_tempfn(void) {
632 char *ret = NULL, *p;
633
634 assert_se(tempfn_xxxxxx("/foo/bar/waldo", NULL, &ret) >= 0);
635 assert_se(streq_ptr(ret, "/foo/bar/.#waldoXXXXXX"));
636 free(ret);
637
638 assert_se(tempfn_xxxxxx("/foo/bar/waldo", "[miau]", &ret) >= 0);
639 assert_se(streq_ptr(ret, "/foo/bar/.#[miau]waldoXXXXXX"));
640 free(ret);
641
642 assert_se(tempfn_random("/foo/bar/waldo", NULL, &ret) >= 0);
643 assert_se(p = startswith(ret, "/foo/bar/.#waldo"));
644 assert_se(strlen(p) == 16);
645 assert_se(in_charset(p, "0123456789abcdef"));
646 free(ret);
647
648 assert_se(tempfn_random("/foo/bar/waldo", "[wuff]", &ret) >= 0);
649 assert_se(p = startswith(ret, "/foo/bar/.#[wuff]waldo"));
650 assert_se(strlen(p) == 16);
651 assert_se(in_charset(p, "0123456789abcdef"));
652 free(ret);
653
654 assert_se(tempfn_random_child("/foo/bar/waldo", NULL, &ret) >= 0);
655 assert_se(p = startswith(ret, "/foo/bar/waldo/.#"));
656 assert_se(strlen(p) == 16);
657 assert_se(in_charset(p, "0123456789abcdef"));
658 free(ret);
659
660 assert_se(tempfn_random_child("/foo/bar/waldo", "[kikiriki]", &ret) >= 0);
661 assert_se(p = startswith(ret, "/foo/bar/waldo/.#[kikiriki]"));
662 assert_se(strlen(p) == 16);
663 assert_se(in_charset(p, "0123456789abcdef"));
664 free(ret);
665}
666
2c9de139
ZJS
667static const char buffer[] =
668 "Some test data\n"
669 "With newlines, and a NUL byte\0"
670 "\n"
671 "an empty line\n"
672 "an ignored line\n"
673 "and a very long line that is supposed to be truncated, because it is so long\n";
674
675static void test_read_line_one_file(FILE *f) {
4f9a66a3
LP
676 _cleanup_free_ char *line = NULL;
677
4f9a66a3
LP
678 assert_se(read_line(f, (size_t) -1, &line) == 15 && streq(line, "Some test data"));
679 line = mfree(line);
680
681 assert_se(read_line(f, 1024, &line) == 30 && streq(line, "With newlines, and a NUL byte"));
682 line = mfree(line);
683
684 assert_se(read_line(f, 1024, &line) == 1 && streq(line, ""));
685 line = mfree(line);
686
687 assert_se(read_line(f, 1024, &line) == 14 && streq(line, "an empty line"));
688 line = mfree(line);
689
690 assert_se(read_line(f, (size_t) -1, NULL) == 16);
691
692 assert_se(read_line(f, 16, &line) == -ENOBUFS);
693 line = mfree(line);
694
695 /* read_line() stopped when it hit the limit, that means when we continue reading we'll read at the first
696 * character after the previous limit. Let's make use of tha to continue our test. */
697 assert_se(read_line(f, 1024, &line) == 61 && streq(line, "line that is supposed to be truncated, because it is so long"));
698 line = mfree(line);
699
700 assert_se(read_line(f, 1024, &line) == 1 && streq(line, ""));
701 line = mfree(line);
702
703 assert_se(read_line(f, 1024, &line) == 0 && streq(line, ""));
704}
705
2c9de139
ZJS
706static void test_read_line(void) {
707 _cleanup_fclose_ FILE *f = NULL;
2c9de139
ZJS
708
709 f = fmemopen((void*) buffer, sizeof(buffer), "re");
710 assert_se(f);
711
712 test_read_line_one_file(f);
713}
714
715static void test_read_line2(void) {
716 char name[] = "/tmp/test-fileio.XXXXXX";
717 int fd;
718 _cleanup_fclose_ FILE *f = NULL;
719
720 fd = mkostemp_safe(name);
721 assert_se(fd >= 0);
722 assert_se((size_t) write(fd, buffer, sizeof(buffer)) == sizeof(buffer));
723
724 assert_se(lseek(fd, 0, SEEK_SET) == 0);
725 assert_se(f = fdopen(fd, "r"));
726
727 test_read_line_one_file(f);
728}
729
730static void test_read_line3(void) {
731 _cleanup_fclose_ FILE *f = NULL;
732 _cleanup_free_ char *line = NULL;
733 int r;
734
735 f = fopen("/proc/cmdline", "re");
736 if (!f && IN_SET(errno, ENOENT, EPERM))
737 return;
738 assert_se(f);
739
740 r = read_line(f, LINE_MAX, &line);
741 assert_se((size_t) r == strlen(line) + 1);
742 assert_se(read_line(f, LINE_MAX, NULL) == 0);
743}
744
f73141d7 745int main(int argc, char *argv[]) {
37f3ffca 746 log_set_max_level(LOG_DEBUG);
1e5413f7
ZJS
747 log_parse_environment();
748 log_open();
749
f73141d7 750 test_parse_env_file();
ac4c8d6d 751 test_parse_multiline_env_file();
37f3ffca 752 test_merge_env_file();
184d1904 753 test_merge_env_file_invalid();
68fee104 754 test_executable_is_script();
69ab8088 755 test_status_field();
1e5413f7 756 test_capeff();
0709b743
RC
757 test_write_string_stream();
758 test_write_string_file();
e07995a3 759 test_write_string_file_no_create();
eb3da901 760 test_write_string_file_verify();
e07995a3 761 test_load_env_file_pairs();
897891f0
RC
762 test_search_and_fopen();
763 test_search_and_fopen_nulstr();
764 test_writing_tmpfile();
765 test_tempfn();
4f9a66a3 766 test_read_line();
2c9de139
ZJS
767 test_read_line2();
768 test_read_line3();
1e5413f7 769
f73141d7
LP
770 return 0;
771}