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