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