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