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