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