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