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