]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/test/test-fileio.c
Merge pull request #1871 from poettering/nspawn-veth-extra
[thirdparty/systemd.git] / src / test / test-fileio.c
CommitLineData
f73141d7
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2013 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <stdio.h>
23#include <fcntl.h>
24#include <unistd.h>
25
b5efdb8a 26#include "alloc-util.h"
1e5413f7 27#include "ctype.h"
3ffd4af2
LP
28#include "def.h"
29#include "env-util.h"
30#include "fd-util.h"
31#include "fileio.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
2d5bdf5b 49 fd = mkostemp_safe(p, O_RDWR|O_CLOEXEC);
d514feaa
TA
50 assert_se(fd >= 0);
51 close(fd);
095b30cb 52
2d5bdf5b 53 fd = mkostemp_safe(t, O_RDWR|O_CLOEXEC);
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
HH
74 "export nine=nineval\n"
75 "ten=", f);
f73141d7
LP
76
77 fflush(f);
78 fclose(f);
79
717603e3 80 r = load_env_file(NULL, t, NULL, &a);
ebc05a09
HH
81 assert_se(r >= 0);
82
83 STRV_FOREACH(i, a)
84 log_info("Got: <%s>", *i);
85
5fba7bbf
TA
86 assert_se(streq_ptr(a[0], "one=BAR"));
87 assert_se(streq_ptr(a[1], "two=bar"));
88 assert_se(streq_ptr(a[2], "three=333\nxxxx"));
89 assert_se(streq_ptr(a[3], "four=44\"44"));
90 assert_se(streq_ptr(a[4], "five=55\'55FIVEcinco"));
91 assert_se(streq_ptr(a[5], "six=seis sechs sis"));
92 assert_se(streq_ptr(a[6], "seven=sevenval#nocomment"));
93 assert_se(streq_ptr(a[7], "eight=eightval #nocomment"));
94 assert_se(streq_ptr(a[8], "export nine=nineval"));
95 assert_se(streq_ptr(a[9], "ten="));
ebc05a09
HH
96 assert_se(a[10] == NULL);
97
039f0e70 98 strv_env_clean(a);
ebc05a09 99
ebc05a09
HH
100 k = 0;
101 STRV_FOREACH(i, b) {
102 log_info("Got2: <%s>", *i);
103 assert_se(streq(*i, a[k++]));
104 }
105
f73141d7
LP
106 r = parse_env_file(
107 t, NULL,
108 "one", &one,
109 "two", &two,
110 "three", &three,
111 "four", &four,
112 "five", &five,
113 "six", &six,
114 "seven", &seven,
db537209 115 "eight", &eight,
ebc05a09
HH
116 "export nine", &nine,
117 "ten", &ten,
f73141d7
LP
118 NULL);
119
120 assert_se(r >= 0);
121
122 log_info("one=[%s]", strna(one));
123 log_info("two=[%s]", strna(two));
124 log_info("three=[%s]", strna(three));
125 log_info("four=[%s]", strna(four));
126 log_info("five=[%s]", strna(five));
127 log_info("six=[%s]", strna(six));
128 log_info("seven=[%s]", strna(seven));
db537209 129 log_info("eight=[%s]", strna(eight));
ebc05a09
HH
130 log_info("export nine=[%s]", strna(nine));
131 log_info("ten=[%s]", strna(nine));
f73141d7
LP
132
133 assert_se(streq(one, "BAR"));
134 assert_se(streq(two, "bar"));
135 assert_se(streq(three, "333\nxxxx"));
136 assert_se(streq(four, "44\"44"));
137 assert_se(streq(five, "55\'55FIVEcinco"));
138 assert_se(streq(six, "seis sechs sis"));
98f59e59
HH
139 assert_se(streq(seven, "sevenval#nocomment"));
140 assert_se(streq(eight, "eightval #nocomment"));
ebc05a09
HH
141 assert_se(streq(nine, "nineval"));
142 assert_se(ten == NULL);
f73141d7 143
095b30cb 144 r = write_env_file(p, a);
98f59e59
HH
145 assert_se(r >= 0);
146
717603e3 147 r = load_env_file(NULL, p, NULL, &b);
98f59e59
HH
148 assert_se(r >= 0);
149
f73141d7 150 unlink(t);
095b30cb 151 unlink(p);
f73141d7
LP
152}
153
ac4c8d6d
ZJS
154static void test_parse_multiline_env_file(void) {
155 char t[] = "/tmp/test-fileio-in-XXXXXX",
156 p[] = "/tmp/test-fileio-out-XXXXXX";
157 int fd, r;
158 FILE *f;
159 _cleanup_strv_free_ char **a = NULL, **b = NULL;
160 char **i;
161
2d5bdf5b 162 fd = mkostemp_safe(p, O_RDWR|O_CLOEXEC);
d514feaa
TA
163 assert_se(fd >= 0);
164 close(fd);
ac4c8d6d 165
2d5bdf5b 166 fd = mkostemp_safe(t, O_RDWR|O_CLOEXEC);
ac4c8d6d
ZJS
167 assert_se(fd >= 0);
168
169 f = fdopen(fd, "w");
170 assert_se(f);
171
172 fputs("one=BAR\\\n"
173 " VAR\\\n"
174 "\tGAR\n"
175 "#comment\n"
176 "two=\"bar\\\n"
177 " var\\\n"
178 "\tgar\"\n"
179 "#comment\n"
180 "tri=\"bar \\\n"
181 " var \\\n"
182 "\tgar \"\n", f);
183
184 fflush(f);
185 fclose(f);
186
717603e3 187 r = load_env_file(NULL, t, NULL, &a);
ac4c8d6d
ZJS
188 assert_se(r >= 0);
189
190 STRV_FOREACH(i, a)
191 log_info("Got: <%s>", *i);
192
5fba7bbf
TA
193 assert_se(streq_ptr(a[0], "one=BAR VAR\tGAR"));
194 assert_se(streq_ptr(a[1], "two=bar var\tgar"));
195 assert_se(streq_ptr(a[2], "tri=bar var \tgar "));
ac4c8d6d
ZJS
196 assert_se(a[3] == NULL);
197
198 r = write_env_file(p, a);
199 assert_se(r >= 0);
200
717603e3 201 r = load_env_file(NULL, p, NULL, &b);
ac4c8d6d
ZJS
202 assert_se(r >= 0);
203
204 unlink(t);
205 unlink(p);
206}
207
208
68fee104
ZJS
209static void test_executable_is_script(void) {
210 char t[] = "/tmp/test-executable-XXXXXX";
211 int fd, r;
212 FILE *f;
213 char *command;
214
2d5bdf5b 215 fd = mkostemp_safe(t, O_RDWR|O_CLOEXEC);
68fee104
ZJS
216 assert_se(fd >= 0);
217
218 f = fdopen(fd, "w");
219 assert_se(f);
220
221 fputs("#! /bin/script -a -b \ngoo goo", f);
222 fflush(f);
223
224 r = executable_is_script(t, &command);
225 assert_se(r > 0);
226 assert_se(streq(command, "/bin/script"));
227 free(command);
228
229 r = executable_is_script("/bin/sh", &command);
230 assert_se(r == 0);
231
232 r = executable_is_script("/usr/bin/yum", &command);
233 assert_se(r > 0 || r == -ENOENT);
234 if (r > 0) {
235 assert_se(startswith(command, "/"));
236 free(command);
237 }
238
239 fclose(f);
240 unlink(t);
241}
242
69ab8088 243static void test_status_field(void) {
1e5413f7
ZJS
244 _cleanup_free_ char *t = NULL, *p = NULL, *s = NULL, *z = NULL;
245 unsigned long long total = 0, buffers = 0;
442e0083 246 int r;
69ab8088 247
c4cd1d4d 248 assert_se(get_proc_field("/proc/self/status", "Threads", WHITESPACE, &t) == 0);
69ab8088
ZJS
249 puts(t);
250 assert_se(streq(t, "1"));
251
c4cd1d4d 252 r = get_proc_field("/proc/meminfo", "MemTotal", WHITESPACE, &p);
1e5413f7 253 if (r != -ENOENT) {
bdf7026e 254 assert_se(r == 0);
1e5413f7
ZJS
255 puts(p);
256 assert_se(safe_atollu(p, &total) == 0);
257 }
69ab8088 258
c4cd1d4d 259 r = get_proc_field("/proc/meminfo", "Buffers", WHITESPACE, &s);
1e5413f7 260 if (r != -ENOENT) {
bdf7026e 261 assert_se(r == 0);
1e5413f7
ZJS
262 puts(s);
263 assert_se(safe_atollu(s, &buffers) == 0);
264 }
69ab8088 265
2b01a801 266 if (p)
bdf7026e 267 assert_se(buffers < total);
1e5413f7
ZJS
268
269 /* Seccomp should be a good test for field full of zeros. */
c4cd1d4d 270 r = get_proc_field("/proc/meminfo", "Seccomp", WHITESPACE, &z);
1e5413f7 271 if (r != -ENOENT) {
bdf7026e 272 assert_se(r == 0);
1e5413f7
ZJS
273 puts(z);
274 assert_se(safe_atollu(z, &buffers) == 0);
275 }
276}
277
278static void test_capeff(void) {
279 int pid, p;
280
281 for (pid = 0; pid < 2; pid++) {
282 _cleanup_free_ char *capeff = NULL;
283 int r;
284
285 r = get_process_capeff(0, &capeff);
286 log_info("capeff: '%s' (r=%d)", capeff, r);
287
288 if (r == -ENOENT || r == -EPERM)
289 return;
290
bdf7026e
TA
291 assert_se(r == 0);
292 assert_se(*capeff);
1e5413f7 293 p = capeff[strspn(capeff, DIGITS "abcdefABCDEF")];
bdf7026e 294 assert_se(!p || isspace(p));
1e5413f7 295 }
69ab8088
ZJS
296}
297
0709b743
RC
298static void test_write_string_stream(void) {
299 char fn[] = "/tmp/test-write_string_stream-XXXXXX";
300 _cleanup_fclose_ FILE *f = NULL;
301 int fd;
302 char buf[64];
303
304 fd = mkostemp_safe(fn, O_RDWR);
305 assert_se(fd >= 0);
306
307 f = fdopen(fd, "r");
308 assert_se(f);
40beecdb 309 assert_se(write_string_stream(f, "boohoo", true) < 0);
0709b743 310
76082570 311 f = freopen(fn, "r+", f);
0709b743
RC
312 assert_se(f);
313
40beecdb 314 assert_se(write_string_stream(f, "boohoo", true) == 0);
0709b743
RC
315 rewind(f);
316
317 assert_se(fgets(buf, sizeof(buf), f));
318 assert_se(streq(buf, "boohoo\n"));
319
40beecdb
DM
320 f = freopen(fn, "w+", f);
321 assert_se(f);
322
323 assert_se(write_string_stream(f, "boohoo", false) == 0);
324 rewind(f);
325
326 assert_se(fgets(buf, sizeof(buf), f));
327 printf(">%s<", buf);
328 assert_se(streq(buf, "boohoo"));
329
0709b743
RC
330 unlink(fn);
331}
332
333static void test_write_string_file(void) {
334 char fn[] = "/tmp/test-write_string_file-XXXXXX";
76082570
RC
335 char buf[64] = {};
336 _cleanup_close_ int fd;
0709b743
RC
337
338 fd = mkostemp_safe(fn, O_RDWR);
339 assert_se(fd >= 0);
340
4c1fc3e4 341 assert_se(write_string_file(fn, "boohoo", WRITE_STRING_FILE_CREATE) == 0);
0709b743 342
cca0efb0 343 assert_se(read(fd, buf, sizeof(buf)) == 7);
0709b743
RC
344 assert_se(streq(buf, "boohoo\n"));
345
346 unlink(fn);
347}
348
e07995a3
RC
349static void test_write_string_file_no_create(void) {
350 char fn[] = "/tmp/test-write_string_file_no_create-XXXXXX";
351 _cleanup_close_ int fd;
352 char buf[64] = {0};
353
354 fd = mkostemp_safe(fn, O_RDWR);
355 assert_se(fd >= 0);
356
4c1fc3e4
DM
357 assert_se(write_string_file("/a/file/which/does/not/exists/i/guess", "boohoo", 0) < 0);
358 assert_se(write_string_file(fn, "boohoo", 0) == 0);
e07995a3 359
696c24fc 360 assert_se(read(fd, buf, sizeof(buf)) == strlen("boohoo\n"));
e07995a3
RC
361 assert_se(streq(buf, "boohoo\n"));
362
363 unlink(fn);
364}
365
e07995a3
RC
366static void test_load_env_file_pairs(void) {
367 char fn[] = "/tmp/test-load_env_file_pairs-XXXXXX";
368 int fd;
369 int r;
370 _cleanup_fclose_ FILE *f = NULL;
371 _cleanup_strv_free_ char **l = NULL;
372 char **k, **v;
373
374 fd = mkostemp_safe(fn, O_RDWR);
375 assert_se(fd >= 0);
376
377 r = write_string_file(fn,
378 "NAME=\"Arch Linux\"\n"
379 "ID=arch\n"
380 "PRETTY_NAME=\"Arch Linux\"\n"
381 "ANSI_COLOR=\"0;36\"\n"
382 "HOME_URL=\"https://www.archlinux.org/\"\n"
383 "SUPPORT_URL=\"https://bbs.archlinux.org/\"\n"
4c1fc3e4
DM
384 "BUG_REPORT_URL=\"https://bugs.archlinux.org/\"\n",
385 WRITE_STRING_FILE_CREATE);
e07995a3
RC
386 assert_se(r == 0);
387
388 f = fdopen(fd, "r");
389 assert_se(f);
390
391 r = load_env_file_pairs(f, fn, NULL, &l);
392 assert_se(r >= 0);
393
394 assert_se(strv_length(l) == 14);
395 STRV_FOREACH_PAIR(k, v, l) {
396 assert_se(STR_IN_SET(*k, "NAME", "ID", "PRETTY_NAME", "ANSI_COLOR", "HOME_URL", "SUPPORT_URL", "BUG_REPORT_URL"));
397 printf("%s=%s\n", *k, *v);
398 if (streq(*k, "NAME")) assert_se(streq(*v, "Arch Linux"));
399 if (streq(*k, "ID")) assert_se(streq(*v, "arch"));
400 if (streq(*k, "PRETTY_NAME")) assert_se(streq(*v, "Arch Linux"));
401 if (streq(*k, "ANSI_COLOR")) assert_se(streq(*v, "0;36"));
402 if (streq(*k, "HOME_URL")) assert_se(streq(*v, "https://www.archlinux.org/"));
403 if (streq(*k, "SUPPORT_URL")) assert_se(streq(*v, "https://bbs.archlinux.org/"));
404 if (streq(*k, "BUG_REPORT_URL")) assert_se(streq(*v, "https://bugs.archlinux.org/"));
405 }
406
407 unlink(fn);
408}
409
f73141d7 410int main(int argc, char *argv[]) {
1e5413f7
ZJS
411 log_parse_environment();
412 log_open();
413
f73141d7 414 test_parse_env_file();
ac4c8d6d 415 test_parse_multiline_env_file();
68fee104 416 test_executable_is_script();
69ab8088 417 test_status_field();
1e5413f7 418 test_capeff();
0709b743
RC
419 test_write_string_stream();
420 test_write_string_file();
e07995a3 421 test_write_string_file_no_create();
e07995a3 422 test_load_env_file_pairs();
1e5413f7 423
f73141d7
LP
424 return 0;
425}