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