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