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
) {
71 if (fputs(line
, f
) == EOF
)
74 if (!(flags
& WRITE_STRING_FILE_AVOID_NEWLINE
) && !endswith(line
, "\n"))
75 if (fputc('\n', f
) == EOF
)
79 struct timespec twice
[2] = {*ts
, *ts
};
81 if (futimens(fileno(f
), twice
) < 0)
85 if (flags
& WRITE_STRING_FILE_SYNC
)
86 return fflush_sync_and_check(f
);
88 return fflush_and_check(f
);
91 static int write_string_file_atomic(
94 WriteStringFileFlags flags
,
95 struct timespec
*ts
) {
97 _cleanup_fclose_
FILE *f
= NULL
;
98 _cleanup_free_
char *p
= NULL
;
104 r
= fopen_temporary(fn
, &f
, &p
);
108 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
109 (void) fchmod_umask(fileno(f
), 0644);
111 r
= write_string_stream_ts(f
, line
, flags
, ts
);
115 if (rename(p
, fn
) < 0) {
127 int write_string_file_ts(
130 WriteStringFileFlags flags
,
131 struct timespec
*ts
) {
133 _cleanup_fclose_
FILE *f
= NULL
;
139 /* We don't know how to verify whether the file contents was already on-disk. */
140 assert(!((flags
& WRITE_STRING_FILE_VERIFY_ON_FAILURE
) && (flags
& WRITE_STRING_FILE_SYNC
)));
142 if (flags
& WRITE_STRING_FILE_ATOMIC
) {
143 assert(flags
& WRITE_STRING_FILE_CREATE
);
145 r
= write_string_file_atomic(fn
, line
, flags
, ts
);
153 if (flags
& WRITE_STRING_FILE_CREATE
) {
162 /* We manually build our own version of fopen(..., "we") that
163 * works without O_CREAT */
164 fd
= open(fn
, O_WRONLY
|O_CLOEXEC
|O_NOCTTY
);
170 f
= fdopen(fd
, "we");
178 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
180 if (flags
& WRITE_STRING_FILE_DISABLE_BUFFER
)
181 setvbuf(f
, NULL
, _IONBF
, 0);
183 r
= write_string_stream_ts(f
, line
, flags
, ts
);
190 if (!(flags
& WRITE_STRING_FILE_VERIFY_ON_FAILURE
))
195 /* OK, the operation failed, but let's see if the right
196 * contents in place already. If so, eat up the error. */
198 q
= verify_file(fn
, line
, !(flags
& WRITE_STRING_FILE_AVOID_NEWLINE
));
205 int read_one_line_file(const char *fn
, char **line
) {
206 _cleanup_fclose_
FILE *f
= NULL
;
216 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
218 r
= read_line(f
, LONG_LINE_MAX
, line
);
219 return r
< 0 ? r
: 0;
222 int verify_file(const char *fn
, const char *blob
, bool accept_extra_nl
) {
223 _cleanup_fclose_
FILE *f
= NULL
;
224 _cleanup_free_
char *buf
= NULL
;
232 if (accept_extra_nl
&& endswith(blob
, "\n"))
233 accept_extra_nl
= false;
235 buf
= malloc(l
+ accept_extra_nl
+ 1);
243 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
245 /* We try to read one byte more than we need, so that we know whether we hit eof */
247 k
= fread(buf
, 1, l
+ accept_extra_nl
+ 1, f
);
249 return errno
> 0 ? -errno
: -EIO
;
251 if (k
!= l
&& k
!= l
+ accept_extra_nl
)
253 if (memcmp(buf
, blob
, l
) != 0)
255 if (k
> l
&& buf
[l
] != '\n')
261 int read_full_stream(FILE *f
, char **contents
, size_t *size
) {
263 _cleanup_free_
char *buf
= NULL
;
269 if (fstat(fileno(f
), &st
) < 0)
274 if (S_ISREG(st
.st_mode
)) {
277 if (st
.st_size
> READ_FULL_BYTES_MAX
)
280 /* Start with the right file size, but be prepared for files from /proc which generally report a file
281 * size of 0. Note that we increase the size to read here by one, so that the first read attempt
282 * already makes us notice the EOF. */
292 t
= realloc(buf
, n
+ 1);
298 k
= fread(buf
+ l
, 1, n
- l
, f
);
303 return errno
> 0 ? -errno
: -EIO
;
308 /* We aren't expecting fread() to return a short read outside
309 * of (error && eof), assert buffer is full and enlarge buffer.
314 if (n
>= READ_FULL_BYTES_MAX
)
317 n
= MIN(n
* 2, READ_FULL_BYTES_MAX
);
322 buf
= NULL
; /* do not free */
330 int read_full_file(const char *fn
, char **contents
, size_t *size
) {
331 _cleanup_fclose_
FILE *f
= NULL
;
340 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
342 return read_full_stream(f
, contents
, size
);
345 static int parse_env_file_internal(
349 int (*push
) (const char *filename
, unsigned line
,
350 const char *key
, char *value
, void *userdata
, int *n_pushed
),
354 _cleanup_free_
char *contents
= NULL
, *key
= NULL
;
355 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;
356 char *p
, *value
= NULL
;
367 SINGLE_QUOTE_VALUE_ESCAPE
,
369 DOUBLE_QUOTE_VALUE_ESCAPE
,
377 r
= read_full_stream(f
, &contents
, NULL
);
379 r
= read_full_file(fname
, &contents
, NULL
);
383 for (p
= contents
; *p
; p
++) {
389 if (strchr(COMMENTS
, c
))
391 else if (!strchr(WHITESPACE
, c
)) {
393 last_key_whitespace
= (size_t) -1;
395 if (!GREEDY_REALLOC(key
, key_alloc
, n_key
+2)) {
405 if (strchr(newline
, c
)) {
409 } else if (c
== '=') {
411 last_value_whitespace
= (size_t) -1;
413 if (!strchr(WHITESPACE
, c
))
414 last_key_whitespace
= (size_t) -1;
415 else if (last_key_whitespace
== (size_t) -1)
416 last_key_whitespace
= n_key
;
418 if (!GREEDY_REALLOC(key
, key_alloc
, n_key
+2)) {
429 if (strchr(newline
, c
)) {
437 /* strip trailing whitespace from key */
438 if (last_key_whitespace
!= (size_t) -1)
439 key
[last_key_whitespace
] = 0;
441 r
= push(fname
, line
, key
, value
, userdata
, n_pushed
);
447 value_alloc
= n_value
= 0;
449 } else if (c
== '\'')
450 state
= SINGLE_QUOTE_VALUE
;
452 state
= DOUBLE_QUOTE_VALUE
;
454 state
= VALUE_ESCAPE
;
455 else if (!strchr(WHITESPACE
, c
)) {
458 if (!GREEDY_REALLOC(value
, value_alloc
, n_value
+2)) {
463 value
[n_value
++] = c
;
469 if (strchr(newline
, c
)) {
478 /* Chomp off trailing whitespace from value */
479 if (last_value_whitespace
!= (size_t) -1)
480 value
[last_value_whitespace
] = 0;
482 /* strip trailing whitespace from key */
483 if (last_key_whitespace
!= (size_t) -1)
484 key
[last_key_whitespace
] = 0;
486 r
= push(fname
, line
, key
, value
, userdata
, n_pushed
);
492 value_alloc
= n_value
= 0;
494 } else if (c
== '\\') {
495 state
= VALUE_ESCAPE
;
496 last_value_whitespace
= (size_t) -1;
498 if (!strchr(WHITESPACE
, c
))
499 last_value_whitespace
= (size_t) -1;
500 else if (last_value_whitespace
== (size_t) -1)
501 last_value_whitespace
= n_value
;
503 if (!GREEDY_REALLOC(value
, value_alloc
, n_value
+2)) {
508 value
[n_value
++] = c
;
516 if (!strchr(newline
, c
)) {
517 /* Escaped newlines we eat up entirely */
518 if (!GREEDY_REALLOC(value
, value_alloc
, n_value
+2)) {
523 value
[n_value
++] = c
;
527 case SINGLE_QUOTE_VALUE
:
531 state
= SINGLE_QUOTE_VALUE_ESCAPE
;
533 if (!GREEDY_REALLOC(value
, value_alloc
, n_value
+2)) {
538 value
[n_value
++] = c
;
543 case SINGLE_QUOTE_VALUE_ESCAPE
:
544 state
= SINGLE_QUOTE_VALUE
;
546 if (!strchr(newline
, c
)) {
547 if (!GREEDY_REALLOC(value
, value_alloc
, n_value
+2)) {
552 value
[n_value
++] = c
;
556 case DOUBLE_QUOTE_VALUE
:
560 state
= DOUBLE_QUOTE_VALUE_ESCAPE
;
562 if (!GREEDY_REALLOC(value
, value_alloc
, n_value
+2)) {
567 value
[n_value
++] = c
;
572 case DOUBLE_QUOTE_VALUE_ESCAPE
:
573 state
= DOUBLE_QUOTE_VALUE
;
575 if (!strchr(newline
, c
)) {
576 if (!GREEDY_REALLOC(value
, value_alloc
, n_value
+2)) {
581 value
[n_value
++] = c
;
587 state
= COMMENT_ESCAPE
;
588 else if (strchr(newline
, c
)) {
605 SINGLE_QUOTE_VALUE_ESCAPE
,
607 DOUBLE_QUOTE_VALUE_ESCAPE
)) {
615 if (last_value_whitespace
!= (size_t) -1)
616 value
[last_value_whitespace
] = 0;
618 /* strip trailing whitespace from key */
619 if (last_key_whitespace
!= (size_t) -1)
620 key
[last_key_whitespace
] = 0;
622 r
= push(fname
, line
, key
, value
, userdata
, n_pushed
);
634 static int check_utf8ness_and_warn(
635 const char *filename
, unsigned line
,
636 const char *key
, char *value
) {
638 if (!utf8_is_valid(key
)) {
639 _cleanup_free_
char *p
= NULL
;
641 p
= utf8_escape_invalid(key
);
642 log_error("%s:%u: invalid UTF-8 in key '%s', ignoring.", strna(filename
), line
, p
);
646 if (value
&& !utf8_is_valid(value
)) {
647 _cleanup_free_
char *p
= NULL
;
649 p
= utf8_escape_invalid(value
);
650 log_error("%s:%u: invalid UTF-8 value for key %s: '%s', ignoring.", strna(filename
), line
, key
, p
);
657 static int parse_env_file_push(
658 const char *filename
, unsigned line
,
659 const char *key
, char *value
,
664 va_list aq
, *ap
= userdata
;
667 r
= check_utf8ness_and_warn(filename
, line
, key
, value
);
673 while ((k
= va_arg(aq
, const char *))) {
676 v
= va_arg(aq
, char **);
698 const char *newline
, ...) {
706 va_start(ap
, newline
);
707 r
= parse_env_file_internal(NULL
, fname
, newline
, parse_env_file_push
, &ap
, &n_pushed
);
710 return r
< 0 ? r
: n_pushed
;
713 static int load_env_file_push(
714 const char *filename
, unsigned line
,
715 const char *key
, char *value
,
718 char ***m
= userdata
;
722 r
= check_utf8ness_and_warn(filename
, line
, key
, value
);
726 p
= strjoin(key
, "=", value
);
730 r
= strv_env_replace(m
, p
);
743 int load_env_file(FILE *f
, const char *fname
, const char *newline
, char ***rl
) {
750 r
= parse_env_file_internal(f
, fname
, newline
, load_env_file_push
, &m
, NULL
);
760 static int load_env_file_push_pairs(
761 const char *filename
, unsigned line
,
762 const char *key
, char *value
,
765 char ***m
= userdata
;
768 r
= check_utf8ness_and_warn(filename
, line
, key
, value
);
772 r
= strv_extend(m
, key
);
777 r
= strv_extend(m
, "");
781 r
= strv_push(m
, value
);
792 int load_env_file_pairs(FILE *f
, const char *fname
, const char *newline
, char ***rl
) {
799 r
= parse_env_file_internal(f
, fname
, newline
, load_env_file_push_pairs
, &m
, NULL
);
809 static int merge_env_file_push(
810 const char *filename
, unsigned line
,
811 const char *key
, char *value
,
815 char ***env
= userdata
;
816 char *expanded_value
;
821 log_error("%s:%u: invalid syntax (around \"%s\"), ignoring.", strna(filename
), line
, key
);
825 if (!env_name_is_valid(key
)) {
826 log_error("%s:%u: invalid variable name \"%s\", ignoring.", strna(filename
), line
, key
);
831 expanded_value
= replace_env(value
, *env
,
832 REPLACE_ENV_USE_ENVIRONMENT
|
833 REPLACE_ENV_ALLOW_BRACELESS
|
834 REPLACE_ENV_ALLOW_EXTENDED
);
838 free_and_replace(value
, expanded_value
);
840 return load_env_file_push(filename
, line
, key
, value
, env
, n_pushed
);
848 /* NOTE: this function supports braceful and braceless variable expansions,
849 * plus "extended" substitutions, unlike other exported parsing functions.
852 return parse_env_file_internal(f
, fname
, NEWLINE
, merge_env_file_push
, env
, NULL
);
855 static void write_env_var(FILE *f
, const char *v
) {
861 fputs_unlocked(v
, f
);
862 fputc_unlocked('\n', f
);
867 fwrite_unlocked(v
, 1, p
-v
, f
);
869 if (string_has_cc(p
, NULL
) || chars_intersect(p
, WHITESPACE SHELL_NEED_QUOTES
)) {
870 fputc_unlocked('\"', f
);
873 if (strchr(SHELL_NEED_ESCAPE
, *p
))
874 fputc_unlocked('\\', f
);
876 fputc_unlocked(*p
, f
);
879 fputc_unlocked('\"', f
);
881 fputs_unlocked(p
, f
);
883 fputc_unlocked('\n', f
);
886 int write_env_file(const char *fname
, char **l
) {
887 _cleanup_fclose_
FILE *f
= NULL
;
888 _cleanup_free_
char *p
= NULL
;
894 r
= fopen_temporary(fname
, &f
, &p
);
898 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
899 (void) fchmod_umask(fileno(f
), 0644);
902 write_env_var(f
, *i
);
904 r
= fflush_and_check(f
);
906 if (rename(p
, fname
) >= 0)
916 int executable_is_script(const char *path
, char **interpreter
) {
918 _cleanup_free_
char *line
= NULL
;
924 r
= read_one_line_file(path
, &line
);
928 if (!startswith(line
, "#!"))
931 ans
= strstrip(line
+ 2);
932 len
= strcspn(ans
, " \t");
937 ans
= strndup(ans
, len
);
946 * Retrieve one field from a file like /proc/self/status. pattern
947 * should not include whitespace or the delimiter (':'). pattern matches only
948 * the beginning of a line. Whitespace before ':' is skipped. Whitespace and
949 * zeros after the ':' will be skipped. field must be freed afterwards.
950 * terminator specifies the terminating characters of the field value (not
951 * included in the value).
953 int get_proc_field(const char *filename
, const char *pattern
, const char *terminator
, char **field
) {
954 _cleanup_free_
char *status
= NULL
;
964 r
= read_full_file(filename
, &status
, NULL
);
974 t
= strstr(t
, pattern
);
978 /* Check that pattern occurs in beginning of line. */
979 pattern_ok
= (t
== status
|| t
[-1] == '\n');
981 t
+= strlen(pattern
);
983 } while (!pattern_ok
);
985 t
+= strspn(t
, " \t");
994 t
+= strspn(t
, " \t");
996 /* Also skip zeros, because when this is used for
997 * capabilities, we don't want the zeros. This way the
998 * same capability set always maps to the same string,
999 * irrespective of the total capability set size. For
1000 * other numbers it shouldn't matter. */
1001 t
+= strspn(t
, "0");
1002 /* Back off one char if there's nothing but whitespace
1004 if (!*t
|| isspace(*t
))
1008 len
= strcspn(t
, terminator
);
1010 f
= strndup(t
, len
);
1018 DIR *xopendirat(int fd
, const char *name
, int flags
) {
1022 assert(!(flags
& O_CREAT
));
1024 nfd
= openat(fd
, name
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
|flags
, 0);
1037 static int search_and_fopen_internal(const char *path
, const char *mode
, const char *root
, char **search
, FILE **_f
) {
1044 if (!path_strv_resolve_uniq(search
, root
))
1047 STRV_FOREACH(i
, search
) {
1048 _cleanup_free_
char *p
= NULL
;
1052 p
= strjoin(root
, *i
, "/", path
);
1054 p
= strjoin(*i
, "/", path
);
1064 if (errno
!= ENOENT
)
1071 int search_and_fopen(const char *path
, const char *mode
, const char *root
, const char **search
, FILE **_f
) {
1072 _cleanup_strv_free_
char **copy
= NULL
;
1078 if (path_is_absolute(path
)) {
1081 f
= fopen(path
, mode
);
1090 copy
= strv_copy((char**) search
);
1094 return search_and_fopen_internal(path
, mode
, root
, copy
, _f
);
1097 int search_and_fopen_nulstr(const char *path
, const char *mode
, const char *root
, const char *search
, FILE **_f
) {
1098 _cleanup_strv_free_
char **s
= NULL
;
1100 if (path_is_absolute(path
)) {
1103 f
= fopen(path
, mode
);
1112 s
= strv_split_nulstr(search
);
1116 return search_and_fopen_internal(path
, mode
, root
, s
, _f
);
1119 int fopen_temporary(const char *path
, FILE **_f
, char **_temp_path
) {
1128 r
= tempfn_xxxxxx(path
, NULL
, &t
);
1132 fd
= mkostemp_safe(t
);
1138 f
= fdopen(fd
, "we");
1152 int fflush_and_check(FILE *f
) {
1159 return errno
> 0 ? -errno
: -EIO
;
1164 int fflush_sync_and_check(FILE *f
) {
1169 r
= fflush_and_check(f
);
1173 if (fsync(fileno(f
)) < 0)
1179 /* This is much like mkostemp() but is subject to umask(). */
1180 int mkostemp_safe(char *pattern
) {
1181 _cleanup_umask_ mode_t u
= 0;
1188 fd
= mkostemp(pattern
, O_CLOEXEC
);
1195 int tempfn_xxxxxx(const char *p
, const char *extra
, char **ret
) {
1207 * /foo/bar/.#<extra>waldoXXXXXX
1211 if (!filename_is_valid(fn
))
1217 t
= new(char, strlen(p
) + 2 + strlen(extra
) + 6 + 1);
1221 strcpy(stpcpy(stpcpy(stpcpy(mempcpy(t
, p
, fn
- p
), ".#"), extra
), fn
), "XXXXXX");
1223 *ret
= path_kill_slashes(t
);
1227 int tempfn_random(const char *p
, const char *extra
, char **ret
) {
1241 * /foo/bar/.#<extra>waldobaa2a261115984a9
1245 if (!filename_is_valid(fn
))
1251 t
= new(char, strlen(p
) + 2 + strlen(extra
) + 16 + 1);
1255 x
= stpcpy(stpcpy(stpcpy(mempcpy(t
, p
, fn
- p
), ".#"), extra
), fn
);
1258 for (i
= 0; i
< 16; i
++) {
1259 *(x
++) = hexchar(u
& 0xF);
1265 *ret
= path_kill_slashes(t
);
1269 int tempfn_random_child(const char *p
, const char *extra
, char **ret
) {
1280 * /foo/bar/waldo/.#<extra>3c2b6219aa75d7d0
1292 t
= new(char, strlen(p
) + 3 + strlen(extra
) + 16 + 1);
1296 x
= stpcpy(stpcpy(stpcpy(t
, p
), "/.#"), extra
);
1299 for (i
= 0; i
< 16; i
++) {
1300 *(x
++) = hexchar(u
& 0xF);
1306 *ret
= path_kill_slashes(t
);
1310 int write_timestamp_file_atomic(const char *fn
, usec_t n
) {
1311 char ln
[DECIMAL_STR_MAX(n
)+2];
1313 /* Creates a "timestamp" file, that contains nothing but a
1314 * usec_t timestamp, formatted in ASCII. */
1316 if (n
<= 0 || n
>= USEC_INFINITY
)
1319 xsprintf(ln
, USEC_FMT
"\n", n
);
1321 return write_string_file(fn
, ln
, WRITE_STRING_FILE_CREATE
|WRITE_STRING_FILE_ATOMIC
);
1324 int read_timestamp_file(const char *fn
, usec_t
*ret
) {
1325 _cleanup_free_
char *ln
= NULL
;
1329 r
= read_one_line_file(fn
, &ln
);
1333 r
= safe_atou64(ln
, &t
);
1337 if (t
<= 0 || t
>= (uint64_t) USEC_INFINITY
)
1344 int fputs_with_space(FILE *f
, const char *s
, const char *separator
, bool *space
) {
1349 /* Outputs the specified string with fputs(), but optionally prefixes it with a separator. The *space parameter
1350 * when specified shall initially point to a boolean variable initialized to false. It is set to true after the
1351 * first invocation. This call is supposed to be use in loops, where a separator shall be inserted between each
1352 * element, but not before the first one. */
1362 r
= fputs(separator
, f
);
1373 int open_tmpfile_unlinkable(const char *directory
, int flags
) {
1378 r
= tmp_dir(&directory
);
1383 /* Returns an unlinked temporary file that cannot be linked into the file system anymore */
1385 /* Try O_TMPFILE first, if it is supported */
1386 fd
= open(directory
, flags
|O_TMPFILE
|O_EXCL
, S_IRUSR
|S_IWUSR
);
1390 /* Fall back to unguessable name + unlinking */
1391 p
= strjoina(directory
, "/systemd-tmp-XXXXXX");
1393 fd
= mkostemp_safe(p
);
1402 int open_tmpfile_linkable(const char *target
, int flags
, char **ret_path
) {
1403 _cleanup_free_
char *tmp
= NULL
;
1409 /* Don't allow O_EXCL, as that has a special meaning for O_TMPFILE */
1410 assert((flags
& O_EXCL
) == 0);
1412 /* Creates a temporary file, that shall be renamed to "target" later. If possible, this uses O_TMPFILE – in
1413 * which case "ret_path" will be returned as NULL. If not possible a the tempoary path name used is returned in
1414 * "ret_path". Use link_tmpfile() below to rename the result after writing the file in full. */
1417 _cleanup_free_
char *dn
= NULL
;
1419 dn
= dirname_malloc(target
);
1423 fd
= open(dn
, O_TMPFILE
|flags
, 0640);
1429 log_debug_errno(errno
, "Failed to use O_TMPFILE on %s: %m", dn
);
1432 r
= tempfn_random(target
, NULL
, &tmp
);
1436 fd
= open(tmp
, O_CREAT
|O_EXCL
|O_NOFOLLOW
|O_NOCTTY
|flags
, 0640);
1446 int open_serialization_fd(const char *ident
) {
1449 fd
= memfd_create(ident
, MFD_CLOEXEC
);
1453 path
= getpid_cached() == 1 ? "/run/systemd" : "/tmp";
1454 fd
= open_tmpfile_unlinkable(path
, O_RDWR
|O_CLOEXEC
);
1458 log_debug("Serializing %s to %s.", ident
, path
);
1460 log_debug("Serializing %s to memfd.", ident
);
1465 int link_tmpfile(int fd
, const char *path
, const char *target
) {
1470 /* Moves a temporary file created with open_tmpfile() above into its final place. if "path" is NULL an fd
1471 * created with O_TMPFILE is assumed, and linkat() is used. Otherwise it is assumed O_TMPFILE is not supported
1472 * on the directory, and renameat2() is used instead.
1474 * Note that in both cases we will not replace existing files. This is because linkat() does not support this
1475 * operation currently (renameat2() does), and there is no nice way to emulate this. */
1478 if (rename_noreplace(AT_FDCWD
, path
, AT_FDCWD
, target
) < 0)
1481 char proc_fd_path
[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(fd
) + 1];
1483 xsprintf(proc_fd_path
, "/proc/self/fd/%i", fd
);
1485 if (linkat(AT_FDCWD
, proc_fd_path
, AT_FDCWD
, target
, AT_SYMLINK_FOLLOW
) < 0)
1492 int read_nul_string(FILE *f
, char **ret
) {
1493 _cleanup_free_
char *x
= NULL
;
1494 size_t allocated
= 0, n
= 0;
1499 /* Reads a NUL-terminated string from the specified file. */
1504 if (!GREEDY_REALLOC(x
, allocated
, n
+2))
1508 if (c
== 0) /* Terminate at NUL byte */
1513 break; /* Terminate at EOF */
1533 int mkdtemp_malloc(const char *template, char **ret
) {
1539 p
= strdup(template);
1552 DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, funlockfile
);
1554 int read_line(FILE *f
, size_t limit
, char **ret
) {
1555 _cleanup_free_
char *buffer
= NULL
;
1556 size_t n
= 0, allocated
= 0, count
= 0;
1560 /* Something like a bounded version of getline().
1562 * Considers EOF, \n and \0 end of line delimiters, and does not include these delimiters in the string
1565 * Returns the number of bytes read from the files (i.e. including delimiters — this hence usually differs from
1566 * the number of characters in the returned string). When EOF is hit, 0 is returned.
1568 * The input parameter limit is the maximum numbers of characters in the returned string, i.e. excluding
1569 * delimiters. If the limit is hit we fail and return -ENOBUFS.
1571 * If a line shall be skipped ret may be initialized as NULL. */
1574 if (!GREEDY_REALLOC(buffer
, allocated
, 1))
1579 _unused_
_cleanup_(funlockfilep
) FILE *flocked
= f
;
1589 c
= fgetc_unlocked(f
);
1591 /* if we read an error, and have no data to return, then propagate the error */
1592 if (ferror_unlocked(f
) && n
== 0)
1593 return errno
> 0 ? -errno
: -EIO
;
1600 if (IN_SET(c
, '\n', 0)) /* Reached a delimiter */
1604 if (!GREEDY_REALLOC(buffer
, allocated
, n
+ 2))
1607 buffer
[n
] = (char) c
;