]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/fileio.c
execute: Properly log errors considering socket fds (#5910)
[thirdparty/systemd.git] / src / basic / fileio.c
CommitLineData
a5c32cff
HH
1/***
2 This file is part of systemd.
3
4 Copyright 2010 Lennart Poettering
5
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18***/
19
11c3a366
TA
20#include <errno.h>
21#include <fcntl.h>
22#include <limits.h>
23#include <stdarg.h>
24#include <stdint.h>
25#include <stdlib.h>
26#include <string.h>
27#include <sys/stat.h>
28#include <sys/types.h>
a5c32cff 29#include <unistd.h>
cda134ab 30
b5efdb8a 31#include "alloc-util.h"
4f5dd394 32#include "ctype.h"
99003e01 33#include "env-util.h"
4f5dd394 34#include "escape.h"
3ffd4af2
LP
35#include "fd-util.h"
36#include "fileio.h"
f4f15635 37#include "fs-util.h"
0d39fa9c 38#include "hexdecoct.h"
93cc7779
TA
39#include "log.h"
40#include "macro.h"
1d9ed171 41#include "missing.h"
33d52ab9 42#include "parse-util.h"
0d39fa9c
LP
43#include "path-util.h"
44#include "random-util.h"
33d52ab9 45#include "stdio-util.h"
07630cea 46#include "string-util.h"
a5c32cff 47#include "strv.h"
93cc7779 48#include "time-util.h"
affb60b1 49#include "umask-util.h"
335c46b5 50#include "utf8.h"
a5c32cff 51
c2d11a63
VC
52#define READ_FULL_BYTES_MAX (4U*1024U*1024U)
53
40beecdb 54int write_string_stream(FILE *f, const char *line, bool enforce_newline) {
dacd6cee 55
717603e3
LP
56 assert(f);
57 assert(line);
58
fec6fc6b 59 fputs(line, f);
40beecdb 60 if (enforce_newline && !endswith(line, "\n"))
a5c32cff
HH
61 fputc('\n', f);
62
dacd6cee 63 return fflush_and_check(f);
a5c32cff
HH
64}
65
4c1fc3e4 66static int write_string_file_atomic(const char *fn, const char *line, bool enforce_newline) {
a5c32cff
HH
67 _cleanup_fclose_ FILE *f = NULL;
68 _cleanup_free_ char *p = NULL;
69 int r;
70
71 assert(fn);
72 assert(line);
73
74 r = fopen_temporary(fn, &f, &p);
75 if (r < 0)
76 return r;
77
0d39fa9c 78 (void) fchmod_umask(fileno(f), 0644);
a5c32cff 79
4c1fc3e4 80 r = write_string_stream(f, line, enforce_newline);
f2997962 81 if (r >= 0) {
a5c32cff
HH
82 if (rename(p, fn) < 0)
83 r = -errno;
a5c32cff
HH
84 }
85
a5c32cff 86 if (r < 0)
0d39fa9c 87 (void) unlink(p);
a5c32cff
HH
88
89 return r;
90}
91
4c1fc3e4
DM
92int write_string_file(const char *fn, const char *line, WriteStringFileFlags flags) {
93 _cleanup_fclose_ FILE *f = NULL;
eb3da901 94 int q, r;
4c1fc3e4
DM
95
96 assert(fn);
97 assert(line);
98
99 if (flags & WRITE_STRING_FILE_ATOMIC) {
100 assert(flags & WRITE_STRING_FILE_CREATE);
101
eb3da901
LP
102 r = write_string_file_atomic(fn, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE));
103 if (r < 0)
104 goto fail;
105
106 return r;
4c1fc3e4
DM
107 }
108
109 if (flags & WRITE_STRING_FILE_CREATE) {
110 f = fopen(fn, "we");
eb3da901
LP
111 if (!f) {
112 r = -errno;
113 goto fail;
114 }
4c1fc3e4
DM
115 } else {
116 int fd;
117
118 /* We manually build our own version of fopen(..., "we") that
119 * works without O_CREAT */
120 fd = open(fn, O_WRONLY|O_CLOEXEC|O_NOCTTY);
eb3da901
LP
121 if (fd < 0) {
122 r = -errno;
123 goto fail;
124 }
4c1fc3e4
DM
125
126 f = fdopen(fd, "we");
127 if (!f) {
eb3da901 128 r = -errno;
4c1fc3e4 129 safe_close(fd);
eb3da901 130 goto fail;
4c1fc3e4
DM
131 }
132 }
133
eb3da901
LP
134 r = write_string_stream(f, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE));
135 if (r < 0)
136 goto fail;
137
138 return 0;
139
140fail:
141 if (!(flags & WRITE_STRING_FILE_VERIFY_ON_FAILURE))
142 return r;
143
144 f = safe_fclose(f);
145
146 /* OK, the operation failed, but let's see if the right
147 * contents in place already. If so, eat up the error. */
148
149 q = verify_file(fn, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE));
150 if (q <= 0)
151 return r;
152
153 return 0;
4c1fc3e4
DM
154}
155
a5c32cff
HH
156int read_one_line_file(const char *fn, char **line) {
157 _cleanup_fclose_ FILE *f = NULL;
158 char t[LINE_MAX], *c;
159
160 assert(fn);
161 assert(line);
162
163 f = fopen(fn, "re");
164 if (!f)
165 return -errno;
166
167 if (!fgets(t, sizeof(t), f)) {
168
169 if (ferror(f))
f5e5c28f 170 return errno > 0 ? -errno : -EIO;
a5c32cff
HH
171
172 t[0] = 0;
173 }
174
175 c = strdup(t);
176 if (!c)
177 return -ENOMEM;
178 truncate_nl(c);
179
180 *line = c;
181 return 0;
182}
183
eb3da901
LP
184int verify_file(const char *fn, const char *blob, bool accept_extra_nl) {
185 _cleanup_fclose_ FILE *f = NULL;
186 _cleanup_free_ char *buf = NULL;
187 size_t l, k;
15dee3f0 188
eb3da901
LP
189 assert(fn);
190 assert(blob);
191
192 l = strlen(blob);
193
194 if (accept_extra_nl && endswith(blob, "\n"))
195 accept_extra_nl = false;
196
197 buf = malloc(l + accept_extra_nl + 1);
198 if (!buf)
199 return -ENOMEM;
200
201 f = fopen(fn, "re");
202 if (!f)
203 return -errno;
204
205 /* We try to read one byte more than we need, so that we know whether we hit eof */
206 errno = 0;
207 k = fread(buf, 1, l + accept_extra_nl + 1, f);
208 if (ferror(f))
209 return errno > 0 ? -errno : -EIO;
210
211 if (k != l && k != l + accept_extra_nl)
212 return 0;
213 if (memcmp(buf, blob, l) != 0)
214 return 0;
215 if (k > l && buf[l] != '\n')
216 return 0;
15dee3f0 217
eb3da901 218 return 1;
15dee3f0
LP
219}
220
717603e3 221int read_full_stream(FILE *f, char **contents, size_t *size) {
a5c32cff
HH
222 size_t n, l;
223 _cleanup_free_ char *buf = NULL;
224 struct stat st;
225
717603e3 226 assert(f);
a5c32cff
HH
227 assert(contents);
228
a5c32cff
HH
229 if (fstat(fileno(f), &st) < 0)
230 return -errno;
231
717603e3 232 n = LINE_MAX;
a5c32cff 233
717603e3
LP
234 if (S_ISREG(st.st_mode)) {
235
236 /* Safety check */
c2d11a63 237 if (st.st_size > READ_FULL_BYTES_MAX)
717603e3
LP
238 return -E2BIG;
239
240 /* Start with the right file size, but be prepared for
241 * files from /proc which generally report a file size
242 * of 0 */
243 if (st.st_size > 0)
244 n = st.st_size;
245 }
a5c32cff 246
717603e3 247 l = 0;
a5c32cff
HH
248 for (;;) {
249 char *t;
250 size_t k;
251
c2d11a63 252 t = realloc(buf, n + 1);
a5c32cff
HH
253 if (!t)
254 return -ENOMEM;
255
256 buf = t;
257 k = fread(buf + l, 1, n - l, f);
c2d11a63
VC
258 if (k > 0)
259 l += k;
a5c32cff 260
c2d11a63
VC
261 if (ferror(f))
262 return -errno;
a5c32cff 263
c2d11a63 264 if (feof(f))
a5c32cff 265 break;
a5c32cff 266
c2d11a63
VC
267 /* We aren't expecting fread() to return a short read outside
268 * of (error && eof), assert buffer is full and enlarge buffer.
269 */
270 assert(l == n);
a5c32cff
HH
271
272 /* Safety check */
c2d11a63 273 if (n >= READ_FULL_BYTES_MAX)
a5c32cff 274 return -E2BIG;
c2d11a63 275
82b103a7 276 n = MIN(n * 2, READ_FULL_BYTES_MAX);
a5c32cff
HH
277 }
278
279 buf[l] = 0;
280 *contents = buf;
d78a28e3 281 buf = NULL; /* do not free */
a5c32cff
HH
282
283 if (size)
284 *size = l;
285
286 return 0;
287}
288
717603e3
LP
289int read_full_file(const char *fn, char **contents, size_t *size) {
290 _cleanup_fclose_ FILE *f = NULL;
291
292 assert(fn);
293 assert(contents);
294
295 f = fopen(fn, "re");
296 if (!f)
297 return -errno;
298
299 return read_full_stream(f, contents, size);
300}
301
f73141d7 302static int parse_env_file_internal(
717603e3 303 FILE *f,
a5c32cff 304 const char *fname,
f73141d7 305 const char *newline,
335c46b5 306 int (*push) (const char *filename, unsigned line,
a5f6c30d
MS
307 const char *key, char *value, void *userdata, int *n_pushed),
308 void *userdata,
309 int *n_pushed) {
f73141d7
LP
310
311 _cleanup_free_ char *contents = NULL, *key = NULL;
2b77f67e 312 size_t key_alloc = 0, n_key = 0, value_alloc = 0, n_value = 0, last_value_whitespace = (size_t) -1, last_key_whitespace = (size_t) -1;
f73141d7
LP
313 char *p, *value = NULL;
314 int r;
335c46b5 315 unsigned line = 1;
a5c32cff 316
f73141d7
LP
317 enum {
318 PRE_KEY,
319 KEY,
f73141d7
LP
320 PRE_VALUE,
321 VALUE,
322 VALUE_ESCAPE,
323 SINGLE_QUOTE_VALUE,
324 SINGLE_QUOTE_VALUE_ESCAPE,
325 DOUBLE_QUOTE_VALUE,
326 DOUBLE_QUOTE_VALUE_ESCAPE,
327 COMMENT,
328 COMMENT_ESCAPE
329 } state = PRE_KEY;
a5c32cff 330
f73141d7 331 assert(newline);
a5c32cff 332
717603e3
LP
333 if (f)
334 r = read_full_stream(f, &contents, NULL);
335 else
336 r = read_full_file(fname, &contents, NULL);
1c17cbed 337 if (r < 0)
a5c32cff
HH
338 return r;
339
f73141d7
LP
340 for (p = contents; *p; p++) {
341 char c = *p;
342
343 switch (state) {
344
345 case PRE_KEY:
ebc05a09 346 if (strchr(COMMENTS, c))
f73141d7
LP
347 state = COMMENT;
348 else if (!strchr(WHITESPACE, c)) {
349 state = KEY;
2b77f67e
LP
350 last_key_whitespace = (size_t) -1;
351
ca2d3784 352 if (!GREEDY_REALLOC(key, key_alloc, n_key+2)) {
f73141d7
LP
353 r = -ENOMEM;
354 goto fail;
355 }
356
357 key[n_key++] = c;
358 }
359 break;
360
361 case KEY:
362 if (strchr(newline, c)) {
363 state = PRE_KEY;
313cefa1 364 line++;
f73141d7 365 n_key = 0;
2b77f67e 366 } else if (c == '=') {
f73141d7 367 state = PRE_VALUE;
2b77f67e
LP
368 last_value_whitespace = (size_t) -1;
369 } else {
370 if (!strchr(WHITESPACE, c))
371 last_key_whitespace = (size_t) -1;
372 else if (last_key_whitespace == (size_t) -1)
373 last_key_whitespace = n_key;
374
ca2d3784 375 if (!GREEDY_REALLOC(key, key_alloc, n_key+2)) {
f73141d7
LP
376 r = -ENOMEM;
377 goto fail;
378 }
379
380 key[n_key++] = c;
381 }
a5c32cff 382
f73141d7
LP
383 break;
384
f73141d7 385 case PRE_VALUE:
98f59e59 386 if (strchr(newline, c)) {
f73141d7 387 state = PRE_KEY;
313cefa1 388 line++;
f73141d7 389 key[n_key] = 0;
a5c32cff 390
f73141d7
LP
391 if (value)
392 value[n_value] = 0;
a5c32cff 393
ebc05a09 394 /* strip trailing whitespace from key */
2b77f67e
LP
395 if (last_key_whitespace != (size_t) -1)
396 key[last_key_whitespace] = 0;
ebc05a09 397
a5f6c30d 398 r = push(fname, line, key, value, userdata, n_pushed);
f73141d7
LP
399 if (r < 0)
400 goto fail;
401
402 n_key = 0;
403 value = NULL;
404 value_alloc = n_value = 0;
2b77f67e 405
f73141d7
LP
406 } else if (c == '\'')
407 state = SINGLE_QUOTE_VALUE;
408 else if (c == '\"')
409 state = DOUBLE_QUOTE_VALUE;
410 else if (c == '\\')
411 state = VALUE_ESCAPE;
412 else if (!strchr(WHITESPACE, c)) {
413 state = VALUE;
414
ca2d3784 415 if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
f73141d7
LP
416 r = -ENOMEM;
417 goto fail;
418 }
419
420 value[n_value++] = c;
421 }
422
423 break;
424
425 case VALUE:
426 if (strchr(newline, c)) {
427 state = PRE_KEY;
313cefa1 428 line++;
98f59e59 429
f73141d7
LP
430 key[n_key] = 0;
431
432 if (value)
433 value[n_value] = 0;
434
2b77f67e
LP
435 /* Chomp off trailing whitespace from value */
436 if (last_value_whitespace != (size_t) -1)
437 value[last_value_whitespace] = 0;
f73141d7 438
ebc05a09 439 /* strip trailing whitespace from key */
2b77f67e
LP
440 if (last_key_whitespace != (size_t) -1)
441 key[last_key_whitespace] = 0;
ebc05a09 442
a5f6c30d 443 r = push(fname, line, key, value, userdata, n_pushed);
f73141d7
LP
444 if (r < 0)
445 goto fail;
446
447 n_key = 0;
448 value = NULL;
449 value_alloc = n_value = 0;
2b77f67e 450
f73141d7
LP
451 } else if (c == '\\') {
452 state = VALUE_ESCAPE;
2b77f67e 453 last_value_whitespace = (size_t) -1;
f73141d7
LP
454 } else {
455 if (!strchr(WHITESPACE, c))
2b77f67e
LP
456 last_value_whitespace = (size_t) -1;
457 else if (last_value_whitespace == (size_t) -1)
458 last_value_whitespace = n_value;
f73141d7 459
ca2d3784 460 if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
f73141d7
LP
461 r = -ENOMEM;
462 goto fail;
463 }
464
465 value[n_value++] = c;
466 }
467
468 break;
469
470 case VALUE_ESCAPE:
471 state = VALUE;
472
473 if (!strchr(newline, c)) {
474 /* Escaped newlines we eat up entirely */
ca2d3784 475 if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
f73141d7
LP
476 r = -ENOMEM;
477 goto fail;
478 }
479
480 value[n_value++] = c;
481 }
482 break;
483
484 case SINGLE_QUOTE_VALUE:
485 if (c == '\'')
486 state = PRE_VALUE;
487 else if (c == '\\')
488 state = SINGLE_QUOTE_VALUE_ESCAPE;
489 else {
ca2d3784 490 if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
f73141d7
LP
491 r = -ENOMEM;
492 goto fail;
493 }
a5c32cff 494
f73141d7
LP
495 value[n_value++] = c;
496 }
a5c32cff 497
f73141d7 498 break;
a5c32cff 499
f73141d7
LP
500 case SINGLE_QUOTE_VALUE_ESCAPE:
501 state = SINGLE_QUOTE_VALUE;
a5c32cff 502
f73141d7 503 if (!strchr(newline, c)) {
ca2d3784 504 if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
a5c32cff 505 r = -ENOMEM;
a5c32cff
HH
506 goto fail;
507 }
508
f73141d7
LP
509 value[n_value++] = c;
510 }
511 break;
512
513 case DOUBLE_QUOTE_VALUE:
514 if (c == '\"')
515 state = PRE_VALUE;
516 else if (c == '\\')
517 state = DOUBLE_QUOTE_VALUE_ESCAPE;
518 else {
ca2d3784 519 if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
f73141d7
LP
520 r = -ENOMEM;
521 goto fail;
a5c32cff
HH
522 }
523
f73141d7
LP
524 value[n_value++] = c;
525 }
526
527 break;
528
529 case DOUBLE_QUOTE_VALUE_ESCAPE:
530 state = DOUBLE_QUOTE_VALUE;
a5c32cff 531
f73141d7 532 if (!strchr(newline, c)) {
ca2d3784 533 if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
f73141d7
LP
534 r = -ENOMEM;
535 goto fail;
536 }
a5c32cff 537
f73141d7 538 value[n_value++] = c;
a5c32cff 539 }
f73141d7
LP
540 break;
541
542 case COMMENT:
543 if (c == '\\')
544 state = COMMENT_ESCAPE;
335c46b5 545 else if (strchr(newline, c)) {
f73141d7 546 state = PRE_KEY;
313cefa1 547 line++;
335c46b5 548 }
f73141d7
LP
549 break;
550
551 case COMMENT_ESCAPE:
552 state = COMMENT;
553 break;
a5c32cff 554 }
f73141d7
LP
555 }
556
371328dc
ZJS
557 if (IN_SET(state,
558 PRE_VALUE,
559 VALUE,
560 VALUE_ESCAPE,
561 SINGLE_QUOTE_VALUE,
562 SINGLE_QUOTE_VALUE_ESCAPE,
563 DOUBLE_QUOTE_VALUE,
564 DOUBLE_QUOTE_VALUE_ESCAPE)) {
a5c32cff 565
f73141d7
LP
566 key[n_key] = 0;
567
568 if (value)
569 value[n_value] = 0;
570
2b77f67e
LP
571 if (state == VALUE)
572 if (last_value_whitespace != (size_t) -1)
573 value[last_value_whitespace] = 0;
574
ebc05a09 575 /* strip trailing whitespace from key */
2b77f67e
LP
576 if (last_key_whitespace != (size_t) -1)
577 key[last_key_whitespace] = 0;
ebc05a09 578
a5f6c30d 579 r = push(fname, line, key, value, userdata, n_pushed);
f73141d7
LP
580 if (r < 0)
581 goto fail;
a5c32cff
HH
582 }
583
f73141d7
LP
584 return 0;
585
a5c32cff 586fail:
f73141d7 587 free(value);
a5c32cff
HH
588 return r;
589}
590
ac466818 591static int check_utf8ness_and_warn(
717603e3 592 const char *filename, unsigned line,
ac466818 593 const char *key, char *value) {
f27f0e21
GB
594
595 if (!utf8_is_valid(key)) {
3587161a 596 _cleanup_free_ char *p = NULL;
550a40ec 597
717603e3
LP
598 p = utf8_escape_invalid(key);
599 log_error("%s:%u: invalid UTF-8 in key '%s', ignoring.", strna(filename), line, p);
f27f0e21
GB
600 return -EINVAL;
601 }
602
603 if (value && !utf8_is_valid(value)) {
3587161a 604 _cleanup_free_ char *p = NULL;
550a40ec 605
717603e3
LP
606 p = utf8_escape_invalid(value);
607 log_error("%s:%u: invalid UTF-8 value for key %s: '%s', ignoring.", strna(filename), line, key, p);
f27f0e21
GB
608 return -EINVAL;
609 }
a5c32cff 610
ac466818
ZJS
611 return 0;
612}
613
614static int parse_env_file_push(
615 const char *filename, unsigned line,
616 const char *key, char *value,
617 void *userdata,
618 int *n_pushed) {
619
620 const char *k;
621 va_list aq, *ap = userdata;
622 int r;
623
624 r = check_utf8ness_and_warn(filename, line, key, value);
625 if (r < 0)
626 return r;
627
f27f0e21 628 va_copy(aq, *ap);
a5c32cff 629
f27f0e21
GB
630 while ((k = va_arg(aq, const char *))) {
631 char **v;
a5c32cff 632
f27f0e21 633 v = va_arg(aq, char **);
a5c32cff 634
f27f0e21
GB
635 if (streq(key, k)) {
636 va_end(aq);
637 free(*v);
638 *v = value;
a5f6c30d
MS
639
640 if (n_pushed)
641 (*n_pushed)++;
642
f27f0e21 643 return 1;
f73141d7 644 }
335c46b5 645 }
a5c32cff 646
f27f0e21 647 va_end(aq);
f73141d7 648 free(value);
717603e3 649
f73141d7
LP
650 return 0;
651}
a5c32cff 652
f73141d7
LP
653int parse_env_file(
654 const char *fname,
655 const char *newline, ...) {
a5c32cff 656
f73141d7 657 va_list ap;
a5f6c30d 658 int r, n_pushed = 0;
a5c32cff 659
f73141d7
LP
660 if (!newline)
661 newline = NEWLINE;
a5c32cff 662
f73141d7 663 va_start(ap, newline);
a5f6c30d 664 r = parse_env_file_internal(NULL, fname, newline, parse_env_file_push, &ap, &n_pushed);
f73141d7 665 va_end(ap);
a5c32cff 666
a5f6c30d 667 return r < 0 ? r : n_pushed;
f73141d7 668}
a5c32cff 669
717603e3
LP
670static int load_env_file_push(
671 const char *filename, unsigned line,
672 const char *key, char *value,
a5f6c30d
MS
673 void *userdata,
674 int *n_pushed) {
f27f0e21
GB
675 char ***m = userdata;
676 char *p;
677 int r;
a5c32cff 678
ac466818
ZJS
679 r = check_utf8ness_and_warn(filename, line, key, value);
680 if (r < 0)
681 return r;
a5c32cff 682
99003e01 683 p = strjoin(key, "=", value);
f27f0e21
GB
684 if (!p)
685 return -ENOMEM;
335c46b5 686
99003e01
ZJS
687 r = strv_env_replace(m, p);
688 if (r < 0) {
689 free(p);
f27f0e21 690 return r;
99003e01 691 }
a5c32cff 692
a5f6c30d
MS
693 if (n_pushed)
694 (*n_pushed)++;
695
f73141d7
LP
696 free(value);
697 return 0;
698}
699
717603e3
LP
700int load_env_file(FILE *f, const char *fname, const char *newline, char ***rl) {
701 char **m = NULL;
702 int r;
703
704 if (!newline)
705 newline = NEWLINE;
706
a5f6c30d 707 r = parse_env_file_internal(f, fname, newline, load_env_file_push, &m, NULL);
717603e3
LP
708 if (r < 0) {
709 strv_free(m);
710 return r;
711 }
712
713 *rl = m;
714 return 0;
715}
716
717static int load_env_file_push_pairs(
718 const char *filename, unsigned line,
719 const char *key, char *value,
a5f6c30d
MS
720 void *userdata,
721 int *n_pushed) {
717603e3
LP
722 char ***m = userdata;
723 int r;
724
ac466818
ZJS
725 r = check_utf8ness_and_warn(filename, line, key, value);
726 if (r < 0)
727 return r;
717603e3
LP
728
729 r = strv_extend(m, key);
730 if (r < 0)
731 return -ENOMEM;
732
733 if (!value) {
734 r = strv_extend(m, "");
735 if (r < 0)
736 return -ENOMEM;
737 } else {
738 r = strv_push(m, value);
739 if (r < 0)
740 return r;
741 }
742
a5f6c30d
MS
743 if (n_pushed)
744 (*n_pushed)++;
745
717603e3
LP
746 return 0;
747}
748
749int load_env_file_pairs(FILE *f, const char *fname, const char *newline, char ***rl) {
f73141d7
LP
750 char **m = NULL;
751 int r;
a5c32cff 752
f73141d7
LP
753 if (!newline)
754 newline = NEWLINE;
755
a5f6c30d 756 r = parse_env_file_internal(f, fname, newline, load_env_file_push_pairs, &m, NULL);
f73141d7
LP
757 if (r < 0) {
758 strv_free(m);
759 return r;
a5c32cff
HH
760 }
761
762 *rl = m;
a5c32cff
HH
763 return 0;
764}
765
37f3ffca
RS
766static int merge_env_file_push(
767 const char *filename, unsigned line,
768 const char *key, char *value,
769 void *userdata,
770 int *n_pushed) {
771
772 char ***env = userdata;
773 char *expanded_value;
774
775 assert(env);
776
184d1904
ZJS
777 if (!value) {
778 log_error("%s:%u: invalid syntax (around \"%s\"), ignoring.", strna(filename), line, key);
779 return 0;
780 }
781
782 if (!env_name_is_valid(key)) {
783 log_error("%s:%u: invalid variable name \"%s\", ignoring.", strna(filename), line, key);
2ea8081a 784 free(value);
184d1904
ZJS
785 return 0;
786 }
787
ccad1fd0 788 expanded_value = replace_env(value, *env,
b82f58bf
RS
789 REPLACE_ENV_USE_ENVIRONMENT|
790 REPLACE_ENV_ALLOW_BRACELESS|
791 REPLACE_ENV_ALLOW_EXTENDED);
37f3ffca
RS
792 if (!expanded_value)
793 return -ENOMEM;
794
795 free_and_replace(value, expanded_value);
796
797 return load_env_file_push(filename, line, key, value, env, n_pushed);
798}
799
800int merge_env_file(
801 char ***env,
802 FILE *f,
803 const char *fname) {
804
ccad1fd0 805 /* NOTE: this function supports braceful and braceless variable expansions,
b82f58bf 806 * plus "extended" substitutions, unlike other exported parsing functions.
ccad1fd0
ZJS
807 */
808
37f3ffca
RS
809 return parse_env_file_internal(f, fname, NEWLINE, merge_env_file_push, env, NULL);
810}
811
768100ef
LP
812static void write_env_var(FILE *f, const char *v) {
813 const char *p;
814
815 p = strchr(v, '=');
816 if (!p) {
817 /* Fallback */
818 fputs(v, f);
819 fputc('\n', f);
820 return;
821 }
822
823 p++;
824 fwrite(v, 1, p-v, f);
825
0ce5a806 826 if (string_has_cc(p, NULL) || chars_intersect(p, WHITESPACE SHELL_NEED_QUOTES)) {
768100ef
LP
827 fputc('\"', f);
828
829 for (; *p; p++) {
0ce5a806 830 if (strchr(SHELL_NEED_ESCAPE, *p))
768100ef
LP
831 fputc('\\', f);
832
833 fputc(*p, f);
834 }
835
836 fputc('\"', f);
837 } else
838 fputs(p, f);
839
840 fputc('\n', f);
841}
842
a5c32cff 843int write_env_file(const char *fname, char **l) {
7fd1b19b 844 _cleanup_fclose_ FILE *f = NULL;
736937e5
LP
845 _cleanup_free_ char *p = NULL;
846 char **i;
a5c32cff
HH
847 int r;
848
736937e5
LP
849 assert(fname);
850
a5c32cff
HH
851 r = fopen_temporary(fname, &f, &p);
852 if (r < 0)
853 return r;
854
855 fchmod_umask(fileno(f), 0644);
856
768100ef
LP
857 STRV_FOREACH(i, l)
858 write_env_var(f, *i);
a5c32cff 859
736937e5
LP
860 r = fflush_and_check(f);
861 if (r >= 0) {
862 if (rename(p, fname) >= 0)
863 return 0;
a5c32cff 864
736937e5 865 r = -errno;
a5c32cff
HH
866 }
867
736937e5 868 unlink(p);
a5c32cff
HH
869 return r;
870}
68fee104
ZJS
871
872int executable_is_script(const char *path, char **interpreter) {
873 int r;
c8b32e11 874 _cleanup_free_ char *line = NULL;
68fee104
ZJS
875 int len;
876 char *ans;
877
878 assert(path);
879
880 r = read_one_line_file(path, &line);
881 if (r < 0)
882 return r;
883
884 if (!startswith(line, "#!"))
885 return 0;
886
887 ans = strstrip(line + 2);
888 len = strcspn(ans, " \t");
889
890 if (len == 0)
891 return 0;
892
893 ans = strndup(ans, len);
894 if (!ans)
895 return -ENOMEM;
896
897 *interpreter = ans;
898 return 1;
899}
69ab8088
ZJS
900
901/**
0a7b53bd 902 * Retrieve one field from a file like /proc/self/status. pattern
c4cd1d4d
AK
903 * should not include whitespace or the delimiter (':'). pattern matches only
904 * the beginning of a line. Whitespace before ':' is skipped. Whitespace and
905 * zeros after the ':' will be skipped. field must be freed afterwards.
906 * terminator specifies the terminating characters of the field value (not
907 * included in the value).
69ab8088 908 */
c4cd1d4d 909int get_proc_field(const char *filename, const char *pattern, const char *terminator, char **field) {
69ab8088 910 _cleanup_free_ char *status = NULL;
90110825 911 char *t, *f;
69ab8088
ZJS
912 size_t len;
913 int r;
914
c4cd1d4d 915 assert(terminator);
69ab8088 916 assert(filename);
7ff7394d 917 assert(pattern);
69ab8088
ZJS
918 assert(field);
919
920 r = read_full_file(filename, &status, NULL);
921 if (r < 0)
922 return r;
923
c4cd1d4d
AK
924 t = status;
925
926 do {
927 bool pattern_ok;
928
929 do {
930 t = strstr(t, pattern);
931 if (!t)
932 return -ENOENT;
933
934 /* Check that pattern occurs in beginning of line. */
935 pattern_ok = (t == status || t[-1] == '\n');
936
937 t += strlen(pattern);
938
939 } while (!pattern_ok);
940
941 t += strspn(t, " \t");
942 if (!*t)
943 return -ENOENT;
944
945 } while (*t != ':');
946
947 t++;
69ab8088 948
4ec29144 949 if (*t) {
1e5413f7
ZJS
950 t += strspn(t, " \t");
951
952 /* Also skip zeros, because when this is used for
953 * capabilities, we don't want the zeros. This way the
954 * same capability set always maps to the same string,
955 * irrespective of the total capability set size. For
956 * other numbers it shouldn't matter. */
957 t += strspn(t, "0");
4ec29144
ZJS
958 /* Back off one char if there's nothing but whitespace
959 and zeros */
1e5413f7 960 if (!*t || isspace(*t))
313cefa1 961 t--;
4ec29144 962 }
69ab8088 963
c4cd1d4d 964 len = strcspn(t, terminator);
69ab8088 965
90110825
LP
966 f = strndup(t, len);
967 if (!f)
69ab8088
ZJS
968 return -ENOMEM;
969
90110825 970 *field = f;
69ab8088
ZJS
971 return 0;
972}
0d39fa9c
LP
973
974DIR *xopendirat(int fd, const char *name, int flags) {
975 int nfd;
976 DIR *d;
977
978 assert(!(flags & O_CREAT));
979
980 nfd = openat(fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags, 0);
981 if (nfd < 0)
982 return NULL;
983
984 d = fdopendir(nfd);
985 if (!d) {
986 safe_close(nfd);
987 return NULL;
988 }
989
990 return d;
991}
992
993static int search_and_fopen_internal(const char *path, const char *mode, const char *root, char **search, FILE **_f) {
994 char **i;
995
996 assert(path);
997 assert(mode);
998 assert(_f);
999
1000 if (!path_strv_resolve_uniq(search, root))
1001 return -ENOMEM;
1002
1003 STRV_FOREACH(i, search) {
1004 _cleanup_free_ char *p = NULL;
1005 FILE *f;
1006
1007 if (root)
605405c6 1008 p = strjoin(root, *i, "/", path);
0d39fa9c 1009 else
605405c6 1010 p = strjoin(*i, "/", path);
0d39fa9c
LP
1011 if (!p)
1012 return -ENOMEM;
1013
1014 f = fopen(p, mode);
1015 if (f) {
1016 *_f = f;
1017 return 0;
1018 }
1019
1020 if (errno != ENOENT)
1021 return -errno;
1022 }
1023
1024 return -ENOENT;
1025}
1026
1027int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **_f) {
1028 _cleanup_strv_free_ char **copy = NULL;
1029
1030 assert(path);
1031 assert(mode);
1032 assert(_f);
1033
1034 if (path_is_absolute(path)) {
1035 FILE *f;
1036
1037 f = fopen(path, mode);
1038 if (f) {
1039 *_f = f;
1040 return 0;
1041 }
1042
1043 return -errno;
1044 }
1045
1046 copy = strv_copy((char**) search);
1047 if (!copy)
1048 return -ENOMEM;
1049
1050 return search_and_fopen_internal(path, mode, root, copy, _f);
1051}
1052
1053int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **_f) {
1054 _cleanup_strv_free_ char **s = NULL;
1055
1056 if (path_is_absolute(path)) {
1057 FILE *f;
1058
1059 f = fopen(path, mode);
1060 if (f) {
1061 *_f = f;
1062 return 0;
1063 }
1064
1065 return -errno;
1066 }
1067
1068 s = strv_split_nulstr(search);
1069 if (!s)
1070 return -ENOMEM;
1071
1072 return search_and_fopen_internal(path, mode, root, s, _f);
1073}
1074
1075int fopen_temporary(const char *path, FILE **_f, char **_temp_path) {
1076 FILE *f;
1077 char *t;
1078 int r, fd;
1079
1080 assert(path);
1081 assert(_f);
1082 assert(_temp_path);
1083
1084 r = tempfn_xxxxxx(path, NULL, &t);
1085 if (r < 0)
1086 return r;
1087
646853bd 1088 fd = mkostemp_safe(t);
0d39fa9c
LP
1089 if (fd < 0) {
1090 free(t);
1091 return -errno;
1092 }
1093
1094 f = fdopen(fd, "we");
1095 if (!f) {
1096 unlink_noerrno(t);
1097 free(t);
1098 safe_close(fd);
1099 return -errno;
1100 }
1101
1102 *_f = f;
1103 *_temp_path = t;
1104
1105 return 0;
1106}
1107
1108int fflush_and_check(FILE *f) {
1109 assert(f);
1110
1111 errno = 0;
1112 fflush(f);
1113
1114 if (ferror(f))
f5e5c28f 1115 return errno > 0 ? -errno : -EIO;
0d39fa9c
LP
1116
1117 return 0;
1118}
1119
61233823 1120/* This is much like mkostemp() but is subject to umask(). */
646853bd 1121int mkostemp_safe(char *pattern) {
3587161a 1122 _cleanup_umask_ mode_t u = 0;
0d39fa9c
LP
1123 int fd;
1124
1125 assert(pattern);
1126
1127 u = umask(077);
1128
646853bd 1129 fd = mkostemp(pattern, O_CLOEXEC);
0d39fa9c
LP
1130 if (fd < 0)
1131 return -errno;
1132
1133 return fd;
1134}
1135
0d39fa9c
LP
1136int tempfn_xxxxxx(const char *p, const char *extra, char **ret) {
1137 const char *fn;
1138 char *t;
1139
1140 assert(p);
1141 assert(ret);
1142
1143 /*
1144 * Turns this:
1145 * /foo/bar/waldo
1146 *
1147 * Into this:
1148 * /foo/bar/.#<extra>waldoXXXXXX
1149 */
1150
1151 fn = basename(p);
1152 if (!filename_is_valid(fn))
1153 return -EINVAL;
1154
1155 if (extra == NULL)
1156 extra = "";
1157
1158 t = new(char, strlen(p) + 2 + strlen(extra) + 6 + 1);
1159 if (!t)
1160 return -ENOMEM;
1161
1162 strcpy(stpcpy(stpcpy(stpcpy(mempcpy(t, p, fn - p), ".#"), extra), fn), "XXXXXX");
1163
1164 *ret = path_kill_slashes(t);
1165 return 0;
1166}
1167
1168int tempfn_random(const char *p, const char *extra, char **ret) {
1169 const char *fn;
1170 char *t, *x;
1171 uint64_t u;
1172 unsigned i;
1173
1174 assert(p);
1175 assert(ret);
1176
1177 /*
1178 * Turns this:
1179 * /foo/bar/waldo
1180 *
1181 * Into this:
1182 * /foo/bar/.#<extra>waldobaa2a261115984a9
1183 */
1184
1185 fn = basename(p);
1186 if (!filename_is_valid(fn))
1187 return -EINVAL;
1188
1189 if (!extra)
1190 extra = "";
1191
1192 t = new(char, strlen(p) + 2 + strlen(extra) + 16 + 1);
1193 if (!t)
1194 return -ENOMEM;
1195
1196 x = stpcpy(stpcpy(stpcpy(mempcpy(t, p, fn - p), ".#"), extra), fn);
1197
1198 u = random_u64();
1199 for (i = 0; i < 16; i++) {
1200 *(x++) = hexchar(u & 0xF);
1201 u >>= 4;
1202 }
1203
1204 *x = 0;
1205
1206 *ret = path_kill_slashes(t);
1207 return 0;
1208}
1209
1210int tempfn_random_child(const char *p, const char *extra, char **ret) {
1211 char *t, *x;
1212 uint64_t u;
1213 unsigned i;
992e8f22 1214 int r;
0d39fa9c 1215
0d39fa9c
LP
1216 assert(ret);
1217
1218 /* Turns this:
1219 * /foo/bar/waldo
1220 * Into this:
1221 * /foo/bar/waldo/.#<extra>3c2b6219aa75d7d0
1222 */
1223
992e8f22
LP
1224 if (!p) {
1225 r = tmp_dir(&p);
1226 if (r < 0)
1227 return r;
1228 }
1229
0d39fa9c
LP
1230 if (!extra)
1231 extra = "";
1232
1233 t = new(char, strlen(p) + 3 + strlen(extra) + 16 + 1);
1234 if (!t)
1235 return -ENOMEM;
1236
1237 x = stpcpy(stpcpy(stpcpy(t, p), "/.#"), extra);
1238
1239 u = random_u64();
1240 for (i = 0; i < 16; i++) {
1241 *(x++) = hexchar(u & 0xF);
1242 u >>= 4;
1243 }
1244
1245 *x = 0;
1246
1247 *ret = path_kill_slashes(t);
1248 return 0;
1249}
33d52ab9
LP
1250
1251int write_timestamp_file_atomic(const char *fn, usec_t n) {
1252 char ln[DECIMAL_STR_MAX(n)+2];
1253
1254 /* Creates a "timestamp" file, that contains nothing but a
1255 * usec_t timestamp, formatted in ASCII. */
1256
1257 if (n <= 0 || n >= USEC_INFINITY)
1258 return -ERANGE;
1259
1260 xsprintf(ln, USEC_FMT "\n", n);
1261
1262 return write_string_file(fn, ln, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC);
1263}
1264
1265int read_timestamp_file(const char *fn, usec_t *ret) {
1266 _cleanup_free_ char *ln = NULL;
1267 uint64_t t;
1268 int r;
1269
1270 r = read_one_line_file(fn, &ln);
1271 if (r < 0)
1272 return r;
1273
1274 r = safe_atou64(ln, &t);
1275 if (r < 0)
1276 return r;
1277
1278 if (t <= 0 || t >= (uint64_t) USEC_INFINITY)
1279 return -ERANGE;
1280
1281 *ret = (usec_t) t;
1282 return 0;
1283}
d390f8ef
LP
1284
1285int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space) {
1286 int r;
1287
1288 assert(s);
1289
1290 /* Outputs the specified string with fputs(), but optionally prefixes it with a separator. The *space parameter
1291 * when specified shall initially point to a boolean variable initialized to false. It is set to true after the
1292 * first invocation. This call is supposed to be use in loops, where a separator shall be inserted between each
1293 * element, but not before the first one. */
1294
1295 if (!f)
1296 f = stdout;
1297
1298 if (space) {
1299 if (!separator)
1300 separator = " ";
1301
1302 if (*space) {
1303 r = fputs(separator, f);
1304 if (r < 0)
1305 return r;
1306 }
1307
1308 *space = true;
1309 }
1310
1311 return fputs(s, f);
1312}
03532f0a
LP
1313
1314int open_tmpfile_unlinkable(const char *directory, int flags) {
1315 char *p;
992e8f22 1316 int fd, r;
03532f0a 1317
992e8f22
LP
1318 if (!directory) {
1319 r = tmp_dir(&directory);
1320 if (r < 0)
1321 return r;
1322 }
03532f0a
LP
1323
1324 /* Returns an unlinked temporary file that cannot be linked into the file system anymore */
1325
03532f0a
LP
1326 /* Try O_TMPFILE first, if it is supported */
1327 fd = open(directory, flags|O_TMPFILE|O_EXCL, S_IRUSR|S_IWUSR);
1328 if (fd >= 0)
1329 return fd;
03532f0a
LP
1330
1331 /* Fall back to unguessable name + unlinking */
1332 p = strjoina(directory, "/systemd-tmp-XXXXXX");
1333
646853bd 1334 fd = mkostemp_safe(p);
03532f0a
LP
1335 if (fd < 0)
1336 return fd;
1337
1338 (void) unlink(p);
1339
1340 return fd;
1341}
1342
1343int open_tmpfile_linkable(const char *target, int flags, char **ret_path) {
1344 _cleanup_free_ char *tmp = NULL;
1345 int r, fd;
1346
1347 assert(target);
1348 assert(ret_path);
1349
1350 /* Don't allow O_EXCL, as that has a special meaning for O_TMPFILE */
1351 assert((flags & O_EXCL) == 0);
1352
1353 /* Creates a temporary file, that shall be renamed to "target" later. If possible, this uses O_TMPFILE – in
1354 * which case "ret_path" will be returned as NULL. If not possible a the tempoary path name used is returned in
1355 * "ret_path". Use link_tmpfile() below to rename the result after writing the file in full. */
1356
03532f0a
LP
1357 {
1358 _cleanup_free_ char *dn = NULL;
1359
1360 dn = dirname_malloc(target);
1361 if (!dn)
1362 return -ENOMEM;
1363
1364 fd = open(dn, O_TMPFILE|flags, 0640);
1365 if (fd >= 0) {
1366 *ret_path = NULL;
1367 return fd;
1368 }
1369
1370 log_debug_errno(errno, "Failed to use O_TMPFILE on %s: %m", dn);
1371 }
03532f0a
LP
1372
1373 r = tempfn_random(target, NULL, &tmp);
1374 if (r < 0)
1375 return r;
1376
1377 fd = open(tmp, O_CREAT|O_EXCL|O_NOFOLLOW|O_NOCTTY|flags, 0640);
1378 if (fd < 0)
1379 return -errno;
1380
1381 *ret_path = tmp;
1382 tmp = NULL;
1383
1384 return fd;
1385}
1386
504afd7c
ZJS
1387int open_serialization_fd(const char *ident) {
1388 int fd = -1;
1389
1390 fd = memfd_create(ident, MFD_CLOEXEC);
1391 if (fd < 0) {
1392 const char *path;
1393
1394 path = getpid() == 1 ? "/run/systemd" : "/tmp";
1395 fd = open_tmpfile_unlinkable(path, O_RDWR|O_CLOEXEC);
1396 if (fd < 0)
1397 return fd;
1398
1399 log_debug("Serializing %s to %s.", ident, path);
1400 } else
1401 log_debug("Serializing %s to memfd.", ident);
1402
1403 return fd;
1404}
1405
03532f0a
LP
1406int link_tmpfile(int fd, const char *path, const char *target) {
1407
1408 assert(fd >= 0);
1409 assert(target);
1410
1411 /* Moves a temporary file created with open_tmpfile() above into its final place. if "path" is NULL an fd
1412 * created with O_TMPFILE is assumed, and linkat() is used. Otherwise it is assumed O_TMPFILE is not supported
1413 * on the directory, and renameat2() is used instead.
1414 *
f8e2f4d6 1415 * Note that in both cases we will not replace existing files. This is because linkat() does not support this
03532f0a
LP
1416 * operation currently (renameat2() does), and there is no nice way to emulate this. */
1417
1418 if (path) {
1419 if (rename_noreplace(AT_FDCWD, path, AT_FDCWD, target) < 0)
1420 return -errno;
1421 } else {
1422 char proc_fd_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(fd) + 1];
1423
1424 xsprintf(proc_fd_path, "/proc/self/fd/%i", fd);
1425
1426 if (linkat(AT_FDCWD, proc_fd_path, AT_FDCWD, target, AT_SYMLINK_FOLLOW) < 0)
1427 return -errno;
1428 }
1429
1430 return 0;
1431}
03c2b288
LP
1432
1433int read_nul_string(FILE *f, char **ret) {
1434 _cleanup_free_ char *x = NULL;
1435 size_t allocated = 0, n = 0;
1436
1437 assert(f);
1438 assert(ret);
1439
1440 /* Reads a NUL-terminated string from the specified file. */
1441
1442 for (;;) {
1443 int c;
1444
1445 if (!GREEDY_REALLOC(x, allocated, n+2))
1446 return -ENOMEM;
1447
1448 c = fgetc(f);
1449 if (c == 0) /* Terminate at NUL byte */
1450 break;
1451 if (c == EOF) {
1452 if (ferror(f))
1453 return -errno;
1454 break; /* Terminate at EOF */
1455 }
1456
1457 x[n++] = (char) c;
1458 }
1459
1460 if (x)
1461 x[n] = 0;
1462 else {
1463 x = new0(char, 1);
1464 if (!x)
1465 return -ENOMEM;
1466 }
1467
1468 *ret = x;
1469 x = NULL;
1470
1471 return 0;
1472}
676bcb0f
LP
1473
1474int mkdtemp_malloc(const char *template, char **ret) {
1475 char *p;
1476
1477 assert(template);
1478 assert(ret);
1479
1480 p = strdup(template);
1481 if (!p)
1482 return -ENOMEM;
1483
1484 if (!mkdtemp(p)) {
1485 free(p);
1486 return -errno;
1487 }
1488
1489 *ret = p;
1490 return 0;
1491}