]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/test/test-fileio.c
shared: add process-util.[ch]
[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
26#include "util.h"
0b452006 27#include "process-util.h"
f73141d7
LP
28#include "fileio.h"
29#include "strv.h"
ebc05a09 30#include "env-util.h"
1e5413f7
ZJS
31#include "def.h"
32#include "ctype.h"
f73141d7
LP
33
34static void test_parse_env_file(void) {
095b30cb
ZJS
35 char t[] = "/tmp/test-fileio-in-XXXXXX",
36 p[] = "/tmp/test-fileio-out-XXXXXX";
f73141d7
LP
37 int fd, r;
38 FILE *f;
ebc05a09
HH
39 _cleanup_free_ char *one = NULL, *two = NULL, *three = NULL, *four = NULL, *five = NULL,
40 *six = NULL, *seven = NULL, *eight = NULL, *nine = NULL, *ten = NULL;
768100ef 41 _cleanup_strv_free_ char **a = NULL, **b = NULL;
f73141d7 42 char **i;
768100ef 43 unsigned k;
f73141d7 44
2d5bdf5b 45 fd = mkostemp_safe(p, O_RDWR|O_CLOEXEC);
d514feaa
TA
46 assert_se(fd >= 0);
47 close(fd);
095b30cb 48
2d5bdf5b 49 fd = mkostemp_safe(t, O_RDWR|O_CLOEXEC);
f73141d7
LP
50 assert_se(fd >= 0);
51
52 f = fdopen(fd, "w");
53 assert_se(f);
54
55 fputs("one=BAR \n"
56 "# comment\n"
57 " # comment \n"
98f59e59 58 " ; comment \n"
f73141d7
LP
59 " two = bar \n"
60 "invalid line\n"
98f59e59 61 "invalid line #comment\n"
f73141d7
LP
62 "three = \"333\n"
63 "xxxx\"\n"
64 "four = \'44\\\"44\'\n"
65 "five = \'55\\\'55\' \"FIVE\" cinco \n"
66 "six = seis sechs\\\n"
67 " sis\n"
98f59e59
HH
68 "seven=\"sevenval\" #nocomment\n"
69 "eight=eightval #nocomment\n"
ebc05a09
HH
70 "export nine=nineval\n"
71 "ten=", f);
f73141d7
LP
72
73 fflush(f);
74 fclose(f);
75
717603e3 76 r = load_env_file(NULL, t, NULL, &a);
ebc05a09
HH
77 assert_se(r >= 0);
78
79 STRV_FOREACH(i, a)
80 log_info("Got: <%s>", *i);
81
5fba7bbf
TA
82 assert_se(streq_ptr(a[0], "one=BAR"));
83 assert_se(streq_ptr(a[1], "two=bar"));
84 assert_se(streq_ptr(a[2], "three=333\nxxxx"));
85 assert_se(streq_ptr(a[3], "four=44\"44"));
86 assert_se(streq_ptr(a[4], "five=55\'55FIVEcinco"));
87 assert_se(streq_ptr(a[5], "six=seis sechs sis"));
88 assert_se(streq_ptr(a[6], "seven=sevenval#nocomment"));
89 assert_se(streq_ptr(a[7], "eight=eightval #nocomment"));
90 assert_se(streq_ptr(a[8], "export nine=nineval"));
91 assert_se(streq_ptr(a[9], "ten="));
ebc05a09
HH
92 assert_se(a[10] == NULL);
93
039f0e70 94 strv_env_clean(a);
ebc05a09 95
ebc05a09
HH
96 k = 0;
97 STRV_FOREACH(i, b) {
98 log_info("Got2: <%s>", *i);
99 assert_se(streq(*i, a[k++]));
100 }
101
f73141d7
LP
102 r = parse_env_file(
103 t, NULL,
104 "one", &one,
105 "two", &two,
106 "three", &three,
107 "four", &four,
108 "five", &five,
109 "six", &six,
110 "seven", &seven,
db537209 111 "eight", &eight,
ebc05a09
HH
112 "export nine", &nine,
113 "ten", &ten,
f73141d7
LP
114 NULL);
115
116 assert_se(r >= 0);
117
118 log_info("one=[%s]", strna(one));
119 log_info("two=[%s]", strna(two));
120 log_info("three=[%s]", strna(three));
121 log_info("four=[%s]", strna(four));
122 log_info("five=[%s]", strna(five));
123 log_info("six=[%s]", strna(six));
124 log_info("seven=[%s]", strna(seven));
db537209 125 log_info("eight=[%s]", strna(eight));
ebc05a09
HH
126 log_info("export nine=[%s]", strna(nine));
127 log_info("ten=[%s]", strna(nine));
f73141d7
LP
128
129 assert_se(streq(one, "BAR"));
130 assert_se(streq(two, "bar"));
131 assert_se(streq(three, "333\nxxxx"));
132 assert_se(streq(four, "44\"44"));
133 assert_se(streq(five, "55\'55FIVEcinco"));
134 assert_se(streq(six, "seis sechs sis"));
98f59e59
HH
135 assert_se(streq(seven, "sevenval#nocomment"));
136 assert_se(streq(eight, "eightval #nocomment"));
ebc05a09
HH
137 assert_se(streq(nine, "nineval"));
138 assert_se(ten == NULL);
f73141d7 139
095b30cb 140 r = write_env_file(p, a);
98f59e59
HH
141 assert_se(r >= 0);
142
717603e3 143 r = load_env_file(NULL, p, NULL, &b);
98f59e59
HH
144 assert_se(r >= 0);
145
f73141d7 146 unlink(t);
095b30cb 147 unlink(p);
f73141d7
LP
148}
149
ac4c8d6d
ZJS
150static void test_parse_multiline_env_file(void) {
151 char t[] = "/tmp/test-fileio-in-XXXXXX",
152 p[] = "/tmp/test-fileio-out-XXXXXX";
153 int fd, r;
154 FILE *f;
155 _cleanup_strv_free_ char **a = NULL, **b = NULL;
156 char **i;
157
2d5bdf5b 158 fd = mkostemp_safe(p, O_RDWR|O_CLOEXEC);
d514feaa
TA
159 assert_se(fd >= 0);
160 close(fd);
ac4c8d6d 161
2d5bdf5b 162 fd = mkostemp_safe(t, O_RDWR|O_CLOEXEC);
ac4c8d6d
ZJS
163 assert_se(fd >= 0);
164
165 f = fdopen(fd, "w");
166 assert_se(f);
167
168 fputs("one=BAR\\\n"
169 " VAR\\\n"
170 "\tGAR\n"
171 "#comment\n"
172 "two=\"bar\\\n"
173 " var\\\n"
174 "\tgar\"\n"
175 "#comment\n"
176 "tri=\"bar \\\n"
177 " var \\\n"
178 "\tgar \"\n", f);
179
180 fflush(f);
181 fclose(f);
182
717603e3 183 r = load_env_file(NULL, t, NULL, &a);
ac4c8d6d
ZJS
184 assert_se(r >= 0);
185
186 STRV_FOREACH(i, a)
187 log_info("Got: <%s>", *i);
188
5fba7bbf
TA
189 assert_se(streq_ptr(a[0], "one=BAR VAR\tGAR"));
190 assert_se(streq_ptr(a[1], "two=bar var\tgar"));
191 assert_se(streq_ptr(a[2], "tri=bar var \tgar "));
ac4c8d6d
ZJS
192 assert_se(a[3] == NULL);
193
194 r = write_env_file(p, a);
195 assert_se(r >= 0);
196
717603e3 197 r = load_env_file(NULL, p, NULL, &b);
ac4c8d6d
ZJS
198 assert_se(r >= 0);
199
200 unlink(t);
201 unlink(p);
202}
203
204
68fee104
ZJS
205static void test_executable_is_script(void) {
206 char t[] = "/tmp/test-executable-XXXXXX";
207 int fd, r;
208 FILE *f;
209 char *command;
210
2d5bdf5b 211 fd = mkostemp_safe(t, O_RDWR|O_CLOEXEC);
68fee104
ZJS
212 assert_se(fd >= 0);
213
214 f = fdopen(fd, "w");
215 assert_se(f);
216
217 fputs("#! /bin/script -a -b \ngoo goo", f);
218 fflush(f);
219
220 r = executable_is_script(t, &command);
221 assert_se(r > 0);
222 assert_se(streq(command, "/bin/script"));
223 free(command);
224
225 r = executable_is_script("/bin/sh", &command);
226 assert_se(r == 0);
227
228 r = executable_is_script("/usr/bin/yum", &command);
229 assert_se(r > 0 || r == -ENOENT);
230 if (r > 0) {
231 assert_se(startswith(command, "/"));
232 free(command);
233 }
234
235 fclose(f);
236 unlink(t);
237}
238
69ab8088 239static void test_status_field(void) {
1e5413f7
ZJS
240 _cleanup_free_ char *t = NULL, *p = NULL, *s = NULL, *z = NULL;
241 unsigned long long total = 0, buffers = 0;
442e0083 242 int r;
69ab8088
ZJS
243
244 assert_se(get_status_field("/proc/self/status", "\nThreads:", &t) == 0);
245 puts(t);
246 assert_se(streq(t, "1"));
247
442e0083 248 r = get_status_field("/proc/meminfo", "MemTotal:", &p);
1e5413f7 249 if (r != -ENOENT) {
bdf7026e 250 assert_se(r == 0);
1e5413f7
ZJS
251 puts(p);
252 assert_se(safe_atollu(p, &total) == 0);
253 }
69ab8088 254
d8a11003 255 r = get_status_field("/proc/meminfo", "\nBuffers:", &s);
1e5413f7 256 if (r != -ENOENT) {
bdf7026e 257 assert_se(r == 0);
1e5413f7
ZJS
258 puts(s);
259 assert_se(safe_atollu(s, &buffers) == 0);
260 }
69ab8088 261
2b01a801 262 if (p)
bdf7026e 263 assert_se(buffers < total);
1e5413f7
ZJS
264
265 /* Seccomp should be a good test for field full of zeros. */
266 r = get_status_field("/proc/meminfo", "\nSeccomp:", &z);
267 if (r != -ENOENT) {
bdf7026e 268 assert_se(r == 0);
1e5413f7
ZJS
269 puts(z);
270 assert_se(safe_atollu(z, &buffers) == 0);
271 }
272}
273
274static void test_capeff(void) {
275 int pid, p;
276
277 for (pid = 0; pid < 2; pid++) {
278 _cleanup_free_ char *capeff = NULL;
279 int r;
280
281 r = get_process_capeff(0, &capeff);
282 log_info("capeff: '%s' (r=%d)", capeff, r);
283
284 if (r == -ENOENT || r == -EPERM)
285 return;
286
bdf7026e
TA
287 assert_se(r == 0);
288 assert_se(*capeff);
1e5413f7 289 p = capeff[strspn(capeff, DIGITS "abcdefABCDEF")];
bdf7026e 290 assert_se(!p || isspace(p));
1e5413f7 291 }
69ab8088
ZJS
292}
293
0709b743
RC
294static void test_write_string_stream(void) {
295 char fn[] = "/tmp/test-write_string_stream-XXXXXX";
296 _cleanup_fclose_ FILE *f = NULL;
297 int fd;
298 char buf[64];
299
300 fd = mkostemp_safe(fn, O_RDWR);
301 assert_se(fd >= 0);
302
303 f = fdopen(fd, "r");
304 assert_se(f);
305 assert_se(write_string_stream(f, "boohoo") < 0);
306
76082570 307 f = freopen(fn, "r+", f);
0709b743
RC
308 assert_se(f);
309
310 assert_se(write_string_stream(f, "boohoo") == 0);
311 rewind(f);
312
313 assert_se(fgets(buf, sizeof(buf), f));
314 assert_se(streq(buf, "boohoo\n"));
315
316 unlink(fn);
317}
318
319static void test_write_string_file(void) {
320 char fn[] = "/tmp/test-write_string_file-XXXXXX";
76082570
RC
321 char buf[64] = {};
322 _cleanup_close_ int fd;
0709b743
RC
323
324 fd = mkostemp_safe(fn, O_RDWR);
325 assert_se(fd >= 0);
326
327 assert_se(write_string_file(fn, "boohoo") == 0);
328
cca0efb0 329 assert_se(read(fd, buf, sizeof(buf)) == 7);
0709b743
RC
330 assert_se(streq(buf, "boohoo\n"));
331
332 unlink(fn);
333}
334
e07995a3
RC
335static void test_write_string_file_no_create(void) {
336 char fn[] = "/tmp/test-write_string_file_no_create-XXXXXX";
337 _cleanup_close_ int fd;
338 char buf[64] = {0};
339
340 fd = mkostemp_safe(fn, O_RDWR);
341 assert_se(fd >= 0);
342
343 assert_se(write_string_file_no_create("/a/file/which/does/not/exists/i/guess", "boohoo") < 0);
344 assert_se(write_string_file_no_create(fn, "boohoo") == 0);
345
696c24fc 346 assert_se(read(fd, buf, sizeof(buf)) == strlen("boohoo\n"));
e07995a3
RC
347 assert_se(streq(buf, "boohoo\n"));
348
349 unlink(fn);
350}
351
e07995a3
RC
352static void test_load_env_file_pairs(void) {
353 char fn[] = "/tmp/test-load_env_file_pairs-XXXXXX";
354 int fd;
355 int r;
356 _cleanup_fclose_ FILE *f = NULL;
357 _cleanup_strv_free_ char **l = NULL;
358 char **k, **v;
359
360 fd = mkostemp_safe(fn, O_RDWR);
361 assert_se(fd >= 0);
362
363 r = write_string_file(fn,
364 "NAME=\"Arch Linux\"\n"
365 "ID=arch\n"
366 "PRETTY_NAME=\"Arch Linux\"\n"
367 "ANSI_COLOR=\"0;36\"\n"
368 "HOME_URL=\"https://www.archlinux.org/\"\n"
369 "SUPPORT_URL=\"https://bbs.archlinux.org/\"\n"
370 "BUG_REPORT_URL=\"https://bugs.archlinux.org/\"\n"
371 );
372 assert_se(r == 0);
373
374 f = fdopen(fd, "r");
375 assert_se(f);
376
377 r = load_env_file_pairs(f, fn, NULL, &l);
378 assert_se(r >= 0);
379
380 assert_se(strv_length(l) == 14);
381 STRV_FOREACH_PAIR(k, v, l) {
382 assert_se(STR_IN_SET(*k, "NAME", "ID", "PRETTY_NAME", "ANSI_COLOR", "HOME_URL", "SUPPORT_URL", "BUG_REPORT_URL"));
383 printf("%s=%s\n", *k, *v);
384 if (streq(*k, "NAME")) assert_se(streq(*v, "Arch Linux"));
385 if (streq(*k, "ID")) assert_se(streq(*v, "arch"));
386 if (streq(*k, "PRETTY_NAME")) assert_se(streq(*v, "Arch Linux"));
387 if (streq(*k, "ANSI_COLOR")) assert_se(streq(*v, "0;36"));
388 if (streq(*k, "HOME_URL")) assert_se(streq(*v, "https://www.archlinux.org/"));
389 if (streq(*k, "SUPPORT_URL")) assert_se(streq(*v, "https://bbs.archlinux.org/"));
390 if (streq(*k, "BUG_REPORT_URL")) assert_se(streq(*v, "https://bugs.archlinux.org/"));
391 }
392
393 unlink(fn);
394}
395
f73141d7 396int main(int argc, char *argv[]) {
1e5413f7
ZJS
397 log_parse_environment();
398 log_open();
399
f73141d7 400 test_parse_env_file();
ac4c8d6d 401 test_parse_multiline_env_file();
68fee104 402 test_executable_is_script();
69ab8088 403 test_status_field();
1e5413f7 404 test_capeff();
0709b743
RC
405 test_write_string_stream();
406 test_write_string_file();
e07995a3 407 test_write_string_file_no_create();
e07995a3 408 test_load_env_file_pairs();
1e5413f7 409
f73141d7
LP
410 return 0;
411}