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