1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2010 Lennart Poettering
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.
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.
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/>.
26 #include <stdio_ext.h>
31 #include <sys/types.h>
34 #include "alloc-util.h"
42 #include "hexdecoct.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"
53 #include "time-util.h"
54 #include "umask-util.h"
57 #define READ_FULL_BYTES_MAX (4U*1024U*1024U)
59 int write_string_stream_ts(
62 WriteStringFileFlags flags
,
63 struct timespec
*ts
) {
73 needs_nl
= !(flags
& WRITE_STRING_FILE_AVOID_NEWLINE
) && !endswith(line
, "\n");
75 if (needs_nl
&& (flags
& WRITE_STRING_FILE_DISABLE_BUFFER
)) {
76 /* If STDIO buffering was disabled, then let's append the newline character to the string itself, so
77 * that the write goes out in one go, instead of two */
79 line
= strjoina(line
, "\n");
83 if (fputs(line
, f
) == EOF
)
87 if (fputc('\n', f
) == EOF
)
91 struct timespec twice
[2] = {*ts
, *ts
};
93 if (futimens(fileno(f
), twice
) < 0)
97 if (flags
& WRITE_STRING_FILE_SYNC
)
98 return fflush_sync_and_check(f
);
100 return fflush_and_check(f
);
103 static int write_string_file_atomic(
106 WriteStringFileFlags flags
,
107 struct timespec
*ts
) {
109 _cleanup_fclose_
FILE *f
= NULL
;
110 _cleanup_free_
char *p
= NULL
;
116 r
= fopen_temporary(fn
, &f
, &p
);
120 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
121 (void) fchmod_umask(fileno(f
), 0644);
123 r
= write_string_stream_ts(f
, line
, flags
, ts
);
127 if (rename(p
, fn
) < 0) {
139 int write_string_file_ts(
142 WriteStringFileFlags flags
,
143 struct timespec
*ts
) {
145 _cleanup_fclose_
FILE *f
= NULL
;
151 /* We don't know how to verify whether the file contents was already on-disk. */
152 assert(!((flags
& WRITE_STRING_FILE_VERIFY_ON_FAILURE
) && (flags
& WRITE_STRING_FILE_SYNC
)));
154 if (flags
& WRITE_STRING_FILE_ATOMIC
) {
155 assert(flags
& WRITE_STRING_FILE_CREATE
);
157 r
= write_string_file_atomic(fn
, line
, flags
, ts
);
165 if (flags
& WRITE_STRING_FILE_CREATE
) {
174 /* We manually build our own version of fopen(..., "we") that
175 * works without O_CREAT */
176 fd
= open(fn
, O_WRONLY
|O_CLOEXEC
|O_NOCTTY
);
182 f
= fdopen(fd
, "we");
190 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
192 if (flags
& WRITE_STRING_FILE_DISABLE_BUFFER
)
193 setvbuf(f
, NULL
, _IONBF
, 0);
195 r
= write_string_stream_ts(f
, line
, flags
, ts
);
202 if (!(flags
& WRITE_STRING_FILE_VERIFY_ON_FAILURE
))
207 /* OK, the operation failed, but let's see if the right
208 * contents in place already. If so, eat up the error. */
210 q
= verify_file(fn
, line
, !(flags
& WRITE_STRING_FILE_AVOID_NEWLINE
));
217 int read_one_line_file(const char *fn
, char **line
) {
218 _cleanup_fclose_
FILE *f
= NULL
;
228 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
230 r
= read_line(f
, LONG_LINE_MAX
, line
);
231 return r
< 0 ? r
: 0;
234 int verify_file(const char *fn
, const char *blob
, bool accept_extra_nl
) {
235 _cleanup_fclose_
FILE *f
= NULL
;
236 _cleanup_free_
char *buf
= NULL
;
244 if (accept_extra_nl
&& endswith(blob
, "\n"))
245 accept_extra_nl
= false;
247 buf
= malloc(l
+ accept_extra_nl
+ 1);
255 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
257 /* We try to read one byte more than we need, so that we know whether we hit eof */
259 k
= fread(buf
, 1, l
+ accept_extra_nl
+ 1, f
);
261 return errno
> 0 ? -errno
: -EIO
;
263 if (k
!= l
&& k
!= l
+ accept_extra_nl
)
265 if (memcmp(buf
, blob
, l
) != 0)
267 if (k
> l
&& buf
[l
] != '\n')
273 int read_full_stream(FILE *f
, char **contents
, size_t *size
) {
275 _cleanup_free_
char *buf
= NULL
;
281 if (fstat(fileno(f
), &st
) < 0)
286 if (S_ISREG(st
.st_mode
)) {
289 if (st
.st_size
> READ_FULL_BYTES_MAX
)
292 /* Start with the right file size, but be prepared for files from /proc which generally report a file
293 * size of 0. Note that we increase the size to read here by one, so that the first read attempt
294 * already makes us notice the EOF. */
304 t
= realloc(buf
, n
+ 1);
310 k
= fread(buf
+ l
, 1, n
- l
, f
);
315 return errno
> 0 ? -errno
: -EIO
;
320 /* We aren't expecting fread() to return a short read outside
321 * of (error && eof), assert buffer is full and enlarge buffer.
326 if (n
>= READ_FULL_BYTES_MAX
)
329 n
= MIN(n
* 2, READ_FULL_BYTES_MAX
);
333 *contents
= TAKE_PTR(buf
);
341 int read_full_file(const char *fn
, char **contents
, size_t *size
) {
342 _cleanup_fclose_
FILE *f
= NULL
;
351 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
353 return read_full_stream(f
, contents
, size
);
356 static int parse_env_file_internal(
360 int (*push
) (const char *filename
, unsigned line
,
361 const char *key
, char *value
, void *userdata
, int *n_pushed
),
365 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;
366 _cleanup_free_
char *contents
= NULL
, *key
= NULL
, *value
= NULL
;
378 SINGLE_QUOTE_VALUE_ESCAPE
,
380 DOUBLE_QUOTE_VALUE_ESCAPE
,
388 r
= read_full_stream(f
, &contents
, NULL
);
390 r
= read_full_file(fname
, &contents
, NULL
);
394 for (p
= contents
; *p
; p
++) {
400 if (strchr(COMMENTS
, c
))
402 else if (!strchr(WHITESPACE
, c
)) {
404 last_key_whitespace
= (size_t) -1;
406 if (!GREEDY_REALLOC(key
, key_alloc
, n_key
+2))
414 if (strchr(newline
, c
)) {
418 } else if (c
== '=') {
420 last_value_whitespace
= (size_t) -1;
422 if (!strchr(WHITESPACE
, c
))
423 last_key_whitespace
= (size_t) -1;
424 else if (last_key_whitespace
== (size_t) -1)
425 last_key_whitespace
= n_key
;
427 if (!GREEDY_REALLOC(key
, key_alloc
, n_key
+2))
436 if (strchr(newline
, c
)) {
444 /* strip trailing whitespace from key */
445 if (last_key_whitespace
!= (size_t) -1)
446 key
[last_key_whitespace
] = 0;
448 r
= push(fname
, line
, key
, value
, userdata
, n_pushed
);
454 value_alloc
= n_value
= 0;
456 } else if (c
== '\'')
457 state
= SINGLE_QUOTE_VALUE
;
459 state
= DOUBLE_QUOTE_VALUE
;
461 state
= VALUE_ESCAPE
;
462 else if (!strchr(WHITESPACE
, c
)) {
465 if (!GREEDY_REALLOC(value
, value_alloc
, n_value
+2))
468 value
[n_value
++] = c
;
474 if (strchr(newline
, c
)) {
483 /* Chomp off trailing whitespace from value */
484 if (last_value_whitespace
!= (size_t) -1)
485 value
[last_value_whitespace
] = 0;
487 /* strip trailing whitespace from key */
488 if (last_key_whitespace
!= (size_t) -1)
489 key
[last_key_whitespace
] = 0;
491 r
= push(fname
, line
, key
, value
, userdata
, n_pushed
);
497 value_alloc
= n_value
= 0;
499 } else if (c
== '\\') {
500 state
= VALUE_ESCAPE
;
501 last_value_whitespace
= (size_t) -1;
503 if (!strchr(WHITESPACE
, c
))
504 last_value_whitespace
= (size_t) -1;
505 else if (last_value_whitespace
== (size_t) -1)
506 last_value_whitespace
= n_value
;
508 if (!GREEDY_REALLOC(value
, value_alloc
, n_value
+2))
511 value
[n_value
++] = c
;
519 if (!strchr(newline
, c
)) {
520 /* Escaped newlines we eat up entirely */
521 if (!GREEDY_REALLOC(value
, value_alloc
, n_value
+2))
524 value
[n_value
++] = c
;
528 case SINGLE_QUOTE_VALUE
:
532 state
= SINGLE_QUOTE_VALUE_ESCAPE
;
534 if (!GREEDY_REALLOC(value
, value_alloc
, n_value
+2))
537 value
[n_value
++] = c
;
542 case SINGLE_QUOTE_VALUE_ESCAPE
:
543 state
= SINGLE_QUOTE_VALUE
;
545 if (!strchr(newline
, c
)) {
546 if (!GREEDY_REALLOC(value
, value_alloc
, n_value
+2))
549 value
[n_value
++] = c
;
553 case DOUBLE_QUOTE_VALUE
:
557 state
= DOUBLE_QUOTE_VALUE_ESCAPE
;
559 if (!GREEDY_REALLOC(value
, value_alloc
, n_value
+2))
562 value
[n_value
++] = c
;
567 case DOUBLE_QUOTE_VALUE_ESCAPE
:
568 state
= DOUBLE_QUOTE_VALUE
;
570 if (!strchr(newline
, c
)) {
571 if (!GREEDY_REALLOC(value
, value_alloc
, n_value
+2))
574 value
[n_value
++] = c
;
580 state
= COMMENT_ESCAPE
;
581 else if (strchr(newline
, c
)) {
598 SINGLE_QUOTE_VALUE_ESCAPE
,
600 DOUBLE_QUOTE_VALUE_ESCAPE
)) {
608 if (last_value_whitespace
!= (size_t) -1)
609 value
[last_value_whitespace
] = 0;
611 /* strip trailing whitespace from key */
612 if (last_key_whitespace
!= (size_t) -1)
613 key
[last_key_whitespace
] = 0;
615 r
= push(fname
, line
, key
, value
, userdata
, n_pushed
);
625 static int check_utf8ness_and_warn(
626 const char *filename
, unsigned line
,
627 const char *key
, char *value
) {
629 if (!utf8_is_valid(key
)) {
630 _cleanup_free_
char *p
= NULL
;
632 p
= utf8_escape_invalid(key
);
633 log_error("%s:%u: invalid UTF-8 in key '%s', ignoring.", strna(filename
), line
, p
);
637 if (value
&& !utf8_is_valid(value
)) {
638 _cleanup_free_
char *p
= NULL
;
640 p
= utf8_escape_invalid(value
);
641 log_error("%s:%u: invalid UTF-8 value for key %s: '%s', ignoring.", strna(filename
), line
, key
, p
);
648 static int parse_env_file_push(
649 const char *filename
, unsigned line
,
650 const char *key
, char *value
,
655 va_list aq
, *ap
= userdata
;
658 r
= check_utf8ness_and_warn(filename
, line
, key
, value
);
664 while ((k
= va_arg(aq
, const char *))) {
667 v
= va_arg(aq
, char **);
689 const char *newline
, ...) {
697 va_start(ap
, newline
);
698 r
= parse_env_file_internal(NULL
, fname
, newline
, parse_env_file_push
, &ap
, &n_pushed
);
701 return r
< 0 ? r
: n_pushed
;
704 static int load_env_file_push(
705 const char *filename
, unsigned line
,
706 const char *key
, char *value
,
709 char ***m
= userdata
;
713 r
= check_utf8ness_and_warn(filename
, line
, key
, value
);
717 p
= strjoin(key
, "=", value
);
721 r
= strv_env_replace(m
, p
);
734 int load_env_file(FILE *f
, const char *fname
, const char *newline
, char ***rl
) {
741 r
= parse_env_file_internal(f
, fname
, newline
, load_env_file_push
, &m
, NULL
);
751 static int load_env_file_push_pairs(
752 const char *filename
, unsigned line
,
753 const char *key
, char *value
,
756 char ***m
= userdata
;
759 r
= check_utf8ness_and_warn(filename
, line
, key
, value
);
763 r
= strv_extend(m
, key
);
768 r
= strv_extend(m
, "");
772 r
= strv_push(m
, value
);
783 int load_env_file_pairs(FILE *f
, const char *fname
, const char *newline
, char ***rl
) {
790 r
= parse_env_file_internal(f
, fname
, newline
, load_env_file_push_pairs
, &m
, NULL
);
800 static int merge_env_file_push(
801 const char *filename
, unsigned line
,
802 const char *key
, char *value
,
806 char ***env
= userdata
;
807 char *expanded_value
;
812 log_error("%s:%u: invalid syntax (around \"%s\"), ignoring.", strna(filename
), line
, key
);
816 if (!env_name_is_valid(key
)) {
817 log_error("%s:%u: invalid variable name \"%s\", ignoring.", strna(filename
), line
, key
);
822 expanded_value
= replace_env(value
, *env
,
823 REPLACE_ENV_USE_ENVIRONMENT
|
824 REPLACE_ENV_ALLOW_BRACELESS
|
825 REPLACE_ENV_ALLOW_EXTENDED
);
829 free_and_replace(value
, expanded_value
);
831 return load_env_file_push(filename
, line
, key
, value
, env
, n_pushed
);
839 /* NOTE: this function supports braceful and braceless variable expansions,
840 * plus "extended" substitutions, unlike other exported parsing functions.
843 return parse_env_file_internal(f
, fname
, NEWLINE
, merge_env_file_push
, env
, NULL
);
846 static void write_env_var(FILE *f
, const char *v
) {
852 fputs_unlocked(v
, f
);
853 fputc_unlocked('\n', f
);
858 fwrite_unlocked(v
, 1, p
-v
, f
);
860 if (string_has_cc(p
, NULL
) || chars_intersect(p
, WHITESPACE SHELL_NEED_QUOTES
)) {
861 fputc_unlocked('\"', f
);
864 if (strchr(SHELL_NEED_ESCAPE
, *p
))
865 fputc_unlocked('\\', f
);
867 fputc_unlocked(*p
, f
);
870 fputc_unlocked('\"', f
);
872 fputs_unlocked(p
, f
);
874 fputc_unlocked('\n', f
);
877 int write_env_file(const char *fname
, char **l
) {
878 _cleanup_fclose_
FILE *f
= NULL
;
879 _cleanup_free_
char *p
= NULL
;
885 r
= fopen_temporary(fname
, &f
, &p
);
889 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
890 (void) fchmod_umask(fileno(f
), 0644);
893 write_env_var(f
, *i
);
895 r
= fflush_and_check(f
);
897 if (rename(p
, fname
) >= 0)
907 int executable_is_script(const char *path
, char **interpreter
) {
908 _cleanup_free_
char *line
= NULL
;
915 r
= read_one_line_file(path
, &line
);
916 if (r
== -ENOBUFS
) /* First line overly long? if so, then it's not a script */
921 if (!startswith(line
, "#!"))
924 ans
= strstrip(line
+ 2);
925 len
= strcspn(ans
, " \t");
930 ans
= strndup(ans
, len
);
939 * Retrieve one field from a file like /proc/self/status. pattern
940 * should not include whitespace or the delimiter (':'). pattern matches only
941 * the beginning of a line. Whitespace before ':' is skipped. Whitespace and
942 * zeros after the ':' will be skipped. field must be freed afterwards.
943 * terminator specifies the terminating characters of the field value (not
944 * included in the value).
946 int get_proc_field(const char *filename
, const char *pattern
, const char *terminator
, char **field
) {
947 _cleanup_free_
char *status
= NULL
;
957 r
= read_full_file(filename
, &status
, NULL
);
967 t
= strstr(t
, pattern
);
971 /* Check that pattern occurs in beginning of line. */
972 pattern_ok
= (t
== status
|| t
[-1] == '\n');
974 t
+= strlen(pattern
);
976 } while (!pattern_ok
);
978 t
+= strspn(t
, " \t");
987 t
+= strspn(t
, " \t");
989 /* Also skip zeros, because when this is used for
990 * capabilities, we don't want the zeros. This way the
991 * same capability set always maps to the same string,
992 * irrespective of the total capability set size. For
993 * other numbers it shouldn't matter. */
995 /* Back off one char if there's nothing but whitespace
997 if (!*t
|| isspace(*t
))
1001 len
= strcspn(t
, terminator
);
1003 f
= strndup(t
, len
);
1011 DIR *xopendirat(int fd
, const char *name
, int flags
) {
1015 assert(!(flags
& O_CREAT
));
1017 nfd
= openat(fd
, name
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
|flags
, 0);
1030 static int search_and_fopen_internal(const char *path
, const char *mode
, const char *root
, char **search
, FILE **_f
) {
1037 if (!path_strv_resolve_uniq(search
, root
))
1040 STRV_FOREACH(i
, search
) {
1041 _cleanup_free_
char *p
= NULL
;
1045 p
= strjoin(root
, *i
, "/", path
);
1047 p
= strjoin(*i
, "/", path
);
1057 if (errno
!= ENOENT
)
1064 int search_and_fopen(const char *path
, const char *mode
, const char *root
, const char **search
, FILE **_f
) {
1065 _cleanup_strv_free_
char **copy
= NULL
;
1071 if (path_is_absolute(path
)) {
1074 f
= fopen(path
, mode
);
1083 copy
= strv_copy((char**) search
);
1087 return search_and_fopen_internal(path
, mode
, root
, copy
, _f
);
1090 int search_and_fopen_nulstr(const char *path
, const char *mode
, const char *root
, const char *search
, FILE **_f
) {
1091 _cleanup_strv_free_
char **s
= NULL
;
1093 if (path_is_absolute(path
)) {
1096 f
= fopen(path
, mode
);
1105 s
= strv_split_nulstr(search
);
1109 return search_and_fopen_internal(path
, mode
, root
, s
, _f
);
1112 int fopen_temporary(const char *path
, FILE **_f
, char **_temp_path
) {
1121 r
= tempfn_xxxxxx(path
, NULL
, &t
);
1125 fd
= mkostemp_safe(t
);
1131 f
= fdopen(fd
, "we");
1145 int fflush_and_check(FILE *f
) {
1152 return errno
> 0 ? -errno
: -EIO
;
1157 int fflush_sync_and_check(FILE *f
) {
1162 r
= fflush_and_check(f
);
1166 if (fsync(fileno(f
)) < 0)
1169 r
= fsync_directory_of_file(fileno(f
));
1176 /* This is much like mkostemp() but is subject to umask(). */
1177 int mkostemp_safe(char *pattern
) {
1178 _cleanup_umask_ mode_t u
= 0;
1185 fd
= mkostemp(pattern
, O_CLOEXEC
);
1192 int tempfn_xxxxxx(const char *p
, const char *extra
, char **ret
) {
1204 * /foo/bar/.#<extra>waldoXXXXXX
1208 if (!filename_is_valid(fn
))
1211 extra
= strempty(extra
);
1213 t
= new(char, strlen(p
) + 2 + strlen(extra
) + 6 + 1);
1217 strcpy(stpcpy(stpcpy(stpcpy(mempcpy(t
, p
, fn
- p
), ".#"), extra
), fn
), "XXXXXX");
1219 *ret
= path_kill_slashes(t
);
1223 int tempfn_random(const char *p
, const char *extra
, char **ret
) {
1237 * /foo/bar/.#<extra>waldobaa2a261115984a9
1241 if (!filename_is_valid(fn
))
1244 extra
= strempty(extra
);
1246 t
= new(char, strlen(p
) + 2 + strlen(extra
) + 16 + 1);
1250 x
= stpcpy(stpcpy(stpcpy(mempcpy(t
, p
, fn
- p
), ".#"), extra
), fn
);
1253 for (i
= 0; i
< 16; i
++) {
1254 *(x
++) = hexchar(u
& 0xF);
1260 *ret
= path_kill_slashes(t
);
1264 int tempfn_random_child(const char *p
, const char *extra
, char **ret
) {
1275 * /foo/bar/waldo/.#<extra>3c2b6219aa75d7d0
1284 extra
= strempty(extra
);
1286 t
= new(char, strlen(p
) + 3 + strlen(extra
) + 16 + 1);
1290 x
= stpcpy(stpcpy(stpcpy(t
, p
), "/.#"), extra
);
1293 for (i
= 0; i
< 16; i
++) {
1294 *(x
++) = hexchar(u
& 0xF);
1300 *ret
= path_kill_slashes(t
);
1304 int write_timestamp_file_atomic(const char *fn
, usec_t n
) {
1305 char ln
[DECIMAL_STR_MAX(n
)+2];
1307 /* Creates a "timestamp" file, that contains nothing but a
1308 * usec_t timestamp, formatted in ASCII. */
1310 if (n
<= 0 || n
>= USEC_INFINITY
)
1313 xsprintf(ln
, USEC_FMT
"\n", n
);
1315 return write_string_file(fn
, ln
, WRITE_STRING_FILE_CREATE
|WRITE_STRING_FILE_ATOMIC
);
1318 int read_timestamp_file(const char *fn
, usec_t
*ret
) {
1319 _cleanup_free_
char *ln
= NULL
;
1323 r
= read_one_line_file(fn
, &ln
);
1327 r
= safe_atou64(ln
, &t
);
1331 if (t
<= 0 || t
>= (uint64_t) USEC_INFINITY
)
1338 int fputs_with_space(FILE *f
, const char *s
, const char *separator
, bool *space
) {
1343 /* Outputs the specified string with fputs(), but optionally prefixes it with a separator. The *space parameter
1344 * when specified shall initially point to a boolean variable initialized to false. It is set to true after the
1345 * first invocation. This call is supposed to be use in loops, where a separator shall be inserted between each
1346 * element, but not before the first one. */
1356 r
= fputs(separator
, f
);
1367 int open_tmpfile_unlinkable(const char *directory
, int flags
) {
1372 r
= tmp_dir(&directory
);
1377 /* Returns an unlinked temporary file that cannot be linked into the file system anymore */
1379 /* Try O_TMPFILE first, if it is supported */
1380 fd
= open(directory
, flags
|O_TMPFILE
|O_EXCL
, S_IRUSR
|S_IWUSR
);
1384 /* Fall back to unguessable name + unlinking */
1385 p
= strjoina(directory
, "/systemd-tmp-XXXXXX");
1387 fd
= mkostemp_safe(p
);
1396 int open_tmpfile_linkable(const char *target
, int flags
, char **ret_path
) {
1397 _cleanup_free_
char *tmp
= NULL
;
1403 /* Don't allow O_EXCL, as that has a special meaning for O_TMPFILE */
1404 assert((flags
& O_EXCL
) == 0);
1406 /* Creates a temporary file, that shall be renamed to "target" later. If possible, this uses O_TMPFILE – in
1407 * which case "ret_path" will be returned as NULL. If not possible a the tempoary path name used is returned in
1408 * "ret_path". Use link_tmpfile() below to rename the result after writing the file in full. */
1411 _cleanup_free_
char *dn
= NULL
;
1413 dn
= dirname_malloc(target
);
1417 fd
= open(dn
, O_TMPFILE
|flags
, 0640);
1423 log_debug_errno(errno
, "Failed to use O_TMPFILE on %s: %m", dn
);
1426 r
= tempfn_random(target
, NULL
, &tmp
);
1430 fd
= open(tmp
, O_CREAT
|O_EXCL
|O_NOFOLLOW
|O_NOCTTY
|flags
, 0640);
1434 *ret_path
= TAKE_PTR(tmp
);
1439 int open_serialization_fd(const char *ident
) {
1442 fd
= memfd_create(ident
, MFD_CLOEXEC
);
1446 path
= getpid_cached() == 1 ? "/run/systemd" : "/tmp";
1447 fd
= open_tmpfile_unlinkable(path
, O_RDWR
|O_CLOEXEC
);
1451 log_debug("Serializing %s to %s.", ident
, path
);
1453 log_debug("Serializing %s to memfd.", ident
);
1458 int link_tmpfile(int fd
, const char *path
, const char *target
) {
1463 /* Moves a temporary file created with open_tmpfile() above into its final place. if "path" is NULL an fd
1464 * created with O_TMPFILE is assumed, and linkat() is used. Otherwise it is assumed O_TMPFILE is not supported
1465 * on the directory, and renameat2() is used instead.
1467 * Note that in both cases we will not replace existing files. This is because linkat() does not support this
1468 * operation currently (renameat2() does), and there is no nice way to emulate this. */
1471 if (rename_noreplace(AT_FDCWD
, path
, AT_FDCWD
, target
) < 0)
1474 char proc_fd_path
[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(fd
) + 1];
1476 xsprintf(proc_fd_path
, "/proc/self/fd/%i", fd
);
1478 if (linkat(AT_FDCWD
, proc_fd_path
, AT_FDCWD
, target
, AT_SYMLINK_FOLLOW
) < 0)
1485 int read_nul_string(FILE *f
, char **ret
) {
1486 _cleanup_free_
char *x
= NULL
;
1487 size_t allocated
= 0, n
= 0;
1492 /* Reads a NUL-terminated string from the specified file. */
1497 if (!GREEDY_REALLOC(x
, allocated
, n
+2))
1501 if (c
== 0) /* Terminate at NUL byte */
1506 break; /* Terminate at EOF */
1525 int mkdtemp_malloc(const char *template, char **ret
) {
1531 p
= strdup(template);
1544 DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, funlockfile
);
1546 int read_line(FILE *f
, size_t limit
, char **ret
) {
1547 _cleanup_free_
char *buffer
= NULL
;
1548 size_t n
= 0, allocated
= 0, count
= 0;
1552 /* Something like a bounded version of getline().
1554 * Considers EOF, \n and \0 end of line delimiters, and does not include these delimiters in the string
1557 * Returns the number of bytes read from the files (i.e. including delimiters — this hence usually differs from
1558 * the number of characters in the returned string). When EOF is hit, 0 is returned.
1560 * The input parameter limit is the maximum numbers of characters in the returned string, i.e. excluding
1561 * delimiters. If the limit is hit we fail and return -ENOBUFS.
1563 * If a line shall be skipped ret may be initialized as NULL. */
1566 if (!GREEDY_REALLOC(buffer
, allocated
, 1))
1571 _unused_
_cleanup_(funlockfilep
) FILE *flocked
= f
;
1581 c
= fgetc_unlocked(f
);
1583 /* if we read an error, and have no data to return, then propagate the error */
1584 if (ferror_unlocked(f
) && n
== 0)
1585 return errno
> 0 ? -errno
: -EIO
;
1592 if (IN_SET(c
, '\n', 0)) /* Reached a delimiter */
1596 if (!GREEDY_REALLOC(buffer
, allocated
, n
+ 2))
1599 buffer
[n
] = (char) c
;