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