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
) {
69 if (!(flags
& WRITE_STRING_FILE_AVOID_NEWLINE
) && !endswith(line
, "\n"))
73 struct timespec twice
[2] = {*ts
, *ts
};
75 if (futimens(fileno(f
), twice
) < 0)
79 if (flags
& WRITE_STRING_FILE_SYNC
)
80 return fflush_sync_and_check(f
);
82 return fflush_and_check(f
);
85 static int write_string_file_atomic(
88 WriteStringFileFlags flags
,
89 struct timespec
*ts
) {
91 _cleanup_fclose_
FILE *f
= NULL
;
92 _cleanup_free_
char *p
= NULL
;
98 r
= fopen_temporary(fn
, &f
, &p
);
102 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
103 (void) fchmod_umask(fileno(f
), 0644);
105 r
= write_string_stream_ts(f
, line
, flags
, ts
);
109 if (rename(p
, fn
) < 0) {
121 int write_string_file_ts(
124 WriteStringFileFlags flags
,
125 struct timespec
*ts
) {
127 _cleanup_fclose_
FILE *f
= NULL
;
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
)));
136 if (flags
& WRITE_STRING_FILE_ATOMIC
) {
137 assert(flags
& WRITE_STRING_FILE_CREATE
);
139 r
= write_string_file_atomic(fn
, line
, flags
, ts
);
147 if (flags
& WRITE_STRING_FILE_CREATE
) {
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
);
164 f
= fdopen(fd
, "we");
172 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
174 if (flags
& WRITE_STRING_FILE_DISABLE_BUFFER
)
175 setvbuf(f
, NULL
, _IONBF
, 0);
177 r
= write_string_stream_ts(f
, line
, flags
, ts
);
184 if (!(flags
& WRITE_STRING_FILE_VERIFY_ON_FAILURE
))
189 /* OK, the operation failed, but let's see if the right
190 * contents in place already. If so, eat up the error. */
192 q
= verify_file(fn
, line
, !(flags
& WRITE_STRING_FILE_AVOID_NEWLINE
));
199 int read_one_line_file(const char *fn
, char **line
) {
200 _cleanup_fclose_
FILE *f
= NULL
;
210 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
212 r
= read_line(f
, LONG_LINE_MAX
, line
);
213 return r
< 0 ? r
: 0;
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
;
226 if (accept_extra_nl
&& endswith(blob
, "\n"))
227 accept_extra_nl
= false;
229 buf
= malloc(l
+ accept_extra_nl
+ 1);
237 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
239 /* We try to read one byte more than we need, so that we know whether we hit eof */
241 k
= fread(buf
, 1, l
+ accept_extra_nl
+ 1, f
);
243 return errno
> 0 ? -errno
: -EIO
;
245 if (k
!= l
&& k
!= l
+ accept_extra_nl
)
247 if (memcmp(buf
, blob
, l
) != 0)
249 if (k
> l
&& buf
[l
] != '\n')
255 int read_full_stream(FILE *f
, char **contents
, size_t *size
) {
257 _cleanup_free_
char *buf
= NULL
;
263 if (fstat(fileno(f
), &st
) < 0)
268 if (S_ISREG(st
.st_mode
)) {
271 if (st
.st_size
> READ_FULL_BYTES_MAX
)
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. */
286 t
= realloc(buf
, n
+ 1);
292 k
= fread(buf
+ l
, 1, n
- l
, f
);
297 return errno
> 0 ? -errno
: -EIO
;
302 /* We aren't expecting fread() to return a short read outside
303 * of (error && eof), assert buffer is full and enlarge buffer.
308 if (n
>= READ_FULL_BYTES_MAX
)
311 n
= MIN(n
* 2, READ_FULL_BYTES_MAX
);
316 buf
= NULL
; /* do not free */
324 int read_full_file(const char *fn
, char **contents
, size_t *size
) {
325 _cleanup_fclose_
FILE *f
= NULL
;
334 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
336 return read_full_stream(f
, contents
, size
);
339 static int parse_env_file_internal(
343 int (*push
) (const char *filename
, unsigned line
,
344 const char *key
, char *value
, void *userdata
, int *n_pushed
),
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
;
361 SINGLE_QUOTE_VALUE_ESCAPE
,
363 DOUBLE_QUOTE_VALUE_ESCAPE
,
371 r
= read_full_stream(f
, &contents
, NULL
);
373 r
= read_full_file(fname
, &contents
, NULL
);
377 for (p
= contents
; *p
; p
++) {
383 if (strchr(COMMENTS
, c
))
385 else if (!strchr(WHITESPACE
, c
)) {
387 last_key_whitespace
= (size_t) -1;
389 if (!GREEDY_REALLOC(key
, key_alloc
, n_key
+2)) {
399 if (strchr(newline
, c
)) {
403 } else if (c
== '=') {
405 last_value_whitespace
= (size_t) -1;
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
;
412 if (!GREEDY_REALLOC(key
, key_alloc
, n_key
+2)) {
423 if (strchr(newline
, c
)) {
431 /* strip trailing whitespace from key */
432 if (last_key_whitespace
!= (size_t) -1)
433 key
[last_key_whitespace
] = 0;
435 r
= push(fname
, line
, key
, value
, userdata
, n_pushed
);
441 value_alloc
= n_value
= 0;
443 } else if (c
== '\'')
444 state
= SINGLE_QUOTE_VALUE
;
446 state
= DOUBLE_QUOTE_VALUE
;
448 state
= VALUE_ESCAPE
;
449 else if (!strchr(WHITESPACE
, c
)) {
452 if (!GREEDY_REALLOC(value
, value_alloc
, n_value
+2)) {
457 value
[n_value
++] = c
;
463 if (strchr(newline
, c
)) {
472 /* Chomp off trailing whitespace from value */
473 if (last_value_whitespace
!= (size_t) -1)
474 value
[last_value_whitespace
] = 0;
476 /* strip trailing whitespace from key */
477 if (last_key_whitespace
!= (size_t) -1)
478 key
[last_key_whitespace
] = 0;
480 r
= push(fname
, line
, key
, value
, userdata
, n_pushed
);
486 value_alloc
= n_value
= 0;
488 } else if (c
== '\\') {
489 state
= VALUE_ESCAPE
;
490 last_value_whitespace
= (size_t) -1;
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
;
497 if (!GREEDY_REALLOC(value
, value_alloc
, n_value
+2)) {
502 value
[n_value
++] = c
;
510 if (!strchr(newline
, c
)) {
511 /* Escaped newlines we eat up entirely */
512 if (!GREEDY_REALLOC(value
, value_alloc
, n_value
+2)) {
517 value
[n_value
++] = c
;
521 case SINGLE_QUOTE_VALUE
:
525 state
= SINGLE_QUOTE_VALUE_ESCAPE
;
527 if (!GREEDY_REALLOC(value
, value_alloc
, n_value
+2)) {
532 value
[n_value
++] = c
;
537 case SINGLE_QUOTE_VALUE_ESCAPE
:
538 state
= SINGLE_QUOTE_VALUE
;
540 if (!strchr(newline
, c
)) {
541 if (!GREEDY_REALLOC(value
, value_alloc
, n_value
+2)) {
546 value
[n_value
++] = c
;
550 case DOUBLE_QUOTE_VALUE
:
554 state
= DOUBLE_QUOTE_VALUE_ESCAPE
;
556 if (!GREEDY_REALLOC(value
, value_alloc
, n_value
+2)) {
561 value
[n_value
++] = c
;
566 case DOUBLE_QUOTE_VALUE_ESCAPE
:
567 state
= DOUBLE_QUOTE_VALUE
;
569 if (!strchr(newline
, c
)) {
570 if (!GREEDY_REALLOC(value
, value_alloc
, n_value
+2)) {
575 value
[n_value
++] = c
;
581 state
= COMMENT_ESCAPE
;
582 else if (strchr(newline
, c
)) {
599 SINGLE_QUOTE_VALUE_ESCAPE
,
601 DOUBLE_QUOTE_VALUE_ESCAPE
)) {
609 if (last_value_whitespace
!= (size_t) -1)
610 value
[last_value_whitespace
] = 0;
612 /* strip trailing whitespace from key */
613 if (last_key_whitespace
!= (size_t) -1)
614 key
[last_key_whitespace
] = 0;
616 r
= push(fname
, line
, key
, value
, userdata
, n_pushed
);
628 static int check_utf8ness_and_warn(
629 const char *filename
, unsigned line
,
630 const char *key
, char *value
) {
632 if (!utf8_is_valid(key
)) {
633 _cleanup_free_
char *p
= NULL
;
635 p
= utf8_escape_invalid(key
);
636 log_error("%s:%u: invalid UTF-8 in key '%s', ignoring.", strna(filename
), line
, p
);
640 if (value
&& !utf8_is_valid(value
)) {
641 _cleanup_free_
char *p
= NULL
;
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
);
651 static int parse_env_file_push(
652 const char *filename
, unsigned line
,
653 const char *key
, char *value
,
658 va_list aq
, *ap
= userdata
;
661 r
= check_utf8ness_and_warn(filename
, line
, key
, value
);
667 while ((k
= va_arg(aq
, const char *))) {
670 v
= va_arg(aq
, char **);
692 const char *newline
, ...) {
700 va_start(ap
, newline
);
701 r
= parse_env_file_internal(NULL
, fname
, newline
, parse_env_file_push
, &ap
, &n_pushed
);
704 return r
< 0 ? r
: n_pushed
;
707 static int load_env_file_push(
708 const char *filename
, unsigned line
,
709 const char *key
, char *value
,
712 char ***m
= userdata
;
716 r
= check_utf8ness_and_warn(filename
, line
, key
, value
);
720 p
= strjoin(key
, "=", value
);
724 r
= strv_env_replace(m
, p
);
737 int load_env_file(FILE *f
, const char *fname
, const char *newline
, char ***rl
) {
744 r
= parse_env_file_internal(f
, fname
, newline
, load_env_file_push
, &m
, NULL
);
754 static int load_env_file_push_pairs(
755 const char *filename
, unsigned line
,
756 const char *key
, char *value
,
759 char ***m
= userdata
;
762 r
= check_utf8ness_and_warn(filename
, line
, key
, value
);
766 r
= strv_extend(m
, key
);
771 r
= strv_extend(m
, "");
775 r
= strv_push(m
, value
);
786 int load_env_file_pairs(FILE *f
, const char *fname
, const char *newline
, char ***rl
) {
793 r
= parse_env_file_internal(f
, fname
, newline
, load_env_file_push_pairs
, &m
, NULL
);
803 static int merge_env_file_push(
804 const char *filename
, unsigned line
,
805 const char *key
, char *value
,
809 char ***env
= userdata
;
810 char *expanded_value
;
815 log_error("%s:%u: invalid syntax (around \"%s\"), ignoring.", strna(filename
), line
, key
);
819 if (!env_name_is_valid(key
)) {
820 log_error("%s:%u: invalid variable name \"%s\", ignoring.", strna(filename
), line
, key
);
825 expanded_value
= replace_env(value
, *env
,
826 REPLACE_ENV_USE_ENVIRONMENT
|
827 REPLACE_ENV_ALLOW_BRACELESS
|
828 REPLACE_ENV_ALLOW_EXTENDED
);
832 free_and_replace(value
, expanded_value
);
834 return load_env_file_push(filename
, line
, key
, value
, env
, n_pushed
);
842 /* NOTE: this function supports braceful and braceless variable expansions,
843 * plus "extended" substitutions, unlike other exported parsing functions.
846 return parse_env_file_internal(f
, fname
, NEWLINE
, merge_env_file_push
, env
, NULL
);
849 static void write_env_var(FILE *f
, const char *v
) {
855 fputs_unlocked(v
, f
);
856 fputc_unlocked('\n', f
);
861 fwrite_unlocked(v
, 1, p
-v
, f
);
863 if (string_has_cc(p
, NULL
) || chars_intersect(p
, WHITESPACE SHELL_NEED_QUOTES
)) {
864 fputc_unlocked('\"', f
);
867 if (strchr(SHELL_NEED_ESCAPE
, *p
))
868 fputc_unlocked('\\', f
);
870 fputc_unlocked(*p
, f
);
873 fputc_unlocked('\"', f
);
875 fputs_unlocked(p
, f
);
877 fputc_unlocked('\n', f
);
880 int write_env_file(const char *fname
, char **l
) {
881 _cleanup_fclose_
FILE *f
= NULL
;
882 _cleanup_free_
char *p
= NULL
;
888 r
= fopen_temporary(fname
, &f
, &p
);
892 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
893 (void) fchmod_umask(fileno(f
), 0644);
896 write_env_var(f
, *i
);
898 r
= fflush_and_check(f
);
900 if (rename(p
, fname
) >= 0)
910 int executable_is_script(const char *path
, char **interpreter
) {
912 _cleanup_free_
char *line
= NULL
;
918 r
= read_one_line_file(path
, &line
);
922 if (!startswith(line
, "#!"))
925 ans
= strstrip(line
+ 2);
926 len
= strcspn(ans
, " \t");
931 ans
= strndup(ans
, len
);
940 * Retrieve one field from a file like /proc/self/status. pattern
941 * should not include whitespace or the delimiter (':'). pattern matches only
942 * the beginning of a line. Whitespace before ':' is skipped. Whitespace and
943 * zeros after the ':' will be skipped. field must be freed afterwards.
944 * terminator specifies the terminating characters of the field value (not
945 * included in the value).
947 int get_proc_field(const char *filename
, const char *pattern
, const char *terminator
, char **field
) {
948 _cleanup_free_
char *status
= NULL
;
958 r
= read_full_file(filename
, &status
, NULL
);
968 t
= strstr(t
, pattern
);
972 /* Check that pattern occurs in beginning of line. */
973 pattern_ok
= (t
== status
|| t
[-1] == '\n');
975 t
+= strlen(pattern
);
977 } while (!pattern_ok
);
979 t
+= strspn(t
, " \t");
988 t
+= strspn(t
, " \t");
990 /* Also skip zeros, because when this is used for
991 * capabilities, we don't want the zeros. This way the
992 * same capability set always maps to the same string,
993 * irrespective of the total capability set size. For
994 * other numbers it shouldn't matter. */
996 /* Back off one char if there's nothing but whitespace
998 if (!*t
|| isspace(*t
))
1002 len
= strcspn(t
, terminator
);
1004 f
= strndup(t
, len
);
1012 DIR *xopendirat(int fd
, const char *name
, int flags
) {
1016 assert(!(flags
& O_CREAT
));
1018 nfd
= openat(fd
, name
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
|flags
, 0);
1031 static int search_and_fopen_internal(const char *path
, const char *mode
, const char *root
, char **search
, FILE **_f
) {
1038 if (!path_strv_resolve_uniq(search
, root
))
1041 STRV_FOREACH(i
, search
) {
1042 _cleanup_free_
char *p
= NULL
;
1046 p
= strjoin(root
, *i
, "/", path
);
1048 p
= strjoin(*i
, "/", path
);
1058 if (errno
!= ENOENT
)
1065 int search_and_fopen(const char *path
, const char *mode
, const char *root
, const char **search
, FILE **_f
) {
1066 _cleanup_strv_free_
char **copy
= NULL
;
1072 if (path_is_absolute(path
)) {
1075 f
= fopen(path
, mode
);
1084 copy
= strv_copy((char**) search
);
1088 return search_and_fopen_internal(path
, mode
, root
, copy
, _f
);
1091 int search_and_fopen_nulstr(const char *path
, const char *mode
, const char *root
, const char *search
, FILE **_f
) {
1092 _cleanup_strv_free_
char **s
= NULL
;
1094 if (path_is_absolute(path
)) {
1097 f
= fopen(path
, mode
);
1106 s
= strv_split_nulstr(search
);
1110 return search_and_fopen_internal(path
, mode
, root
, s
, _f
);
1113 int fopen_temporary(const char *path
, FILE **_f
, char **_temp_path
) {
1122 r
= tempfn_xxxxxx(path
, NULL
, &t
);
1126 fd
= mkostemp_safe(t
);
1132 f
= fdopen(fd
, "we");
1146 int fflush_and_check(FILE *f
) {
1153 return errno
> 0 ? -errno
: -EIO
;
1158 int fflush_sync_and_check(FILE *f
) {
1163 r
= fflush_and_check(f
);
1167 if (fsync(fileno(f
)) < 0)
1173 /* This is much like mkostemp() but is subject to umask(). */
1174 int mkostemp_safe(char *pattern
) {
1175 _cleanup_umask_ mode_t u
= 0;
1182 fd
= mkostemp(pattern
, O_CLOEXEC
);
1189 int tempfn_xxxxxx(const char *p
, const char *extra
, char **ret
) {
1201 * /foo/bar/.#<extra>waldoXXXXXX
1205 if (!filename_is_valid(fn
))
1211 t
= new(char, strlen(p
) + 2 + strlen(extra
) + 6 + 1);
1215 strcpy(stpcpy(stpcpy(stpcpy(mempcpy(t
, p
, fn
- p
), ".#"), extra
), fn
), "XXXXXX");
1217 *ret
= path_kill_slashes(t
);
1221 int tempfn_random(const char *p
, const char *extra
, char **ret
) {
1235 * /foo/bar/.#<extra>waldobaa2a261115984a9
1239 if (!filename_is_valid(fn
))
1245 t
= new(char, strlen(p
) + 2 + strlen(extra
) + 16 + 1);
1249 x
= stpcpy(stpcpy(stpcpy(mempcpy(t
, p
, fn
- p
), ".#"), extra
), fn
);
1252 for (i
= 0; i
< 16; i
++) {
1253 *(x
++) = hexchar(u
& 0xF);
1259 *ret
= path_kill_slashes(t
);
1263 int tempfn_random_child(const char *p
, const char *extra
, char **ret
) {
1274 * /foo/bar/waldo/.#<extra>3c2b6219aa75d7d0
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);
1440 int open_serialization_fd(const char *ident
) {
1443 fd
= memfd_create(ident
, MFD_CLOEXEC
);
1447 path
= getpid_cached() == 1 ? "/run/systemd" : "/tmp";
1448 fd
= open_tmpfile_unlinkable(path
, O_RDWR
|O_CLOEXEC
);
1452 log_debug("Serializing %s to %s.", ident
, path
);
1454 log_debug("Serializing %s to memfd.", ident
);
1459 int link_tmpfile(int fd
, const char *path
, const char *target
) {
1464 /* Moves a temporary file created with open_tmpfile() above into its final place. if "path" is NULL an fd
1465 * created with O_TMPFILE is assumed, and linkat() is used. Otherwise it is assumed O_TMPFILE is not supported
1466 * on the directory, and renameat2() is used instead.
1468 * Note that in both cases we will not replace existing files. This is because linkat() does not support this
1469 * operation currently (renameat2() does), and there is no nice way to emulate this. */
1472 if (rename_noreplace(AT_FDCWD
, path
, AT_FDCWD
, target
) < 0)
1475 char proc_fd_path
[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(fd
) + 1];
1477 xsprintf(proc_fd_path
, "/proc/self/fd/%i", fd
);
1479 if (linkat(AT_FDCWD
, proc_fd_path
, AT_FDCWD
, target
, AT_SYMLINK_FOLLOW
) < 0)
1486 int read_nul_string(FILE *f
, char **ret
) {
1487 _cleanup_free_
char *x
= NULL
;
1488 size_t allocated
= 0, n
= 0;
1493 /* Reads a NUL-terminated string from the specified file. */
1498 if (!GREEDY_REALLOC(x
, allocated
, n
+2))
1502 if (c
== 0) /* Terminate at NUL byte */
1507 break; /* Terminate at EOF */
1527 int mkdtemp_malloc(const char *template, char **ret
) {
1533 p
= strdup(template);
1546 DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, funlockfile
);
1548 int read_line(FILE *f
, size_t limit
, char **ret
) {
1549 _cleanup_free_
char *buffer
= NULL
;
1550 size_t n
= 0, allocated
= 0, count
= 0;
1554 /* Something like a bounded version of getline().
1556 * Considers EOF, \n and \0 end of line delimiters, and does not include these delimiters in the string
1559 * Returns the number of bytes read from the files (i.e. including delimiters — this hence usually differs from
1560 * the number of characters in the returned string). When EOF is hit, 0 is returned.
1562 * The input parameter limit is the maximum numbers of characters in the returned string, i.e. excluding
1563 * delimiters. If the limit is hit we fail and return -ENOBUFS.
1565 * If a line shall be skipped ret may be initialized as NULL. */
1568 if (!GREEDY_REALLOC(buffer
, allocated
, 1))
1573 _unused_
_cleanup_(funlockfilep
) FILE *flocked
= f
;
1583 c
= fgetc_unlocked(f
);
1585 /* if we read an error, and have no data to return, then propagate the error */
1586 if (ferror_unlocked(f
) && n
== 0)
1587 return errno
> 0 ? -errno
: -EIO
;
1594 if (IN_SET(c
, '\n', 0)) /* Reached a delimiter */
1598 if (!GREEDY_REALLOC(buffer
, allocated
, n
+ 2))
1601 buffer
[n
] = (char) c
;