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
) {
68 if (fputs(line
, f
) == EOF
)
71 if (!(flags
& WRITE_STRING_FILE_AVOID_NEWLINE
) && !endswith(line
, "\n"))
72 if (fputc('\n', f
) == EOF
)
76 struct timespec twice
[2] = {*ts
, *ts
};
78 if (futimens(fileno(f
), twice
) < 0)
82 if (flags
& WRITE_STRING_FILE_SYNC
)
83 return fflush_sync_and_check(f
);
85 return fflush_and_check(f
);
88 static int write_string_file_atomic(
91 WriteStringFileFlags flags
,
92 struct timespec
*ts
) {
94 _cleanup_fclose_
FILE *f
= NULL
;
95 _cleanup_free_
char *p
= NULL
;
101 r
= fopen_temporary(fn
, &f
, &p
);
105 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
106 (void) fchmod_umask(fileno(f
), 0644);
108 r
= write_string_stream_ts(f
, line
, flags
, ts
);
112 if (rename(p
, fn
) < 0) {
124 int write_string_file_ts(
127 WriteStringFileFlags flags
,
128 struct timespec
*ts
) {
130 _cleanup_fclose_
FILE *f
= NULL
;
136 /* We don't know how to verify whether the file contents was already on-disk. */
137 assert(!((flags
& WRITE_STRING_FILE_VERIFY_ON_FAILURE
) && (flags
& WRITE_STRING_FILE_SYNC
)));
139 if (flags
& WRITE_STRING_FILE_ATOMIC
) {
140 assert(flags
& WRITE_STRING_FILE_CREATE
);
142 r
= write_string_file_atomic(fn
, line
, flags
, ts
);
150 if (flags
& WRITE_STRING_FILE_CREATE
) {
159 /* We manually build our own version of fopen(..., "we") that
160 * works without O_CREAT */
161 fd
= open(fn
, O_WRONLY
|O_CLOEXEC
|O_NOCTTY
);
167 f
= fdopen(fd
, "we");
175 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
177 if (flags
& WRITE_STRING_FILE_DISABLE_BUFFER
)
178 setvbuf(f
, NULL
, _IONBF
, 0);
180 r
= write_string_stream_ts(f
, line
, flags
, ts
);
187 if (!(flags
& WRITE_STRING_FILE_VERIFY_ON_FAILURE
))
192 /* OK, the operation failed, but let's see if the right
193 * contents in place already. If so, eat up the error. */
195 q
= verify_file(fn
, line
, !(flags
& WRITE_STRING_FILE_AVOID_NEWLINE
));
202 int read_one_line_file(const char *fn
, char **line
) {
203 _cleanup_fclose_
FILE *f
= NULL
;
213 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
215 r
= read_line(f
, LONG_LINE_MAX
, line
);
216 return r
< 0 ? r
: 0;
219 int verify_file(const char *fn
, const char *blob
, bool accept_extra_nl
) {
220 _cleanup_fclose_
FILE *f
= NULL
;
221 _cleanup_free_
char *buf
= NULL
;
229 if (accept_extra_nl
&& endswith(blob
, "\n"))
230 accept_extra_nl
= false;
232 buf
= malloc(l
+ accept_extra_nl
+ 1);
240 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
242 /* We try to read one byte more than we need, so that we know whether we hit eof */
244 k
= fread(buf
, 1, l
+ accept_extra_nl
+ 1, f
);
246 return errno
> 0 ? -errno
: -EIO
;
248 if (k
!= l
&& k
!= l
+ accept_extra_nl
)
250 if (memcmp(buf
, blob
, l
) != 0)
252 if (k
> l
&& buf
[l
] != '\n')
258 int read_full_stream(FILE *f
, char **contents
, size_t *size
) {
260 _cleanup_free_
char *buf
= NULL
;
266 if (fstat(fileno(f
), &st
) < 0)
271 if (S_ISREG(st
.st_mode
)) {
274 if (st
.st_size
> READ_FULL_BYTES_MAX
)
277 /* Start with the right file size, but be prepared for files from /proc which generally report a file
278 * size of 0. Note that we increase the size to read here by one, so that the first read attempt
279 * already makes us notice the EOF. */
289 t
= realloc(buf
, n
+ 1);
295 k
= fread(buf
+ l
, 1, n
- l
, f
);
300 return errno
> 0 ? -errno
: -EIO
;
305 /* We aren't expecting fread() to return a short read outside
306 * of (error && eof), assert buffer is full and enlarge buffer.
311 if (n
>= READ_FULL_BYTES_MAX
)
314 n
= MIN(n
* 2, READ_FULL_BYTES_MAX
);
319 buf
= NULL
; /* do not free */
327 int read_full_file(const char *fn
, char **contents
, size_t *size
) {
328 _cleanup_fclose_
FILE *f
= NULL
;
337 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
339 return read_full_stream(f
, contents
, size
);
342 static int parse_env_file_internal(
346 int (*push
) (const char *filename
, unsigned line
,
347 const char *key
, char *value
, void *userdata
, int *n_pushed
),
351 _cleanup_free_
char *contents
= NULL
, *key
= NULL
;
352 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;
353 char *p
, *value
= NULL
;
364 SINGLE_QUOTE_VALUE_ESCAPE
,
366 DOUBLE_QUOTE_VALUE_ESCAPE
,
374 r
= read_full_stream(f
, &contents
, NULL
);
376 r
= read_full_file(fname
, &contents
, NULL
);
380 for (p
= contents
; *p
; p
++) {
386 if (strchr(COMMENTS
, c
))
388 else if (!strchr(WHITESPACE
, c
)) {
390 last_key_whitespace
= (size_t) -1;
392 if (!GREEDY_REALLOC(key
, key_alloc
, n_key
+2)) {
402 if (strchr(newline
, c
)) {
406 } else if (c
== '=') {
408 last_value_whitespace
= (size_t) -1;
410 if (!strchr(WHITESPACE
, c
))
411 last_key_whitespace
= (size_t) -1;
412 else if (last_key_whitespace
== (size_t) -1)
413 last_key_whitespace
= n_key
;
415 if (!GREEDY_REALLOC(key
, key_alloc
, n_key
+2)) {
426 if (strchr(newline
, c
)) {
434 /* strip trailing whitespace from key */
435 if (last_key_whitespace
!= (size_t) -1)
436 key
[last_key_whitespace
] = 0;
438 r
= push(fname
, line
, key
, value
, userdata
, n_pushed
);
444 value_alloc
= n_value
= 0;
446 } else if (c
== '\'')
447 state
= SINGLE_QUOTE_VALUE
;
449 state
= DOUBLE_QUOTE_VALUE
;
451 state
= VALUE_ESCAPE
;
452 else if (!strchr(WHITESPACE
, c
)) {
455 if (!GREEDY_REALLOC(value
, value_alloc
, n_value
+2)) {
460 value
[n_value
++] = c
;
466 if (strchr(newline
, c
)) {
475 /* Chomp off trailing whitespace from value */
476 if (last_value_whitespace
!= (size_t) -1)
477 value
[last_value_whitespace
] = 0;
479 /* strip trailing whitespace from key */
480 if (last_key_whitespace
!= (size_t) -1)
481 key
[last_key_whitespace
] = 0;
483 r
= push(fname
, line
, key
, value
, userdata
, n_pushed
);
489 value_alloc
= n_value
= 0;
491 } else if (c
== '\\') {
492 state
= VALUE_ESCAPE
;
493 last_value_whitespace
= (size_t) -1;
495 if (!strchr(WHITESPACE
, c
))
496 last_value_whitespace
= (size_t) -1;
497 else if (last_value_whitespace
== (size_t) -1)
498 last_value_whitespace
= n_value
;
500 if (!GREEDY_REALLOC(value
, value_alloc
, n_value
+2)) {
505 value
[n_value
++] = c
;
513 if (!strchr(newline
, c
)) {
514 /* Escaped newlines we eat up entirely */
515 if (!GREEDY_REALLOC(value
, value_alloc
, n_value
+2)) {
520 value
[n_value
++] = c
;
524 case SINGLE_QUOTE_VALUE
:
528 state
= SINGLE_QUOTE_VALUE_ESCAPE
;
530 if (!GREEDY_REALLOC(value
, value_alloc
, n_value
+2)) {
535 value
[n_value
++] = c
;
540 case SINGLE_QUOTE_VALUE_ESCAPE
:
541 state
= SINGLE_QUOTE_VALUE
;
543 if (!strchr(newline
, c
)) {
544 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)) {
564 value
[n_value
++] = c
;
569 case DOUBLE_QUOTE_VALUE_ESCAPE
:
570 state
= DOUBLE_QUOTE_VALUE
;
572 if (!strchr(newline
, c
)) {
573 if (!GREEDY_REALLOC(value
, value_alloc
, n_value
+2)) {
578 value
[n_value
++] = c
;
584 state
= COMMENT_ESCAPE
;
585 else if (strchr(newline
, c
)) {
602 SINGLE_QUOTE_VALUE_ESCAPE
,
604 DOUBLE_QUOTE_VALUE_ESCAPE
)) {
612 if (last_value_whitespace
!= (size_t) -1)
613 value
[last_value_whitespace
] = 0;
615 /* strip trailing whitespace from key */
616 if (last_key_whitespace
!= (size_t) -1)
617 key
[last_key_whitespace
] = 0;
619 r
= push(fname
, line
, key
, value
, userdata
, n_pushed
);
631 static int check_utf8ness_and_warn(
632 const char *filename
, unsigned line
,
633 const char *key
, char *value
) {
635 if (!utf8_is_valid(key
)) {
636 _cleanup_free_
char *p
= NULL
;
638 p
= utf8_escape_invalid(key
);
639 log_error("%s:%u: invalid UTF-8 in key '%s', ignoring.", strna(filename
), line
, p
);
643 if (value
&& !utf8_is_valid(value
)) {
644 _cleanup_free_
char *p
= NULL
;
646 p
= utf8_escape_invalid(value
);
647 log_error("%s:%u: invalid UTF-8 value for key %s: '%s', ignoring.", strna(filename
), line
, key
, p
);
654 static int parse_env_file_push(
655 const char *filename
, unsigned line
,
656 const char *key
, char *value
,
661 va_list aq
, *ap
= userdata
;
664 r
= check_utf8ness_and_warn(filename
, line
, key
, value
);
670 while ((k
= va_arg(aq
, const char *))) {
673 v
= va_arg(aq
, char **);
695 const char *newline
, ...) {
703 va_start(ap
, newline
);
704 r
= parse_env_file_internal(NULL
, fname
, newline
, parse_env_file_push
, &ap
, &n_pushed
);
707 return r
< 0 ? r
: n_pushed
;
710 static int load_env_file_push(
711 const char *filename
, unsigned line
,
712 const char *key
, char *value
,
715 char ***m
= userdata
;
719 r
= check_utf8ness_and_warn(filename
, line
, key
, value
);
723 p
= strjoin(key
, "=", value
);
727 r
= strv_env_replace(m
, p
);
740 int load_env_file(FILE *f
, const char *fname
, const char *newline
, char ***rl
) {
747 r
= parse_env_file_internal(f
, fname
, newline
, load_env_file_push
, &m
, NULL
);
757 static int load_env_file_push_pairs(
758 const char *filename
, unsigned line
,
759 const char *key
, char *value
,
762 char ***m
= userdata
;
765 r
= check_utf8ness_and_warn(filename
, line
, key
, value
);
769 r
= strv_extend(m
, key
);
774 r
= strv_extend(m
, "");
778 r
= strv_push(m
, value
);
789 int load_env_file_pairs(FILE *f
, const char *fname
, const char *newline
, char ***rl
) {
796 r
= parse_env_file_internal(f
, fname
, newline
, load_env_file_push_pairs
, &m
, NULL
);
806 static int merge_env_file_push(
807 const char *filename
, unsigned line
,
808 const char *key
, char *value
,
812 char ***env
= userdata
;
813 char *expanded_value
;
818 log_error("%s:%u: invalid syntax (around \"%s\"), ignoring.", strna(filename
), line
, key
);
822 if (!env_name_is_valid(key
)) {
823 log_error("%s:%u: invalid variable name \"%s\", ignoring.", strna(filename
), line
, key
);
828 expanded_value
= replace_env(value
, *env
,
829 REPLACE_ENV_USE_ENVIRONMENT
|
830 REPLACE_ENV_ALLOW_BRACELESS
|
831 REPLACE_ENV_ALLOW_EXTENDED
);
835 free_and_replace(value
, expanded_value
);
837 return load_env_file_push(filename
, line
, key
, value
, env
, n_pushed
);
845 /* NOTE: this function supports braceful and braceless variable expansions,
846 * plus "extended" substitutions, unlike other exported parsing functions.
849 return parse_env_file_internal(f
, fname
, NEWLINE
, merge_env_file_push
, env
, NULL
);
852 static void write_env_var(FILE *f
, const char *v
) {
858 fputs_unlocked(v
, f
);
859 fputc_unlocked('\n', f
);
864 fwrite_unlocked(v
, 1, p
-v
, f
);
866 if (string_has_cc(p
, NULL
) || chars_intersect(p
, WHITESPACE SHELL_NEED_QUOTES
)) {
867 fputc_unlocked('\"', f
);
870 if (strchr(SHELL_NEED_ESCAPE
, *p
))
871 fputc_unlocked('\\', f
);
873 fputc_unlocked(*p
, f
);
876 fputc_unlocked('\"', f
);
878 fputs_unlocked(p
, f
);
880 fputc_unlocked('\n', f
);
883 int write_env_file(const char *fname
, char **l
) {
884 _cleanup_fclose_
FILE *f
= NULL
;
885 _cleanup_free_
char *p
= NULL
;
891 r
= fopen_temporary(fname
, &f
, &p
);
895 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
896 (void) fchmod_umask(fileno(f
), 0644);
899 write_env_var(f
, *i
);
901 r
= fflush_and_check(f
);
903 if (rename(p
, fname
) >= 0)
913 int executable_is_script(const char *path
, char **interpreter
) {
915 _cleanup_free_
char *line
= NULL
;
921 r
= read_one_line_file(path
, &line
);
925 if (!startswith(line
, "#!"))
928 ans
= strstrip(line
+ 2);
929 len
= strcspn(ans
, " \t");
934 ans
= strndup(ans
, len
);
943 * Retrieve one field from a file like /proc/self/status. pattern
944 * should not include whitespace or the delimiter (':'). pattern matches only
945 * the beginning of a line. Whitespace before ':' is skipped. Whitespace and
946 * zeros after the ':' will be skipped. field must be freed afterwards.
947 * terminator specifies the terminating characters of the field value (not
948 * included in the value).
950 int get_proc_field(const char *filename
, const char *pattern
, const char *terminator
, char **field
) {
951 _cleanup_free_
char *status
= NULL
;
961 r
= read_full_file(filename
, &status
, NULL
);
971 t
= strstr(t
, pattern
);
975 /* Check that pattern occurs in beginning of line. */
976 pattern_ok
= (t
== status
|| t
[-1] == '\n');
978 t
+= strlen(pattern
);
980 } while (!pattern_ok
);
982 t
+= strspn(t
, " \t");
991 t
+= strspn(t
, " \t");
993 /* Also skip zeros, because when this is used for
994 * capabilities, we don't want the zeros. This way the
995 * same capability set always maps to the same string,
996 * irrespective of the total capability set size. For
997 * other numbers it shouldn't matter. */
999 /* Back off one char if there's nothing but whitespace
1001 if (!*t
|| isspace(*t
))
1005 len
= strcspn(t
, terminator
);
1007 f
= strndup(t
, len
);
1015 DIR *xopendirat(int fd
, const char *name
, int flags
) {
1019 assert(!(flags
& O_CREAT
));
1021 nfd
= openat(fd
, name
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
|flags
, 0);
1034 static int search_and_fopen_internal(const char *path
, const char *mode
, const char *root
, char **search
, FILE **_f
) {
1041 if (!path_strv_resolve_uniq(search
, root
))
1044 STRV_FOREACH(i
, search
) {
1045 _cleanup_free_
char *p
= NULL
;
1049 p
= strjoin(root
, *i
, "/", path
);
1051 p
= strjoin(*i
, "/", path
);
1061 if (errno
!= ENOENT
)
1068 int search_and_fopen(const char *path
, const char *mode
, const char *root
, const char **search
, FILE **_f
) {
1069 _cleanup_strv_free_
char **copy
= NULL
;
1075 if (path_is_absolute(path
)) {
1078 f
= fopen(path
, mode
);
1087 copy
= strv_copy((char**) search
);
1091 return search_and_fopen_internal(path
, mode
, root
, copy
, _f
);
1094 int search_and_fopen_nulstr(const char *path
, const char *mode
, const char *root
, const char *search
, FILE **_f
) {
1095 _cleanup_strv_free_
char **s
= NULL
;
1097 if (path_is_absolute(path
)) {
1100 f
= fopen(path
, mode
);
1109 s
= strv_split_nulstr(search
);
1113 return search_and_fopen_internal(path
, mode
, root
, s
, _f
);
1116 int fopen_temporary(const char *path
, FILE **_f
, char **_temp_path
) {
1125 r
= tempfn_xxxxxx(path
, NULL
, &t
);
1129 fd
= mkostemp_safe(t
);
1135 f
= fdopen(fd
, "we");
1149 int fflush_and_check(FILE *f
) {
1156 return errno
> 0 ? -errno
: -EIO
;
1161 int fflush_sync_and_check(FILE *f
) {
1166 r
= fflush_and_check(f
);
1170 if (fsync(fileno(f
)) < 0)
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
))
1214 t
= new(char, strlen(p
) + 2 + strlen(extra
) + 6 + 1);
1218 strcpy(stpcpy(stpcpy(stpcpy(mempcpy(t
, p
, fn
- p
), ".#"), extra
), fn
), "XXXXXX");
1220 *ret
= path_kill_slashes(t
);
1224 int tempfn_random(const char *p
, const char *extra
, char **ret
) {
1238 * /foo/bar/.#<extra>waldobaa2a261115984a9
1242 if (!filename_is_valid(fn
))
1248 t
= new(char, strlen(p
) + 2 + strlen(extra
) + 16 + 1);
1252 x
= stpcpy(stpcpy(stpcpy(mempcpy(t
, p
, fn
- p
), ".#"), extra
), fn
);
1255 for (i
= 0; i
< 16; i
++) {
1256 *(x
++) = hexchar(u
& 0xF);
1262 *ret
= path_kill_slashes(t
);
1266 int tempfn_random_child(const char *p
, const char *extra
, char **ret
) {
1277 * /foo/bar/waldo/.#<extra>3c2b6219aa75d7d0
1289 t
= new(char, strlen(p
) + 3 + strlen(extra
) + 16 + 1);
1293 x
= stpcpy(stpcpy(stpcpy(t
, p
), "/.#"), extra
);
1296 for (i
= 0; i
< 16; i
++) {
1297 *(x
++) = hexchar(u
& 0xF);
1303 *ret
= path_kill_slashes(t
);
1307 int write_timestamp_file_atomic(const char *fn
, usec_t n
) {
1308 char ln
[DECIMAL_STR_MAX(n
)+2];
1310 /* Creates a "timestamp" file, that contains nothing but a
1311 * usec_t timestamp, formatted in ASCII. */
1313 if (n
<= 0 || n
>= USEC_INFINITY
)
1316 xsprintf(ln
, USEC_FMT
"\n", n
);
1318 return write_string_file(fn
, ln
, WRITE_STRING_FILE_CREATE
|WRITE_STRING_FILE_ATOMIC
);
1321 int read_timestamp_file(const char *fn
, usec_t
*ret
) {
1322 _cleanup_free_
char *ln
= NULL
;
1326 r
= read_one_line_file(fn
, &ln
);
1330 r
= safe_atou64(ln
, &t
);
1334 if (t
<= 0 || t
>= (uint64_t) USEC_INFINITY
)
1341 int fputs_with_space(FILE *f
, const char *s
, const char *separator
, bool *space
) {
1346 /* Outputs the specified string with fputs(), but optionally prefixes it with a separator. The *space parameter
1347 * when specified shall initially point to a boolean variable initialized to false. It is set to true after the
1348 * first invocation. This call is supposed to be use in loops, where a separator shall be inserted between each
1349 * element, but not before the first one. */
1359 r
= fputs(separator
, f
);
1370 int open_tmpfile_unlinkable(const char *directory
, int flags
) {
1375 r
= tmp_dir(&directory
);
1380 /* Returns an unlinked temporary file that cannot be linked into the file system anymore */
1382 /* Try O_TMPFILE first, if it is supported */
1383 fd
= open(directory
, flags
|O_TMPFILE
|O_EXCL
, S_IRUSR
|S_IWUSR
);
1387 /* Fall back to unguessable name + unlinking */
1388 p
= strjoina(directory
, "/systemd-tmp-XXXXXX");
1390 fd
= mkostemp_safe(p
);
1399 int open_tmpfile_linkable(const char *target
, int flags
, char **ret_path
) {
1400 _cleanup_free_
char *tmp
= NULL
;
1406 /* Don't allow O_EXCL, as that has a special meaning for O_TMPFILE */
1407 assert((flags
& O_EXCL
) == 0);
1409 /* Creates a temporary file, that shall be renamed to "target" later. If possible, this uses O_TMPFILE – in
1410 * which case "ret_path" will be returned as NULL. If not possible a the tempoary path name used is returned in
1411 * "ret_path". Use link_tmpfile() below to rename the result after writing the file in full. */
1414 _cleanup_free_
char *dn
= NULL
;
1416 dn
= dirname_malloc(target
);
1420 fd
= open(dn
, O_TMPFILE
|flags
, 0640);
1426 log_debug_errno(errno
, "Failed to use O_TMPFILE on %s: %m", dn
);
1429 r
= tempfn_random(target
, NULL
, &tmp
);
1433 fd
= open(tmp
, O_CREAT
|O_EXCL
|O_NOFOLLOW
|O_NOCTTY
|flags
, 0640);
1443 int open_serialization_fd(const char *ident
) {
1446 fd
= memfd_create(ident
, MFD_CLOEXEC
);
1450 path
= getpid_cached() == 1 ? "/run/systemd" : "/tmp";
1451 fd
= open_tmpfile_unlinkable(path
, O_RDWR
|O_CLOEXEC
);
1455 log_debug("Serializing %s to %s.", ident
, path
);
1457 log_debug("Serializing %s to memfd.", ident
);
1462 int link_tmpfile(int fd
, const char *path
, const char *target
) {
1467 /* Moves a temporary file created with open_tmpfile() above into its final place. if "path" is NULL an fd
1468 * created with O_TMPFILE is assumed, and linkat() is used. Otherwise it is assumed O_TMPFILE is not supported
1469 * on the directory, and renameat2() is used instead.
1471 * Note that in both cases we will not replace existing files. This is because linkat() does not support this
1472 * operation currently (renameat2() does), and there is no nice way to emulate this. */
1475 if (rename_noreplace(AT_FDCWD
, path
, AT_FDCWD
, target
) < 0)
1478 char proc_fd_path
[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(fd
) + 1];
1480 xsprintf(proc_fd_path
, "/proc/self/fd/%i", fd
);
1482 if (linkat(AT_FDCWD
, proc_fd_path
, AT_FDCWD
, target
, AT_SYMLINK_FOLLOW
) < 0)
1489 int read_nul_string(FILE *f
, char **ret
) {
1490 _cleanup_free_
char *x
= NULL
;
1491 size_t allocated
= 0, n
= 0;
1496 /* Reads a NUL-terminated string from the specified file. */
1501 if (!GREEDY_REALLOC(x
, allocated
, n
+2))
1505 if (c
== 0) /* Terminate at NUL byte */
1510 break; /* Terminate at EOF */
1530 int mkdtemp_malloc(const char *template, char **ret
) {
1536 p
= strdup(template);
1549 DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, funlockfile
);
1551 int read_line(FILE *f
, size_t limit
, char **ret
) {
1552 _cleanup_free_
char *buffer
= NULL
;
1553 size_t n
= 0, allocated
= 0, count
= 0;
1557 /* Something like a bounded version of getline().
1559 * Considers EOF, \n and \0 end of line delimiters, and does not include these delimiters in the string
1562 * Returns the number of bytes read from the files (i.e. including delimiters — this hence usually differs from
1563 * the number of characters in the returned string). When EOF is hit, 0 is returned.
1565 * The input parameter limit is the maximum numbers of characters in the returned string, i.e. excluding
1566 * delimiters. If the limit is hit we fail and return -ENOBUFS.
1568 * If a line shall be skipped ret may be initialized as NULL. */
1571 if (!GREEDY_REALLOC(buffer
, allocated
, 1))
1576 _unused_
_cleanup_(funlockfilep
) FILE *flocked
= f
;
1586 c
= fgetc_unlocked(f
);
1588 /* if we read an error, and have no data to return, then propagate the error */
1589 if (ferror_unlocked(f
) && n
== 0)
1590 return errno
> 0 ? -errno
: -EIO
;
1597 if (IN_SET(c
, '\n', 0)) /* Reached a delimiter */
1601 if (!GREEDY_REALLOC(buffer
, allocated
, n
+ 2))
1604 buffer
[n
] = (char) c
;