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