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