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