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