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