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