]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/test/test-fileio.c
fileio: consolidate write_string_file*()
[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);
40beecdb 305 assert_se(write_string_stream(f, "boohoo", true) < 0);
0709b743 306
76082570 307 f = freopen(fn, "r+", f);
0709b743
RC
308 assert_se(f);
309
40beecdb 310 assert_se(write_string_stream(f, "boohoo", true) == 0);
0709b743
RC
311 rewind(f);
312
313 assert_se(fgets(buf, sizeof(buf), f));
314 assert_se(streq(buf, "boohoo\n"));
315
40beecdb
DM
316 f = freopen(fn, "w+", f);
317 assert_se(f);
318
319 assert_se(write_string_stream(f, "boohoo", false) == 0);
320 rewind(f);
321
322 assert_se(fgets(buf, sizeof(buf), f));
323 printf(">%s<", buf);
324 assert_se(streq(buf, "boohoo"));
325
0709b743
RC
326 unlink(fn);
327}
328
329static void test_write_string_file(void) {
330 char fn[] = "/tmp/test-write_string_file-XXXXXX";
76082570
RC
331 char buf[64] = {};
332 _cleanup_close_ int fd;
0709b743
RC
333
334 fd = mkostemp_safe(fn, O_RDWR);
335 assert_se(fd >= 0);
336
4c1fc3e4 337 assert_se(write_string_file(fn, "boohoo", WRITE_STRING_FILE_CREATE) == 0);
0709b743 338
cca0efb0 339 assert_se(read(fd, buf, sizeof(buf)) == 7);
0709b743
RC
340 assert_se(streq(buf, "boohoo\n"));
341
342 unlink(fn);
343}
344
e07995a3
RC
345static void test_write_string_file_no_create(void) {
346 char fn[] = "/tmp/test-write_string_file_no_create-XXXXXX";
347 _cleanup_close_ int fd;
348 char buf[64] = {0};
349
350 fd = mkostemp_safe(fn, O_RDWR);
351 assert_se(fd >= 0);
352
4c1fc3e4
DM
353 assert_se(write_string_file("/a/file/which/does/not/exists/i/guess", "boohoo", 0) < 0);
354 assert_se(write_string_file(fn, "boohoo", 0) == 0);
e07995a3 355
696c24fc 356 assert_se(read(fd, buf, sizeof(buf)) == strlen("boohoo\n"));
e07995a3
RC
357 assert_se(streq(buf, "boohoo\n"));
358
359 unlink(fn);
360}
361
e07995a3
RC
362static void test_load_env_file_pairs(void) {
363 char fn[] = "/tmp/test-load_env_file_pairs-XXXXXX";
364 int fd;
365 int r;
366 _cleanup_fclose_ FILE *f = NULL;
367 _cleanup_strv_free_ char **l = NULL;
368 char **k, **v;
369
370 fd = mkostemp_safe(fn, O_RDWR);
371 assert_se(fd >= 0);
372
373 r = write_string_file(fn,
374 "NAME=\"Arch Linux\"\n"
375 "ID=arch\n"
376 "PRETTY_NAME=\"Arch Linux\"\n"
377 "ANSI_COLOR=\"0;36\"\n"
378 "HOME_URL=\"https://www.archlinux.org/\"\n"
379 "SUPPORT_URL=\"https://bbs.archlinux.org/\"\n"
4c1fc3e4
DM
380 "BUG_REPORT_URL=\"https://bugs.archlinux.org/\"\n",
381 WRITE_STRING_FILE_CREATE);
e07995a3
RC
382 assert_se(r == 0);
383
384 f = fdopen(fd, "r");
385 assert_se(f);
386
387 r = load_env_file_pairs(f, fn, NULL, &l);
388 assert_se(r >= 0);
389
390 assert_se(strv_length(l) == 14);
391 STRV_FOREACH_PAIR(k, v, l) {
392 assert_se(STR_IN_SET(*k, "NAME", "ID", "PRETTY_NAME", "ANSI_COLOR", "HOME_URL", "SUPPORT_URL", "BUG_REPORT_URL"));
393 printf("%s=%s\n", *k, *v);
394 if (streq(*k, "NAME")) assert_se(streq(*v, "Arch Linux"));
395 if (streq(*k, "ID")) assert_se(streq(*v, "arch"));
396 if (streq(*k, "PRETTY_NAME")) assert_se(streq(*v, "Arch Linux"));
397 if (streq(*k, "ANSI_COLOR")) assert_se(streq(*v, "0;36"));
398 if (streq(*k, "HOME_URL")) assert_se(streq(*v, "https://www.archlinux.org/"));
399 if (streq(*k, "SUPPORT_URL")) assert_se(streq(*v, "https://bbs.archlinux.org/"));
400 if (streq(*k, "BUG_REPORT_URL")) assert_se(streq(*v, "https://bugs.archlinux.org/"));
401 }
402
403 unlink(fn);
404}
405
f73141d7 406int main(int argc, char *argv[]) {
1e5413f7
ZJS
407 log_parse_environment();
408 log_open();
409
f73141d7 410 test_parse_env_file();
ac4c8d6d 411 test_parse_multiline_env_file();
68fee104 412 test_executable_is_script();
69ab8088 413 test_status_field();
1e5413f7 414 test_capeff();
0709b743
RC
415 test_write_string_stream();
416 test_write_string_file();
e07995a3 417 test_write_string_file_no_create();
e07995a3 418 test_load_env_file_pairs();
1e5413f7 419
f73141d7
LP
420 return 0;
421}